我试图制作它以便程序检查导航标题,然后相应地填充单元格。使用硬编码数组这很容易,但使用Core Data对象会让事情变得艰难。
初始化程序 - 每个公司有3个产品,并且在检查页面标题后将它们设置为空数组:
let defaultProductsApple = ["iPhone", "iPad", "Macbook"]
let defaultProductsGoogle = ["Search", "Firebase", "Magic Leap"]
let defaultProductsFacebook = ["Facebook", "Instagram", "WhatsApp"]
let defaultProductsTesla = ["Model S", "Model X", "PowerWall"]
let defaultProductsTwitter = ["Twitter", "Periscope", "Vine"]
var defaultProducts = [String]()
viewDidLoad - 检查页面标题并填充空数组,然后在删除时设置为Core Data for persistence:
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(Cell.self, forCellReuseIdentifier: cellId)
// Navbar stuff
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Back", style: .plain, target: self, action: #selector(handleBackButton))
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Add", style: .plain, target: self, action: #selector(handleAdd))
let entity = NSEntityDescription.entity(forEntityName: "Product", in: managedContext)!
switch self.navigationItem.title! {
case "Apple":
defaultProducts = defaultProductsApple
case "Google":
defaultProducts = defaultProductsGoogle
case "Twitter":
defaultProducts = defaultProductsTwitter
case "Tesla":
defaultProducts = defaultProductsTesla
case "Facebook":
defaultProducts = defaultProductsFacebook
default:
defaultProducts = defaultProductsApple
}
for productName in defaultProducts {
let product = NSManagedObject(entity: entity,insertInto: managedContext)
product.setValue(productName, forKey: "name")
products.append(product)
}
do {
try managedContext.save()
tableView.reloadData()
} catch let error as NSError {
print("Could not save. \(error), \(error.userInfo)")
}
}
最后在cellForRow中设置标签:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! Cell
let product = products[indexPath.row]
cell.textLabel?.text = product.value(forKey: "name") as? String
return cell
}
细胞在第一次尝试时应该填充 - 即如果我点击" Apple"在上一个屏幕中,单元格显示了Apple的3个产品。但是,如果我回过头来点击谷歌",那么这些小组现在会显示Apple的3个产品以及Google的3个产品,依此类推。依此类推。
我怎样才能使cell.textLabel?.text = product.value(forKey: "name") as? String
仅加载该公司的产品?
编辑:viewWillAppear
和save
方法:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
//1
guard let appDelegate =
UIApplication.shared.delegate as? AppDelegate else {
return
}
let managedContext =
appDelegate.persistentContainer.viewContext
//2
let fetchRequest =
NSFetchRequest<NSManagedObject>(entityName: "Product")
//3
do {
products = try managedContext.fetch(fetchRequest)
} catch let error as NSError {
print("Could not fetch. \(error), \(error.userInfo)")
}
}
func save(name: String) {
guard let appDelegate =
UIApplication.shared.delegate as? AppDelegate else {
return
}
let managedContext =
appDelegate.persistentContainer.viewContext
let entity =
NSEntityDescription.entity(forEntityName: "Product",
in: managedContext)!
let product = NSManagedObject(entity: entity,
insertInto: managedContext)
product.setValue(name, forKey: "name")
do {
try managedContext.save()
products.append(product)
} catch let error as NSError {
print("Could not save. \(error), \(error.userInfo)")
}
}
最终编辑 - 一次性设置所有默认值
// Default 5 companies at launch - user can delete/add/edit
func setDefaults() {
let userDefaults = UserDefaults.standard
let defaultValues = ["firstRun" : true]
userDefaults.register(defaults: defaultValues)
if userDefaults.bool(forKey: "firstRun") {
let defaultProducts = ["Apple" : ["iPhone", "iPad", "Macbook"],
"Google" : ["Search", "Firebase", "Magic Leap"],
"Facebook" : ["Facebook", "Instagram", "WhatsApp"],
"Tesla" : ["Model S", "Model X", "PowerWall"],
"Twitter" : ["Twitter", "Periscope", "Vine"]]
let companyEntity = NSEntityDescription.entity(forEntityName: "Company", in: managedContext)!
let productEntity = NSEntityDescription.entity(forEntityName: "Product", in: managedContext)!
// Setting the default company data (name, logo, and stockPrice)
let url = URL(string: "https://query.yahooapis.com/v1/public/yql?q=select%20symbol%2C%20Ask%2C%20YearHigh%2C%20YearLow%20from%20yahoo.finance.quotes%20where%20symbol%20in%20(%22AAPL%22%2C%22GOOG%22%2C%22TWTR%22%2C%22TSLA%22%2C%20%22FB%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys")!
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
if error != nil {
print(error!)
} else if let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 {
let json = JSON(data: data!)
if let quotes = json["query"]["results"]["quote"].array {
for quote in quotes {
let symbol = quote["symbol"].stringValue
let name = NSLocalizedString(symbol, comment:"")
let ask = quote["Ask"].stringValue
let company = NSManagedObject(entity: companyEntity,insertInto: managedContext)
company.setValue(name, forKey: "name")
company.setValue(name, forKey: "logo")
company.setValue(ask, forKey: "stockPrice")
companies.append(company)
print(json)
}
// Setting the default products - should I be doing this here too?
let companyProducts = defaultProducts[companyName]
// iterate through all those products names...
for productName in companyProducts {
// create the corresponding Product:
let product = NSManagedObject(entity: productEntity,insertInto: managedContext)
// set its name attribute...
product.setValue(productName, forKey: "name")
// then set the relationship to the relevant Company...
product.setValue(company, forKey: "company")
}
DispatchQueue.main.async {
do {
try managedContext.save()
vc.tableView.reloadData()
userDefaults.set(false, forKey: "firstRun")
} catch let error as NSError {
print("Could not save. \(error), \(error.userInfo)")
}
}
}
} else {
print("The data couldn't be loaded")
}
}
task.resume()
}
}
答案 0 :(得分:1)
首先创建从Company
到Product
的关系,并将其命名为&#34; products&#34;。每个Company
都可以包含多个Products
,因此请建立关系&#34; to-many&#34;。同样,创建从Product
到Company
的关系,并将其命名为&#34; company&#34;。每个Product
只与一个Company
相关(我假设),因此将关系&#34; to-one&#34;并将其反转设置为&#34; products&#34;
为了简化生活,请在创建默认Company
数据的同时添加默认值(不确定您现在在哪里做)。请注意,我已将您的五个产品数组更改为字典(defaultProducts
),并将公司名称作为键:这样可以更容易地一次性加载到CoreData中:
func setDefaults() {
let userDefaults = UserDefaults.standard
let defaultValues = ["firstRun" : true]
userDefaults.register(defaults: defaultValues)
if userDefaults.bool(forKey: "firstRun") {
let defaultProducts = ["Apple" : ["iPhone", "iPad", "Macbook"],
"Google" : ["Search", "Firebase", "Magic Leap"],
"Facebook" : ["Facebook", "Instagram", "WhatsApp"],
"Tesla" : ["Model S", "Model X", "PowerWall"],
"Twitter" : ["Twitter", "Periscope", "Vine"]]
let companyEntity = NSEntityDescription.entity(forEntityName: "Company", in: managedContext)!
let productEntity = NSEntityDescription.entity(forEntityName: "Product", in: managedContext)!
// Setting the default company data (name, logo, and stockPrice)
let url = URL(string: "https://query.yahooapis.com/v1/public/yql?q=select%20symbol%2C%20Ask%2C%20YearHigh%2C%20YearLow%20from%20yahoo.finance.quotes%20where%20symbol%20in%20(%22AAPL%22%2C%22GOOG%22%2C%22TWTR%22%2C%22TSLA%22%2C%20%22FB%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys")!
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
if error != nil {
print(error!)
} else if let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 {
let json = JSON(data: data!)
if let quotes = json["query"]["results"]["quote"].array {
for quote in quotes {
let symbol = quote["symbol"].stringValue
let name = NSLocalizedString(symbol, comment:"")
let ask = quote["Ask"].stringValue
let company = NSManagedObject(entity: companyEntity,insertInto: managedContext)
company.setValue(name, forKey: "name")
company.setValue(name, forKey: "logo")
company.setValue(ask, forKey: "stockPrice")
companies.append(company)
// Move the default products code here:
let companyProducts = defaultProducts[name]
// iterate through all those products names...
for productName in companyProducts {
// create the corresponding Product:
let product = NSManagedObject(entity: productEntity, insertInto:managedContext)
// set its name attribute...
product.setValue(productName, forKey: "name")
// then set the relationship to the relevant Company...
product.setValue(company, forKey: "company")
}
print(json)
}
DispatchQueue.main.async {
do {
try managedContext.save()
vc.tableView.reloadData()
userDefaults.set(false, forKey: "firstRun")
} catch let error as NSError {
print("Could not save. \(error), \(error.userInfo)")
}
}
}
} else {
print("The data couldn't be loaded")
}
}
task.resume()
}
}
在视图控制器中,您可以删除代码以设置viewDidLoad
的默认产品。
您当前正在使用导航项目标题来确定您应该展示哪些公司的产品。因此,在viewWillAppear
中,您需要修改提取以限制结果。使用predicate
:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
//1
guard let appDelegate =
UIApplication.shared.delegate as? AppDelegate else {
return
}
let managedContext =
appDelegate.persistentContainer.viewContext
//2
let companyToDisplay = self.navigationItem.title!
let fetchRequest =
NSFetchRequest<NSManagedObject>(entityName: "Product")
fetchRequest.predicate = NSPredicate(format:"company.name == %@",companyToDisplay)
//3
do {
products = try managedContext.fetch(fetchRequest)
} catch let error as NSError {
print("Could not fetch. \(error), \(error.userInfo)")
}
}
答案 1 :(得分:0)
在执行switch self.navigationItem.title! {
之前,请按以下方式重置阵列:
defaultProducts.removeAll()
您的viewController可能未被释放,因此defaultProducts
数组会保留其先前的项目。通过在填充之前清除它,该问题应该消失。