2016-05-20 8 views
1

検索に入力するとムービーの結果をプルアップするアプリがあります。 (IMDbのように)themoviedb.orgの無料APIを使用して結果を読み込みます。私はそれらをTableViewControllerにロードします。 .dataTaskWithRequestメソッドのmodを使用して結果のポスターを読み込みます。それを同期させる。それ以外は、映画やテレビ番組のタイトル、ジャンル、年の基本的なAPIの送受信です。遅れのためTableViewControllerの検索結果が正しく読み込まれない

私は速すぎて入力すると遅くなりますが、は完全にではありません。同期ロードのために画像が読み込まれずに画像が読み込まれてもアプリが遅れます。今これは問題ですが、問題は、アプリが単語を画面に読み込んで遅れをとったときに、結果が画面上にある単語の一部の結果です。たとえば、「The Simpsons」と入力すると速すぎると「The Sim」の結果が表示されますが、一度バックスペースして「The Simpsons」を再入力すると結果が正しく読み込まれます。物事をさらに複雑にするものは、時にはトップ結果が古い、部分的な結果の1つになることがあり、残りは正常であり、下にロードされるということです。

Here is a video状況を説明します。私が初めて「シンプソンズ」を打つと、あなたは遅れを見ることができます。私はそれをすべて本当に速く入力しましたが、単語 "the"より遅れています。読み込みが完了すると、存在しないはずのベオウルフ結果が読み込まれます。何が起こっているのか分かりません。イメージをロードせずに入力が遅くならない場合でも、の結果はに更新されません。

ここに関連するコードスニペットがあります。ご希望の場合は、お気軽にお問い合わせください。私は一度にあまりにも多くのコードであなたを砲撃したくない:

テキストは検索バーに入力されているときに、検索結果を更新:

extension SearchTable : UISearchResultsUpdating { 
    func updateSearchResultsForSearchController(searchController: UISearchController) { 

     //To Handle nils 
     var searchBarText = searchController.searchBar.text 
     if (searchBarText == nil) { 
      searchBarText = "" 
     } 

     searchBarText! = searchBarText!.condenseWhitespace() 

     //To Handle Disallowed Characters 
     searchBarText = searchBarText!.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet()) 

     //Find Results from themoviedb 
     let urlString = "https://api.themoviedb.org/3/search/multi?query=" + searchBarText! + "&api_key= (I can't post the api key publicly online, sorry)" 


     let results = NSURL(string: urlString) 
     if (results == nil) { 
      //Server Error 
     } 


     //Wire Up Results with matchingItems Array 
     let task = NSURLSession.sharedSession().dataTaskWithURL(results!) { (data, response, error) -> Void in 
      if let jsonData = data { 

       do { 
        let jsonData = try NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.MutableContainers) 


        if var results = jsonData["results"] as? [NSDictionary] { 
         if results.count > 0 { 
          //Clean out non-english results: 
          //I wrote the function, it shouldn't be the source of the lag, but I can still provide it. 
          self.cleanArray(&results) 
          self.matchingItems = results 
         } else { 
          self.matchingItems = [] 
         } 
        } 
       } catch { 
        //JSON Serialization Error 
       } 

      } 
     } 
     task.resume() 
     self.tableView.reloadData() 

    } 
} 

その後、私は結果を取得した後、私はリロードTableViewDataSourceの2つの必要なメソッドを使用してテーブルを作成します。

//Table Data Source 
extension SearchTable { 

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
     return matchingItems.count 
    } 

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 

     let cell = tableView.dequeueReusableCellWithIdentifier("cell")! as! CustomCell 

     //Safe-Guard. This shouldn't be needed if I understood what I was doing 
     if (indexPath.row < matchingItems.count) { 
      cell.entry = matchingItems[indexPath.row] //404 

      //Name & Type & Year 
//This is only for TV Shows, I removed the rest for simplicity 
       cell.title.text = matchingItems[indexPath.row]["name"] as? String 
       cell.icon.image = UIImage(named: "tv.png") 

       let date = (matchingItems[indexPath.row]["first_air_date"] as? String) 
       cell.year.text = date == nil ? "" : "(" + date!.substringToIndex(date!.startIndex.advancedBy(4)) + ")" 

      //Genre 
      //Code here removed for simplicity 

      //Poster 
      cell.poster.image = UIImage(named: "Placeholder.jpg") 
      if let imagePath = matchingItems[indexPath.row]["poster_path"] as? String { 
       let url = NSURL(string: "http://image.tmdb.org/t/p/w185" + imagePath) 
       let urlRequest = NSURLRequest(URL: url!) 
       let session = NSURLSession.sharedSession() 
       //Synchronous Request 
       let semaphore = dispatch_semaphore_create(0) 
       let task = session.dataTaskWithRequest(urlRequest) { data, response, error in 
        if let poster = UIImage(data: data!) { 
         cell.poster.image = poster 
        } 
        dispatch_semaphore_signal(semaphore) 
       } 
       task.resume() 
       dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER) 
      } 
     } 

     return cell 
    } 

} 

