目标C:使用块的init类?

时间:2012-10-09 09:46:45

标签: objective-c ios objective-c-blocks

是否可以使用块作为View Controller的init方法中的完成处理程序,以便父视图控制器能够填充块中的详细信息,而无需创建自定义initWithNibName:andResourceBundle:andThis :andThat:对于每个可能的属性?

// ... in the didSelectRowAtIndexPath method of the main view controller :
SubViewController *subviewController = [[SubViewController alloc] initWithNibName:nil bundle:nil completionHandler:^(SubViewController * vc) {
    vc.property1 = NO;
    vc.property2 = [NSArray array];
    vc.property3 = SomeEnumValue;
    vc.delegate = self;
}];
[self.navigationController pushViewController:subviewController animated:YES];
[subviewController release];
SubViewController.m中的

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil completionHandler:(void (^)(id newObj))block {
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        block(self);
    }
    return self;
}

而不是

// ... in the didSelectRowAtIndexPath method of the main view controller :
SubViewController *subviewController = [[SubViewController alloc] initWithNibName:nil bundle:nil andProperty1:NO andProperty2:[NSArray array] andProperty3:SomeEnumValue andDelegate:self];
[self.navigationController pushViewController:subviewController animated:YES];
[subviewController release];

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil andProperty1:(BOOL)p1 andProperty2:(NSArray *)p2 andProperty3:(enum SomeEnum)p3 andDelegate:(id<MyDelegateProtocol>)myDelegate {
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
       self.property1 = p1;
       self.property2 = p2;
       self.property3 = p3;
       self.delegate = myDelegate;
    }
    return self;
}

这样我就可以在主控制器中执行任何操作,而不是调用预定义的init方法(并且必须为每个可能的初始化编写一个)。

这是不是很糟糕?会有保留周期吗?

5 个答案:

答案 0 :(得分:3)

您在使用街区时会看到哪些优势?初始化程序通常用于设置实例的私有状态。无法从块访问此私有状态,因为该块在其他位置实现。

如果您只使用公共属性,为什么不在初始化后进行设置?

SubViewController *vc = [[SubViewController alloc] initWithNibName:nil bundle:nil];
vc.property1 = NO;
vc.property2 = [NSArray array];
vc.property3 = SomeEnumValue;
vc.delegate = self;

这正是块版本的作用(没有麻烦)。

  

这是不是很糟糕?会有保留周期吗?

不,但是我会因为体系结构原因而忽略你的命题:你要么打破了类的封装,要么在初始化之后只执行块所做的事情上没有任何优势。

答案 1 :(得分:2)

问题是:

  1. 这种方式有什么好处?
  2. 您能否有效管理此代码?

  3. 请注意,当程序增长时,将添加新级别的调用,这将使您的代码难以阅读,维护,扩展或开发。考虑未来的子类化以及将来如何调试此代码以找到一些不匹配的值。 块可以使您的代码更快,但委托模式将使您的代码清晰并在一个线程中运行,这在将来很容易维护,这对专业程序员来说是真正的价值。

答案 2 :(得分:1)

您可以定义

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil completionHandler:(void (^)(id newObj))block;

UIViewController类别中的方法;从那里你可以调用initWithNib,然后在刚刚分配的self上执行你的完成块:

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil completionHandler:(void (^)(id newObj))block
{
    if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
        block(self);
    }
    return self;
}

我认为这应该可行。

答案 3 :(得分:1)

这是可能的,没有retain个问题。一切都将在同一个线程上同步调用。

<强> BUT 不这么做的好处是什么 - 在init之后调用另一种方法,例如

MyController* controller = [[[MyController alloc] init] autorelease];
[self updateController:controller];
是否可以从init方法调用代码?

一般情况下,如果您想以不同方式初始化对象,我建议您创建单独的init...方法。

答案 4 :(得分:1)

我真的不确定你为什么采取这种方法(除非你想引起OOD警察的注意)。 it's not a good idea

您的控制器可以定义一个返回实例的函数或方法,并以其想要的方式初始化。