0

I am trying to fetch images from album and this code fetch all images from specific album, but on scrolling app will close and give error "Message from debugger: Terminated due to memory issue". Please check the code and find the error.(I want to fetch all albums and images like "Lalalab" app without memory warning).

 func fatchImagesfromAlbum() {
        DispatchQueue.global(qos: .background).async {
        self.photoAssets = self.fetchResult as! PHFetchResult<AnyObject>

        let fetchOptions = PHFetchOptions()
        fetchOptions.predicate = NSPredicate(format: "mediaType = %d", PHAssetMediaType.image.rawValue)


        self.photoAssets = PHAsset.fetchAssets(in: self.assetCollection, options: fetchOptions) as! PHFetchResult<AnyObject>

        for i in 0..<self.photoAssets.count{
                let asset = self.photoAssets.object(at: i)
                let imageSize = CGSize(width: asset.pixelWidth,
                                       height: asset.pixelHeight)

                let options = PHImageRequestOptions()
                options.deliveryMode = .fastFormat
                options.isSynchronous = true

                self.imageManager.requestImage(for: asset as! PHAsset, targetSize: imageSize, contentMode: .aspectFill, options: options, resultHandler: { (image, info) -> Void in


                    self.images.append(image!)
                    let url:NSURL = info!["PHImageFileURLKey"] as! NSURL
                    let urlString: String = url.path!
                    let theFileName = (urlString as NSString).lastPathComponent
                    print("file name\(info!)")
                    self.imageName.append("\(theFileName)")
                    self.imagePath.append("\(urlString)")

                })

                print(self.imagePath)
                print(self.imageName)
                DispatchQueue.main.async
                    {
                        [unowned self] in

                        self.collectionView.reloadData()
                }


        }
    }
    PHPhotoLibrary.shared().register(self)

    if fetchResult == nil {
        let allPhotosOptions = PHFetchOptions()
        allPhotosOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: true)]
        fetchResult = PHAsset.fetchAssets(with: allPhotosOptions)
    }


    }
Pankaj Jangid
  • 812
  • 9
  • 18
  • "Please check the code and find the error." The problem is your approach. Saveing all UIImage objects in an array is not a good approach at all. – El Tomato Sep 24 '18 at 06:39
  • I also tried to load image with local path, but it showing "Path does not exist". – Pankaj Jangid Sep 24 '18 at 06:44

2 Answers2

1

Faced such an issue; It has nothing to do with making weak or unowned references. When objects have been created by either your Objective-C code or using Cocoa classes, what you should do is to deal with autoreleasepool, try to call your method inside autoreleasepool:

autoreleasepool {
    fatchImagesfromAlbum()
}

Should it be fetchImagesfromAlbum instead of fatchImagesfromAlbum?

Citing from Advanced Memory Management Programming Guide:

Autorelease pool blocks provide a mechanism whereby you can relinquish ownership of an object, but avoid the possibility of it being deallocated immediately (such as when you return an object from a method). Typically, you don’t need to create your own autorelease pool blocks, but there are some situations in which either you must or it is beneficial to do so.

However, it should not be required to execute the whole method in the autoreleasepool, probably the reason of the memory issue is caused by executing fetchAssets or requestImage iteratively (inside the for loop).


Refers to: Is it necessary to use autoreleasepool in a Swift program?

Ahmad F
  • 30,560
  • 17
  • 97
  • 143
  • When I add all images into Document Directory, in that given code, It will again show that error. How can be resolved that error? – Pankaj Jangid Sep 24 '18 at 16:33
0

You need to create a diapatch group then whenever you run loop enter group and leave. After loop has finished iteration you can call diapatch.notify and relaod your UI

Ashish
  • 204
  • 1
  • 8