[杂谈] iOS 开发跳坑记:使用 NSSet 对象

Delphi 中开发 iOS 程序中,许多地方需要一个 NSSet 类型的参数,但是,怎么使用很伤脑筋。可怜的少的可怜的文档,都不如我的 QDAC 了(至少俺绝大部分代码有函数注释,这连个注释都没有)。为了搞明白怎么用,本人利用了源码搜索大法,搜索 Delphi 自带的 Source 目录下,看看它自身是如何使用的。整个源码中找到四处位置:

NSSetFiles

好了,接下来分析下,后面两个明显是声明,俺们就不关心了。前面两个才是实际使用的例子,可以看到以下几点:

  1. NSSet 对象不是通过 TNSSet.Create 方法,说明这么做是不对的(否则官方为啥不这么干,对不?),至于为什么,我不知道,没细研究,别问我:)
  2. 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]);

是不是感觉可读性好多了。

分享到: