感觉这两个概念有点朦胧,为了学习路线的完整性,这里浅浅地学习下,不懂的以后实践再去想懂~


1.复制对象

Foundation类实现了名为copy和mutableCopy的方法 可以用这些方法来创建对象的副本。

代码实例:

 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];//NSLog(@"1326");NSMutableArray *dArray = [NSMutableArray arrayWithObjects:@"a",@"b",@"c",@"d",nil];NSMutableArray *dArray2 ;dArray2 = dArray;[dArray2 removeObjectAtIndex:0];NSLog(@"dArray:");for(NSString *elem in dArray){NSLog(@"%@",elem);}NSLog(@"dArray2:");for(NSString *elem2 in dArray2){NSLog(@"%@",elem2);}dArray2 = [dataArray mutableCopy];[dArray2 removeObjectAtIndex:0];NSLog(@"dArray:");for(NSString *elem in dArray){NSLog(@"%@",elem);}NSLog(@"dArray2:");for(NSString *elem2 in dArray2){NSLog(@"%@",elem2);}[pool drain];

在win下的开发环境编译出错,这个错误暂时没解决,代码逻辑上是没错的,有时间再xcode下去跑一遍,

结果是:赋值的数组传的是指针引用 remove后 双方原先的索引0的字符串没有了,而赋值的数组将是以对象的形式存在于dArray2,删除索引0而不影响到原数组。

此外还可以通过实现<NSCopying>及<NSMutableCopying>协议来实现复制对象。

如:@interface F:NSObject<NSCopying> 你们F.m中就必须添加方法 -(id) copyWith:(NSzone*) zone{...}

还可以用复制方法和取值方法复制对象:只要实现复制方法或是取值方法,都应考虑变量中存储的内容、要检索的内容以及时候需要保护这些值。

