Tôi đang tìm cách tạo danh mục để thay thế các phương thức ủy nhiệm với các lần gọi lại chặn cho rất nhiều API iOS đơn giản. Tương tự như khối sendAsyc trên NSURLConnection. Có 2 kỹ thuật bị rò rỉ miễn phí và dường như hoạt động tốt. Những ưu/khuyết điểm về mỗi cái là gì? Có cách nào tốt hơn?Kỹ thuật tốt nhất để thay thế các phương thức đại biểu bằng các khối
Tùy chọn 1. Sử dụng danh mục để triển khai phương thức gọi lại của đại biểu trên NSObject với khối gọi lại bên ngoài được sắp xếp.
// 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
Điều này bổ sung thêm nhiều phương pháp trên NSObject và có thể gây ra sự cố với bất kỳ lớp nào khác đang cố gắng sử dụng phương pháp đại biểu tiêu chuẩn. Nhưng nó giữ khối sống với đối tượng và trả về cuộc gọi lại mà không có bất kỳ rò rỉ nào mà tôi đã tìm thấy.
Tùy chọn 2. Tạo một lớp trọng lượng nhẹ để chứa khối, liên kết động với lớp để nó ở lại trong heap và xóa nó khi hoàn thành gọi lại.
// 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
Tôi thích điều này không thêm bất kỳ thứ gì lên trên NSObject và mọi thứ được tách biệt hơn một chút. Nó gắn với cá thể thông qua địa chỉ của hàm.
Tùy chọn 3: Phân lớp 'UIAlertView'. –
Phải. Phân lớp hoạt động. Nhưng nó sẽ lộn xộn và có ít mã có thể tái sử dụng hơn khi tôi phân lớp mọi API táo để thêm một cuộc gọi phương thức. Ngoài ra tôi đang đặt tất cả các API này trong một lớp để dễ dàng nhập và sử dụng các danh mục cho phép phương thức gọi sạch hơn và gần hơn với các API của Apple. Nếu có kết thúc là một cách chung chung tốt đẹp để giữ và trả về khối, sau đó mã đó có thể được tái sử dụng với những thay đổi nhỏ bất cứ khi nào tôi cần phải thêm vào một phương pháp chặn không đồng bộ hơn cho một API táo. – puppybits
Ok tôi hiểu rồi. Đó là một cam kết khá. Tôi chỉ cố gắng cứu bạn khỏi việc nhạo báng với thời gian chạy. –