所以我正在编写看起来像这样的API:
@implementation TheApi
- (ObjectLoaderCallbackDelegate *)createLoaderDelegateForCallback:(ObjectLoaderCallback)callback
{
ObjectLoaderCallbackDelegate *loaderDelegate = [[ObjectLoaderCallbackDelegate alloc] init];
loaderDelegate.didLoadObject = ^(id object) {
callback(object);
};
return loaderDelegate;
}
- (void)loadString:(ObjectLoaderCallback)callback
{
ObjectLoaderCallbackDelegate *callbackDelegate = [self createLoaderDelegateForCallback:callback];
ObjectLoader *loader = [[ObjectLoader alloc] init];
[loader load:@"string" delegate:callbackDelegate];
}
- (void)loadNumber:(ObjectLoaderCallback)callback
{
ObjectLoaderCallbackDelegate *callbackDelegate = [self createLoaderDelegateForCallback:callback];
ObjectLoader *loader = [[ObjectLoader alloc] init];
[loader load:@"number" delegate:callbackDelegate];
}
@end
当我调用[loader load:delegate:]时,它不会保留对委托的强引用(这是有道理的)。但是因为加载器在调用委托之前执行异步操作,所以委托在被调用之前被释放,从而导致程序崩溃。这是我的解决方案(看起来有点脏):
@interface TheApi : NSObject
- (void)loadString:(ObjectLoaderCallback)callback;
- (void)loadNumber:(ObjectLoaderCallback)callback;
- (void)runCalls;
@end
@implementation TheApi
{
NSMutableDictionary *loaderDelegates;
NSMutableSet *callbacksCompleted;
}
- (TheApi *) init
{
self = [super init];
if (self != nil) {
loaderDelegates = [[NSMutableDictionary alloc] init];
callbacksCompleted = [[NSMutableSet alloc] init];
}
return self;
}
- (void)runCalls
{
[loader runLoop];
}
- (ObjectLoaderCallbackDelegate *)createLoaderDelegateForCallback:(ObjectLoaderCallback)callback
{
NSNumber *delegateRefKey = [NSNumber numberWithUnsignedInt:arc4random()];
ObjectLoaderCallbackDelegate *loaderDelegate = [[ObjectLoaderCallbackDelegate alloc] init];
loaderDelegate.didLoadObject = ^(id object) {
callback(object);
[callbacksCompleted addObject:delegateRefKey];
};
[loaderDelegates setObject:loaderDelegate forKey:delegateRefKey];
return loaderDelegate;
}
- (void)removeCompletedDelegates
{
// So we can remove items from callbacksCompleted in the loop...
NSMutableSet *callbacksCompletedIterSet = [callbacksCompleted copy];
// Remove old delegates for calls already completed which are stored
for (id key in callbacksCompletedIterSet) {
[loaderDelegates removeObjectForKey:key];
[callbacksCompleted removeObject:key];
}
}
- (void)loadString:(ObjectLoaderCallback)callback
{
[self removeCompletedDelegates];
ObjectLoaderCallbackDelegate *callbackDelegate = [self createLoaderDelegateForCallback:callback];
ObjectLoader *loader = [[ObjectLoader alloc] init];
[loader load:@"string" delegate:callbackDelegate];
}
- (void)loadNumber:(ObjectLoaderCallback)callback
{
[self removeCompletedDelegates];
ObjectLoaderCallbackDelegate *callbackDelegate = [self createLoaderDelegateForCallback:callback];
ObjectLoader *loader = [[ObjectLoader alloc] init];
[loader load:@"number" delegate:callbackDelegate];
}
@end
所以在这里,我在实例级字典中保留对代理的引用,其中每个API方法调用的密钥都是唯一的。
所以我的问题是:有没有更好的方法来保持代理被释放,然后在加载器调用它们之后释放它们?
答案 0 :(得分:0)
我最近问了similar question并了解了“相关对象”。这似乎可以解决您的问题。
@CRD在他的回答中提供了一个很好的解释 - 见https://stackoverflow.com/a/17351118/423565