对于我当前的项目,我想实现一个与 Apple Preview 应用程序非常相似的用户界面 - 左侧有一个 PDF 文件列表,右侧有一个大的 UI 部分,用于显示当前选定的文档:
(理想情况下,左侧的文件列表将显示缩略图而不是文件名,但这是稍后的事。)
关于我的背景,我在 C++ 和 Qt 方面拥有丰富的经验,但在 Objective C 和 XCode 方面我完全是新手。我正在 Mac OS X 10.8.5 和 XCode 5.1.1(这是 Mountain Lion 上的最新版本)下工作。
我已经建立了一个 XCode 项目,引入了通常的 Core Data元素( NSPersistentStoreCoordinator 、 NSManagedObjectModel 和 NSManagedObjectContext ),我自己添加并连接了文件列表和 PDF View :
@interface AppDelegate : NSObject <NSApplicationDelegate>
@property (assign) IBOutlet NSWindow *window;
@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
@property (weak) IBOutlet NSScrollView *fileList;
@property (weak) IBOutlet PDFView *pdfView;
(IBAction)saveAction:(id)sender;
@end
显示文件列表的UI元素实际上是一个NSTableView仅一列且没有标题。 (不确定 fileList
属性是否真的应该是 NSScrollView ,但这似乎是添加 socket 时弹出窗口中的唯一选项。)
到目前为止我所取得的成就如下:
- 在 PDF View 中显示 PDF 文档(带有硬编码路径),代码如下
NSString *path = @"/POSIX/path/to/sample/PDF/document.pdf"; NSURL *url = [NSURL fileURLWithPath: path]; PDFDocument *pdfDoc = [[PDFDocument alloc] initWithURL: url]; self.pdfView.document = pdfDoc;
- 设置我的核心数据模型:其中最相关的实体是
Document
有一个filename
属性。我想表格 View 应该显示这些列表。 - 我还生成了 NSManagedObject数据模型中每个实体的子类,但我还没有使用它们,因为我不知道如何处理它们:o)
- 扫描(硬编码)工作文件夹中的 PDF 文档,按谓词进行过滤,并使用文件名填充(或更新)我的核心数据模型 - 即使只有一个提取请求:-)。数据自动保存在
~/Library/Application Support/<organization>.<application>/<application>.storedata
.
(目前,大部分功能都捆绑在 [AppDelegate applicationDidFinishLaunching]
方法中。)
所以现在,我觉得我已经具备了大部分所需的功能,但我只是没有看到这一切如何协同工作的大局。
我的问题:
- 如何使 TableView 显示存储在我的核心数据模型中的文件列表?
目前,应用程序委托(delegate)设置为 TableView 数据源和委托(delegate),因此根据我的理解,它必须实现一些“数据源协议(protocol)”(?!?)(并且“protocol ”似乎类似于一个接口(interface),只是没有一个类来捆绑它们?!?) - 如何使 PDF View 显示文件列表中选定的文档?
我有一种感觉,需要通知某个实例(应用程序委托(delegate)?)用户选择了不同的文件,然后使 PDF View 显示该文件... - NSFetchedResultsController 会怎样?在这里发挥作用?
我认为它也可以用作 TableView 数据源,只有当核心数据模型发生任何变化时才会通知它,因此可以自动更新 TableView ,例如列表中的文件消失了?!?
正如您可能会说的那样,我对代表、协议(protocol)等的了解有限。因此,如果有人能够告诉我主要参与者是什么以及谁与谁有联系并获得通知或更新,我将不胜感激或其他什么。
我显然已经在线进行了尽职调查,除了官方 Apple 文档之外,这些页面特别有用:
- http://www.objc.io/issue-4/full-core-data-application.html
- http://www.raywenderlich.com/934/core-data-tutorial-for-ios-getting-started
- http://code.tutsplus.com/tutorials/iphone-core-data--mobile-752
但现在大多数在线资源(包括 SO)都集中在 iOS 或最近的 Swift 上,虽然我知道它们有很多相似之处,但我没有任何 Storyboard、主/详细 View Controller 或 segues 以及所有这些让我更加困惑。
我觉得我已经很接近了。有人可以帮我吗?
最佳答案
这是多种可能的方法中的一种。创建 NSViewController 的子类来管理主视图的每个部分。例如,我的一个应用程序有一个类来管理类似的列表:
@interface SongsController : NSViewController <NSTableViewDataSource, NSTableViewDelegate, NSDraggingSource>
我在 MainMenu.xib
中创建了一个实例,并将其连接为我的应用程序委托(delegate)的强大属性。它有自己的 .xib 用于设计其细节。然后在 applicationDidFinishLaunching:
中有代码:
[self.mainView addSubview:[self.songsController view]];
(mainView
是我的主 NSWindow
内分割 View 的占位符 subview 。我喜欢 NSSplitView
因为我通常希望将各个部分是可调整的。)这让我可以将与列表管理有关的任何内容移出应用程序委托(delegate)。
我倾向于将数据处理部分移到它们自己的类中,一个处理所有 CoreData 内容的单例,另一个通过将“业务逻辑”应用于 CoreData 信息来提供数据模型。
在这种情况下,我的数据模型没有使用NSFetchedResultsController
,因为我对列表中可能显示的内容有很多过滤器,因此我自己进行获取以进行刷新似乎更简单。
这意味着在列表中选择不同的项目可以归结为:
- (void)tableViewSelectionDidChange:(NSNotification *)aNotification {
NSTableView *view = [aNotification object];
NSInteger row = [view selectedRow];
Song *s = [DATA_MODEL songAtRow:row];
[[NSNotificationCenter defaultCenter] postNotificationName:mSongChanged object:s];
}
主视图右侧的构造和连接有些相同。它会监听 mSongChanged
通知,并在通知到达时更新其显示的内容。
这并不能回答您所有的问题,但也许它会让您获得一个不那么困惑的结构。
关于objective-c - 核心数据&TableView&PDFView : How does it all come together?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27999960/