-(void) setName:(NSString *)theName
{
name = [theName copy];
}
//当然,要使赋值方法的内存管理更友好一些,首先应该释放旧的值
-(void) setName:(NSString *)theName
{
[name autorelease];
name = [theName copy];
}
//property声明
@property (nonatomic,copy) NSString *name;
//会生成一个合并的方法,其类型类似于:
-(void) setName :(NSString *) theName
{if(theName!=name){[name = release];name = [theName copy];
}
这里使用nonatomic(默认是atomic)是为了告诉系统不要使用mutex(互斥)锁定保护属性存取器方法
这种方法会在设置新值时释放变量的旧值,确保旧的值不会被销毁。
如果在多线程环境中运行,需要考虑使用atomic存取器方法。

简单总结就是赋值的实例变量实际是原变量的引用,而复制的对象变量是它的完整副本。

2.归档

归档是指用某种个性来保存一个或多个对象,以便以后还原这些对象的过程。(类似序列化~)

2.1使用XML属性列表进行归档 以key -value键值对写入文件

  NSDictionary *glossary=[NSDictionary dictionaryWithObjectsAndKeys: @"a",@"aaa",@"b",@"bbb",@"c",@"ccc",nil];if([glossary writeToFile:@"glossary"atomically:YES]==NO){NSLog(@"save failed!");}

atomically:YES这里是为字典写入文件创建一个glossary临时备份文件,若一旦成功将把数据转移到名为glossary的指定文件中。

在win开发环境下最后生成的程序文件不是XML文件这点等在xcode下再测一遍=.=

要将文件中的内容读入程序,可以用dictionaryWithContentsOfFile:或arrayWithContentsOfFile:方法。读回数据可使用dataWithContentsOfFile:,读回字符串对象可使用stringWithContentsOfFile:方法。

   NSDictionary *g;g= [NSDictionary dictionaryWithContentsOfFile :@"glossary"];for(NSString *k in g){NSLog(@"%@:%@",[g objectForKey:k]);}

2.2使用NSKeyedArchiver归档 以带键key的文档把对象存入文件中

在IPhone中使用归档功能必须使用NSKeyedArchiver<Foundation/NSKeyedArchiver.h>

   NSDictionary *glossary=[NSDictionary dictionaryWithObjectsAndKeys: @"aa",@"aaa",@"bb",@"bbb",@"cc",@"ccc",nil];[NSKeyedArchiver archiveRootObject:glossary toFile:@"glossary.archive"];

把字典对象归档到当前目录下,也可以通过NSKeyedUnarchiver的unArchiveObjectWithFile:方法把创建的归档读入程序中。

   NSDictionary *glossary;glossary=[NSKeyedUnarchiver unArchiveObjectWithFile:@"glossary.archive"];

在辉旭glossary后,程序可以通过枚举祺内容来验证恢复是否成功~

2.3编码和解码

通常自定义类对象不能直接归档,必须告知系统如何归档(或编码)你的对象,以及如何解归档(解码)它们。必须遵守<NSCoding>协议,在类定义中添加encodeWithCoder:方法和initWithCoder:方法以实现归档对象和恢复对象

在带键的档案中编码和解码基本数据类型:

编码方法

解码方法

encodeBool:forKey

decodeBool:forKey

encodeInt:forKey

decodeInt:forKey

encodeInt31:forKey

decodeInt32:forKey

encodeInt64:forKey

decodeInt64:forKey

encodeFloat:forKey

decodeFloat:forKey

encodeDouble:forKey

decodeDouble:forKey

对于基本的Objective-C类,可以使用
encodeObject:forKey:和decodeObjectforKey:编码和解
//基本的Objective-C类编码和解码示例:
//Addresscard.h Interface File
#import <Foundation/Foundation.h>
@interface AddressCard : NSObject<NSCopying,NSCoding> {
NSString *name;
NSString *email;
}
@property (nonatomic, copy) NSString *name, *email;
-(void) setName: (NSString *) theNameandEmail: (NSString *) theEmail;
-(void) retainName: (NSString *) theNameandEmail: (NSString *) theEmail;
-(NSComparisonResult) compareNames: (id) element;
-(void) print;
@end#import "AddressCard.h"
@implementation AddressCard
@synthesize name, email;
-(void) setName: (NSString *) theNameandEmail: (NSString *) theEmail
{
[self setName: theName];
[self setEmail: theEmail];
}
// Compare the two names from the specified address cards
-(NSComparisonResult) compareNames: (id) element
{
return [name compare: [element name]];
}
-(void) print
{
NSLog (@"====================================");
NSLog (@"| |");
NSLog (@"| %-31s |", [name UTF8String]);
NSLog (@"| %-31s |", [email UTF8String]);
NSLog (@"| |");
NSLog (@"| |");
NSLog (@"| |");
NSLog (@"| O O |");
NSLog (@"====================================");
}
-(AddressCard *) copyWithZone: (NSZone *) zone
{
AddressCard *newCard = [[AddressCardallocWithZone: zone] init];[newCardretainName: name andEmail: email];return newCard;
}
-(void) retainName: (NSString *) theNameandEmail: (NSString *) theEmail
{name = [theName retain];email = [theEmail retain];
}
-(void) encodeWithCoder: (NSCoder *) encoder
{[encoder encodeObject: name forKey: @"AddressCardName"];[encoder encodeObject: email forKey: @"AddressCardEmail"];
}
-(id) initWithCoder: (NSCoder *) decoder
{name = [[decoder decodeObjectForKey: @"AddressCardName"] retain];email = [[decoder decodeObjectForKey: @"AddressCardEmail"] retain];return self;
}
-(void) dealloc
{[name release];[email release];[super dealloc];
}
@end
#import "AddressCard.h"
@interface AddressBook: NSObject<NSCopying,NSCoding>
{
NSString *bookName;
NSMutableArray *book;
}
@property (nonatomic, copy) NSString *bookName;
@property (nonatomic, copy) NSMutableArray *book;
-(id) initWithName: (NSString *) name;
-(void) sort;
-(void) addCard: (AddressCard *) theCard;
-(void) removeCard: (AddressCard *) theCard;
-(int) entries;
-(void) list;
-(AddressCard *) lookup: (NSString *) theName;
-(void) dealloc;
@end#import "AddressBook.h"
@implementation AddressBook
@synthesize book, bookName;
// set up the AddressBook’s name and an empty book
-(id) initWithName: (NSString *) name{
self = [super init];
if (self) {
bookName = [[NSStringalloc] initWithString: name];
book = [[NSMutableArrayalloc] init];
}
return self;
}
-(void) sort
{
[book sortUsingSelector: @selector(compareNames:)];
}
-(void) addCard: (AddressCard *) theCard
{
[book addObject: theCard];
}
-(void) removeCard: (AddressCard *) theCard
{
[book removeObjectIdenticalTo: theCard];
}
-(int) entries
{
return [book count];
}
-(void) list
{
NSLog (@"======== Contents of: %@ =========", bookName);
for ( AddressCard *theCard in book )
NSLog (@"%-20s %-32s", [theCard.name UTF8String],
[theCard.email UTF8String]);
NSLog (@"==================================================");
}
// lookup address card by name — assumes an exact match
-(AddressCard *) lookup: (NSString *) theName
{
for ( AddressCard *nextCard in book )
if ( [[nextCard name] caseInsensitiveCompare: theName] == NSOrderedSame )
return nextCard;
return nil;
}
-(void) dealloc{
[bookName release];
[book release];
[super dealloc];
}
-(void) encodeWithCoder: (NSCoder *) encoder{
[encoder encodeObject:bookNameforKey:@"AddressBookBookName"];
[encoder encodeObject:bookforKey: @"AddressBookBook"];
}
-(id) initWithCoder: (NSCoder *) decoder{
bookName= [[decoder decodeObjectForKey: @"AddressBookBookName"] retain];
book= [[decoder decodeObjectForKey: @"AddressBookBook"] retain];
return self;
}
// Method for NSCopying protocol
-(id) copyWithZone: (NSZone *) zone
{
AddressBook *newBook = [[self class] allocWithZone: zone];[newBookinitWithName: bookName];[newBooksetBook: book];return newBook;
}
@end

实现:

#import "AddressBook.h"
#import <Foundation/NSAutoreleasePool.h>
int main (intargc, char *argv[]){
NSString *aName = @"Julia Kochan";
NSString *aEmail = @"jewls337@axlc.com";
NSString *bName = @"Tony Iannino";
NSString *bEmail = @"tony.iannino@techfitness.com";
NSString *cName = @"Stephen Kochan";
NSString *cEmail = @"steve@steve_kochan.com";
NSString *dName = @"Jamie Baker";
NSString *dEmail = @"jbaker@hitmail.com";
NSAutoreleasePool * pool = [[NSAutoreleasePoolalloc] init];
AddressCard *card1 = [[AddressCardalloc] init];
AddressCard *card2 = [[AddressCardalloc] init];
AddressCard *card3 = [[AddressCardalloc] init];
AddressCard *card4 = [[AddressCardalloc] init];
AddressBook *myBook = [AddressBookalloc];
// First set up four address cards
[card1 setName: aNameandEmail: aEmail];
[card2 setName: bNameandEmail: bEmail];
[card3 setName: cNameandEmail: cEmail];
[card4 setName: dNameandEmail: dEmail];
myBook = [myBookinitWithName: @"Steve’s Address Book"];
// Add some cards to the address book
[myBookaddCard: card1];
[myBookaddCard: card2];
[myBookaddCard: card3];
[myBookaddCard: card4];
[myBook sort];
if ([NSKeyedArchiverarchiveRootObject: myBooktoFile:
@"addrbook.arch"]  == NO)
NSLog (@"archiving failed");
[card1 release];
[card2 release];
[card3 release];
[card4 release];
[myBook release];
[pool drain];
return 0;
}// Addresscard.h Interface File 对AddressBook解码
#import "AddressBook.h"
#import <Foundation/NSAutoreleasePool.h>
int main (intargc, char *argv[]){
AddressBook *myBook;
NSAutoreleasePool * pool = [[NSAutoreleasePoolalloc] init];
myBook = [NSKeyedUnarchiverunarchiveObjectWithFile:  @"addrbook.arch"];
[myBook list];
[pool drain];
return 0;
}
输出:
======== Contents of: Steve’s Address Book =========
Jamie Baker jbaker@hitmail.com
Julia Kochan jewls337@axlc.com
Stephen Kochan steve@steve_kochan.com
Tony Iannino tony.iannino@techfitness.com
====================================================

在解码地址簿过程中,自动调用向两个类添加的解码方法。

encodeObject:forKey:方法

内置类行数据编码示例

@interface Foo: NSObject<NSCoding>
{
NSString *strVal;
intintVal;float floatVal;
}
@property (copy, nonatomic) NSString *strVal;
@property intintVal;
@property float floatVal;
@end
@implementation Foo
@synthesize strVal, intVal, floatVal;
-(void) encodeWithCoder: (NSCoder *) encoder
{   //对每个实例变量编码 归档对象的三个实例变量
    [encoder encodeObject: strValforKey: @”FoostrVal”];[encoder encodeInt: intVal forKey: @”FoointVal”];[encoder encodeFloat: floatValforKey: @”FoofloatVal”];
}
-(id) initWithCoder: (NSCoder *) decoder
{   //解码每个实例变量
strVal = [[decoder decodeObjectForKey: @”FoostrVal”] retain];
intVal = [decoder decodeIntForKey: @”FoointVal”];
floatVal = [decoder decodeFloatForKey: @”FoofloatVal”];return self;
}
@end
#import <Foundation/NSObject.h>
#import <Foundation/NSString.h>
#import <Foundation/NSKeyedArchiver.h>
#import <Foundation/NSAutoreleasePool.h>
#import “Foo.h” // Definition for our Foo class
int main (intargc, char *argv[]){
NSAutoreleasePool * pool = [[NSAutoreleasePoolalloc] init];
Foo *myFoo1 = [[Fooalloc] init];  Foo *myFoo2;
[myFoo1 setStrVal: @”This is the string”];
[myFoo1 setIntVal: 12345];
[myFoo1 setFloatVal: 98.6];
[NSKeyedArchiverarchiveRootObject: myFoo1 toFile: @”foo.arch”];
myFoo2 = [NSKeyedUnarchiverunarchiveObjectWithFile: @”foo.arch”];
NSLog (@”%@\n%i\n%g”, [myFoo2 strVal], [myFoo2 intVal], [myFoo2 floatVal]);
[myFoo1 release];
[pool drain];
return 0;
}

结果:

This is the string
12345
98.6
2.4使用NSData创建自定义归档 (NSData数据流对象类)
比如想手机一些或全部对象,并将其存储到单个档案文件中,可以使用自定义归档
代码实例:
//归档
#import <Foundation/NSObject.h>
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSString.h>
#import <Foundation/NSKeyedArchiver.h>
#import <Foundation/NSCoder.h>
#import <Foundation/NSData.h>
#import "AddressBook.h"
#import "Foo.h"
int main (intargc, char *argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePoolalloc] init];
Foo *myFoo1 = [[Fooalloc] init];
Foo *myFoo2;
NSMutableData *dataArea;
NSKeyedArchiver *archiver;
AddressBook *myBook;
// in myBook containing four address cards[myFoo1 setStrVal: @"This is the string"];[myFoo1 setIntVal: 12345];[myFoo1 setFloatVal: 98.6];
// Set up a data area and connect it to an NSKeyedArchiver object
dataArea = [NSMutableData data];
archiver = [[NSKeyedArchiveralloc]
initForWritingWithMutableData: dataArea];
// Now we can begin to archive objects[archiverencodeObject: myBookforKey: @"myaddrbook"];[archiverencodeObject: myFoo1 forKey: @"myfoo1"];[archiverfinishEncoding];
// Write the archived data  to a fileif ( [dataAreawriteToFile: @"myArchive" atomically: YES] == NO)
NSLog (@"Archiving failed!");[archiver release];[myFoo1 release];[pool drain];return 0;
}
//解码
#import <Foundation/NSObject.h>
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSString.h>
#import <Foundation/NSKeyedArchiver.h>
#import <Foundation/NSCoder.h>
#import <Foundation/NSData.h>
#import "AddressBook.h"
#import "Foo.h"
int main (intargc, char *argv[]){
NSAutoreleasePool * pool = [[NSAutoreleasePoolalloc] init];
NSData *dataArea;
NSKeyedUnarchiver *unarchiver;
Foo *myFoo1;
AddressBook *myBook;// Read in the archive and connect an// NSKeyedUnarchiver object to it
dataArea = [NSDatadataWithContentsOfFile: @"myArchive"];
if (! dataArea) {
NSLog (@"Can’t read back archive file! ");return (1);
}
unarchiver = [[NSKeyedUnarchiveralloc] initForReadingWithData: dataArea];
// Decode the objects we previously stored in the archive
myBook = [unarchiverdecodeObjectForKey: @"myaddrbook"];
myFoo1 = [unarchiverdecodeObjectForKey: @"myfoo1"];
[unarchiverfinishDecoding];
[unarchiver release];
// Verify that the restore was successful
[myBook list];
NSLog(@"%@\n%i\n%g", [myFoo1 strVal],[myFoo1 intVal], [myFoo1 floatVal]);
[pool release];
return 0;
}

