在NSTextView中修改字符串内容在viewDidLoad方法下工作,但不在myMethod下

时间:2017-08-13 09:42:30

标签: objective-c

我正在尝试将连接到myViewController的NSTextView的内容更新为作为子类myViewController的文件所有者的引用插座。

当我从按钮使用IBAction或使用控制器的Stage方法时,我可以更新文本。但是,当我尝试从另一个类(在此示例中称为viewDidLoad)运行该方法时,它会运行该方法,但textview不会更改。

myViewController.h:

anotherViewController

myViewController.m:

#import <Cocoa/Cocoa.h>
#import "anotherViewController.h"


@interface myViewController : NSViewController { }
@property (unsafe_unretained) IBOutlet NSTextView *outText;
@property (weak) IBOutlet NSButton *updateMeButton;

- (void)updateTextView:(NSString *)argText;
- (void)updateTextViewWithoutArg;

@end

anotherViewController.m 中,有所有相关的导入,我称之为:

#import "myViewController.h"

@interface myViewController ()
@end

@implementation myViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.outText.string = @"I work successfully";
}   

- (IBAction)updateMeButton:(id)sender {
    self.outText.string = @"I am updated text!  I also work!";
}

- (void)updateTextView:(NSString *)argText {
    self.outText.string = @"I don't make it to the NSTextView :(";
    NSLog(@"Should have updated text view");
}

- (void)updateTextViewWithoutArg {
    self.outText.string = @"I don't make it to the NSTextView :(";
    NSLog(@"Should have updated text view");
}

@end

什么都没发生。该方法运行并记录它应该已更新,但没有文本更新。我尝试了很多不同的方法,包括textstorage和scrollrange方法,它们都在已经工作的部分工作,但是在不工作的部分没有区别。

我也尝试过只是为了好玩:

myViewController *viewtask = [[myViewController alloc] init];
[viewtask updateTextViewWithoutArg];
  • 还使用实例变量myViewController *viewtask; [viewtask updateTextViewWithoutArg];
  • 还使用_outText
  • 还使用[self.outText setString:@"string"];

同样,它们可以工作,但仅限于已经在工作的部分。

这应该很简单,但对我来说不合逻辑。在swift,我需要做的就是  [_outText setString:@"string"];

2 个答案:

答案 0 :(得分:1)

您在Interface Builder中创建的视图是懒惰创建的,因此如果您在调用viewDidLoad之前访问它们,则它们为nil

如果您的情况,请致电

 myViewController *viewtask = [[myViewController alloc] init];

不会导致创建视图,因此在您调用

[viewtask updateTextViewWithoutArg];

self.outTextnil

您可以通过更新代码来了解这是发生的事情:

- (void)updateTextView:(NSString *)argText {
    NSAssert(self.outText != nil, @"self.outText must not be nil");
    self.outText.string = @"I don't make it to the NSTextView :(";
    NSLog(@"Should have updated text view");
}

你应该看到断言。

答案 1 :(得分:0)

我似乎通过使myViewController成为单身类并使用sharedInstance找到了解决方案。对于这个特殊应用程序,myViewController是一个调试输出窗口,永远不需要放在另一个视图中。

我不会接受这个答案,因为这不是我确定的最好的答案。 可能仍然存在正确的解决方案,允许查找适用的myViewController实例,并修改附加到其上的outText属性。使用这个单例使得子类繁琐,因为如果我想能够解决10个视图控制器的问题,我必须为每个实例创建一个新类。

无论如何 - 我能够满足我的简单要求的方式:

<强> myViewController.h:

#import <Cocoa/Cocoa.h>
#import "anotherViewController.h"


@interface myViewController : NSViewController { }
@property (unsafe_unretained) IBOutlet NSTextView *outText;
@property (weak) IBOutlet NSButton *updateMeButton;

- (void)updateTextView:(NSString *)argText;
- (void)updateTextViewWithoutArg;

+ (id)sharedInstance;
@end

<强> myViewController.m:

#import "myViewController.h"

@interface myViewController ()
@end

@implementation myViewController

static myViewController *sharedInstance = nil;

+ (myViewController *)sharedInstance {
    static myViewController *sharedInstance = nil;
    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{
        sharedInstance = [[myViewController alloc] init];
    });
    return sharedInstance;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    sharedInstance = self;  
}

- (void)viewDidUnload {
    sharedInstance = nil;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    self.outText.string = @"I work successfully";
}   

- (IBAction)updateMeButton:(id)sender {
    sharedInstance.outText.string = @"Button Pressed";
}

- (void)updateTextView:(NSString *)argText {
    sharedInstance.outText.string = argText;
}

- (void)updateTextViewWithoutArg {
    sharedInstance.outText.string = @"I make it to the TextView now";
}

@end

现在,当我在 anotherViewController.m 中使用此代码时,它会更新正确的实例:

[myViewController.sharedInstance updateTextView:@"Updating with this string"];