What does the underscore mean in this case? - syntax

my code before the migation to Swift 2.0:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if (segue.identifier == "RhymeFavoriten") {
// pass data to next view
let dest = segue.destinationViewController as! FavoritenViewController
let source = segue.sourceViewController as! RhymeViewController // !!!!!!
dest.favoritenType = 1
dest.delegate = self
}
}
the migration told me to change it to
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if (segue.identifier == "RhymeFavoriten") {
// pass data to next view
let dest = segue.destinationViewController as! FavoritenViewController
_ = segue.sourceViewController as! RhymeViewController // !!!!!!!!!!
dest.favoritenType = 1
dest.delegate = self
}
or
func textSelected(selectedText:String, selectedType:Int) {
var fullTextArr = text.componentsSeparatedByString("\n")
var myArray = [String]() // !!!!!!
to
func textSelected(selectedText:String, selectedType:Int) {
var fullTextArr = text.componentsSeparatedByString("\n")
_ = [String]() // !!!!!!!!!
I canĀ“t see, what is _ = standing for :-(

_ is a placeholder. It means that the values assigned to _ are ignored.
Xcode's migration tool made this changes because it has detected that you didn't use source or myArray anywhere, thus replaced these variables by the placeholder.
Now instead of being assigned to a variable, the returning result of segue.sourceViewController as! RhymeViewController and the returning result of [String]() are ignored.
The returning result is ignored but the expression is still evaluated at runtime: if it has side effects, these effects will occur.
So if you actually don't need these instructions you should get rid of them entirely.

Related

UserDefault in Xcode is not saving the text

This code won't save the text for same reason. How to fix it?
import UIKit
class ViewControllertextview: UIViewController {
#IBOutlet weak var text: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
_ = UserDefaults.standard
let value = UserDefaults.standard.string(forKey: "onekey")
if value != nil{
text.text = value
}
else {
text.text = "Here you can make Notes"
}
}
let defaults = Foundation.UserDefaults.standard
#IBAction func Sbutton(_ sender: Any) {
UserDefaults.standard.set(text.text, forKey: "onekey")
}
#IBAction func ggbutton(_ sender: Any) {
}
}
UserDefaults don't immediately write data to storage. You can try calling UserDefaults.standard.synchronize() to save immediately, right after UserDefaults.standard.set(..

Found nil while unwrapping an optional value - Swift 2

I am getting this error which I cannot explain:
#IBOutlet weak var licencePlateLabel: UILabel!
var editItem: CarValues? {
didSet {
// Update the view.
self.configureView()
}
}
func configureView() {
// Update the user interface for the detail item.
if let editedCar = self.editItem {
if let licencePlate = self.licencePlateLabel {
licencePlate.text? = editedCar.licencePlate!//this gives me nil
}
else {
print("value was nil")
}
print(editedCar.licencePlate!)//this is giving me the correct value
}
if I replace the
if let licencePlate = self.licencePlateLabel {
licencePlate.text! = editedCar.licencePlate!
}//this throws an error "found nil......"
even if I do this I m still getting the "found nil..."
func configureView() {
licencePlateLabel.text = "test"
[...]
}
BUT if I put the above on viewDidLoad then it works fine
override func viewDidLoad() {
licencePlateLabel.text = "test"
[...]
}
What is going on in this code?
EDIT
I am passing the value of the editItem from the detailView to the EditView like this:
#IBAction func editButtonTapped(sender: AnyObject) {
let storyBoard = UIStoryboard(name: "Main", bundle:nil)
let editScreen = storyBoard.instantiateViewControllerWithIdentifier("ID_EditViewController")
self.navigationController?.pushViewController(editScreen, animated: true)
let controller = EditViewController()
controller.editItem = detailItem
controller.navigationItem.leftBarButtonItem = self.splitViewController?.displayModeButtonItem()
controller.navigationItem.leftItemsSupplementBackButton = true
}
You don't unwrap properties to set them, only to read from them. So your code can simply be:
if let licencePlate = self.licencePlateLabel {
licencePlate.text = editedCar.licencePlate
}
Note that because licencePlate.text is an optional value anyway, there is also no need to unwrap editedCar.licencePlate. It's ok to use its value whether it is nil or contains a String.

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?
}
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.

