2016-08-20 9 views
0

すべての非同期呼び出しがループ内で終了したときに、dataSourceの更新が終了した後にTableViewを再ロードしようとしました。しかし、postLike.likeUserがforスコープの外側で明確になるようです。ループ内の非同期呼び出しからテーブルビューのdataSourceを変更できません。

class MyTableView: UITableViewController { 
let reuseIden = "postLikeCell" 

var postLikes: [PostLike]? 

var userFetchingCompleted = false 

var userFetched: Int = 0  

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

func startFetchingLikeUsers(){ 
    if postLikes != nil{ 
     for (index, postLike) in postLikes!.enumerate(){ 
      postLike.likeUser = User(id: postLike.likeUserId, completionHandler: { 
     // the User initilizer requires to fetch info from the server 
       (succeed, info) in 
        if succeed{ 
        self.userFetched += 1 
         print(self.userFetched) 
         print(self.postLikes![index].likeUser?.fullname) 

         if self.userFetched == self.postLikes!.count{ 
          self.userFetchingCompleted = true 
          dispatch_async(dispatch_get_main_queue(), { 
           self.tableView.reloadData() 
          }) 
         } 
        } 
       }) 
     } 
    } 
} 


// MARK: - Table view data source 

override func numberOfSectionsInTableView(tableView: UITableView) -> Int { 
    // #warning Incomplete implementation, return the number of sections 
    return 1 
} 

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
    // #warning Incomplete implementation, return the number of rows 
    return userFetchingCompleted ? (postLikes?.count ?? 0) : 0 
} 


override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 
    let cell = tableView.dequeueReusableCellWithIdentifier("postLikeCell", forIndexPath: indexPath) as! PostLikeTableViewCell  
    print(postLikes![indexPath.row].likeUser) //always print nil 
    cell.postLike = postLikes![indexPath.row] 
    return cell 
} 


} 

上記のコードのサンプル出力は

1 //the first iteration 
Optional("Nicholas Tse") 
user get cleared //it seems the postLike.likeUser gets deInitialized since I have a deInit in my User class 

2 //second iteration 
Optional("Kesong Xie") 
user get cleared 

nil //this comes from cellForRowAtIndex 
nil 

PostLikeクラスのための私の実装のより良い方法非同期呼び出しからのデータソースを更新するためには何

class PostLike{ 
    let postLikeId: Int 
    let likeTime: String 
    let likeUserId: Int 
    unowned var post: Post 
    weak var likeUser: User? //the user who liked the post 


    init(postLikeId: Int, likeTime: String, likeUserId: Int, post: Post){ 
     self.postLikeId = postLikeId 
     self.likeTime = likeTime 
     self.likeUserId = likeUserId 
     self.post = post 

    } 

} 

更新

私は派遣・グループを使用して自分のコードを変更したが、結果は同じであるが、postLike.likeUserは明らか離れる

func startFetchingLikeUsers(completionHandler:() -> Void){ 
     if postLikes != nil{ 
      dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), { //don't block the main thread 
       let loadingGroup = dispatch_group_create() 

       for (index, postLike) in self.postLikes!.enumerate(){ 
        dispatch_group_enter(loadingGroup) 
        postLike.likeUser = User(id: postLike.likeUserId, completionHandler: { 
        (succeed, info) in 
         dispatch_group_leave(loadingGroup) 
         print(self.postLikes![index].likeUser?.fullname) 
        }) 
        self.postLikes![index].likeUser = postLike.likeUser 
       } 

       dispatch_group_wait(loadingGroup, DISPATCH_TIME_FOREVER) 
       dispatch_async(dispatch_get_main_queue(), { 
        completionHandler() 
       }) 
      }) 
     } 
    } 

出力:postLike.likeUserは常に割り当て解除を取得する理由

Optional("Nicholas Tse") 
user get cleared 
Optional("Kesong Xie") 
user get cleared 
nil 
nil 
+0

あなたの構造は意味がありません。あなたのUserイニシャライザはどのように構築されますか?通常、戻り値と完了ブロックはありません。また、ここにはスレッドセーフではないコードがたくさんあります。補完ブロックのカウンタをインクリメントするようなもの。あなたはdispatch_groupとdispatch_notifyを使うべきです – Paulw11

+0

私の初期化子の中で、私はすでにdispatch_async(dispatch_get_main_queue()、{})を使っていて、そこから補完ハンドラを呼び出しています。したがって、完了ブロックで行われたすべてがメインスレッドにあります。ユーザーイニシャライザは、サーバーからユーザーのフルネーム、電子メールアドレスなどの情報を取得する必要があります。そのため、完成ブロックを構築する必要があります。完了ブロックが実行されたときにすべてのユーザーデータが使用可能になっていることを確認したい@ Paulw11 –

+0

dispatch_groupが私が探しているものだと思う、thanks @ Paulw11 –

答えて

0

理由私のPostLike実装では、私はweak var likeUser: User?を持っています。 postLike.likeUserがループの範囲を超え、Userオブジェクトへの強力な参照がないため、Userは割り当てが解除されます。 weak var likeUser: User?var likeUser!に変更すると問題が解決されます。

class PostLike{ 
    let postLikeId: Int 
    let likeTime: String 
    let likeUserId: Int 
    unowned var post: Post 
    var likeUser: User! //the user who liked the post 


    init(postLikeId: Int, likeTime: String, likeUserId: Int, post: Post){ 
     self.postLikeId = postLikeId 
     self.likeTime = likeTime 
     self.likeUserId = likeUserId 
     self.post = post 

    } 
} 

出力

Optional("Nicholas Tse") 
Optional("Kesong Xie") 
Optional("Nicholas Tse") 
Optional("Kesong Xie") 
関連する問題