TableView があり、データベースから取得したデータを入力しています。画像以外はすべて正常に動作します。セルの再利用動作のため、 で画像を取得していcellForRowAtIndexPath
ます。cellForRowAtIndexPath
詳細取得機能 ( でトリガーされる) で別の要求を行う必要があるため、画像をフェッチすることにしましたviewDidLoad
。これにより、他の問題が発生しています (画像 URL を保存する前にテーブルビューをリロードする)。
問題は、高速スクロールすると、ユーザー画像の表示中に再利用可能なセルがバグるということです
override func viewDidLoad() {
super.viewDidLoad()
fetchData()
}
var theUser =
func fetchData() {
//.. after data is retrieved
var innerDict = [String:String]()
if let user = details.value![key] {
if let name = user["name"] {
// works
innerDict["name"] = name
}
if let image = user["imageName"] {
// gets the image name but at this point I need to;
// a) retrieve the url here (with another call), which will eventually fail
// to catch up with `innerDict` so `innerDict` won't contain `image` variable.
// ie;
myRef.downloadURLWithCompletion { (URL, error) -> Void in }
// b) Store the `image` name in innerDict and download image from url
// in `cellForRowAtIndexPath`. I chose this method:
innerDict["image"] = image
}
user[id] = innerDict
tableView.reloadData()
}
これで、通常どおり tableView が表示されます。
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = ...
// more stuff
if let imageName = user["image"] {
let storage = FIRStorage.storage()
let storageRef = storage.referenceForURL("gs://bucket.com").child(user[id]).child(imageName)
storageRef.downloadURLWithCompletion { (URL, error) -> Void in
if (error != nil) {
// handle
} else {
// I thought using Haneke would help to cache the image
cell.image.hnk_setImage(URL!)
}
}
}
これは私が到達できる最も近いものです。ただし、高速スクロールすると画像が表示されなくなります。
編集:
私もこの方法を試してみましたが、この方法では同じ画像を複数回ダウンロードしているため、同じ画像が表示されるまでに時間がかかります。
islandRef.dataWithMaxSize(1 * 1024 * 1024) { (data, error) -> Void in
if (error != nil) {
// Uh-oh, an error occurred!
} else {
let image: UIImage! = UIImage(data: data!)
cell.userImage.hnk_setImage(image, key: "\(userID)")
}
}
しかし、トップアプローチではスピードが非常に速かった。上記のコードの唯一の問題は、高速スクロール時の不具合でした。
編集 2
var images = [UIImage]()
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("ItemCell", forIndexPath: indexPath) as! ItemDetailTableViewCell
let item = items[indexPath.section][indexPath.row]
if let uid = item["owner"] as? String {
if let user = users[uid] {
if let imageName = user["image"] {
if let img: UIImage = images[indexPath.row] { // crash here "fatal error: Index out of range"
cell.userImage.image = img
}
} else {
let storage = FIRStorage.storage()
let storageRef = storage.referenceForURL("gs://bucket").child(uid).child(imageName)
storageRef.downloadURLWithCompletion { (URL, error) -> Void in
if (error != nil) {
} else {
dispatch_async(dispatch_get_main_queue(), {
cell.userImage.hnk_setImageFromURL(URL!)
self.images[indexPath.row] = cell.image.image!
})
}
}
}
}
}