ありがとう!

答えて

0

まず、は、同期リクエストを使用しないことを強くお勧めします。これは主に、完了するまでUIをブロックし、これがアプリの応答が非常に悪いためです。

UIImageのプレースホルダを置くことができます。要求が完了すると、正しい画像に置き換えられます。より高速なタイピングのあなたの問題について

、それはまたはデバウンススロットルと呼ばれる、Appleが推奨しています。

パフォーマンスの問題。検索操作が非常に迅速に実行できる場合、デリゲートオブジェクトに対してsearchBar:textDidChange:メソッドを実装することによって、ユーザーが入力しているときに検索結果を更新することができます。ただし、検索操作に時間がかかる場合は、searchBarSearchButtonClicked:メソッドで検索を開始する前にユーザーが[検索]ボタンをタップするまで待つ必要があります。メインスレッドをブロックしないように、バックグラウンドスレッドの検索操作を常に実行します。これにより、検索の実行中にアプリがユーザーに反応しやすくなり、ユーザーエクスペリエンスが向上します。

は、しかし、あなたがするまで、それは自分で処理したい場合は、この2つの良い答えは、それを正しく処理する方法を説明する見ることができます。

私はあなたがハンドルをお勧めしますAppleが推奨するように、またはあなたの哲学を変えて自動的にあなたのためにそれを扱ういくつかのライブラリを採用することができます:

  • RxSwift
  • 学ぶことがより簡単で最初の

    • は、もう一つはそれはあなた次第です、リプログラミングと関数型プログラミングの概念を学習する必要があります。

      私はこれがあなたに役立つことを願っています。

    +0

    これは完璧です!検索の絞り込みはまさに私が望んでいたものです!どうもありがとうございます!! また、画像を読み込まなくても検索結果がまだバグだった理由がわかりました。私が検索するたびに、非同期に行われたので、検索が完了する前にテーブルがリロードされることがありました。 [これは私の多くを助けた](http://stackoverflow.com/questions/35421631/in-swift-tableview-data-loaded-from-json-only-loads-80-of-the-time) 両方を使用するこれらのうち、私はこれを解決することにかなり自信があります。ありがとうありがとう!これは3日間私を困らせている! – QuantumHoneybees

    +0

    ちょうど質問ですが、BondとRxSwiftは正確に何をしていますか?私はドキュメントを開き、彼らが私を助けるためにできることを本当に理解できませんでした... – QuantumHoneybees

    +0

    Well Bondはデータバインディングを行うライブラリに過ぎず、例えばAppleが提案したデフォルトのクラシックMVCの代わりにMVVMパターンを採用することができます。ボンドではスロットルを操作できます。 RxSwiftはReactive Programmingと呼ばれる別のコンセプトを採用するライブラリですが、RxSwiftの紹介が本当にうまくいけば、この記事をお勧めします。http://www.thedroidsonroids.com/blog/ios/rxswift-by-examples -1-the-basics/ –

    0

    今後もこの同じ問題で苦労しているかもしれない人々のためだけです。まず、Victor Siglerの答えに私のコメントを読んでください。

    は、ここでの問題だった:

    1 - 私はオンラインこれは、コードを継続しながら、バックグラウンドで実行されていました非同期メソッドである)(.dataTaskWithURLを使用して結果を探索しました。したがって、新しい結果が入る前にテーブルがリロードされることがありました。詳細については、this threadを参照してください。私はあなたが学習スウィフトを真剣に考えている場合は同時実行でこのチュートリアルをお調べし、高度

    www.raywenderlich.com/79149/grand-central-dispatch-tutorial-swift-part-1

    2 - ビクターが言ったように、検索が同期的であるために画像が遅れていた。彼の答えは残りの部分をかなり扱うので、それを読んでください!

    関連する問題