IOS下一个异步加载图像的类

IPhone上手机性能不佳,批量加载网络图像时很慢,所以写了一个异步加载图像的类.
有待进一步实现的功能是图像的硬盘cache.

unit FMX.AsyncImage.IOS;

interface
uses FMX.Types,FMX.Graphics,System.Types, System.Generics.Collections, iOSapi.Foundation, Macapi.ObjectiveC, iOSapi.UIKit;

type
NSURLConnectionDelegate = interface(IObjectiveC)
['{682BABAC-89E0-4A9B-BFF5-96A7EE7881A6}']
end;

NSURLConnectionDataDelegate = interface(NSURLConnectionDelegate)
['{6F015871-FCF4-4F8D-B9E5-C6484D6F60E7}']
procedure connection(connection: NSURLConnection; didReceiveData: NSData); cdecl;
procedure connectionDidFinishLoading(connection: NSURLConnection); cdecl;
end;

TAsyncImageReqeust = class(TOCLocal, NSURLConnectionDataDelegate)
private
FBitmap:TBitmap;
FConnection:NSURLConnection;
FData:NSMutableData;
protected
public
constructor Create(ABitmap:TBitmap;AUrl:string);
destructor Destroy;override;
procedure Cancel;
procedure connection(connection: NSURLConnection; didReceiveData: NSData); cdecl;
procedure connectionDidFinishLoading(connection: NSURLConnection); cdecl;
end;

TAsyncImageLoader=class
private
FRequestMap:TDictionary;
public
constructor Create;
destructor Destroy;override;
procedure Request(AUrl:string;ABitmap:TBitmap);
procedure Cancel(ABitmap:TBitmap);
procedure CancelAll;
end;

implementation
uses System.Math, FMX.Types3D, iOSapi.CoreGraphics, System.IOUtils, System.SysUtils, System.Classes;

{ TAsyncImageLoader }

procedure TAsyncImageLoader.Cancel(ABitmap: TBitmap);
var
request: TAsyncImageReqeust;
begin
if not FRequestMap.ContainsKey(ABitmap) then
Exit;
request:=FRequestMap[ABitmap];
request.Cancel;
end;

procedure TAsyncImageLoader.CancelAll;
var
request:TAsyncImageReqeust;
begin
for request in FRequestMap.Values do
begin
Request.cancel;
end;
end;

constructor TAsyncImageLoader.Create;
begin
FRequestMap:=TDictionary.Create;
end;

destructor TAsyncImageLoader.Destroy;
begin
CancelAll;
FRequestMap.Free;
inherited;
end;

procedure TAsyncImageLoader.Request(AUrl: string; ABitmap: TBitmap);
begin
if FRequestMap.ContainsKey(ABitmap) then
Exit;
FRequestMap.Add(ABitmap, TAsyncImageReqeust.Create(ABitmap, AUrl));
end;

{ TAsyncImageReqeust }

procedure TAsyncImageReqeust.Cancel;
begin
FConnection.cancel;
end;

procedure TAsyncImageReqeust.connection(connection: NSURLConnection;
didReceiveData: NSData);
begin
FData.appendData(didReceiveData);
end;

procedure TAsyncImageReqeust.connectionDidFinishLoading(
connection: NSURLConnection);
var
stream:TMemoryStream;
begin
stream:=TMemoryStream.Create;
try
stream.Write(FData.bytes^, Fdata.length);
stream.position:=0;
FBitmap.LoadFromStream(stream);
finally
stream.free;
end;
end;

constructor TAsyncImageReqeust.Create(ABitmap: TBitmap; AUrl: string);
var
url:NSURL;
request:NSURLRequest;
begin
inherited Create;
FBitmap:=ABitmap;
url:=TNSURL.Wrap(TNSURL.OCClass.URLWithString(NSSTR(Aurl)));
request:=TNSURLRequest.Wrap(TNSURLRequest.OCClass.requestWithURL(url, NSURLRequestUseProtocolCachePolicy, 60));
FConnection:=TNSURLConnection.Create;
FConnection.initWithRequest(request, Self.GetObjectID);
FData:=TNSMutableData.Create;
end;

destructor TAsyncImageReqeust.Destroy;
begin

FConnection.cancel;
FConnection.release;
FData.release;

inherited;
end;

end.