obj-c编程15[Cocoa实例03]:MVC以及归档化演示样例
前面的博文里介绍了归档和解档,这里我们把它实际应用到一个简单的代码中去,将它作为一个多文档应用程序的打开和保存的背后支持。另外这里介绍一下MVC思想,这个在不论什么语言里都会有,它是一种设计思想,主要能够概括为一个程序由3部分组成:
1 模式:是程序的数据支持;
2 视图:是程序的表示支持;
3 控制:连接模式和视图,将程序构为一个总体;
Cocoa框架中对MVC提供了非常好的支持,你仅仅须要写非常少的代码就能够完毕一个程序的MVC绑定了。以下的样例中,我生成一个基于多文档的程序,使用了NSArrayController类作为控制器,它的数据源为NSArray,当中每个元素由我定义的类Person来描写叙述;主窗体中的tab_view作为主类中的outlets,主类为Document,它派生自NSDocument用来支持多文档中的每个文档窗体。
加入add和removebutton,都与NSArrayController中的add和remove方法绑定;tab_view控件的两列分别与Person类中的2个属性绑定,每一行自然是Person数组中的每个Person对象了。这样每个视图中的数据表示(tab_view)通过控制器与模式相连,视图内容的改变(通过add和removebutton)也通过控制器从而导致模式数据的改变;而模式自身的改变(通过读档操作)也会更新视图的显示哦。这样保证了视图和模式的独立性:模式能够在其它视图上显示,而视图也能够绑定其它的模式。
最后,利用归档化实现了程序的save和open功能,也基本没写几行代码,并且save后的文件也自己主动与我们的程序绑定起来,假设双击该文件,会自己主动用我们的app打开哦,真是十分的方便。详细请看代码:
//
// Document.h
// mac_doc
//
// Created by kinds on 14-7-7.
// Copyright (c) 2014年 kinds. All rights reserved.
// #import <Cocoa/Cocoa.h> @interface Document : NSDocument{
IBOutlet NSTableView *tab_view;
NSMutableArray *persons;
} -(void)setPersons:(NSMutableArray *)ary; @end
//
// Document.m
// mac_doc
//
// Created by kinds on 14-7-7.
// Copyright (c) 2014年 kinds. All rights reserved.
// #import "Document.h" @interface Document () @end @implementation Document - (instancetype)init {
self = [super init];
if (self) {
// Add your subclass-specific initialization here.
persons = [[NSMutableArray alloc]init];
}
return self;
} -(void)setPersons:(NSMutableArray *)ary{
if(ary == persons) return;
persons = ary;
} - (void)windowControllerDidLoadNib:(NSWindowController *)aController {
[super windowControllerDidLoadNib:aController]; // Add any code here that needs to be executed once the windowController has loaded the document's window. } + (BOOL)autosavesInPlace {
return YES;
} - (NSString *)windowNibName {
// Override returning the nib file name of the document
// If you need to use a subclass of NSWindowController or if your document supports multiple NSWindowControllers, you should remove this method and override -makeWindowControllers instead.
return @"Document";
} - (NSData *)dataOfType:(NSString *)name error:(NSError **)out_err {
// Insert code here to write your document to data of the specified type. If outError != NULL, ensure that you create and set an appropriate error when returning nil.
// You can also choose to override -fileWrapperOfType:error:, -writeToURL:ofType:error:, or -writeToURL:ofType:forSaveOperation:originalContentsURL:error: instead.
[[tab_view window] endEditingFor:nil];
return [NSKeyedArchiver archivedDataWithRootObject:persons];
} - (BOOL)readFromData:(NSData *)data ofType:(NSString *)name \
error:(NSError **)out_err {
// 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.
NSMutableArray *new_ary = nil;
@try{
new_ary = [NSKeyedUnarchiver unarchiveObjectWithData:data];
}@catch(NSException *e){
NSLog(@"exception = %@",e);
if(out_err){
NSDictionary *d = [NSDictionary dictionaryWithObject:\
@"data is corrupted!" \
forKey:NSLocalizedFailureReasonErrorKey];
*out_err = [NSError errorWithDomain:NSOSStatusErrorDomain \
code:unimpErr userInfo:d];
}
return NO;
}
[self setPersons:new_ary];
return YES;
} @end
//
// Person.h
// mac_doc
//
// Created by kinds on 14-7-7.
// Copyright (c) 2014年 kinds. All rights reserved.
// #import <Foundation/Foundation.h> @interface Person : NSObject <NSCoding>{
NSString *name;
float exp_raise;
} @property(readwrite,copy)NSString *name;
@property(readwrite)float exp_raise; @end
//
// Person.m
// mac_doc
//
// Created by kinds on 14-7-7.
// Copyright (c) 2014年 kinds. All rights reserved.
// #import "Person.h" @implementation Person @synthesize name,exp_raise; -(id)initWithCoder:(NSCoder *)coder{
self = [super init];
if(self){
name = [coder decodeObjectForKey:@"name"];
exp_raise = [coder decodeFloatForKey:@"exp_raise"];
}
return self;
} -(void)encodeWithCoder:(NSCoder *)coder{
[coder encodeObject:name forKey:@"name"];
[coder encodeFloat:exp_raise forKey:@"exp_raise"];
} -(id)init{
self = [super init];
if(self){
exp_raise = 0.05;
name = @"no_name";
}
return self;
} -(void)setNilValueForKey:(NSString *)key{
if([key isEqualToString:@"exp_raise"])
self.exp_raise = 0.0;
else
[super setNilValueForKey:key];
} @end
程序运行界面例如以下:
我们还能够设置私有存档文件的图标以及扩展名,例如以下图:
obj-c编程15[Cocoa实例03]:MVC以及归档化演示样例的更多相关文章
- obj-c编程15[Cocoa实例03]:MVC以及归档化示例
前面的博文里介绍了归档和解档,这里我们把它实际应用到一个简单的代码中去,将它作为一个多文档应用程序的打开和保存的背后支持.另外这里介绍一下MVC思想,这个在任何语言里都会有,它是一种设计思想,主要可以 ...
- [原创]obj-c编程15[Cocoa实例02]:KVC和KVO的实际运用
原文链接:obj-c编程15[Cocoa实例02]:KVC和KVO的实际运用 我们在第16和第17篇中分别介绍了obj-c的KVC与KVO特性,当时举的例子比较fun,太抽象,貌似和实际不沾边哦.那么 ...
- 【UNIX网络编程(三)】TCP客户/server程序演示样例
上一节给出了TCP网络编程的函数.这一节使用那些基本函数编写一个完毕的TCP客户/server程序演示样例. 该样例运行的过程例如以下: 1.客户从标准输入读入一行文本,并写给server. 2.se ...
- obj-c编程15[Cocoa实例01]:一个会发声的随机数生成器
哇!终于到了obj-c编程系列的第15篇喽,一路走过来满不容易的哦!(怎么个意思,这才哪到哪啊!),为了能够更好的练习obj-c在Cocoa框架上的编程,接下来会以N篇Cocoa实例的博文来巩固和记忆 ...
- obj-c编程15[Cocoa实例02]:KVC和KVO的实际运用
我们在第16和第17篇中分别介绍了obj-c的KVC与KVO特性,当时举的例子比较fun,太抽象,貌似和实际不沾边哦.那么下面我们就用一个实际中的例子来看看KVC与KVO是如何运用的吧. 该例中用到了 ...
- obj-c编程15[Cocoa实例04]:基于Core Data的多文档程序示例[未完待续]
上一个例子我们使用的模式数据实际上是基于一个Person数组,现在我们看一下如何使用Cocoa中的Core Data框架支持,几乎不用写一行代码,完成模式数据的建立. 我们这里模式的元素使用的是Car ...
- MVC模式编程演示样例-登录验证(静态)
好,上篇博客分享了本人总结的JSP-Servlet-JavaBean三层架构编程模式的实现思想和基本流程,接下来给大家分享一个MVC编程模式的实现演示样例-登录验证的过程,这里我仍然用的是静态的验证u ...
- Android中MVP模式与MVC模式比較(含演示样例)
原文链接 http://sparkyuan.me/ 转载请注明出处 MVP 介绍 MVP模式(Model-View-Presenter)是MVC模式的一个衍生. 主要目的是为了解耦,使项目易于维护. ...
- C编程规范, 演示样例代码。
/*************************************************************** *Copyright (c) 2014,TianYuan *All r ...
随机推荐
- SQLServer2008-2012资源及性能监控—CPU使用率监控具体解释
前言: CPU是server中最重要的资源.在数据库server中,CPU的使用情况应该时刻监控以便SQLServer一直处于最佳状态. 本文将会使用可靠性和性能监视器来获取CPU相关的使用统计信息 ...
- Linux在什么样的从脚本文件数据库sh格式改变sql格式
在软件开发过程中,经常参与Linux从下一个脚本文件数据库sh格式改变sql格式问题.在本文中,一个实际的脚本文件,例如.描述格式转换过程. 1. sh文件内容 本文中的文件名称为exa ...
- bootstrap使用汇总
//大多数功能都能够指定data属性来指定 但是,有必要的情况下使用jquery由于事件是不同的过程 //活动通常有两种状态show shown 通用和过去的 <!DOCTYPE html> ...
- CVE-2014-4113:飓风熊猫(HURRICANE PANDA)Win64bit提起权0day破绽
飓风熊猫被觉得是原产于中国.主要针对基础设施公司的先进攻击者.我们知道它们除了拥有0day漏洞外.还有其它的三种本地特权提升漏洞.我们知道飓风熊猫使用的是"ChinaChopper" ...
- BizTalk开发小技巧
BizTalk开发小技巧 随笔分类 - Biztalk Biztalk 使用BizTalk实现RosettaNet B2B So Easy 摘要: 使用BizTalk实现RosettaNet B2B ...
- android adb 不同的方式使用特定的解释
本文介绍windows 在程序中使用adb 方法.没有引进adb 该命令. 1) 启动adb 流程.获得输出从管道. 这样的方式的弊端有多少,我也不知道.反正就是各种问题吧.可是眼下我问过非常多朋友. ...
- poj3414--Pots(bfs,记录路径)
Pots Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 10149 Accepted: 4275 Special J ...
- 它们的定义TextView使之具有跑马灯的效果
一.引入问题 使用通用textview快乐效应,焦点事件不启动滚动,button目前的焦点事件,但丑,因此,需要定制TextView 天生焦点 个textview FocusedTextView.ja ...
- 最大流量dinci模板
我们知道.增广路径EK时间是在充电算法的O(n*m^2).找到最短增广路径的时间复杂度为O(m*n^2).这样的时间复杂度主要是寻找扩充道路. 这里也有一个演示Dinci算法,使用BFS层次结构图,然 ...
- oracle connect by 说明
Oracle能够通过START WITH . . . CONNECT BY . . .子句来实现SQL分层查询,这递归查询 例如: select level||'月' 月份 from dual con ...