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

Objective c 为什么有两个ViewController实例以及如何修复它?,objective-c,xcode,cocoa,Objective C,Xcode,Cocoa,首先,我会给你一个简短的概述 我是 创建新的cocoa项目 定制AppDelegate(请参见清单1) 将“自定义视图”添加到my MainMenu.xib 在项目中创建一个新的Cocoa类(NSViewController+XIB),称之为MyTableViewController* 向最近添加的ViewController添加“表视图”,如中所述 MyTableViewController的代码如清单2所示 现在来谈谈我的问题。 该表及其内容如下所示。 但是,如果我选择表中的一项并按下此子视

首先,我会给你一个简短的概述

我是

  • 创建新的cocoa项目
  • 定制AppDelegate(请参见清单1)
  • 将“自定义视图”添加到my MainMenu.xib
  • 在项目中创建一个新的Cocoa类(NSViewController+XIB),称之为MyTableViewController*
  • 向最近添加的ViewController添加“表视图”,如中所述
  • MyTableViewController的代码如清单2所示
  • 现在来谈谈我的问题。 该表及其内容如下所示。 但是,如果我选择表中的一项并按下此子视图上的按钮(连接到
    (iAction)action:(id)sender
    ),则输出中将显示
    (无索引)
    (请参阅:
    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
    
    //文件:AppDelegate.h
    #进口
    @类MyTableViewController;
    @接口AppDelegate:NSObject
    @属性(非原子,赋值)NSViewController*currentViewController;
    @属性(非原子,强)MyTableViewController*MyTableViewController;
    @属性(弱)IBMView*myview;
    @结束
    //文件:AppDelegate.m
    #导入“AppDelegate.h”
    #导入“MyTableViewController.h”
    @接口AppDelegate()
    @属性(弱)窗口*窗口;
    @结束
    @实现AppDelegate
    -(无效)ApplicationIDFinishLaunching:(NSNotification*)通知{
    [自动更改视图控制器];
    }
    -(无效)申请将终止:(NSNotification*)通知{
    //在此处插入代码以删除应用程序
    }
    -(BOOL)应用程序应在最后一个窗口关闭后终止:(n应用程序*)应用程序{
    返回YES;
    }
    -(无效)changeViewController
    {
    如果([self.currentViewController视图]!=nil){
    [[self.currentViewController视图]从SuperView移除];
    }
    开关(0){
    案例0:
    违约:
    if(self.myTableViewController==nil){
    _myTableViewController=[[myTableViewController alloc]initWithNibName:@“myTableViewController”捆绑包:nil];
    }
    self.currentViewController=self.myTableViewController;
    NSLog(@“EndView”);
    打破
    }
    [self.myview addSubview:[self.currentViewController视图]];
    [[self.currentViewController视图]设置帧:[self.myview边界]];
    [self.currentViewController setRepresentedObject:[NSNumber numberWithUnsignedInteger:[[self.currentViewController视图]子视图]计数]];
    [self-didChangeValueForKey:@“视图控制器”];
    NSLog(@“视图控制器已更改”);
    }
    @结束
    
    清单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
    
    //文件:MyTableViewController.h
    #进口
    @接口MyTableViewController:NSViewController
    @属性(弱)ibnstableview*tview;
    -(iAction)操作:(id)发送方;
    @结束
    //文件:MyTableViewController.m
    #导入“MyTableViewController.h”
    #导入“AppDelegate.h”
    @接口MyTableViewController()
    @结束
    @MyTableViewController的实现
    -(NSUTEGER)行数表格视图:(NSTableView*)表格视图OBJ{
    返回2;
    }
    -(id)tableView:(NSTableView*)tableView对象值for tableColumn:(NSTableColumn*)tableColumn行:(NSInteger)行{
    如果([tableView tableColumns][0]==tableColumn){
    返回@“bla”;
    }else if([tableView tableColumns][1]==tableColumn){
    返回@“blub”;
    }
    NSLog(@“通过表列标识符删除”);
    返回NULL;
    }
    -(iAction)操作:(id)发件人{
    //选定的列索引
    NSLog(@“%@,[self.tview selectedColumnIndexes]);
    }
    @结束
    

    一个类的两个实例(当您只希望/想要一个实例时)可能是由于没有意识到xib文件中的对象本身就是该类的实际自动生成实例而导致的

    您是否已将蓝色多维数据集拖到任何一个xib文件中,并将其类设置为视图控制器子类?如果你有,那么这将解释你看到的一个物体——苹果的机器为你创造它。第二个对象是您在
    changeViewController
    方法中以代码创建的对象

    我得到的印象是,您只是试图创建一个窗口,其中包含一个
    NSTableView
    ,该窗口反过来从您自己的
    NSViewController
    子类获取其数据。这是正确的吗?如果是这样,那么您应该删除第二个xib文件,而只使用在创建项目时为您创建的xib

    简言之
  • 将蓝色对象立方体拖动到Interface Builder dock中,并使用Identity Inspector将其子类设置为
    MyTableViewController
  • 选择view controller blue cube后,转到连接检查器并从
    视图
    选项拖动到表视图-必须确保拖动到的是表视图,而不是包含它的滚动视图或剪辑视图
  • 选择表视图(再次确保它确实是您选择的表视图),然后转到它的连接检查器。从
    数据源
    委派
    选项拖动到蓝色视图控制器多维数据集
  • 实施相关的数据整理方法
  • 提示:如果您不确定哪个检查器是哪个,请在Xcode中打开右侧边栏,然后从左侧文件查看器边栏中选择一个xib文件。将光标放在右侧边栏顶部的每个图标上,工具提示将告诉您哪个是哪个

    更新 识别特定对象的一个好方法是设置它们的
    标识符
    ,这有助于调试。在属性检查器中,这是还原ID。对
    NSTableView
    实例和
    NSTableColumn
    实例执行此操作。然后,在您的数据源方法中对它们进行一些日志记录-例如,作为此方法的第一个参数传递的表视图是否具有预期的
    标识符
    ,wh