Получение изображений без исчерпания памяти

Я пытаюсь получить изображения из фотопленки пользователя, но столкнулся с проблемой нехватки памяти. Я загружаю 50 изображений за раз, но, к сожалению, после нескольких загрузок заканчивается память и происходит сбой. Я попытался обернуть весь оператор в autoreleasepool, но это оказалось неэффективным. вот мой код...

func retrieveImages(thumbnail: Bool, indexOfLibrary: Int) {
    /* Retrieve the items in order of modification date, ascending */
    var indexSet: NSIndexSet!

    let options = PHFetchOptions()

    options.sortDescriptors = [NSSortDescriptor(key: "creationDate",
        ascending: false)]

    /* Then get an object of type PHFetchResult that will contain
    all our image assets */
    let assetResults = PHAsset.fetchAssetsWithMediaType(.Image,
        options: options)

    if totalPostsCounted == false {
        assetResults.enumerateObjectsUsingBlock { (object: AnyObject!, count: Int, stop: UnsafeMutablePointer<ObjCBool>) -> Void in
            if object is PHAsset {
                self.totalPosts = count
            } else {
                self.totalPostsCounted = true
            }
        }
    }

    if thumbnail == true {
        if totalPosts - libraryImageThumbnails.count < 50 {
            allImagesLoaded = true
        } else {
            if firstTimeLoadedThumb == true {

            } else {
                firstTimeLoadedThumb = true

            }
        }

    } else {
        if totalPosts - libraryImages.count < 50 {
            allImagesLoaded = true
        } else {
            if firstTimeLoaded == true {
            } else {
                firstTimeLoaded = true

            }
        }


    }


    if thumbnail == true {
        fiftyIncrementThumb = fiftyIncrementThumb + 50
        increment = fiftyIncrementThumb
    } else {
        fiftyIncrement = fiftyIncrement + 50
        increment = fiftyIncrement
    }

    let imageManager = PHCachingImageManager()
    autoreleasepool { () -> () in

        assetResults.enumerateObjectsUsingBlock { (object, count: Int, stop: UnsafeMutablePointer<ObjCBool>) -> Void in
            if object is PHAsset {

                var imageSize: CGSize!

                var array: NSArray!

                if thumbnail == true {
                    array = self.libraryImageThumbnails
                } else {
                    array = self.libraryImages
                }
                autoreleasepool {
                    if count >= array.count && count <= increment {
                        if thumbnail == true {
                            imageSize = CGSize(width: 100, height: 100)

                        } else {
                            imageSize = CGSize(width: self.cameraView.bounds.width, height: self.cameraView.bounds.height)

                        }

                        let asset = object as! PHAsset
                        let options = PHImageRequestOptions()
                        options.deliveryMode = .FastFormat
                        options.synchronous = true

                        imageManager.requestImageForAsset(asset,
                            targetSize: imageSize,
                            contentMode: .AspectFill,
                            options: options,
                            resultHandler: { (image, _: [NSObject : AnyObject]?) -> Void in
                                if thumbnail == true {
                                    self.libraryImageThumbnails.append(image!)
                                } else {
                                    self.libraryImages.append(image!)
                                }
                        })
                    }
                }
            }
        }


    }


}

Я также пробовал это, и он вернул ноль и разбился...

    let library = ALAssetsLibrary()
        library.enumerateGroupsWithTypes(ALAssetsGroupAll, usingBlock: { (group: ALAssetsGroup!, stop: UnsafeMutablePointer<ObjCBool>) -> Void in

            group.enumerateAssetsUsingBlock({ (asset, count: Int, stop: UnsafeMutablePointer<ObjCBool>) -> Void in
                if asset != nil {
                    self.libraryImageThumbnails.append(asset)
                    self.collectionTable.reloadData()

                }

            })
            }, failureBlock: { (error: NSError!) -> Void in

        })

Скажите, если вам нужна дополнительная информация! Спасибо!


person John Doe    schedule 26.01.2016    source источник
comment
Что вам нужно сделать, так это получить URL-адрес изображений, а затем загрузить изображения в фоновую очередь, используя dispatch_async из этого URL-адреса.   -  person Dhaivat Vyas    schedule 26.01.2016
comment
@DhaivatVyas Как мне получить изображения из фотопленки, используя URL-адрес файла?   -  person John Doe    schedule 26.01.2016


