只要一个块的要求是你的而不是系统的。
就像我说的,有几种方法。函数指针需要最少的样板文件,但它们需要一个额外的参数来从调用者传递上下文(self
在你的情况下)。函子和指向成员的指针通常需要模板机制才能工作,我们不要去那里。因此,使用函数指针,它的运行方式如下:
//Let's define a callback datatype
typedef void (*ResourceLoadObjFuncPtr)(void *, void*);
//argument 1 is ptr to ResourceLoadDescriptor, argument 2 is iconSlot, whatever it is
//Function that implements that type:
void MyLoad(void *img, void *iconSlot)
{
UIImage* img2 = (UIImage*)img;
UIImageView* iv = [[UIImageView alloc] initWithImage:img2];
iv.backgroundColor = [UIColor clearColor];
[(TheTypeOfIconslot*)iconSlot addSubview:iv];
iconLoaded(iv);
[iv release];
}
而且您必须修改 的原型queueLoadImageWithBlock
以接受ResourceLoadObjFuncPtr
参数而不是ResourceLoadObjCBlockCB
,以及上下文的另一个参数(仅iconSlot
在我们的例子中)。
并调用:
[[GameViewController getInstance] getResourceLoadMediator]->
queueLoadImageWithFunction([self.url UTF8String], MyLoad, self.iconSlot);
块是闭包——它们捕获声明它们的函数的变量。C++ 不提供 iOS 上的 GCC 支持的闭包(除了块)。因此,您必须手动将变量从函数范围传递给函数参数。在我们的例子中,如果我的假设是正确的,那么只有一个变量;在更复杂的情况下,您必须将它们包装在一个结构中并传递一个指向其中的指针。
另一种方法是使用抽象基类和通过其构造函数捕获上下文的具体实现。这将是这样的:
//Callback type
class ResourceLoader
{
public:
virtual void Load(void *) = 0;
};
//A callback implementation - not a function, but a class
class MyResourceLoader : public ResourceLoader
{
IconSlotType *iconSlot;
void Load(void *img)
{
//Same loader stuff as above
}
public:
MyResourceLoader(IconSlotType *isl)
:iconSlot(isl)
{}
};
queueLoadImageWithBlock
等效项现在将采用类型的第二个参数,并且ResourceLoader*
没有第三个参数。至于调用,存在回调对象生命周期的问题。是queueLoadImageWithBlock
异步的——也就是说,它是否在调用回调之前返回?如果是这样,那么 MyResourceLoader 的本地实例将无法使用,您必须动态创建一个并以某种方式处置它。假设它是同步的(即在它返回后不调用回调):
MyResourceLoader ResLoader(self.iconSlot);
[[GameViewController getInstance] getResourceLoadMediator]->
queueLoadImageWithLoader([self.url UTF8String], &ResLoader);
如果不是:
[[GameViewController getInstance] getResourceLoadMediator]->
queueLoadImageWithLoader([self.url UTF8String], new MyResourceLoader(self.iconSlot));