Jus*_*ier 2 user-experience ios swift apple-watch watchkit
在我的Apple Watch应用程序中,我有一个大约25行的表,每一行都有一些文本和一个需要从互联网上加载的图像.类似于Instagram风格的Feed,但这些是每张约8k的个人资料图片.
当我基于传入的JSON数据构建表时,我正在利用WatchKit的内置图像缓存正确地做所有事情,以减少不必要的网络流量.
该应用程序"工作",图像显示正确.但问题是视图需要10-20秒才能为用户进行交互做好准备.在那些10-20秒之前,滚动缓慢,并且在所有图像都已加载之前按钮不会执行任何操作.
我想要的是在用户向下滚动时延迟加载图像的一些方法.
我已经尝试过实现一个分页解决方案,但它也有缺点,并没有完全解决我原来的问题.
如果我只填充文本位(无图像),表格会立即显示并准备好进行交互.
***更新:Mike Swanson的回答非常彻底,确实解决了我的大部分问题.缓慢和阻碍已经消失.
我想发布最终代码给任何其他人,并有类似的问题.具体来说,我想展示我是如何实现后台调度的.
我现在还在主线程中暂时将图像设置为占位符以显示活动.一旦实际图像加载并传输到手表,它就会被替换.如果上传了新图像,我还改进了图像缓存键.
新代码:
let qualityOfServiceClass = QOS_CLASS_BACKGROUND
let backgroundQueue = dispatch_get_global_queue(qualityOfServiceClass, 0)
i = 0
for p in self.profiles {
if let profileId = p["id"] as? NSNumber {
var profileIdStr = "\(profileId)"
let row = self.profilesTable.rowControllerAtIndex(i) as! WatchProfileRow
if let hasImage = p["has_image"] as? NSNumber {
let profileImageCacheKey = "\(profileIdStr)-\(hasImage)"
// if the image is already in cache, show it
if self.device.cachedImages[profileImageCacheKey] != nil {
row.profileImageThumbnail.setImageNamed(profileImageCacheKey)
// otherwise, get the image from the cdn and cache it
} else {
if let imageHost = self.imageHost as String! {
var imageURL = NSURL(string: NSString(format: "%@%@-thumbnail?version=%@", imageHost, profileId, hasImage) as String)
var imageRequest = NSURLRequest(URL: imageURL!)
NSURLConnection.sendAsynchronousRequest(imageRequest, queue: NSOperationQueue.mainQueue()) {
(response, data, error) -> Void in
if error == nil {
row.profileImageThumbnail.setImageNamed("profile-placeholder")
dispatch_async(backgroundQueue, {
self.device.addCachedImageWithData(data, name: profileImageCacheKey)
dispatch_async(dispatch_get_main_queue(), { () -> Void in
row.profileImageThumbnail.setImageNamed(profileImageCacheKey)
})
})
}
}
} else {
row.profileImageThumbnail.setImageNamed("profile-placeholder")
}
}
} else {
row.profileImageThumbnail.setImageNamed("profile-placeholder")
}
}
i++
}
Run Code Online (Sandbox Code Playgroud)
原始代码:
i = 0
for p in self.profiles {
if let profileId = p["id"] as? NSNumber {
var profileIdStr = "\(profileId)"
let row = self.profilesTable.rowControllerAtIndex(i) as! WatchProfileRow
if let hasImage = p["has_image"] as? NSNumber {
// if the image is already in cache, show it
if self.device.cachedImages[profileIdStr] != nil {
row.profileImageThumbnail.setImageNamed(profileIdStr)
// otherwise, get the image from the cdn and cache it
} else {
if let imageHost = self.imageHost as String! {
var imageURL = NSURL(string: NSString(format: "%@%@-thumbnail?version=%@", imageHost, profileId, hasImage) as String)
var imageRequest = NSURLRequest(URL: imageURL!)
NSURLConnection.sendAsynchronousRequest(imageRequest, queue: NSOperationQueue.mainQueue()) {
(response, data, error) -> Void in
if error == nil {
var image = UIImage(data: data)
row.profileImageThumbnail.setImage(image)
self.device.addCachedImage(image!, name: profileIdStr)
}
}
} else {
row.profileImageThumbnail.setImageNamed("profile-placeholder")
}
}
} else {
row.profileImageThumbnail.setImageNamed("profile-placeholder")
}
}
i++
}
Run Code Online (Sandbox Code Playgroud)
首先,WatchKit中没有方法来确定a中的当前位置WKInterfaceTable.这意味着您使用的任何逻辑都必须解决这个问题.
其次,看起来您正在发送异步网络请求,然后setImage在拥有数据时使用.setImage在将图像传输到设备之前将图像编码为PNG,并且在现有代码中,这发生在主线程上.如果您不需要PNG图像,我会考虑使用setImageData发送JPEG编码的数据来进一步减少需要传输到Watch的字节数.
最后,您似乎正在双重传输图像.一次setImage和两次addCachedImage.收到你的图像后,我建议你调度一个后台线程,然后使用WKInterfaceDevice's addCachedImageWithData(可以安全地在后台线程上使用)来发送数据.然后,在使用之前设置now-cached图像之前,将调度回主线程setImageNamed.
| 归档时间: |
|
| 查看次数: |
1160 次 |
| 最近记录: |