Có thể chuyển một khối Objective-C cho đối số @selector trong UIButton không?
Lấy tất cả các câu trả lời đã được cung cấp, câu trả lời là Có nhưng một chút công việc là cần thiết để thiết lập một số danh mục.
Tôi khuyên bạn nên sử dụng NSInvocation vì bạn có thể làm được nhiều việc với điều này chẳng hạn như với bộ định thời, được lưu trữ dưới dạng một đối tượng và được gọi ra ... vv ...
Đây là những gì tôi đã làm, nhưng lưu ý rằng tôi đang sử dụng ARC.
Đầu tiên là một danh mục đơn giản trên NSObject:
.h
@interface NSObject (CategoryNSObject)
- (void) associateValue:(id)value withKey:(NSString *)aKey;
- (id) associatedValueForKey:(NSString *)aKey;
@end
.m
#import "Categories.h"
#import <objc/runtime.h>
@implementation NSObject (CategoryNSObject)
#pragma mark Associated Methods:
- (void) associateValue:(id)value withKey:(NSString *)aKey {
objc_setAssociatedObject( self, (__bridge void *)aKey, value, OBJC_ASSOCIATION_RETAIN );
}
- (id) associatedValueForKey:(NSString *)aKey {
return objc_getAssociatedObject( self, (__bridge void *)aKey );
}
@end
Tiếp theo là một danh mục trên NSInvocation để lưu trữ trong một khối:
.h
@interface NSInvocation (CategoryNSInvocation)
+ (NSInvocation *) invocationWithTarget:(id)aTarget block:(void (^)(id target))block;
+ (NSInvocation *) invocationWithSelector:(SEL)aSelector forTarget:(id)aTarget;
+ (NSInvocation *) invocationWithSelector:(SEL)aSelector andObject:(__autoreleasing id)anObject forTarget:(id)aTarget;
@end
.m
#import "Categories.h"
typedef void (^BlockInvocationBlock)(id target);
#pragma mark - Private Interface:
@interface BlockInvocation : NSObject
@property (readwrite, nonatomic, copy) BlockInvocationBlock block;
@end
#pragma mark - Invocation Container:
@implementation BlockInvocation
@synthesize block;
- (id) initWithBlock:(BlockInvocationBlock)aBlock {
if ( (self = [super init]) ) {
self.block = aBlock;
} return self;
}
+ (BlockInvocation *) invocationWithBlock:(BlockInvocationBlock)aBlock {
return [[self alloc] initWithBlock:aBlock];
}
- (void) performWithTarget:(id)aTarget {
self.block(aTarget);
}
@end
#pragma mark Implementation:
@implementation NSInvocation (CategoryNSInvocation)
#pragma mark - Class Methods:
+ (NSInvocation *) invocationWithTarget:(id)aTarget block:(void (^)(id target))block {
BlockInvocation *blockInvocation = [BlockInvocation invocationWithBlock:block];
NSInvocation *invocation = [NSInvocation invocationWithSelector:@selector(performWithTarget:) andObject:aTarget forTarget:blockInvocation];
[invocation associateValue:blockInvocation withKey:@"BlockInvocation"];
return invocation;
}
+ (NSInvocation *) invocationWithSelector:(SEL)aSelector forTarget:(id)aTarget {
NSMethodSignature *aSignature = [aTarget methodSignatureForSelector:aSelector];
NSInvocation *aInvocation = [NSInvocation invocationWithMethodSignature:aSignature];
[aInvocation setTarget:aTarget];
[aInvocation setSelector:aSelector];
return aInvocation;
}
+ (NSInvocation *) invocationWithSelector:(SEL)aSelector andObject:(__autoreleasing id)anObject forTarget:(id)aTarget {
NSInvocation *aInvocation = [NSInvocation invocationWithSelector:aSelector
forTarget:aTarget];
[aInvocation setArgument:&anObject atIndex:2];
return aInvocation;
}
@end
Đây là cách sử dụng nó:
NSInvocation *invocation = [NSInvocation invocationWithTarget:self block:^(id target) {
NSLog(@"TEST");
}];
[invocation invoke];
Bạn có thể làm được nhiều điều với lời gọi và các Phương thức Objective-C tiêu chuẩn. Ví dụ: bạn có thể sử dụng NSInvocationOperation (initWithInvocation :), NSTimer (isedTimerWithTimeInterval: invocation: lặp lại :)
Điểm mấu chốt là biến khối của bạn thành một NSInvocation linh hoạt hơn và có thể được sử dụng như sau:
NSInvocation *invocation = [NSInvocation invocationWithTarget:self block:^(id target) {
NSLog(@"My Block code here");
}];
[button addTarget:invocation
action:@selector(invoke)
forControlEvents:UIControlEventTouchUpInside];
Một lần nữa đây chỉ là một gợi ý.
objc_implementationWithBlock()
vàclass_addMethod()
giải quyết vấn đề này theo cách hiệu quả hơn một chút so với việc sử dụng các đối tượng được liên kết (ngụ ý tra cứu băm không hiệu quả như tra cứu phương pháp). Có thể là một sự khác biệt hiệu suất không liên quan, nhưng nó là một sự thay thế.