我在TableView Cell中有一个UICollectionView。 CollectionView单元格本身包含UIImageView和Label。 CollectionView单元格应显示其下方名字的用户图片。此数据模型在ViewDidLoad中构建,并输出正确的数据。但是,我的UICollectionViews在不稳定的位置产生用户图片和用户名(即,用户图片和名称显示在该不同TableView行的相应UICollectionViews内的不同TableView行上)。如果需要,我可以尝试更详细地说明这一点。
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("userCell", forIndexPath: indexPath) as! wigoCollectionViewCell
var sumSections = 0
for i in 0 ..< indexPath.section {
let rowsInSection = eventFeed.numberOfRowsInSection(i)
sumSections = sumSections + rowsInSection
}
let currentRow = sumSections + indexPath.row
// Flip the collectionView
var scalingTransform : CGAffineTransform!
scalingTransform = CGAffineTransformMakeScale(-1, 1);
cell.transform = scalingTransform
// Make user profile picture circular and dispose of remaining image resources not visible
cell.userPicture.layer.cornerRadius = cell.userPicture.frame.size.width/2
cell.userPicture.clipsToBounds = true
for (key, value) in (sortedArray[currentRow]["usersJoining"]!! as? NSDictionary)! {
if key as? String != FIRAuth.auth()?.currentUser?.uid {
var name = String()
var photoUrl = NSURL()
name = value["userName"] as! String
let nameSplit = name.characters.split(" ").map(String.init)
// Edit label
cell.userNameLabel.text = nameSplit[0]
// Make UIImage = user picture
photoUrl = NSURL(string: value["userPhotoUrl"] as! String)!
let data = NSData(contentsOfURL: photoUrl)
cell.userPicture.image = UIImage(data: data!)
}
}
return cell
}
在打印任何特定变量时,输出正是我想要的。所以这完全是在单元格中显示正确信息的问题。
据我所知,我正确使用prepareForReuse
。
override func prepareForReuse() {
userPicture.image = nil
userNameLabel.text = ""
super.prepareForReuse()
}
我能想到的唯一解决方案围绕使用dispatch_async
方法在后台线程中添加图像。但是,我似乎无法解决我的问题。
我希望有人可以帮助指导我解决问题的正确方法,因为我还没有通过StackOverflow或其他互联网找到解决我特定问题的解决方案(或解释)它非常适合Swift 2.0 +)。
提前致谢。
答案 0 :(得分:0)
也许以下一些评论会对您有所帮助:
您使用UIImage
初始化NSData
,而不是名称,因此您必须使用适当的构造函数:
cell.userPicture.image = UIImage(data: data!)
一个好的做法是下载用户的图片异步(以防止在网络连接不良时用户界面冻结):
// Somewhere in your code
func getImageFromUrl(url:NSURL, completion: ((data: NSData?, response: NSURLResponse?, error: NSError? ) -> Void)) {
NSURLSession.sharedSession().dataTaskWithURL(url) { (data, response, error) in
completion(data: data, response: response, error: error)
}.resume()
}
在tableView...cellForItemAtIndexPath
功能中:
// Make UIImage = user picture
var photoUrl = value["userPhotoUrl"] as! String
// Start working in background
let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
dispatch_async(dispatch_get_global_queue(priority, 0)) { () -> Void in
// Call the function with callback
getImageFromUrl(NSURL(string: photoUrl)!) { (data, response, error) in
guard let data = data where error == nil else { return }
// Set the image in place in the main thread
dispatch_async(dispatch_get_main_queue()) {
cell.userPicture.image = UIImage(data: data!)
}
}
}
如果单元格在滚动时开始显示不正确的数据:
我假设您在UITableViewController
设置内部UICollectionView
。因此,在设置每个内部集合的数据之后,尝试在主队列中调用reloadData()
,如下所示:
dispatch_async(dispatch_get_main_queue()) {
myCollectionView.reloadData()
}
答案 1 :(得分:0)
我对这个问题没有答案,但我注意到我在混合的Swift / ObjC代码库中看到的一些我要评论的内容。
Swift和Objective-C之间的主要区别之一是使用nil
的类型系统和行为。在Objective-C中,使用nil或多或少是安全的(它可能导致意外行为但不会崩溃。当nil
被强制转换为非可选类型时,Swift代码会崩溃。当消息发生时也会发生崩溃被发送到nil
对象。
换句话说,nil
在Swift中非常危险,因此应该避免强制解包运算符!
和强制转换as!
。
在您的代码中,可以在许多地方看到这些危险操作,因此当输入意外或例如,代码可能会崩溃。无法找到图像的数据。
如果您的代码是沿着以下几行,它会更安全,也更清晰,因为它包括更少的强制演员阵容和展开。代码未经过测试,我可能对您的数据类型做了一些错误的假设。
guard let a = sortedArray as? [NSDictionary],
let d = a[currentRow]["usersJoining"] as? NSDictionary,
let currentUID = FIRAuth.auth()?.currentUser?.uid
else { return nil }
for (key, value) in d {
guard let k = key as? String where k != currentUID,
let name = value["userName"] as? String
else { continue }
guard let urlString = value["userPhotoUrl"] as? String,
let photoUrl = NSURL(string: urlString),
let data = NSData(contentsOfURL: photoUrl)
else { continue }
let nameSplit = name.characters.split(" ").map(String.init)
let firstName = nameSplit[0]
cell.userNameLabel.text = firstName
cell.userPicture.image = UIImage(named: data)
}
理想情况下,解析数据以键入安全的Swift数据类型应该在除collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath)
之外的其他地方完成
答案 2 :(得分:0)
我最终找到了解决问题的方法。所以对于任何好奇或有类似问题的人来说:
问题在于遍历 cellForItemAtIndexPath
方法中的NSDictionary 。当以编程方式创建时,NSDictionaries本质上是无序的,并且通过遍历字典来获取我需要的数据导致出现,好像CollectionView
中的单元格中的图像存在负载问题。
解决方案只是将NSDictionary
变为Array
并使用indexPath.item
作为索引从数组中检索我需要的值。
这是一个非常简单的解决方案,根本不会发生在我身上。因此,如果您像我一样正在寻找类似问题的解决方案,请确保您的逻辑是可靠的!