为什么ViewController有两个实例以及如何修复它?

时间:2014-10-31 13:46:54

标签: objective-c xcode cocoa

首先,我将简要介绍一下。

我......

  1. 创建一个新的可可项目
  2. 自定义AppDelegate(参见清单1)
  3. 向我的MainMenu.xib添加“自定义视图”
  4. 在项目中创建一个新的Cocoa类(NSViewController + XIB),将其命名为MyTableViewController。*
  5. 向最近添加的ViewController添加“Table View”,如LINK
  6. 中所述
  7. 我的MyTableViewController的代码可以在清单2中看到
  8. 现在我的问题。 表格及其内容显示。 但是,如果我选择表格中的某个项目并按下此子视图上的按钮(连接到(IBAction)action:(id)sender),则输出中会显示<NSIndexSet: 0x60000022c100>(no indexes)(请参阅:selectedColumnIndexes)。 经过一段时间的实验,我发现有两个MyTableViewController类的实例。

    有人可以解释一下为什么有两个实例并帮我解决这个问题。

    THX

    列出1:

    // FILE: AppDelegate.h
    #import <Cocoa/Cocoa.h>
    @class MyTableViewController;
    @interface AppDelegate : NSObject <NSApplicationDelegate>
    @property (nonatomic, assign) NSViewController *        currentViewController;
    @property (nonatomic, strong) MyTableViewController *     myTableViewController;
    @property (weak) IBOutlet NSView *myview;
    @end
    
    // FILE: AppDelegate.m
    #import "AppDelegate.h"
    #import "MyTableViewController.h"
    
    @interface AppDelegate ()
    @property (weak) IBOutlet NSWindow *window;
    @end
    
    @implementation AppDelegate
    
    - (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    [self changeViewController];
    }
    
    - (void)applicationWillTerminate:(NSNotification *)aNotification {
    // Insert code here to tear down your application
    }
    
    - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication {
    return YES;
    }
    
    - (void)changeViewController
    {
    if ([self.currentViewController view] != nil) {
        [[self.currentViewController view] removeFromSuperview];
    }
    switch (0) {
        case 0:
        default:
            if (self.myTableViewController == nil) {
                _myTableViewController = [[MyTableViewController alloc] initWithNibName:@"MyTableViewController" bundle:nil];
            }
            self.currentViewController = self.myTableViewController;
            NSLog(@"EndView");
            break;
    }
    
    [self.myview addSubview:[self.currentViewController view]];
    [[self.currentViewController view] setFrame:[self.myview bounds]];
    [self.currentViewController setRepresentedObject:[NSNumber numberWithUnsignedInteger:[[[self.currentViewController view] subviews] count]]];
    [self didChangeValueForKey:@"viewController"];
    NSLog(@"ViewController changed");
    }
    
    @end
    

    列出2:

    // FILE: MyTableViewController.h
    #import <Cocoa/Cocoa.h>
    @interface MyTableViewController : NSViewController
    @property (weak) IBOutlet NSTableView *tview;
    - (IBAction)action:(id)sender;
    @end
    
    // FILE: MyTableViewController.m
    #import "MyTableViewController.h"
    #import "AppDelegate.h"
    
    @interface MyTableViewController ()
    @end
    
    @implementation MyTableViewController
    
    - (NSUInteger)numberOfRowsInTableView:(NSTableView *)tableViewObj {
    return 2;
    }
    
    - (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
    if ([tableView tableColumns][0] == tableColumn) {
        return @"bla";
    } else if ([tableView tableColumns][1] == tableColumn) {
        return @"blub";
    }
    NSLog(@"dropped through tableColumn identifiers");
    return NULL;
    }
    
    - (IBAction)action:(id)sender {
    //    selectedColumnIndexes
    NSLog(@"%@", [self.tview selectedColumnIndexes]);
    }
    @end
    

    FilesOwner-Connections TableView-Connections TableView.app

1 个答案:

答案 0 :(得分:0)

当您只期望/想要一个类的两个实例时,可能是由于未能理解xib文件中的对象本身是该类的实际自动生成的实例而引起的。

您是否已将蓝色多维数据集拖入任一xib文件并将其类设置为视图控制器子类?如果你有,那么这将占你所看到的一个对象 - Apple的机器代表你创建它。第二个对象是您在代码中使用changeViewController方法创建的对象。

我得到的印象是,您只是尝试创建一个包含NSTableView的窗口,该窗口又从您自己的NSViewController子类获取其数据。它是否正确?如果是,那么你应该取消第二个xib文件,而只是使用在创建项目时为你创建的xib。

简介

  1. 将蓝色对象多维数据集拖到Interface Builder停靠栏中,并使用 Identity Inspector 将其子类设置为MyTableViewController
  2. 选择视图控制器蓝色立方体后,转到 Connections Inspector 并从view选项拖动到表格视图 - 您必须确保拖动到表格视图,而不是包围它的滚动视图或剪辑视图。
  3. 选择表视图(再次确保它确实是您选择的表视图),然后转到它的Connections Inspector。从data sourcedelegate选项拖动到蓝色视图控制器多维数据集。
  4. 实施相关的数据 - 方法
  5. 提示:如果您不确定哪个检查员是哪个,请在Xcode中打开右侧边栏,然后从左侧文件查看器侧边栏中选择一个xib文件。将光标放在右侧边栏顶部的每个图标上,工具提示将告诉您哪个是哪个。

    更新

    识别特定对象以及可以帮助调试的一种好方法是设置identifier。在属性检查器中,这是恢复ID。为您的NSTableView实例以及NSTableColumn实例执行此操作。然后,在您的数据源方法中使用它们进行一些日志记录 - 例如,作为此方法的第一个参数传递的表视图是否具有预期的identifier,那么表列呢?