2016-12-20 10 views
1

SwiftでiOS用のウィジェットを構築しています。主なアプリケーションの目的は、URLニュースフィードに接続して最新のニュースを取得することです。ウィジェットは、TodayビューのtableViewに表示するタイトルのみを取得します。Jsonデータがテーブルビューに表示されない

ウィジェットのデータを取得するためにこのメソッドを書いたのですが、何らかの理由で何も表示されません。私はそれをデバッグしようとしましたが、実際に不可能に見えるウィジェットです。

これは、フィードに接続してデータを抽出しようとするcellForRowAtです。面白い部分は、メインアプリは基本的に同じコードを使用し、それは完全に動作します。

 override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
     let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) 


     let urlRequest = URLRequest(url: URL(string: "https://newsapi.org/v1/articles?source=techcrunch&sortBy=top&apiKey=c64849bc30eb484fb820b80a136c9b0a")!) 


     let task = URLSession.shared.dataTask(with: urlRequest) { (data,response,error) in 

      do{ 

       let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String: AnyObject] 

       if let articlesFromJson = json["articles"] as? [[String: AnyObject]] { 

        if !(error != nil) { 

          var resultArray: NSMutableArray = NSMutableArray() 

          for articlesFromJson in articlesFromJson { 

           if let title = articlesFromJson["title"] as? String{ 
            resultArray.add(title) 

           } 

           let array:NSArray = resultArray.reverseObjectEnumerator().allObjects as NSArray 
           resultArray = array as! NSMutableArray 
           let title:String = resultArray.object(at: indexPath.row) as! String 
           cell.textLabel?.text = title 

          } 
        }    
       } 

       //reload on main thread to speed it up 
       DispatchQueue.main.async { 
       self.tableView.reloadData() 
       } 

      } catch let error { 
       print(error) 
      }    
     } 
     task.resume() 

     return cell 
} 

誰かが、それは大きな助けになるミスがi've今日間、この問題に貼付されて、ここで私が把握することができます。ありがとう

+2

スウィフトであなたのObjective-Cの習慣を​​複製しようとしないでください。たとえば、NSArray/NSMutableArray/NSDictionary/NSMutableDictionaryを使用せず、代わりにSwiftコレクションを使用してください。また、強制アンラッピングと強制キャストは避けてください。最後の提案:テーブルビュー内でネットワークやパースをしないでください。 tableViewは、ダウンロードして解析している別のクラスの準備済みコンテンツを使用します。 – Moritz

+0

ありがとう、私はジャスティンのような別の方法ですべてのネットワーキングを以下に提案しました。NSMutableArraysの代わりにコレクションを使用します。 – MrRobot0150

答えて

3

あなたはcellForRowの外でネットワークリクエストを作成し、それが完了したらreloadDataを使って、tableViewがcellForRowを呼び出すセルをリロードするようにします。

は、要求の範囲外でデータの配列を格納するため、関数外から参照することができます。

var resultArray: NSMutableArray = [] 

override func viewDidLoad() { 
    super.viewDidLoad() 
    getData() 
}  

func getData() { 
    let urlRequest = URLRequest(url: URL(string: "https://newsapi.org/v1/articles?source=techcrunch&sortBy=top&apiKey=c64849bc30eb484fb820b80a136c9b0a")!) 

    let task = URLSession.shared.dataTask(with: urlRequest) {[weak self] (data,response,error) in 
    guard let strongSelf = self else { return } 
    do{ 
     let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String: AnyObject] 
     if let articlesFromJson = json["articles"] as? [[String: AnyObject]] { 
      if error == nil { 
       for articlesFromJson in articlesFromJson { 
        if let title = articlesFromJson["title"] as? String{ 
         strongSelf.resultArray.add(title) 
        } 
        let array:NSArray = strongSelf.resultArray.reverseObjectEnumerator().allObjects as NSArray 
        strongSelf.resultArray = array as! NSMutableArray 

        DispatchQueue.main.async { 
         strongSelf.tableView.reloadData() 
        } 

       } catch let error { 
        print(error) 
       }    
      } 
      task.resume() 
    } 

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) 

    let title:String = resultArray.object(at: indexPath.row) as! String 

    cell.textLabel?.text = title 

    return cell 
} 
+0

上記のEric Ayaのアドバイスに必ず従ってください。この回答は、望ましい結果を得るための再編成に焦点を当てています。 – JustinM

+0

お返事ありがとうございます。残念ながら私はあなたの提案を試みましたが、データをロードしていませんでした。実際には3つの空のtablerowsの代わりに "Unable to load" – MrRobot0150

+0

私はオリジナルの答えで作った間違いに気付きました。私は 'エラーの場合は!= nil'(エラーがなければ何をするか)と書いていました。私は 'error == nilなら'に変更しました。それはあなたがその問題を抱えていた理由かもしれません。その変更を加えて、まだ問題がある場合はお知らせください – JustinM

0
checks proper if TableView delegate or datasource proper connected. and check array count before load data in cell 
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) 
if (resultArray.count > 0){ 
     let title:String = resultArray.object(at: indexPath.row) as! String 

    cell.textLabel?.text = title 
} 
else 
{ 
    print("Error: resultArray contain nil value ") 
} 


    return cell 
} 
関連する問題