我目前正在使用Alamofire请求数据并使用Realm写入磁盘。具体来说,我从Facebook Graph GET请求中获取24个源URL,然后发出24个单独的请求来检索每个图像的数据。一旦检索到数据,我就用Realm写入磁盘。
以下是我如何获取24个来源:
FBAPI
Alamofire.request(.GET, FBPath.photos, parameters: params).responseJSON { response in
guard response.result.error == nil else {
print("error calling GET on \(FBPath.photos)")
print(response.result.error!)
completion(latestDate: nil, photosCount: 0, error: response.result.error)
return
}
if let value = response.result.value {
let json = JSON(value)
if let photos = json[FBResult.data].array {
for result in photos {
let manager = PTWPhotoManager()
manager.downloadAndSaveJsonData(result)
}
正如您所看到的,我有一个for循环遍历每个JSON,其中包含照片图像的源URL,然后我在其中为每个URL发出另一个网络请求,如下所示:
管理器
func downloadAndSaveJsonData(photoJSON : JSON) {
let source = photoJSON[FBResult.source].string
let id = photoJSON[FBResult.id].string
let created_time = photoJSON[FBResult.date.createdTime].string
let imageURL = NSURL(string: source!)
print("image requested")
Alamofire.request(.GET, imageURL!).response() {
(request, response, data, error) in
if (error != nil) {
print(error?.localizedDescription)
}
else {
print("image response")
let photo = PTWPhoto()
photo.id = id
photo.sourceURL = source
photo.imageData = data
photo.createdTime = photo.createdTimeAsDate(created_time!)
let realm = try! Realm()
try! realm.write {
realm.add(photo)
}
print("photo saved")
}
}
}
在请求每个图像数据和收到响应之间似乎存在很长的延迟,并且它似乎也不是异步的。这是一个线程问题还是有更有效的方式来请求这样的数据数组?还应该注意的是,我正在从Apple Watch本身提出此网络请求。
答案 0 :(得分:2)
这些请求大部分都是异步的,如您所愿。但是有一些同步发生,您可能不知道:
结合使用这两者意味着只要网络请求成功并继续进行,您就会阻止主线程,这也会导致您的应用无响应。
我建议尝试不同的尝试。您可以使用GCD的调度组来同步不同的异步任务。
在下面的示例中,对象全部保存在内存中,直到全部下载为止。
进一步的改进可能是将下载的数据写入磁盘而仅存储Realm对象中文件的路径。 (有很多图像缓存库,可以很容易地帮助你。)
如果您选择的路径仅取决于PWTPhoto
的字段(或数据的属性,您可以通过快速HEAD请求),那么您可以先检查此路径是否已在本地存在之前再次下载文件。通过这样做,您可以在更新照片时节省流量,或者在第一次尝试时未成功下载所有照片。 (例如,应用程序被用户强行关闭,崩溃,设备关闭)
class PTWPhotoManager {
static func downloadAllPhotos(params: [String : AnyObject], completion: (latestDate: NSDate?, photosCount: NSUInteger, error: NSError?)) {
Alamofire.request(.GET, FBPath.photos, parameters: params).responseJSON { response in
guard response.result.error == nil else {
print("error calling GET on \(FBPath.photos)")
print(response.result.error!)
completion(latestDate: nil, photosCount: 0, error: response.result.error)
return
}
if let value = response.result.value {
let json = JSON(value)
if let photos = json[FBResult.data].array {
let group = dispatch_group_create()
var persistablePhotos = [PTWPhoto](capacity: photos.count)
let manager = PTWPhotoManager()
for result in photos {
dispatch_group_enter(group)
let request = manager.downloadAndSaveJsonData(result) { photo, error in
if let photo = photo {
persistablePhotos.add(photo)
dispatch_group_leave(group)
} else {
completion(latestDate: nil, photosCount: 0, error: error!)
}
}
}
dispatch_group_notify(group, dispatch_get_main_queue()) {
let realm = try! Realm()
try! realm.write {
realm.add(persistablePhotos)
}
let latestDate = …
completion(latestDate: latestDate, photosCount: persistablePhotos.count, error: nil)
}
}
}
}
}
func downloadAndSaveJsonData(photoJSON: JSON, completion: (PTWPhoto?, NSError?) -> ()) -> Alamofire.Request {
let source = photoJSON[FBResult.source].string
let id = photoJSON[FBResult.id].string
let created_time = photoJSON[FBResult.date.createdTime].string
let imageURL = NSURL(string: source!)
print("image requested")
Alamofire.request(.GET, imageURL!).response() { (request, response, data, error) in
if let error = error {
print(error.localizedDescription)
completion(nil, error)
} else {
print("image response")
let photo = PTWPhoto()
photo.id = id
photo.sourceURL = source
photo.imageData = data
photo.createdTime = photo.createdTimeAsDate(created_time!)
completion(photo, nil)
}
}
}
}