无法从文档 class 中的标签更改字符串值(基于文档的应用程序,Mac)
Can't change stringValue from label in Document class (Document based application, Mac)
我正在创建一个 'test' 基于文档的应用程序以了解有关它们如何工作的更多信息。我想加载一个我之前保存的数组。
- (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError
{
NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSArray *array = [string componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
documentTitle.stringValue = [array objectAtIndex:0];
// For testing
NSLog(@"%@", array);
}
我加载了文件并获取了数据。我将数据转换为 NSString。该文件有多行,每一行都有自己的值。第一行是文档标题。所以我创建了一个 NSArray,将每一行分别放在数组中。然后我将文档的第一行设置为 documentTitle 标签。出于测试目的,我也创建了一个 NSLog 函数。它必须记录数组。
问题是当我 运行 代码时,它根本没有做任何事情。 documentTitle.stringValue 没有改变。但奇怪的是它确实记录了数组:
2015-09-22 16:57:40.098 DocBased Test[10765:277445]
(
"The awesome title!",
"This is a document!"
)
我在 Document.h 中这样声明文档标题:
#import <Cocoa/Cocoa.h>
@interface Document : NSDocument
{
IBOutlet NSTextField *documentTitle;
}
@end
如果您需要查看 Xcode 中的项目,这里是 link:The link。
有谁知道如何更改 Document class 中 documentTitle(或任何)标签的字符串值?
幸运的是这是一个常见问题:)
确定包含您的 NSTextView
的 .xib 文件。比如说它叫做 MyViewController.xib
。
在 Interface Builder 中,打开 Utilities 面板(右侧面板,按钮位于右上角)。在实用程序面板的底部,单击带有正方形的圆圈图标,然后搜索 "Object"
现在单击 Object
并将其拖动到左侧(文档大纲)中 "Placeholders" 部分下方。
这将创建一个名为 "Objects" 的新部分。
在文档大纲中单击您的新对象。
现在回到实用程序面板,转到 "Identity Inspector"
将 "Class" 更改为 Document
现在转到“实用程序”面板中的 "Connections Inspector"。
Document
的 (IB) 网点应该出现在这里,它们看起来像这样:
除了 "nextKeyView" 你会看到 documentTitle
单击并拖动出口右侧的圆圈,然后在您想要成为 documentTitle
的 NSTextField
上方松开。
现在让我们谈谈将要发生的事情。
- 首先,您将使用如下方法实例化您的
MyViewController
initWithNibName:...
- 请注意,支持
MyViewController.xib
的 nib
尚未加载(这称为延迟加载)
- 当您尝试访问
NSViewController
的 view
属性 时,它会加载与其关联的笔尖
- nib加载完成,里面的对象全部实例化
init
方法都在这些对象中的每一个上调用
- 出口连接现已建立,包括您与
Document
对象的连接到您的 NSTextView
-awakeFromNib
发送到所有通过 nib 实例化的对象
此时,您的 属性 documentTitle
现在正在引用一个有效的 NSTextField
对象,不再是 nil
。您现在可以设置
stringValue
随便你
希望对您有所帮助!
给定你的项目@https://www.mediafire.com/?z6drw20suvt0re0,
我能够让它工作。写一个新答案,因为我的原件已经非常笨重,更适合一般情况;而这个答案将非常具体地针对您的代码
只有几处变化:
1) 因为你的 Document.xib 的所有者是 Document
,所以你不需要将文档 Object 拖到你的文档大纲中。所以我删除了那个。
2) 我 select 编辑了文件的所有者(文档),并设置了与您的 NSTextField 的连接 属性
3)我删除了ivar
@interface Document : NSDocument
{
IBOutlet NSTextField *documentTitle;
}
所以你的 header 现在看起来像这样:
@interface Document : NSDocument
@end
4) 我在你的实现文件 (Document.m) 中创建了 属性 以及 NSString
属性(我稍后会解释)
@property NSString *titleString;
@property IBOutlet NSTextField *documentTitle;
5) 因此,如果您继续覆盖 -awakeFromNib
方法(只需在其中放置一个 NSLog
或其他内容),您将看到实际上正在调用 -awakeFromNib
在 -readFromData
之后。现在请记住我所说的—— object 已实例化,但在加载视图并发送 -awakeFromNib
消息之前不会建立连接。
那么会发生什么:
- 您单击 "Open" 和 select 一个文件
- 您的
Document
已实例化
-readData...
在实例化期间立即被调用,但尚未建立与 NSTextField
的连接,因此它是 nil
调用 -awakeFromNib
,并建立从 Document
到任何 NSView
(包括您的 NSTextField
)的连接
- 但为时已晚。
所以解决方法很简单,
在 -readData
方法中,而不是设置你的 NSTextField
的 stringValue
,你应该只将你读取的字符串保存到 NSString
属性 (我提到的早些时候)
然后当您的 -awakeFromNib
被调用时,您可以访问 NSString
属性 以获得您想要的值,然后设置 stringValue
。
以下是更改的两种方法:
-(void)awakeFromNib
{
if( self.titleString )
{
[self.documentTitle setStringValue:self.titleString];
}
}
- (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError {
// Insert code here to read your document from the given data of the specified type. If outError != NULL, ensure that you create and set an appropriate error when returning NO.
// You can also choose to override -readFromFileWrapper:ofType:error: or -readFromURL:ofType:error: instead.
// If you override either of these, you should also override -isEntireFileLoaded to return NO if the contents are lazily loaded.
NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSArray *array = [string componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
NSLog(@"\r%@", array);
self.titleString = [array objectAtIndex:1];
return YES;
}
如果您想在任何地方获得更多解释,请告诉我,但这对您有用:)
我正在创建一个 'test' 基于文档的应用程序以了解有关它们如何工作的更多信息。我想加载一个我之前保存的数组。
- (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError
{
NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSArray *array = [string componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
documentTitle.stringValue = [array objectAtIndex:0];
// For testing
NSLog(@"%@", array);
}
我加载了文件并获取了数据。我将数据转换为 NSString。该文件有多行,每一行都有自己的值。第一行是文档标题。所以我创建了一个 NSArray,将每一行分别放在数组中。然后我将文档的第一行设置为 documentTitle 标签。出于测试目的,我也创建了一个 NSLog 函数。它必须记录数组。
问题是当我 运行 代码时,它根本没有做任何事情。 documentTitle.stringValue 没有改变。但奇怪的是它确实记录了数组:
2015-09-22 16:57:40.098 DocBased Test[10765:277445]
(
"The awesome title!",
"This is a document!"
)
我在 Document.h 中这样声明文档标题:
#import <Cocoa/Cocoa.h>
@interface Document : NSDocument
{
IBOutlet NSTextField *documentTitle;
}
@end
如果您需要查看 Xcode 中的项目,这里是 link:The link。
有谁知道如何更改 Document class 中 documentTitle(或任何)标签的字符串值?
幸运的是这是一个常见问题:)
确定包含您的 NSTextView
的 .xib 文件。比如说它叫做 MyViewController.xib
。
在 Interface Builder 中,打开 Utilities 面板(右侧面板,按钮位于右上角)。在实用程序面板的底部,单击带有正方形的圆圈图标,然后搜索 "Object"
现在单击 Object
并将其拖动到左侧(文档大纲)中 "Placeholders" 部分下方。
这将创建一个名为 "Objects" 的新部分。
在文档大纲中单击您的新对象。 现在回到实用程序面板,转到 "Identity Inspector"
将 "Class" 更改为 Document
现在转到“实用程序”面板中的 "Connections Inspector"。
Document
的 (IB) 网点应该出现在这里,它们看起来像这样:
除了 "nextKeyView" 你会看到 documentTitle
单击并拖动出口右侧的圆圈,然后在您想要成为 documentTitle
的 NSTextField
上方松开。
现在让我们谈谈将要发生的事情。
- 首先,您将使用如下方法实例化您的
MyViewController
initWithNibName:...
- 请注意,支持
MyViewController.xib
的nib
尚未加载(这称为延迟加载) - 当您尝试访问
NSViewController
的view
属性 时,它会加载与其关联的笔尖 - nib加载完成,里面的对象全部实例化
init
方法都在这些对象中的每一个上调用- 出口连接现已建立,包括您与
Document
对象的连接到您的NSTextView
-awakeFromNib
发送到所有通过 nib 实例化的对象
此时,您的 属性 documentTitle
现在正在引用一个有效的 NSTextField
对象,不再是 nil
。您现在可以设置
stringValue
随便你
希望对您有所帮助!
给定你的项目@https://www.mediafire.com/?z6drw20suvt0re0,
我能够让它工作。写一个新答案,因为我的原件已经非常笨重,更适合一般情况;而这个答案将非常具体地针对您的代码
只有几处变化:
1) 因为你的 Document.xib 的所有者是 Document
,所以你不需要将文档 Object 拖到你的文档大纲中。所以我删除了那个。
2) 我 select 编辑了文件的所有者(文档),并设置了与您的 NSTextField 的连接 属性
3)我删除了ivar
@interface Document : NSDocument
{
IBOutlet NSTextField *documentTitle;
}
所以你的 header 现在看起来像这样:
@interface Document : NSDocument
@end
4) 我在你的实现文件 (Document.m) 中创建了 属性 以及 NSString
属性(我稍后会解释)
@property NSString *titleString;
@property IBOutlet NSTextField *documentTitle;
5) 因此,如果您继续覆盖 -awakeFromNib
方法(只需在其中放置一个 NSLog
或其他内容),您将看到实际上正在调用 -awakeFromNib
在 -readFromData
之后。现在请记住我所说的—— object 已实例化,但在加载视图并发送 -awakeFromNib
消息之前不会建立连接。
那么会发生什么:
- 您单击 "Open" 和 select 一个文件
- 您的
Document
已实例化 -readData...
在实例化期间立即被调用,但尚未建立与NSTextField
的连接,因此它是nil
调用 -awakeFromNib
,并建立从Document
到任何NSView
(包括您的NSTextField
)的连接- 但为时已晚。
所以解决方法很简单,
在 -readData
方法中,而不是设置你的 NSTextField
的 stringValue
,你应该只将你读取的字符串保存到 NSString
属性 (我提到的早些时候)
然后当您的 -awakeFromNib
被调用时,您可以访问 NSString
属性 以获得您想要的值,然后设置 stringValue
。
以下是更改的两种方法:
-(void)awakeFromNib
{
if( self.titleString )
{
[self.documentTitle setStringValue:self.titleString];
}
}
- (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError {
// Insert code here to read your document from the given data of the specified type. If outError != NULL, ensure that you create and set an appropriate error when returning NO.
// You can also choose to override -readFromFileWrapper:ofType:error: or -readFromURL:ofType:error: instead.
// If you override either of these, you should also override -isEntireFileLoaded to return NO if the contents are lazily loaded.
NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSArray *array = [string componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
NSLog(@"\r%@", array);
self.titleString = [array objectAtIndex:1];
return YES;
}
如果您想在任何地方获得更多解释,请告诉我,但这对您有用:)