【问题标题】:awakeFromNib method called multiple timesawakeFromNib 方法被多次调用
【发布时间】:2011-10-28 20:57:54
【问题描述】:

在我基于 NSPersistenDocument 的项目中,我有这样的结构

myDocument (NSPersistentDocument) -> myDocument.xib (windows xib)
                                           |
                                           |-> view (the self.view) --> ... "other view"
                                           |
                                           |-> some NSArrayController 
                                           |
                                           |-> myResourceViewController --> myResourceViewController.xib
                                                                                          |
                                                                                          |-> view (the self.view)
                                                                                          |
                                                                                          |-> myTreeController (a NSTreeController subclass)

基本上,myResourceViewController 是管理 resourceView 并管理其数据的 viewController 的一个实例。

在 myDocument 的 awakeFromNib 方法中,我有以下代码

- (void)windowControllerDidLoadNib:(NSWindowController *)aController
{
    ...
    [leftBar addSubview:resourceViewController.view]; //i add resourceViewController's view 
    resourceViewController.view.frame = leftBar.bounds;
    ...
}

在 myResourceViewController awakeFromNib 方法中我有:

-(void)awakeFromNib;
{
    NSLog(@"%@", [self description]);

    [removeButton bind:@"enabled" toObject:resourceTreeController withKeyPath:@"selection" options:[NSDictionary dictionaryWithObject:NSIsNotNilTransformerName forKey:NSValueTransformerNameBindingOption]];

    NSArray *draggedTypes = [NSArray arrayWithObjects:ResourceURIPasteBoardType, nil];
    [resourceOutlineView registerForDraggedTypes:draggedTypes];
}

NSLog 说 myResourceViewController 的同一实例的 awakeFromNib 被调用了 4 次,我不明白为什么。我唯一的 ResourceViewController 是在 myDocument xib 中创建的。我不会到处使用 NSNib 加载方法。

【问题讨论】:

  • 你确定是同一个对象吗?试试NSLog(@"%p %@", self, [self description])
  • 是的,我用 NSLog(@"%@", [self description]);
  • myDocument.xib 是唯一的 nib 吗?
  • 不,myResourceViewController 有一个名为 myResourceViewController.xib 的 xib。

标签: objective-c cocoa binding interface-builder xib


【解决方案1】:

解决方法是在makeViewWithIdentifier:owner:中不设置所有者为self

这使得 awakefromNib 被多次调用。

【讨论】:

    【解决方案2】:

    我找到了解决方案。每次NSTableCellViewNSOutlineView 创建时,都会调用awakeFromNib

    【讨论】:

    • 好吧,在我的例子中,很明显 awakeFromNib 被称为 # of cells 次 .. 但是,解决方法是什么?子类 NSTableCellView?
    • 非常气愤,有谁知道如何阻止这个?
    • 这是一种解决方法,但我在 init 中设置了 BOOL initialize = NO,然后仅在 initialize = NO 时执行 awakeFromNib 中的代码(并在该 if 语句中将其设置为 YES)
    • 在 10.8 上,您可以使用 registerNib:forIdentifier: 以便加载 cellview 时使用不同的 nib。
    • @Mazyod 解决方法是不要将makeViewWithIdentifier:owner:中的owner设置为self
    【解决方案3】:

    这不容易弄清楚,但对我来说,不知何故,我的表格视图更改为内容模式的“基于视图”与“基于单元格”。

    切换回“基于单元格”,awakeFromNib 只运行一次。

    注意:在 Interface Builder 中选择您的表格视图三次以到达正确的级别。或者,只需从文档大纲中选择您的“表格视图”。

    【讨论】:

    • 我使用的是 xcode 5.0.2,但找不到我的表格的“内容模式”属性,知道吗?
    【解决方案4】:

    根本原因在方法 makeViewWithIdentifier 的 NSTableView 头文件中进行了描述:“...。请注意,每次实例化对象时,'owner' 都会获得 'awakeFromNib:' 调用。”

    我的解决方案很简单,但我认为并不适合所有人:只需定义例如tableView 作为所有者:

    - (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
    {
        NSTableCellView *view = [tableView makeViewWithIdentifier:kTextViewIdentifier owner:tableView];
    
        return view;
    }
    

    【讨论】:

    • 加载原型视图时,可以简单地为所有者传递 nil。
    【解决方案5】:

    我在 NSTableView 中注意到了同样的情况。 NSTableView 是通过 NSArrayController 更新的,我注意到 NSTableView 已将委托设置为文件所有者,当我删除对文件所有者的委托时,awakeFromNib 只调用了一次。

    【讨论】:

      【解决方案6】:

      我像这样将代码放在我的 awakeFromNib 内的同步块中。

      例如

      @implementation {
          BOOL _initialize;
      }
      
          - (id)init {
              self = [super init];
              if (self) {
                  _initialize = YES;
              }
              return self;
          }
      
          - (void)awakeFromNib {
              @synchronized(self) {
                  if (_initialize) {
                      _initialize = NO;
      
                      /* code to execute once */
                  }
              }
      
              /* code to re-execute */
          }
      }
      

      【讨论】:

        【解决方案7】:

        我不知道为什么它被调用了四次,但至少我可以解释两次awakeFromNib 的调用。重要的是要记住 awakeFromNib 甚至会为 nib 文件的文件所有者调用,而不仅仅是 nib 文件中包含的对象。

        因此,您的 ResourceViewController 的 awakeFromNib 至少会被调用两次:当它被加载到 myDocument.xib 中时,然后当由 ResourceViewController 管理的视图从另一个 nib 加载时。

        最好在其他调用时间更明确的方法中进行初始化,如...didLoadapplicationDidFinish...

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-06-02
          • 1970-01-01
          相关资源
          最近更新 更多