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?
}
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.
Related
I'm trying to load data from the firebase. I successfully load the data like usename and email, but somehow it fails to load the image. I'm attaching my code which I have used to load the data from firebase. Please help. thank you.
code :
import UIKit
import FirebaseDatabase
import Firebase
class ProfileVC: UIViewController {
#IBOutlet weak var currentphoto: UIImageView!
#IBOutlet weak var usernameLabel: UILabel!
#IBOutlet weak var BioOrEmailLabel: UILabel!
var databasereff : DatabaseReference!
override func viewDidLoad() {
super.viewDidLoad()
databasereff = Database.database().reference()
if let userid = Auth.auth().currentUser?.uid
{
databasereff.child("users").child(userid).observeSingleEvent(of: .value, with: { (snapshot) in
let dict = snapshot.value as? [String:Any]
let username = dict?["username"] as? String
let email = dict?["email"] as? String
if let photourl = dict?["profileimageUrl"] as? String
{
let url = URL(string: photourl)
URLSession.shared.dataTask(with: url!, completionHandler: { (data, response, error) in
if error != nil{
print(error?.localizedDescription)
return
}
OperationQueue.main.addOperation {
self.currentphoto.image = UIImage(data: data!)
}
}).resume()
}
self.usernameLabel.text = username
self.BioOrEmailLabel.text = email
})
{
(error) in
print(error.localizedDescription)
}
}
// Do any additional setup after loading the view.
}
}
You need to create FIRStorage reference to retrieve files from Firebase Data Base.
First:
import FirebaseStorage
Second take a storage reference:
var storage: FIRStorage!
Then Initialize it
storage = FIRStorage.storage()
Now:
let dbRef = database.reference().child("myFiles")
dbRef.observeEventType(.ChildAdded, withBlock: { (snapshot) in
// Get download URL from snapshot
let downloadURL = snapshot.value() as! String
// Create a storage reference from the URL
let storageRef = storage.referenceFromURL(downloadURL)
// Download the data, assuming a max size of 1MB (you can change this as necessary)
storageRef.dataWithMaxSize(1 * 1024 * 1024) { (data, error) -> Void in
// Create a UIImage, add it to the array
let pic = UIImage(data: data)
picArray.append(pic)
})
})
In your case path is different so just change the path and Cheers!
Reference: from here
So, here is the part of class OnboardingViewController, where declared and initialized reviewConsentStep.
class OnboardingViewController: UIViewController {
// MARK: IB actions
#IBAction func joinButtonTapped(sender: UIButton) {
let consentDocument = ConsentDocument()
let consentStep = ORKVisualConsentStep(identifier: "VisualConsentStep", document: consentDocument)
let healthDataStep = HealthDataStep(identifier: "Health")
let signature = consentDocument.signatures!.first!
let reviewConsentStep = ORKConsentReviewStep(identifier: "ConsentReviewStep", signature: signature, inDocument: consentDocument)
reviewConsentStep.text = "Review the consent form."
reviewConsentStep.reasonForConsent = "Consent to join the Developer Health Research Study."
let passcodeStep = ORKPasscodeStep(identifier: "Passcode")
passcodeStep.text = "Now you will create a passcode to identify yourself to the app and protect access to information you've entered."
let completionStep = ORKCompletionStep(identifier: "CompletionStep")
completionStep.title = "Welcome aboard."
completionStep.text = "Thank you for joining this study."
let orderedTask = ORKOrderedTask(identifier: "Join", steps: [consentStep, reviewConsentStep, healthDataStep, passcodeStep, completionStep])
let taskViewController = ORKTaskViewController(task: orderedTask, taskRunUUID: nil)
taskViewController.delegate = self
presentViewController(taskViewController, animated: true, completion: nil)
}
I want to use reviewConsentStep.signature?.givenName and reviewConsentStep.signature?.familyName here:
#IBOutlet var applicationNameLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
applicationNameLabel.text = reviewConsentStep.signature?.givenName/////////... here
If it possible, please tell me how can I do it?
I'd like to read data from an array and write data to a file and viceversa. The file itself has a known path.
The BTTableCell class manages and populates the tableView.
I'm using dati_Riga class in order to have a single array. I thought it would be easier to read and save data using WriteToFile in order to write data and NSMutableArray to read them, but I'm having trouble.
In the following code snippet of the ViewController file you can see functions I wrote in order to open and save data which don't work.
Where did I get wrong? My idea is to save data using BTTableCell but I wasn't able to make it work.
Data structure:
import Cocoa
class BPTableCell:NSTableCellView {
#IBOutlet weak var item_IconaFile: NSImageView!
#IBOutlet weak var item_NomeFile: NSTextField!
#IBOutlet weak var item_PathFile: NSTextField!
#IBOutlet weak var item_MD5: NSTextField!
#IBOutlet weak var item_SHA1: NSTextField!
}
class dati_Riga {
var dati_Riga_item_IconaFile: NSImage!
var dati_Riga_item_NomeFile: String!
var dati_Riga_item_PathFile: String!
var dati_Riga_item_MD5: String!
var dati_Riga_item_SHA1: String!
init (dati_Riga_item_IconaFile: NSImage, dati_Riga_item_NomeFile: String, dati_Riga_item_PathFile: String, dati_Riga_item_MD5: String, dati_Riga_item_SHA1: String)
{
self.dati_Riga_item_IconaFile = dati_Riga_item_IconaFile
self.dati_Riga_item_NomeFile = dati_Riga_item_NomeFile
self.dati_Riga_item_PathFile = dati_Riga_item_PathFile
self.dati_Riga_item_MD5 = dati_Riga_item_MD5
self.dati_Riga_item_SHA1 = dati_Riga_item_SHA1
}
}
Extract from "ViewController.swift":
import Cocoa
import Foundation
import AppKit
import CryptoSwift
class ViewController: NSViewController, NSTableViewDataSource, NSTableViewDelegate {
#IBOutlet weak var tableview: NSTableView!
var item_IconaFile = [NSImage]()
var item_NomeFile = [String]()
var item_PathFile = [String]()
var item_MD5 = [String]()
var item_SHA1 = [String]()
var miei_Dati_Riga : [dati_Riga] = [dati_Riga(dati_Riga_item_IconaFile: NSImage(), dati_Riga_item_NomeFile: "", dati_Riga_item_PathFile: "", dati_Riga_item_MD5: "", dati_Riga_item_SHA1: "")]
override func viewDidLoad() {
super.viewDidLoad()
self.miei_Dati_Riga.removeAtIndex(0)
}
override var representedObject: AnyObject? {
didSet {
// Update the view, if already loaded.
}
}
// MARK: Funzioni relative la TableView
func tableView(tableView: NSTableView, viewForTableColumn tableColumn: NSTableColumn?, row: Int) -> NSView? {
let result : BPTableCell = tableView.makeViewWithIdentifier(tableColumn!.identifier, owner: self) as! BPTableCell
result.item_IconaFile.image = item_IconaFile[row]
result.item_NomeFile.stringValue = item_NomeFile[row]
result.item_PathFile.stringValue = item_PathFile[row]
result.item_MD5.stringValue = item_MD5[row]
result.item_SHA1.stringValue = item_SHA1[row]
return result
}
func numberOfRowsInTableView(tableView: NSTableView) -> Int {
let num_Righe = item_NomeFile.count
return num_Righe
}
// MARK: Apri e Salva file
#IBAction func Save_File(sender: NSMenuItem) {
let salva_File = NSSavePanel()
salva_File.extensionHidden = true
salva_File.canSelectHiddenExtension = true
salva_File.allowedFileTypes = ["cpa"]
salva_File.beginWithCompletionHandler { (result:Int) -> Void in
if result == NSFileHandlingPanelOKButton {
let save_URL_File = salva_File.URL
let mio_Array: NSArray = self.miei_Dati_Riga
print(self.miei_Dati_Riga.count)
print(self.miei_Dati_Riga[0])
if mio_Array.writeToFile((save_URL_File?.path)!, atomically: true) {
print("File Salvato")}
else {
print("File Non Salvato")
}
}
}
}
#IBAction func Open_File(sender: NSMenuItem) {
let apri_File = NSOpenPanel()
apri_File.allowedFileTypes = ["cpa"]
apri_File.beginWithCompletionHandler { (result:Int) -> Void in
if result == NSFileHandlingPanelOKButton {
let contenuto_File = NSMutableArray (contentsOfURL: apri_File.URL!)
self.tableview.reloadData()
}
}
}
I'm getting this error message in relation to the exclamation mark at the end of this line:
sound1.URL = soundURL!
"Cannot assign a value of type ‘NSURL’ to a value of type ‘NSURL’
Type"
I've googled this issue and looked at a couple of explanations for this error code but I still can't work out what's wrong. Can anyone help?
import UIKit
import AVFoundation
class SoundListViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
var audioPlayer = AVAudioPlayer()
var sounds: [Sound] = []
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.tableView.dataSource = self
self.tableView.delegate = self
var soundPath = NSBundle.mainBundle().pathForResource("mhsTesting", ofType: "m4a")
var soundURL = NSURL.fileURLWithPath(soundPath!)
var sound1 = Sound()
sound1.name = "Michael"
sound1.URL = soundURL!
self.sounds.append(sound1)
}
}
This is your Sound class?
class Sound{
var name: String?
var URL : NSURL.Type?
}
Try with code below:
class Sound{
var name: String?
var URL : NSURL?
}
I'm trying to setup a sign in page using parse and swift in Xcode but I keep getting an error with 'signInBackgroundWithBlock' how do I make this work?
I keep receiving the message
Cannot invoke 'signUpInBackgroundWithBlock' with an argument list of
type ((Bool!, NSError!) -> Void)
so far this is what I have and I just have an error with that part.
import UIKit
import Parse
class EmailLogin: UIViewController, UITextFieldDelegate {
#IBOutlet weak var emailTextField: UITextField!
#IBOutlet weak var statusLabel: UILabel!
#IBOutlet weak var createAccountButton: UIButton!
#IBOutlet weak var passwordTextField: UITextField!
override func viewDidLoad()
{
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
emailTextField.delegate = self;
passwordTextField.delegate = self;
}
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func createAccountButtonPressed(sender: AnyObject)
{
if verifyEmailDomain(self.emailTextField.text)
{
createAccount(self.emailTextField.text, password: self.passwordTextField.text)
}
else
{
//self.statusLabel.text = "Email domain is not valid.";
let alert = UIAlertView()
alert.title = "Invalid Email Domain"
alert.message = "Make sure you entered in your address correctly. If you did, ask your system about using PageMD! Thanks."
alert.addButtonWithTitle("Close")
alert.show()
}
}
func verifyEmailDomain(email: String) -> Bool
{
var isVerifiedDomain = false
let userDomain: String = (email.componentsSeparatedByString("#")).last!
//NSLog(userDomain)
let validDomainsFileLocation = NSBundle.mainBundle().pathForResource("ValidDomains", ofType: "txt")
var validDomainsFileContent = NSString(contentsOfFile: validDomainsFileLocation!, encoding: NSUTF8StringEncoding, error: nil)
//NSLog(validDomainsFileContent!)
let validDomains = validDomainsFileContent!.componentsSeparatedByString("\n")
for domain in validDomains
{
NSLog(domain as! NSString as String)
if userDomain == (domain as! NSString)
{
isVerifiedDomain = true
break
}
}
return isVerifiedDomain
}
func createAccount(email: String, password: String)
{
var newUser = PFUser()
newUser.username = email // We want the user to login only with their email.
newUser.email = email
newUser.password = password
//this where i get my error//
newUser.signUpInBackgroundWithBlock { (succeeded: Bool!, error: NSError!) -> Void in
if error == nil
{
// Account created successfully!
if succeeded == true
{
self.statusLabel.text = "Account created!"
}
}
else
{
if let errorField = error.userInfo
{
self.statusLabel.text = (errorField["error"] as NSString)
}
else
{
// No userInfo dictionary present
// Help from http://stackoverflow.com/questions/25381338/nsobject-anyobject-does-not-have-a-member-named-subscript-error-in-xcode
}
}
}
}
func textFieldShouldReturn(textField: UITextField) -> Bool
{
textField.resignFirstResponder()
return true;
}
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
If you are using swift 1.2 (Xcode 6.3) you need to call the function by:
newUser.signUpInBackgroundWithBlock({(succeeded:Bool, error:NSError?) -> Void in
})
And if you are using swift 1.1 (Xcode 6.1, 6.2) you need to call the function by:
newUser.signUpInBackgroundWithBlock({(succeded:Bool, error:NSError!) -> Void in
})
This is different because of the swift update 1.2 which has changes with using optionals.
Another way is to write it like this:
(Works in old and new swift)
newuser.signUpInBackgroundWithBlock { (succeded, error) -> Void in
}