首先,错误:
> Assertion failure in
-[UITableView _dequeueReusableViewOfType:withIdentifier:],
/SourceCache/UIKit_Sim/UIKit-3232.3/UITableView.m:5978
2014-06-18 17:49:51.887 Twitter App[21909:583896] \
***Terminating app due to uncaught exception 'NSInternalInconsistencyException',
reason: 'invalid nib registered for identifier (CustomTimelineCell) - nib must contain exactly one top level object which must be a UITableViewCell instance'**
其次,背景:TableViewController
从Twitter中提取时间线,解析它,更新使用动态原型自定义单元格的tableView
。通过创建具有该推文属性的虚拟单元格然后返回高度,在heightForRowAtIndexPath
中计算每个单元格的高度。一切正常,但是当离开视图并返回按钮时,视图会重复该过程并崩溃。
相关守则:
var tweetsArray:NSArray = NSArray()
var accountStore:ACAccountStore = ACAccountStore()
var account:ACAccount = ACAccount()
var profileImages:NSMutableDictionary = NSMutableDictionary()
let identifier:NSString = "CustomTimelineCell"
//viewWillAppear simply requests authorization and calls the following functions to do the work
func reloadTimeline() {
requestAuthorization()
var url: NSURL = NSURL.URLWithString("https://api.twitter.com/1.1/statuses/home_timeline.json")
var params: NSDictionary = ["trim_user" : "false", "count" : "200"]
var request: SLRequest = SLRequest(forServiceType: SLServiceTypeTwitter, requestMethod: SLRequestMethod.GET, URL: url, parameters: params)
request.account = account
// Execute the Request
let requestHandler: SLRequestHandler = {responseData, urlResponse, error in
if responseData {
if urlResponse.statusCode >= 200 && urlResponse.statusCode < 300 {
var error: NSError? = NSError()
let feedData:NSArray? = NSJSONSerialization.JSONObjectWithData(responseData, options: NSJSONReadingOptions.AllowFragments, error: &error) as? NSArray
if feedData {
self.updateFeed(feedData!)
//println("Timeline Response: \(self.tweetsArray)")
}
}
else {
println("Response Status Code: \(urlResponse.statusCode)")
}
}
if error {
println(error.localizedDescription)
}
UIApplication.sharedApplication().networkActivityIndicatorVisible = false
}
request.performRequestWithHandler(requestHandler)
UIApplication.sharedApplication().networkActivityIndicatorVisible = true
}
func updateFeed(feedData: NSArray) {
tweetsArray = feedData
self.tableView.layoutIfNeeded()
tableView.reloadData()
self.stopRefresh()
}
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
var cell : CustomTimelineCell = tableView!.dequeueReusableCellWithIdentifier(identifier, forIndexPath: indexPath!) as CustomTimelineCell
let currentTweet:NSDictionary = tweetsArray.objectAtIndex(indexPath.row) as NSDictionary
let currentUser:NSDictionary = currentTweet.objectForKey("user") as NSDictionary
cell.username.text = currentUser.objectForKey("name") as NSString!
cell.tweetText.text = currentTweet.objectForKey("text") as NSString!
cell.userImage.image = UIImage(named: "bird_twitter.png")
// Adds and Configures Gesture Recognizer for Profile Image (uses segue made from unused IB gesture recognizer)
if !cell.userImage.gestureRecognizers {
cell.userImage.userInteractionEnabled = true
var imageTapRecognizer:UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "profileImageTap")
imageTapRecognizer.numberOfTapsRequired = 1
imageTapRecognizer.numberOfTouchesRequired = 1
cell.userImage.addGestureRecognizer(imageTapRecognizer)
}
// May or may not be necessary, but including constraint resizing restrictions
cell.setTranslatesAutoresizingMaskIntoConstraints(true)
cell.username.setTranslatesAutoresizingMaskIntoConstraints(false)
cell.tweetText.setTranslatesAutoresizingMaskIntoConstraints(false)
cell.userImage.setTranslatesAutoresizingMaskIntoConstraints(false)
let imageDimension:CGSize = CGSize(width: 48, height: 48)
cell.sizeThatFits(imageDimension)
var usernameString = currentUser.objectForKey("name") as NSString!
if profileImages.objectForKey(usernameString) {
cell.userImage.image = profileImages.objectForKey(usernameString) as UIImage!
}
else {
// Creates Concurrent Queue for Image Fetching
var concurrentQueue:dispatch_queue_t = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
// Asynchronously get URL String and convert to NSURL
dispatch_async(concurrentQueue, {
var imageURLString:NSString = currentUser.objectForKey("profile_image_url") as NSString!
var imageURL = NSURL(string: imageURLString)
// Synchronously download image data and save to profileImages array (1 by 1)
dispatch_sync(concurrentQueue, {
var imageData:NSData = NSData(contentsOfURL: imageURL)
self.profileImages.setObject((UIImage(data:imageData)), forKey: usernameString)
})
// In Main Queue, set the profileImage for each cell from newly populated array
dispatch_sync(dispatch_get_main_queue(), {
cell.userImage.image = self.profileImages.objectForKey(usernameString) as UIImage!
})
})
}
return cell
}
应用程序总是在此函数中崩溃(我不知道在dequeueReusableCell
行,Swift如何处理nil对象,是否一切都得到了适当处理。
override func tableView(tableView: UITableView!, heightForRowAtIndexPath indexPath: NSIndexPath!) -> CGFloat {
var currentTweet:NSDictionary = tweetsArray.objectAtIndex(indexPath.row) as NSDictionary
var currentUser:NSDictionary = currentTweet.objectForKey("user") as NSDictionary
var usernameString = currentUser.objectForKey("name") as NSString!
var tweetTextString = currentTweet.objectForKey("text") as NSString!
var prototypeCell = tableView!.dequeueReusableCellWithIdentifier(identifier) as? CustomTimelineCell
if let customCell = prototypeCell {
customCell.username.text = usernameString
customCell.tweetText.text = tweetTextString
customCell.userImage.image = UIImage(named: "bird_twitter.png")
var size:CGSize = customCell.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
return size.height+1
}
else {
var customCell:CustomTimelineCell = CustomTimelineCell(style: UITableViewCellStyle.Default, reuseIdentifier: "CustomTimelineCell")
customCell.username.text = usernameString
customCell.tweetText.text = tweetTextString
customCell.userImage.image = UIImage(named: "bird_twitter.png")
var size:CGSize = customCell.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
return size.height+1
}
}
我通过StackOverflow上下搜索与其相关的每个错误以及尝试修复它时弹出的所有内容,但没有任何效果。我不知道是不是因为Swift处理事情的方式,但我相信问题在于返回视图时是否将单元格出列,或者在我离开之前某些连接没有关闭/回。有什么想法吗?
编辑:一些可能相关的新信息:在最初加载后滚动浏览tableView时,每个单元格都会调用-heightForRowAtIndexPath两次,我无法理解原因。此外,当从另一个视图返回到tableView时,当它重新加载时,它会为前几个单元格调用-heightforRowAtIndexPath两次,但对其余单元格只调用一次(0,1,0,1,2,3 ...)。这与exc_bad_access崩溃有关吗?