2017-01-24 11 views
0

プログラムがナビゲーションタイトルをチェックして、それに応じてセルを設定するようにしています。これは、ハードコードされた配列では十分に簡単ですが、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 - のためのコアデータに設定され、その後、ページタイトルをチェックして、空の配列を移入cellForRowにラベルを

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

} 

そして最後に設定します:永続削除するとき

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つの製品が表示されます。しかし、私が「Google」に戻ってタップすると、セルにはAppleの3つの製品とGoogleの3つの製品などが表示されます。

cell.textLabel?.text = product.value(forKey: "name") as? Stringはどのようにして同社の製品をロードできますか?

EDIT: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)") 
    } 
} 

決勝編集 - 1ですべてのデフォルトを設定すると、あなたのswitch self.navigationItem.title! {を実行する前に、

// 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

あなたは 'products'配列、おそらくフェッチ要求を実行することで、例えばを更新し、他のコードを持っていますか。 'viewWillAppear'または他のライフサイクルメソッドの1つにありますか? – pbasdf

+0

@pbasdfはい、 'viewWillAppear'と' save'メソッドを含めるように私の質問を編集しました。どんな助けも大いに評価されるでしょう! – d0xi45

+0

ありがとうございます - それはあなたが観察していることを説明しています。フェッチ要求(viewWillAppear内)はすべてをフェッチします。あなたはAppleの製品をGoogle(と他の人たち)と区別するために何らかの方法が必要です。 Productエンティティに「company」属性を追加するか、「Company」エンティティに関係を追加することで、これを行うことができます。これらのデフォルトを一度しかロードしないようにコードを修正する必要もあります。私は後で完全な答えを追加します... – pbasdf

答えて

1

CompanyからProductまでの関係を作成し、「製品」という名前をつけます。それぞれのCompanyは多くのProductsを持つことができるので、関係を "to-many"にしてください。同様にProductからCompanyまでの関係を作成し、それを「company」と命名します。それぞれProductは1つだけに関連しているので、関係を「1対1」にし、その逆数を「プロダクト」に設定します。

デフォルトの値をデフォルトの値に加えて、デフォルトのCompanyデータを作成すると同時に(現在行っている場所がわからない場合)私はキーとして、会社名で、辞書(defaultProducts)への製品のあなたの5つの配列を変更したことに注意してください:これは、簡単に一度に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)") 
    } 
} 
+0

です。あなたは今、私のヒーローです。コアデータをより効率的に処理する方法を理解するためには間違いありません。 – d0xi45

+0

クイックアップデート - 私は既定の会社を設定したのと同じ場所にこのソリューションを展開しようとしています(3つの製品をそれぞれ持つ5つのデフォルト企業でアプリを起動し、ユーザーが削除して追加できるようにします)。私は辞書を使って各社の製品を割り当てるというアイデアが大好きです。私の機能にどのように取り組むかはわかりません。私はあなたが見てみたい(または私は別の質問をすることができます)、私の質問の一番下に 'setDefaults()'関数を貼り付けましたが、時間がなければそれを汗ばませないでください。すでに大きな助けをしてきました! – d0xi45

+0

@ d0xi45私は自分の答えを編集しました。あなたは非常に近くでした。製品を設定するには、それぞれの会社に設定するために 'for quote in quotes {}'ループ内に設定する必要があります。 – pbasdf

0

を行くこのようなあなたの配列をリセットします。

defaultProducts.removeAll() 

あなたのvi ewControllerは割り振り解除されていない可能性が高いので、配列defaultProductsは前の項目を保持します。あなたがそれを設定する前にそれをクリアすることによって、その問題はなくなるはずです。

+0

私はこれを試しました(switch文の前に 'viewDidLoad'を入れてください)、残念なことにそれは動作しませんでした。 – d0xi45

+0

numberOfRows:セクションコードを投稿できますか? – CodeBender

+0

私は 'products.count'を返します。製品は' var products = [NSManagedObject]() ' – d0xi45

関連する問題