zoukankan      html  css  js  c++  java
  • 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

    程序运行界面例如以下:


    我们还能够设置私有存档文件的图标以及扩展名,例如以下图:



  • 相关阅读:
    java XML
    异常
    String、StringBuffer、StringBuilder区别
    java面试测试题
    多态
    如何用模板渲染后台返回不确定的data
    +new Date()是什么意思?
    nodejs使用技巧
    jquery拖拽(最浅显易懂的分析)
    z-index在子节点设置得很大却不生效?
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/4483008.html
Copyright © 2011-2022 走看看