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]);
是不是感觉可读性好多了。