根据页面标题

时间:2017-01-24 21:53:24

标签: ios swift xcode uitableview core-data

我试图制作它以便程序检查导航标题,然后相应地填充单元格。使用硬编码数组这很容易,但使用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仅加载该公司的产品?

编辑:viewWillAppearsave方法:

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()
    }
}

2 个答案:

答案 0 :(得分:1)

首先创建从CompanyProduct的关系,并将其命名为&#34; products&#34;。每个Company都可以包含多个Products,因此请建立关系&#34; to-many&#34;。同样,创建从ProductCompany的关系,并将其命名为&#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数组会保留其先前的项目。通过在填充之前清除它,该问题应该消失。