我在創建一個類別,用很多簡單的iOS API的回調塊替換委託方法。類似於NSURLConnection上的sendAsyc塊。有兩種技術是無泄漏的,似乎工作正常。每個人有什麼優點/缺點?有沒有更好的辦法?用塊替換委託方法的最佳方法
選項1.使用一個類別在NSObject上實現委託的回調方法,並將外部回調塊作用域。
// Add category on NSObject to respond to the delegate
@interface NSObject(BlocksDelegate)
- (void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex;
@end
@implementation NSObject(BlocksDelegate)
- (void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
// Self is scoped to the block that was copied
void(^callback)(NSInteger) = (id)self;
// Call the callback passed if
callback(buttonIndex);
[self release];
}
@end
// Alert View Category
@implementation UIAlertView (BlocksDelegate)
+ (id) alertWithTitle:(NSString*)title
message:(NSString*)message
clickedBlock:(void(^)(NSInteger))buttonIndexClickedBlock
cancelButtonTitle:(NSString*)cancelButtonTitle
otherButtonTitles:(NSString*)otherButtonTitles
{
// Copy block passed in to the Heap and will stay alive with the UIAlertView
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title
message:message
delegate:[buttonIndexClickedBlock copy]
cancelButtonTitle:cancelButtonTitle
otherButtonTitles:otherButtonTitles, nil];
// Display the alert
[alert show];
// Autorelease the alert
return [alert autorelease];
}
@end
這在NSObject上增加了很多方法,似乎它可能會導致任何其他類嘗試使用標準委託方法的問題。但它使塊保持與對象一起活動,並返回回調而沒有發現任何泄漏。
選項2.創建輕量類以包含塊,動態地將其與類關聯所以它會留在堆和回調完成時將其刪除。
// Generic Block Delegate
@interface __DelegateBlock:NSObject
typedef void (^HeapBlock)(NSInteger);
@property (nonatomic, copy) HeapBlock callbackBlock;
@end
@implementation __DelegateBlock
@synthesize callbackBlock;
- (id) initWithBlock:(void(^)(NSInteger))callback
{
// Init and copy Callback Block to the heap (@see accessor)
if (self = [super init])
[self setCallbackBlock:callback];
return [self autorelease];
}
- (void) dealloc
{
// Release the block
[callbackBlock release], callbackBlock = nil;
[super dealloc];
}
- (void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
// Return the result to the callback
callbackBlock(buttonIndex);
// Detach the block delegate, will decrement retain count
SEL key = @selector(alertWithTitle:message:clickedBlock:cancelButtonTitle:otherButtonTitles:);
objc_setAssociatedObject(alertView, key, nil, OBJC_ASSOCIATION_RETAIN);
key = nil;
// Release the Alert
[alertView release];
}
@end
@implementation UIAlertView (BlocksDelegate)
+ (id) alertWithTitle:(NSString*)title
message:(NSString*)message
clickedBlock:(void(^)(NSInteger))buttonIndexClickedBlock
cancelButtonTitle:(NSString*)cancelButtonTitle
otherButtonTitles:(NSString*)otherButtonTitles
{
// Create class to hold delegatee and copy block to heap
DelegateBlock *delegatee = [[__DelegateBlock alloc] initWithBlock:buttonIndexClickedBlock];
[[delegatee retain] autorelease];
// Create delegater
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title
message:message
delegate:delegatee
cancelButtonTitle:cancelButtonTitle
otherButtonTitles:otherButtonTitles, nil];
// Attach the Delegate Block class to the Alert View, increase the retain count
objc_setAssociatedObject(alert, _cmd, delegatee, OBJC_ASSOCIATION_RETAIN);
// Display the alert
[alert show];
return alert;
}
@end
我喜歡,這並不在NSObject中的頂部添加任何東西,事情多一點分開。它通過函數的地址附加到實例。
方案3:子類'UIAlertView'。 – 2011-12-27 20:54:31
對。子類化作品。但是,爲了添加一個方法調用,我將每個蘋果API進行子類化時,它會變得雜亂無章並且可重用代碼更少。此外,我將所有這些API放在一個類中,因此很容易導入和使用類別,這樣方法調用就可以更清晰,更接近Apple API。如果最終成爲一個很好的通用方法來保存並返回塊,那麼無論何時我需要將另一個異步塊方法添加到Apple API時,該代碼都可以重複使用,並進行較小的更改。 – puppybits 2011-12-28 15:11:47
好的,我明白了。這是一項非常重要的任務。我只是試圖讓你免受運行時間的影響。 – 2011-12-28 19:51:27