Why am I receiving these errors when trying to pass a variable on a segue in swift?

I am trying to build upon answer which I was given here. What I am trying to is very simple - I want a text field which you can enter text into. You press the go button and it takes you to a new view and replaces the text on a label on that page with whatever the user entered in the box. The is the code I am using on the first page.
import UIKit
class ViewController: UIViewController {
#IBOutlet var entry: UITextField!
let dictionary = entry.text // Line 7 ERROR
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "viewTwo"
{
if let destinationVC = segue.destinationViewController as? viewTwo{
destinationVC.dictionary = self.dictionary // Line 24 ERROR
}
}
}
#IBAction func goToViewTwo(sender: AnyObject) {
performSegueWithIdentifier("viewTwo", sender: self)
}
}
I am only including the code from the first view because i know the code from the second view is working.
I didn't encounter an error until I tried to use the text field - before when I just had a pre-choses text to transfer over it worked. Before, instead of having let dictionary = entry.text I had let dictionary = "foo" and it worked.
So my question is exactly the same thing but have a text field instead of pre-chosen text - what I really want to know is why my code didn't work before.
The errors I got were on line 7 (I have labeled the lines above which had the errors) - 'ViewController.Type' does not have member names 'entry' and there was also an error on line 24 but I suspect this is related to this error and will be fixed if this error is also fixed. Just incase though, the error on line 24 was: 'ViewController.Type' does not have member names 'dictionary'
Thank you.
You should set the dictionary to var dictionary = "" in the declaration. You use var instead of let here, so that you can change the value of the dictionary later.
Then inside your #IBAction func goToViewTwo(sender: AnyObject){} method, you set the self.dictionary = entry.text
#IBAction func goToViewTwo(sender: AnyObject) {
dictionary = entry.text
performSegueWithIdentifier("viewTwo", sender: self)
}
Alternatively, you can just do the following inside prepareForSegue() method.
This way, you dont need to declare a dictionary to hold the text value of your UITextField, you can just pass the text value from your entry to the second view controller's dictionary variable.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "viewTwo"
{
if let destinationVC = segue.destinationViewController as? viewTwo{
destinationVC.dictionary = self.entry.text
}
}
}
A dictionary is not constant, so declare it as lazy var, not let:
lazy var dictionary: String {
return entry.text
}()

Swift Saving data and crash when I attempt to save another value on to original variable

My main issue is one of saving and retrieving data outside of Core Data.
I am looking to save 1 variable with persistent data.
The routine crashes after second button press.
override func viewDidLoad() {
super.viewDidLoad()
var amy="2"
NSUserDefaults.standardUserDefaults().setObject((amy), forKey: "ggpass")
}
#IBAction func pass(sender: AnyObject) {
// Retrieve the original Variable
NSUserDefaults.standardUserDefaults().synchronize()
var aname5 = (NSUserDefaults.standardUserDefaults().objectForKey("ggpass"))! as String
gpass = (aname5.toInt())!
gpass=gpass+1
///Save Data
NSUserDefaults.standardUserDefaults().setObject((gpass), forKey: "ggpass")
}
You are creating the NSUserDefaults as a string, reading it assuming it's a string, and then writing it back as a number - that won't work. You need to either stick to numbers for your values, or strings. Here's a version sticking to strings - a bit clumsy, but closest to your existing code:
#IBAction func pass(sender: AnyObject) {
var aname5 = NSUserDefaults.standardUserDefaults().objectForKey("ggpass") as? String
if let gpass = aname5?.toInt() {
NSUserDefaults.standardUserDefaults().setObject("\(gpass+1)", forKey: "ggpass")
}
}
Note that you don't need the synchronize() call in iOS8 or Yosemite, see http://www.codingexplorer.com/nsuserdefaults-a-swift-introduction/.
Retrive the original value of amy by using this code:
amy = NSUserDefaults.standardUserDefaults().integerForKey("ggpass")
Then assign its value to aname5.
var aname5 = amy
Your code now looks like:
#IBAction func pass(sender: AnyObject) {
amy = NSUserDefaults.standardUserDefaults().integerForKey("ggpass")
var aname5 = amy
gpass = (aname5.toInt())!
gpass++
///Save Data
NSUserDefaults.standardUserDefaults().setObject((gpass), forKey: "ggpass")
}

Resources