Сохранение изображений на iOS в Delphi: работа с UIImageWriteToSavedPhotosAlbum и обработка ошибок
Введение
Работа с фотогалереей на iOS в Delphi требует особого подхода из-за ограничений системы безопасности Apple. В этой статье мы рассмотрим, как сохранять изображения с использованием функции UIImageWriteToSavedPhotosAlbum, правильно обрабатывать ошибки и реализовывать callback-механизм в Delphi.
Основной способ сохранения изображений
Самый простой способ сохранить изображение в фотогалерее iOS из Delphi-приложения выглядит так:
Этот код запросит у пользователя разрешение на доступ к фотогалерее (если оно еще не было предоставлено) и сохранит изображение. Однако у этого подхода есть недостаток — мы не получаем информацию об успешности операции.
Реализация обработчика завершения
Для получения информации о результате сохранения нам нужно реализовать callback-механизм. Вот полное решение:
uses
Macapi.ObjectiveC, iOSapi.Foundation, iOSapi.UIKit, System.TypInfo;
type
ICompletionTarget = interface(NSObject)
['{GUID-GOES-HERE}'] // Сгенерируйте уникальный GUID
[MethodName('image:didFinishSavingWithError:contextInfo:')]
procedure saveImageCompletionHandler(image: UIImage; error: NSError; contextInfo: Pointer); cdecl;
end;
TCompletionTarget = class(TOCLocal)
private
FOnComplete: TProc<Boolean, string>;
function GetNativeObject: NSObject;
protected
function GetObjectiveCClass: PTypeInfo; override;
public
constructor Create(AOnComplete: TProc<Boolean, string>);
[MethodName('image:didFinishSavingWithError:contextInfo:')]
procedure saveImageCompletionHandler(image: UIImage; error: NSError; contextInfo: Pointer); cdecl;
property NativeObject: NSObject read GetNativeObject;
end;
constructor TCompletionTarget.Create(AOnComplete: TProc<Boolean, string>);
begin
inherited Create;
FOnComplete := AOnComplete;
end;
procedure TCompletionTarget.saveImageCompletionHandler(image: UIImage; error: NSError; contextInfo: Pointer);
begin
if Assigned(FOnComplete) then
begin
if error = nil then
FOnComplete(True, 'Image saved successfully')
else
FOnComplete(False, string(error.localizedDescription.UTF8String));
end;
end;
function TCompletionTarget.GetNativeObject: NSObject;
begin
Result := Super;
end;
function TCompletionTarget.GetObjectiveCClass: PTypeInfo;
begin
Result := TypeInfo(ICompletionTarget);
end;
Использование обработчика
Теперь мы можем сохранять изображения с обработкой результата:
procedure TForm1.SaveImageWithHandler(Image: TUIImage);
var
CompletionTarget: TCompletionTarget;
begin
CompletionTarget := TCompletionTarget.Create(
procedure(Success: Boolean; Msg: string)
begin
TThread.Synchronize(nil,
procedure
begin
if Success then
ShowMessage('Success: ' + Msg)
else
ShowMessage('Error: ' + Msg);
end);
end);
try
UIImageWriteToSavedPhotosAlbum(
NSObjectToID(Image),
NSObjectToID(CompletionTarget.NativeObject),
sel_getUid('image:didFinishSavingWithError:contextInfo:'),
nil);
finally
// Не освобождаем CompletionTarget - он должен жить до вызова обработчика
// В реальном приложении нужно предусмотреть механизм освобождения
end;
end;
Решение проблемы с кодированием сигнатуры метода
Как отметил alejandro.sawers, в Delphi 12.2 существует проблема с кодированием сигнатуры метода для Objective-C. Решение — модификация файла Macapi.ObjectiveC.pas:
// В методе class function TRegisteredDelphiClass.RegisterClass
if MethodName = 'image:didFinishSavingWithError:contextInfo:' then
MangledName := 'v@:@@^v'; // Исправленная сигнатура
Альтернативное решение с PHPhotoLibrary
Более современный подход — использование фреймворка PHPhotoLibrary, который предоставляет больше контроля над разрешениями:
uses iOSapi.Photos;
procedure TForm1.SaveWithPhotoLibrary(Image: TUIImage);
begin
TPHPhotoLibrary.OCClass.requestAuthorization(
procedure(status: PHAuthorizationStatus)
begin
if status = PHAuthorizationStatusAuthorized then
begin
PHPhotoLibrary.sharedPhotoLibrary.performChanges(
procedure
var
Request: PHAssetChangeRequest;
begin
Request := TPHAssetChangeRequest.OCClass.creationRequestForAssetFromImage(Image);
end,
nil);
end
else
begin
TThread.Synchronize(nil,
procedure
begin
ShowMessage('Permission denied');
end);
end;
end);
end;
Заключение
Мы рассмотрели два способа сохранения изображений в фотогалерее iOS из Delphi-приложения:
Простой способ с UIImageWriteToSavedPhotosAlbum и обработкой ошибок через callback
Более современный способ с использованием PHPhotoLibrary
Первый подход проще в реализации, но второй предоставляет больше контроля над процессом и разрешениями. Выбор между ними зависит от требований вашего приложения.
Важно помнить, что все операции с фотогалереей должны выполняться с учетом ограничений iOS и с уважением к конфиденциальности пользователей. Всегда запрашивайте разрешение перед доступом к фотографиям и корректно обрабатывайте случаи отказа.
Статья описывает методы сохранения изображений в фотогалерее iOS из Delphi-приложений с использованием `UIImageWriteToSavedPhotosAlbum` и `PHPhotoLibrary`, включая обработку ошибок и реализацию callback-механизмов.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.