我在Cocoa中回调delegate的方法时判断delegate是否已经被释放中描述了如何使用delegate的isa判断其所属类是否改变,从而判断delegate是否被释放。但是Nike指出:一旦此delegate注册过KVO,其isa就会被改变了。除非保证delegate不会被注册KVO(这要求判断delegate是否被释放时保证delegate必须是我们自己创建的,而不是其他任何人,而且我们要手工保证此delegate不会注册KVO),否则使用此种方法判断理论和实际上都是不可靠的。虽然iphone上的YAJL库目前也采用了这种方式判断对象类型,但是自从知道了KVO的那些事儿后,我觉得isa的方式还是很不靠谱的。
周末闲来无事读了读Objective-C
Runtime Reference,发现objc的runtime中有两种判断类型的方式比较靠谱,他们可以直接取得任意一个objc_object(和id是完全一样的数据类型)的类或者类名。其函数如下:
//Returns the class name of a given object. const char *object_getClassName(id obj); //Returns the class of an object. Class object_getClass(id object);
第一个函数可以返回任意一个id的类名,第二个函数可以返回任意一个id的Class。
而第二个函数会牵扯到isa-swizzling问题,参考八楼Nike大神的回复。
object_getClassName会不会牵扯到isa-swizzling问题我还没试过,没时间尝试~
以下为使用object_getClass判断delegate是否存在的一个例子,例子中MasterViewController将创建一个新线程试图回调DetailViewController的callback方法(涉及isa-swizzling,所以KVO下无效,但是下面例子的代码我没时间修改了)。
首先声明好用于回调的Protocol:
@protocol CallbackProtocol <NSObject> @required - (void)callback; @end
然后在MasterViewController的成员变量里加上一个Class变量,用于存放delegate刚刚被设置进来时其Class:
@interface MasterViewController : UITableViewController { __unsafe_unretained id <CallbackProtocol> _delegate; Class _originalClass; }
在设置delegate的同时,将其Class保存在_originalClass成员变量中:
_originalClass = object_getClass(_delegate);
在回调时首先判断_delegate是否为空,若不为空再判断其类型是否改变,若类型已改变,则此对象已被释放(在Cocoa中回调delegate的方法时判断delegate是否已经被释放中已经有相关叙述)。
if (_delegate != nil) { Class currentClass = object_getClass(_delegate); if (currentClass == _originalClass) { [_delegate callback]; } else { NSLog(@"orginal:%d present:%d - Not same class",(int)_originalClass,(int)currentClass); } } else { NSLog(@"Delegate is nil"); }
若成员变量不保存Class类型而仅仅将其指针保存为int则性能更优。
刚刚提到object_getClass没有被手动声明的话编译时此函数会被warning。为此我们需要自己手动声明此函数。不管你写在哪,我是写在了.m里。
在用了object_getClass的.m的#import语句之下,@implemention语句之上,加上下面两句话:
//Returns the class of an object. Class object_getClass(id object);
至此大功告成。
回调demo下载地址:git://github.com/OpenFibers/CallbackDemo.git,demo中首先由master
view进入detail view,再由detail view返回master view,返回后开辟新的线程,新的线程在3秒之后判断detail view是否存在。
以上
–OpenThread
转自:http://pingguohe.net/2011/12/04/whether_a_delegate_is_released_again/