Search code examples
xcodeswiftcore-datansmanagedobjectnsfetchrequest

How to fetch using string in swift


I was just wondering how would I be able to use a searched barcode to fetch using Core Data in Swift. I'm basically passing a barcode to a static func method, but how would I be able to use that to fetch the data from the Core Data?

Here is the barcode when detected:

func barcodeDetected(code: String) {

    // Let the user know we've found something.

    let alert = UIAlertController(title: "Found a Barcode!", message: code, preferredStyle: UIAlertControllerStyle.Alert)
    alert.addAction(UIAlertAction(title: "Search", style: UIAlertActionStyle.Destructive, handler: { action in

        // Remove the spaces.

        let trimmedCode = code.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceCharacterSet())

        // EAN or UPC?
        // Check for added "0" at beginning of code.

        let trimmedCodeString = "\(trimmedCode)"
        var trimmedCodeNoZero: String

        if trimmedCodeString.hasPrefix("0") && trimmedCodeString.characters.count > 1 {
            trimmedCodeNoZero = String(trimmedCodeString.characters.dropFirst())

            // Send the doctored barcode
            ProductDetailsViewController.searchCode(trimmedCodeNoZero)
        } else {

            // Send the doctored barcode
            ProductDetailsViewController.searchCode(trimmedCodeString)

        }

        self.navigationController?.popViewControllerAnimated(true)
    }))

    self.presentViewController(alert, animated: true, completion: nil)
}

My Product Class:

import UIKit
import Foundation
import CoreData


class ProductDetailsViewController: UIViewController, NSFetchedResultsControllerDelegate {

    @IBOutlet weak var productLabel: UILabel!
    @IBOutlet weak var priceLabel: UILabel!

    @IBAction func addProduct(sender: AnyObject) {
        let AppDel = UIApplication.sharedApplication().delegate as? AppDelegate
        let context:NSManagedObjectContext = (AppDel?.managedObjectContext)!

        let ent = NSEntityDescription.entityForName("Products", inManagedObjectContext: context)

        var newProduct = ProductItem(entity: ent!, insertIntoManagedObjectContext: context)
        newProduct.title = productLabel.text
        //newProduct.price = priceLabel.text

        /*context.save(nil)
        print(newProduct)
        print("Object Saved")*/

    }

    private(set) var PRODUCT_NAME = ""
    private(set) var PRODUCT_PRICE = ""
    private var menuItems:[ProductItem] = []

    static func searchCode(codeNumber: String) -> String{

        let barcodeNumber = codeNumber
        return barcodeNumber

    }
        deinit{
        NSNotificationCenter.defaultCenter().removeObserver(self)
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        productLabel.text = "Scan a Product"
        priceLabel.text = ""

        NSNotificationCenter.defaultCenter().addObserver(self, selector: "setLabels:", name: "ProductNotification", object: nil)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }   

}

I already added the items into Core Data successfully and was able to load all items into a table in my app. Now with the barcode scanned I want to be able to just load the products with the barcode and i'm stuck on that part. As you can see my static fun searchCode is receiving the barcode from barcodeDetected but what should I do next to fetch it? Thanks.

EDIT:

Core Data Entity

import Foundation
import CoreData
@objc(ProductItem)

class ProductItem: NSManagedObject{
    @NSManaged var barcodeNum:String?
    @NSManaged var box_height:NSNumber?
    @NSManaged var box_length:NSNumber?
    @NSManaged var box_width:NSNumber?
    @NSManaged var price:NSNumber?
    @NSManaged var sku:String?
    @NSManaged var weight:NSNumber?
    @NSManaged var title:String?


}

Solution

  • To fetch the correct ProductItem, you need to use a predicate (see the Apple Documentation here). In your case, you could use something like this:

    let AppDel = UIApplication.sharedApplication().delegate as? AppDelegate
    let context:NSManagedObjectContext = (AppDel?.managedObjectContext)!
    let fetchRequest = NSFetchRequest(entityName: "ProductItem")
    fetchRequest.predicate = NSPredicate(format: "barcodeNum == %@",codeNumber)
    let results = try! context.executeFetchRequest(fetchRequest) as! [ProductItem]
    if results.count > 0 { // great, you found (at least one) matching item
        let scannedProduct = results[0]
        // from here you can access the attributes of the product
        // such as title, price, sku, etc.
        ...
    } else { // not found
        ...
    }
    

    Note that I've use try! for brevity, but in practice you should use proper do ... catch syntax and handle any errors.

    I'm not clear why you are using a static func in the ProductDetailsViewController; a common approach would be to use the above fetch within your barcodeDetected method, and then to segue to the ProductDetailsViewController passing the relevant ProductItem for display/editing or whatever. Or to display an alert view if the product was not found.