I'm trying to get some photos (PHAsset's) from a user's Photos library, and convert them to UIImage's.
Here's the code for fetching the assets from the library:
func fetchPhotos() {
let fetchOptions = PHFetchOptions()
fetchOptions.predicate = NSPredicate(format: "(mediaSubtype & %d) != 0", PHAssetMediaSubtype.photoScreenshot.rawValue)
//Fetching Screen Shots
fetchedResult = PHAsset.fetchAssets(with: .image, options: fetchOptions)
let f: FetchResult = FetchResult(fetchedResult!)
var fetchCount = 0
for i in f {
fetchCount += 1
print("Fetch count \(fetchCount)")
let img = i.getAssetThumbnail()
testImages.append(img)
}
}
Below is the code for getting a UIImage out of a PHAsset:
extension PHAsset {
func getAssetThumbnail() -> UIImage {
let manager = PHImageManager.default()
let option = PHImageRequestOptions()
var thumbnail = UIImage()
option.isSynchronous = true
manager.requestImage(for: self,
targetSize: CGSize(width: self.pixelWidth, height: self.pixelHeight),
contentMode: .aspectFit,
options: option,
resultHandler: {(result, info) -> Void in
thumbnail = result!
})
return thumbnail
}
}
I'm currently getting this crash output when trying to run the code:
Details
The app “AppClassificationDemo” on Nick’s iPhone quit unexpectedly.
Domain: IDEDebugSessionErrorDomain
Code: 11
Failure Reason: Message from debugger: Terminated due to memory issue
User Info: {
DVTErrorCreationDateKey = "2022-11-14 22:19:19 +0000";
IDERunOperationFailingWorker = DBGLLDBLauncher;
}
--
Analytics Event: com.apple.dt.IDERunOperationWorkerFinished : {
"device_model" = "iPhone14,2";
"device_osBuild" = "16.1.1 (20B101)";
"device_platform" = "com.apple.platform.iphoneos";
"launchSession_schemeCommand" = Run;
"launchSession_state" = 2;
"launchSession_targetArch" = arm64;
"operation_duration_ms" = 6369;
"operation_errorCode" = 11;
"operation_errorDomain" = IDEDebugSessionErrorDomain;
"operation_errorWorker" = DBGLLDBLauncher;
"operation_name" = IDEiPhoneRunOperationWorkerGroup;
"param_consoleMode" = 0;
"param_debugger_attachToExtensions" = 0;
"param_debugger_attachToXPC" = 1;
"param_debugger_type" = 5;
"param_destination_isProxy" = 0;
"param_destination_platform" = "com.apple.platform.iphoneos";
"param_diag_MainThreadChecker_stopOnIssue" = 0;
"param_diag_MallocStackLogging_enableDuringAttach" = 0;
"param_diag_MallocStackLogging_enableForXPC" = 1;
"param_diag_allowLocationSimulation" = 1;
"param_diag_checker_tpc_enable" = 1;
"param_diag_gpu_frameCapture_enable" = 0;
"param_diag_gpu_shaderValidation_enable" = 0;
"param_diag_gpu_validation_enable" = 0;
"param_diag_memoryGraphOnResourceException" = 0;
"param_diag_queueDebugging_enable" = 1;
"param_diag_runtimeProfile_generate" = 0;
"param_diag_sanitizer_asan_enable" = 0;
"param_diag_sanitizer_tsan_enable" = 0;
"param_diag_sanitizer_tsan_stopOnIssue" = 0;
"param_diag_sanitizer_ubsan_stopOnIssue" = 0;
"param_diag_showNonLocalizedStrings" = 0;
"param_diag_viewDebugging_enabled" = 1;
"param_diag_viewDebugging_insertDylibOnLaunch" = 1;
"param_install_style" = 0;
"param_launcher_UID" = 2;
"param_launcher_allowDeviceSensorReplayData" = 0;
"param_launcher_kind" = 0;
"param_launcher_style" = 0;
"param_launcher_substyle" = 0;
"param_runnable_appExtensionHostRunMode" = 0;
"param_runnable_productType" = "com.apple.product-type.application";
"param_runnable_type" = 2;
"param_testing_launchedForTesting" = 0;
"param_testing_suppressSimulatorApp" = 0;
"param_testing_usingCLI" = 0;
"sdk_canonicalName" = "iphoneos16.1";
"sdk_osVersion" = "16.1";
"sdk_variant" = iphoneos;
}
--
System Information
macOS Version 13.0.1 (Build 22A400)
Xcode 14.1 (21534.1) (Build 14B47b)
Timestamp: 2022-11-14T14:19:19-08:00
I'm fairly certain it's do the size of the image thumbnail being generated; when I set width and height to both be 100, the processing works as expected.
When changing it self.pixelWidth and self.pixelHeight, the app crashes.
Don't try to convert the
PHAssettoUIImageand store in array. BecauseUIImagewill use the full memory size of the image. So too many images in an array will cause a memory leak.Hence just fetch the required
PHAsseton demand and request for theUIImagewhen needed. Please see an example below.Also I will suggest you to use the asynchronous image request to avoid the UI performance issues.
Hope this helps!