I've seen all the problems with keyword Use of 'self' in property
but still couldn't solve it. I just started learning swift 3.01 and my Xcode version is 8.2. Please help me!
I was changing the app Apple provided .
I want to create a textView
so users can type text and store it. While I was changing the Meal.swift
, I got the error: Error :Use of 'self' in property access 'content' before self.init initializes self
just at the end of the code:
import UIKit
import os.log
class Meal: NSObject, NSCoding {
//MARK: Properties
var name: String
var photo: UIImage?
var content: String
//MARK: Archiving Paths
static let DocumentsDirectory = FileManager().urls(for: .documentDirectory, in: .userDomainMask).first!
static let ArchiveURL = DocumentsDirectory.appendingPathComponent("meals")
//MARK: Types
struct PropertyKey {
static let name = "name"
static let photo = "photo"
static let content = "content"
}
//MARK: Initialization
init?(name: String, photo: UIImage?, content: String) {
// The name must not be empty
guard !name.isEmpty else {
return nil
}
// The content must not be empty
guard !content.isEmpty else {
return nil
}
// Initialize stored properties.
self.name = name
self.photo = photo
self.content = content
}
//MARK: NSCoding
func encode(with aCoder: NSCoder) {
aCoder.encode(name, forKey: PropertyKey.name)
aCoder.encode(photo, forKey: PropertyKey.photo)
aCoder.encode(content, forKey: PropertyKey.content)
}
required convenience init?(coder aDecoder: NSCoder) {
// The name is required. If we cannot decode a name string, the initializer should fail.
guard let name = aDecoder.decodeObject(forKey: PropertyKey.name) as? String else {
os_log("Unable to decode the name for a Meal object.", log: OSLog.default, type: .debug)
return nil
}
// Because photo is an optional property of Meal, just use conditional cast.
let photo = aDecoder.decodeObject(forKey: PropertyKey.photo) as? UIImage
// Must call designated initializer.
self.init(name: name, photo: photo, content: content)// Error happened to here by this : Error :Use of 'self' in property access 'content' before self.init initializes self
}
}
Please help me to find up the what's wrong in there, Best regard!
You have to decode content
, too
required convenience init?(coder aDecoder: NSCoder) {
// The name is required. If we cannot decode a name string, the initializer should fail.
let name = aDecoder.decodeObject(forKey: PropertyKey.name) as! String
// Because photo is an optional property of Meal, just use conditional cast.
let photo = aDecoder.decodeObject(forKey: PropertyKey.photo) as? UIImage
let content = aDecoder.decodeObject(forKey: PropertyKey.content) as! String
// Must call designated initializer.
self.init(name: name, photo: photo, content: content)
}
By the way: guard
ing values in encode
/ decode
methods reveals developer / design errors. Nobody else but the application can create those objects and you are supposed to know that the value does exist. You must not guard
to catch runtime errors which should actually never occur.
I've solved my problem add let content = content.text
in MealViewController
's func prepare
It's totally looks like that :
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)
// Configure the destination view controller only when the save button is pressed.
guard let button = sender as? UIBarButtonItem, button === saveButton else {
os_log("The save button was not pressed, cancelling", log: OSLog.default, type: .debug)
return
}
let name = nameTextField.text ?? ""
let photo = photoImageView.image
let content = content.text // Add this new code.
// Set the meal to be passed to MealTableViewController after the unwind segue.
meal = Meal(name: name, photo: photo, content: content!)
}
Just give everyone to be a referance. Hope you will enjoy.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.