0

我花了很多时间来更好地理解 Objective-C 中的委托。我让它适用于大多数情况,但在特定情况下存在问题,我觉得很难理解。让我解释一下我想要做什么:

我有一个名为 的自定义视图GridLayoutView,它是UIView. 我还有一个视图控制器SomeViewController,它是GridLayoutView.

我有一个自定义initWithFrame方法,我有条件地调用另一个初始化方法baseInit。该方法有时会调用委托方法。以下是一些代码GridLayoutView

//
// Delegator
// GridLayoutView.m
//

@implementation GridLayoutView

- (id)initWithFrame:(CGRect)frame 
       numberOfRows:(NSUInteger)rows
       numberOfCols:(NSUInteger)cols
{
    self = [super initWithFrame:frame];
    if (self) {
        self.numberOfRows = rows;
        self.numberOfCols = cols;
        self.numberOfCells = rows * cols;

        if (self.numberOfCells > 0) [self baseInit];
    }
    return self;
}

- (void)baseInit
{
    // do some more initialization stuff here
    // ...

    // then call a delegate method
    [self.delegate someMethod:someObj];

    // However, this method is not called because self.delegate is nil
}

和一些代码SomeViewController

//
// Delegate
// SomeViewController.m
//

@implementation SomeViewController

// ...

    // in some method
    self.gridLayoutView = [[GridLayoutView alloc] initWithFrame:gridLayoutFrame
                                                   numberOfRows:rowsCount
                                                   numberOfCols:colsCount];
    self.gridLayoutView.delegate = self;

// ...

委托方法永远不会在 内部被调用baseInit,因为委托是nil在那个时候,它在方法完成initWithFrame之后被设置。baseInit我已经证实了这一点。

我感觉我的委派工作流程有问题。我有一个解决方案,但我认为这不是最好的方法。解决方案基本上是SomeViewController通过修改方法将实例传递给委托人,initWithFrame例如:

- (id)initWithFrame:(CGRect)frame 
       numberOfRows:(NSUInteger)rows
       numberOfCols:(NSUInteger)cols
           delegate:(id<GridLayoutViewDelegate>)aDelegate

这种方法有效,但由于传递SomeViewControllerGridLayoutView它的initWithRect. 我想知道这是否是与代表团合作的好方法还是有更好的方法?如果有人能为我解决这个问题,我将不胜感激。

4

2 回答 2

4

如果我的理解正确,这里没有太多选择。

  1. 修改您的初始化程序(如您所建议的那样)以传入委托。没什么不好的,不知道为什么不喜欢。

  2. 在初始化期间删除对委托的依赖,而是在通过覆盖 setter 设置委托属性时发送任何合适的委托消息:


- (void)setDelegate:(id<GridLayoutViewDelegate>)aDelegate
{
    _delegate = aDelegate;
    // send whatever message makes sense to the delegate
    [_delegate someMethod:object];
}

编辑 - 注意到你的评论

您的初始化方法不应花费任何大量时间。目前尚不清楚“加载视图”是什么意思。如果您只是指创建子视图并将其添加到视图中,那么这很快,并且不需要将进度传达给委托(无论如何您都不能这样做 b/c 初始化在主线程上,而 UI 不会更新直到所有初始化完成)。

If you mean loading data that takes a long time, you should disconnect that from initialization and load the data in a background operation, sending progress messages to a delegate.

于 2013-03-29T19:58:54.437 回答
0

i would implement the setDelegate function and then call [self someMethod:someObj]; from there

于 2013-03-29T20:02:33.673 回答