Delphi 中开发 iOS 程序中,许多地方需要一个 NSSet 类型的参数,但是,怎么使用很伤脑筋。可怜的少的可怜的文档,都不如我的 QDAC 了(至少俺绝大部分代码有函数注释,这连个注释都没有)。为了搞明白怎么用,本人利用了源码搜索大法,搜索 Delphi 自带的 Source 目录下,看看它自身是如何使用的。整个源码中找到四处位置:
好了,接下来分析下,后面两个明显是声明,俺们就不关心了。前面两个才是实际使用的例子,可以看到以下几点:
- NSSet 对象不是通过 TNSSet.Create 方法,说明这么做是不对的(否则官方为啥不这么干,对不?),至于为什么,我不知道,没细研究,别问我:)
- NSSet 是通过 TNSSet.OCClass.setXXX 方法创建实例,然后通过 TNSSet.Wrap 转换为 NSSet 接口的。
现在来看下源码中的用法:
procedure TiOSBannerAd.SetBannerAdControl(const AValue: TCustomBannerAd);
var
SizesArray: NSMutableArray;
SizesSet: NSSet;
begin
FAdControl := AValue;
if FAdControl <> nil then
begin
FAd := TADBannerView.Create;
FDelegate := TiOSBannerAdDelegate.Create;
FDelegate.SetAd(Self);
FAd.setDelegate(FDelegate.GetObjectID);
SizesArray := TNSMutableArray.Create;
SizesArray.addObject((ADBannerContentSizeIdentifierLandscape as ILocalObject).GetObjectID);
SizesArray.addObject((ADBannerContentSizeIdentifierPortrait as ILocalObject).GetObjectID);
SizesSet := TNSSet.Wrap(TNSSet.OCClass.setWithArray(SizesArray));
SizesArray.release;
FAd.setRequiredContentSizeIdentifiers(SizesSet);
UpdateControlMetrics
end
else
begin
FAd.setDelegate(nil);
FAd.release;
FAd := nil;
FDelegate := nil;
end;
end;好吧,TNSMutableArray 是可以创建实例的,注意 addObject 添加的对象需要先将接口转换为 ILocalObject ,然后调用 GetObjectID,返回的指针才是需要的对象地址。感觉好麻烦对不对,好吧,麻烦也就麻烦了,不过我是一个怕麻烦的人,记住这么一堆东西脑仁会比较痛苦(天生脑容量小,记不住事),所以封装了两个函数,分享给大家:
function NSObjectArray(const AItems: array of IInterface): NSArray;
var
I: Integer;
ATemp: NSMutableArray;
begin
ATemp := TNSMutableArray.Create;
Result := ATemp;
for I := 0 to High(AItems) do
ATemp.addObject((AItems[I] as ILocalObject).GetObjectID);
end;
function NSArraySet(const AItems: array of IInterface): NSSet;
var
I: Integer;
begin
Result := TNSSet.Wrap(TNSSet.OCClass.setWithArray(NSObjectArray(AItems)));
end;这样象上面官方的代码中相关的部分就可以直接写成:
SizesSet := NSArraySet([ADBannerContentSizeIdentifierLandscape,ADBannerContentSizeIdentifierPortrait]);
是不是感觉可读性好多了。

