连续发出多个异步HTTP请求并使用Realm编写

安迪

我目前正在使用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本身发出此网络请求的。

马里乌斯

这些请求通常会按照您的意愿异步发生。但是同步发生了,您可能不知道:

  1. Alamofire的响应关闭将分派到主线程。因此,您的网络响应会与您执行的任何UI更新竞争。
  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)
            }
        }
    }

}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章