Ответы (3)


Вот что я сделал в проекте, который может помочь:

Некоторые свойства:

let requestOptions = PHImageRequestOptions()
let fetchOptions = PHFetchOptions()
let cachingImageManager = PHCachingImageManager()
var assets: [PHAsset] = [] {
    willSet {
        cachingImageManager.stopCachingImagesForAllAssets()
    }

    didSet {
        cachingImageManager.startCachingImagesForAssets(assets,
            targetSize: PHImageManagerMaximumSize,
            contentMode: .AspectFit,
            options: self.requestOptions
        )
    }
}


func fetchPhotos() {
    requestOptions.resizeMode = PHImageRequestOptionsResizeMode.Exact
    requestOptions.version = .Current
    requestOptions.deliveryMode = PHImageRequestOptionsDeliveryMode.HighQualityFormat
    requestOptions.synchronous = true

    fetchOptions.sortDescriptors = [NSSortDescriptor(key:"creationDate", ascending: false)]
    if #available(iOS 9.0, *) {
        fetchOptions.fetchLimit = 50
    } else {

        // Fallback on earlier versions
    }

    fetchResults = PHAsset.fetchAssetsWithMediaType(PHAssetMediaType.Image, options: fetchOptions)
    guard let fetchResults = fetchResults else {
        print("No PHAssets")
        return
    }
    dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)) { [weak self] in
        fetchResults.enumerateObjectsUsingBlock{ object, index, stop in
            let asset = object as! PHAsset
            self?.assets.append(asset)
        }
        dispatch_async(dispatch_get_main_queue()) {
            self?.photoCollectionView.reloadData()
        }
    }
}
person jasonnoahchoi    schedule 26.01.2016
comment
Потрясающий. Рад помочь! - person jasonnoahchoi; 26.01.2016

Попробуйте этот код и убедитесь, что вы импортируете <AssetsLibrary/AssetsLibrary.h> и делаете цель развертывания 7.1.

код Objective-C

NSMutableArray *imageArray=[[NSMutableArray alloc] init];
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];

[library enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:^(ALAssetsGroup *group, BOOL *stop)
{

    [group enumerateAssetsUsingBlock:^(ALAsset *asset, NSUInteger index, BOOL *stop)
     {
         if (asset) {
             [imageArray addObject:asset];
             NSLog(@"imageArray :: %@",imageArray);
         }
     }];
} failureBlock:^(NSError *error) {
    NSLog(@"error :: %@",error);
}];

Swift-код

var imageArray: [AnyObject] = [AnyObject]()
var library: ALAssetsLibrary = ALAssetsLibrary()

   library.enumerateGroupsWithTypes(ALAssetsGroupSavedPhotos, usingBlock: {(group: ALAssetsGroup, stop: Bool) -> Void in
    group.enumerateAssetsUsingBlock({(asset: ALAsset, index: Int, stop: Bool) -> Void in
        if asset != nil {
            imageArray.append(asset)
            NSLog("imageArray :: %@", imageArray)
        }
   })
}, failureBlock: {(error: NSError) -> Void in
NSLog("error :: %@", error!)
})

результат: введите здесь описание изображения

проверьте приведенный ниже URL для справки

https://stackoverflow.com/a/15570221/4101371

https://stackoverflow.com/a/25732673/4101371

https://stackoverflow.com/a/32472476/4101371

и вы также можете использовать фреймворк для фотографий, начиная с iOS 8. фреймворк для фотографий

Надеюсь, это поможет.

person Dhaivat Vyas    schedule 26.01.2016
comment
Я только что попробовал одно из предложений и отредактировал свой вопрос, чтобы показать, что произошло, когда я это сделал. - person John Doe; 26.01.2016
comment
Ммм по какой-то причине, когда я пытаюсь, это работает, но когда я пытаюсь установить изображение в ячейке ForRow, оно вылетает. - person John Doe; 26.01.2016

Установка приведенного ниже кода помогла мне ограничить выборку

let assetFetchOptions = PHFetchOptions()
assetFetchOptions.fetchLimit = 50

Тогда я получил только 50 фотографий, а не 15 000 на телефоне моих друзей!!

person nlapham21    schedule 27.10.2016