输出:
======== Contents of: Steve’s Address Book =========
Jamie Baker jbaker@hitmail.com
Julia Kochan jewls337@axlc.com
Stephen Kochan steve@steve_kochan.com
Tony Iannino tony.iannino@techfitness.com
===================================================
This is the string
12345
98.6
如果把地址簿和Foo对象成功解码,也就会输出以上结果咯~
2.5使用归档程序复制对象:深复制 (难道是反射?)
前面对象复制对可变字符串元素创建了对象副本,然而实际上是没有复制字符串本身,只是复制对他们的引用。
这里可以使用Foundation的归档能力来创建对象的深复制。例如:可以通兑dataArray归档到一个缓冲区,然后把它接档,将结果指派到dataArray2,这个过程不需要使用文件,归档和解档都可以再内存中发生。
#import <Foundation/NSObject.h>
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSString.h>
#import <Foundation/NSKeyedArchiver.h>
#import <Foundation/NSArray.h>
int main (intargc, char *argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePoolalloc] init];
NSData *data;
NSMutableArray *dataArray = [NSMutableArrayarrayWithObjects:[NSMutableStringstringWithString: @"one"],[NSMutableStringstringWithString: @"two"],[NSMutableStringstringWithString: @"three"],nil];
NSMutableArray *dataArray2;
NSMutableString *mStr;
    // Make a deep copy using the archiverdata = [NSKeyedArchiverarchivedDataWithRootObject: dataArray];dataArray2 = [NSKeyedUnarchiverunarchiveObjectWithData: data]; 
