1

我真的很喜欢块的工作方式,并认为将它们添加到一些地方会很好,比如为UIRefreshControl.

所以我创建了category一个UIRefreshControl

@interface UIRefreshControl (Blocks)

@property (nonatomic, copy) void (^actionBlock)();

- (id)initWitActionBlock:(void (^)())actionBlock;

@end

@implementation UIRefreshControl (Blocks)

- (id)initWitActionBlock: (void (^)())actionBlock {
    self = [super init];
    if (self) {
        self.actionBlock = [actionBlock copy];
        [self addTarget:self action:@selector(fireActionBlock) forControlEvents:UIControlEventValueChanged];
    }
    return self;
}

- (void)fireActionBlock {
        self.actionBlock();
}

@end

这是崩溃:原因:'-[UIRefreshControl setActionBlock:]:无法识别的选择器发送到实例

但我真的不太了解积木,而且我也没有真正看到这categorysubclass做同样的事情之间的区别。

我想我不完全了解属性发生了什么,所以我的问题是我应该怎么做?如果可能的话,这样可以吗?或者也许我不应该这样做?

编辑: *带有相关参考的解决方案感谢@Martin R!

static char const * const ActionBlockKey = "ActionBlockKey";

@interface UIRefreshControl (Blocks)

@property (nonatomic, copy) void (^actionBlock)();

- (id)initWitActionBlock:(void (^)())actionBlock;

@end

@implementation UIRefreshControl (Blocks)
@dynamic actionBlock;

- (id)initWitActionBlock: (void (^)())actionBlock {
    self = [super init];
    if (self) {
        self.actionBlock = [actionBlock copy];
        [self addTarget:self action:@selector(fireActionBlock) forControlEvents:UIControlEventValueChanged];
    }
    return self;
}

- (void)fireActionBlock {
        self.actionBlock();
}

- (id)actionBlock{
    return objc_getAssociatedObject(self, ActionBlockKey);
}

- (void)setActionBlock:(void (^)())actionBlock{
    objc_setAssociatedObject(self, ActionBlockKey, actionBlock,  OBJC_ASSOCIATION_COPY_NONATOMIC);
}

@end
4

3 回答 3

1

该问题与块无关。

编译器不会综合类类别中定义的属性,因为这需要相应的实例变量,并且您不能在类类别中添加实例变量。

实际上你应该得到一个警告

属性 'actionBlock' 需要定义方法 'actionBlock' - 使用 @dynamic 或在此类别中提供方法实现

我建议改为创建一个子类。

于 2013-10-15T14:23:59.597 回答
0

我给你一些提示,但还没有测试代码。请注意,您不应该像我刚才那样扩展 UIKit 类。

@interface MYUIRefreshControl : UIRefreshControl

@property (nonatomic, copy) void (^actionBlock)();

- (id)initWitActionBlock:(void (^)())actionBlock;

@end

@implementation MYUIRefreshControl
@synthesize actionBlock = _actionBlock;

- (id)initWitActionBlock: (void (^)())actionBlock {
    self = [super init];
    if (self) {
        _actionBlock = [actionBlock copy];
        [self addTarget:self action:@selector(fireActionBlock) forControlEvents:UIControlEventValueChanged];
    }
    return self;
}

- (void)fireActionBlock {
      if(_actionBlock)
        _actionBlock();
}

@end
于 2013-10-15T14:28:41.840 回答
0
    Try Class Extension. 

    File- New - Swift class - Create one.

    public extension UIRefreshControl
    {
        func makeRefreshView()
        {

            attributedTitle = NSAttributedString(string: "Refreshing ")
            backgroundColor = UIColor.clearColor()
            addTarget(self, action: "refreshnow", forControlEvents: UIControlEvents.ValueChanged)

        }
        func refreshnow()
        {
            print("refreshing and loading")
            endRefreshing()
        }
    }


    Implementation.

let refreshControl = UIRefreshControl()
refreshControl.makeRefreshView()
self.bidderlisttable.addSubview(refreshControl)
refreshControl.refreshnow()
于 2015-09-10T13:51:43.627 回答