【问题标题】:Modifying string content in NSTextView works under viewDidLoad method, but not under myMethod在 NSTextView 中修改字符串内容在 viewDidLoad 方法下有效,但在 myMethod 下无效
【发布时间】:2017-08-13 09:42:29
【问题描述】:

我正在尝试更新连接到 myViewController 的 NSTextView 的内容,作为文件所有者的引用出口,该文件所有者是 myViewController 的子类。

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

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;

@end

myViewController.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

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

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

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

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

myViewController *viewtask;
[viewtask updateTextViewWithoutArg];
  • 同样使用实例变量_outText
  • 也使用[self.outText setString:@"string"];
  • 也使用[_outText setString:@"string"];

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

这应该很简单,但对我来说不合逻辑。我需要做的就是迅速 self.outText.string = "I update whenever I'm called!"

【问题讨论】:

标签: objective-c


【解决方案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");
}

您应该会看到断言触发。

【讨论】:

  • 感谢您的信息。在我的情况下,首先创建视图(这是一个调试输出窗口)(通过“显示”segue),然后我将通过单击 其他视图。你知道如何向已经创建的视图发送消息吗?
  • 如果无法查看所有涉及的代码,很难给出具体的答案,但主要有两种方式:(1)在创建调试视图控制器时,您可以获得指向它的指针在prepareForSegue 中使用[segue destinationViewController] 以获得更松散耦合的解决方案(2)使用NSNotificationCenter。既然你提到你可能想从许多视图控制器(2)访问它可能是要走的路。
【解决方案2】:

我似乎通过将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"];

【讨论】:

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