mStr = [dataArray2 objectAtIndex: 0];[mStrappendString: @"ONE"];
NSLog (@"dataArray: ");for ( NSString *elem in dataArray )
NSLog ("%@", elem);
NSLog (@"\ndataArray2: ");for ( NSString *elem in dataArray2 )
NSLog ("%@", elem);[pool drain];return 0;
}

结果:

dataArray:
one
two
three
dataArray2:
oneONE
two
three
----------------------------
NICE, 把复制对象和归档的内容了解完了,那么Objc的基础知识学习也就告一段落啦~

ObjC学习11-复制对象与归档相关推荐

  1. ObjC学习8-重头戏来了!Foundation框架

    学习7-C语言特性还漏了个运算符: sizeof运算符号 //返回指定项的字节大小 NSLog(@"%i",sizeof(int)); 感觉C与objc特性那样结束好像挺不合适的. ...

  2. JavaScript 复制对象与Object.assign方法无法实现深复制

    在JavaScript这门语言中,数据类型分为两大类:基本数据类型和复杂数据类型.基本数据类型包括Number.Boolean.String.Null.String.Symbol(ES6 新增),而复 ...

  3. php对象魔术方法,php学习之类与对象的魔术方法的使用

    原标题:php学习之类与对象的魔术方法的使用 魔术方法有哪些 __construct:构造方法 __destuct:析构方法 __call:在对象中调用一个不可访问的方法时.__call()会被调用 ...

  4. PHP学习之类和对象

    class 每个类的定义都以关键字 class 开头,后面跟着类名,后面跟着一对花括号,里面包含有类的属性与方法的定义. 一个类可以包含有属于自己的常量,变量(称为"属性")以及函 ...

  5. Unity Instantiate函数用于复制对象

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一.Instantia()的使用方法 二.参数详解 1. Object original 2.Transform pa ...

  6. 复制对象clone(深复制和浅复制)

    Java中对象的创建 clone顾名思义就是复制, 在Java语言中, clone方法被对象调用,所以会复制对象.所谓的复制对象,首先要分配一个和源对象同样大小的空间,在这个空间中创建一个新的对象.那 ...

  7. python代码学习——类与对象提升(继承、超继承,类的例题,魔术方法)

    python代码学习--类与对象提升 继承 继承的特殊属性: 代码示例 方法的重写和覆盖(overrrid) 总结 超继承 继承中的初始化 多继承 例题 类的魔术方法 哈希(hash)和eq方法 bo ...

  8. Java学习-11 XML与JSON

    Java学习-11 XML与JSON 1.XML 1.1.简介 可扩展标记语言(eXtensible Markup Language). 特性:1. xml具有平台无关性, 是一门独立的标记语言.2. ...

  9. 使用BeanCopier复制对象

    在开发过程中经常需要深度复制对象,才用Spring的BeanCopier方案是个不错的选择. 直接看代码,先准备好实体类. import lombok.Data;import java.io.Seri ...

