当所有异步调用在循环内完成时,我尝试在dataSource完成更新后重新加载TableView。但是,似乎postLike.likeUser在for范围之外变得很清楚。
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
}
}
从异步调用更新dataSource的更好方法是什么
更新资料
我已经使用调度组修改了我的代码,但是结果是一样的,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()
})
})
}
}
输出:
Optional("Nicholas Tse")
user get cleared
Optional("Kesong Xie")
user get cleared
nil
nil
最佳答案
postLike.likeUser
总是被释放的原因是在我的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")