最新文章

  1. PPT幻灯片从自动翻页设置为手动翻页技巧图文教程
  2. C# 房贷计算器(等本降息)
  3. Tensorflow安装笔记
  4. sonar api 获取质量数据
  5. LeetCode - Easy - 637. Average of Levels in Binary Tree
  6. 他将国际奥赛变成个人秀,哈佛为他打破校规,他的选择让国人骄傲
  7. 快速迁移数据中心:华为云数据库SQL Server实践案例技术解析
  8. chrome15调试-使用devtools作为代码编辑器
  9. ubuntu下,rubyonrails环境搭建
  10. 新的信息工作者简历或简历模板
  11. “百度开放云编程马拉松”成都赛区19件作品及团队介绍
  12. 介绍兴趣爱好的网页html,介绍兴趣爱好的作文5篇
  13. linux watchdog超时时间,S3C2440看门狗定时器(Watchdog)
  14. leaflet 常用方法总结
  15. git fatal: The remote end hung up unexpectedly 错误
  16. 525、Java工程师的进阶之路 -【 RocketMQ (二)】 2022.01.06
  17. 全球与中国LED检查灯市场深度研究分析报告
  18. 讲人话科普,Python是个啥?为啥大家都在学?
  19. 联发科技嵌入式_【MTK联发科技嵌入式软件开发工程师面试题目|面试经验】-看准网...
  20. unity随机生成怪物(抽奖)代码

热门文章

  1. C# 最小化到系统托盘的实现(一)
  2. PaddlePaddle eval后报错terminate all the procs的解决方法
  3. html鼠标互动旋转立方体,css3 transform及原生js实现鼠标拖动3D立方体旋转的示例介绍...
  4. java mongodb 语句,MongoDB语句
  5. mysql集群集成springboot_springboot配置数据库包括集群下 配置
  6. mate7 刷机 android 7,Mate7 四大版本完整稳定版刷机包大集合!
  7. 在python的解释器中使用函数_浅析Windows 嵌入python解释器的过程
  8. 苹果6发布时间_iPhone12promax11月6日几点预售 11.6苹果12mini预售时间
  9. 21天jenkins打卡Day2-安装Jenkins
  10. python21天打卡day4