怎么通过ios nsarray 初始化解析 ios

(今天编码时遇到深拷贝与浅拷贝的问题,网上找到这篇文章,转载下 by:yangchen)
阅读本文之前首先了解copy与retain的区别,如果有不正确的地方望大家多多指教:
copy与retain的区别:
copy是创建一个新对象,retain是创建一个指针,引用对象计数加1。Copy属性表示两个对象内容相同,新的对象retain为1&,与旧有对象的引用计数无关,旧有对象没有变化。copy减少对象对上下文的依赖。
& & & &retain属性表示两个对象地址相同(建立一个指针,指针拷贝),内容当然相同,这个对象的retain值+1也就是说,retain&是指针拷贝,copy&是内容拷贝。
当然在ios中并不是所有的对象都支持copy,mutableCopy,遵守NSCopying 协议的类可以发送copy消息,遵守NSMutableCopying 协议的类才可以发送mutableCopy消息。假如发送了一个没有遵守上诉两协议而发送 copy或者 mutableCopy,那么就会发生异常。但是默认的ios类并没有遵守这两个协议。如果想自定义一下copy 那么就必须遵守NSCopying,并且实现 copyWithZone: 方法,如果想自定义一下mutableCopy 那么就必须遵守NSMutableCopying,并且实现 mutableCopyWithZone: 方法。
首先我们需要有这样的一个前提:  [array addObject:obj];  这样obj的引用计数会增加1,如果使用remove则obj的引用计数会减一。  ios对集合的内存处理就是这样的。  那么,假设obj只被array拥有:  id temp = [array objectAtIndex:0];  [array removeObjectAtIndex:0];  如果你再要使用temp就会出错,因为这个时候obj已经被释放了。  (提醒一下,如果用NSString做测试,要注意@&abc&是常量 :-)& )  由于在程序中经常会遇到集合类的传值,所以,简单的retain未必够用,需要对集合内容的拷贝,也就是深拷贝。  下面我们就来探讨一下。  Ios提供了copy和mutablecopy方法,顾名思义,copy就是复制了一个imutable的对象,而mutablecopy就是复制了一个mutable的对象。以下将举几个例子来说明。  1.&&&& 系统的非容器类对象  这里指的是NSString,NSNumber等等一类的对象。  NSString *string = @"origion";  NSString *stringCopy = [string copy];  NSMutableString *stringMCopy = [string mutableCopy];  [stringMCopy appendString:@"!!"];  查看内存可以发现,string和stringCopy指向的是同一块内存区域(又叫apple弱引用weak reference),此时stringCopy的引用计数和string的一样都为2。而stringMCopy则是我们所说的真正意义上的复制,系统为其分配了新内存,但指针所指向的字符串还是和string所指的一样。  再看下面的例子:&&&& NSMutableString *string = [NSMutableString stringWithString: @"origion"];&&& NSString *stringCopy = [string copy];&&& NSMutableString *mStringCopy = [string copy];&&& NSMutableString *stringMCopy = [string mutableCopy];&&& [mStringCopy appendString:@"mm"];//error&&& [string appendString:@" origion!"];&&& [stringMCopy appendString:@"!!"];以上四个NSString对象所分配的内存都是不一样的。但是对于mStringCopy其实是个imutable对象,所以上述会报错。对于系统的非容器类对象,我们可以认为,如果对一不可变对象复制,copy是指针复制(浅拷贝)和mutableCopy就是对象复制(深拷贝)。如果是对可变对象复制,都是深拷贝,但是copy返回的对象是不可变的。2.&&&& 系统的容器类对象&指NSArray,NSDictionary等。对于容器类本身,上面讨论的结论也是适用的,需要探讨的是复制后容器内对象的变化。&&& //copy返回不可变对象,mutablecopy返回可变对象&&& NSArray *array1 = [NSArray arrayWithObjects:@"a",@"b",@"c",nil];&&& NSArray *arrayCopy1 = [array1 copy];&&& //arrayCopy1是和array同一个NSArray对象(指向相同的对象),包括array里面的元素也是指向相同的指针&&& NSLog(@"array1 retain count: %d",[array1 retainCount]);&&& NSLog(@"array1 retain count: %d",[arrayCopy1 retainCount]);&&& NSMutableArray *mArrayCopy1 = [array1 mutableCopy];&&& //mArrayCopy1是array1的可变副本,指向的对象和array1不同,但是其中的元素和array1中的元素指向的是同一个对象。mArrayCopy1还可以修改自己的对象&&& [mArrayCopy1 addObject:@"de"];[mArrayCopy1 removeObjectAtIndex:0];array1和arrayCopy1是指针复制,而mArrayCopy1是对象复制,mArrayCopy1还可以改变期内的元素:删除或添加。但是注意的是,容器内的元素内容都是指针复制。下面用另一个例子来测试一下。&&& NSArray *mArray1 = [NSArray arrayWithObjects:[NSMutableString stringWithString:@"a"],@"b",@"c",nil];&&& NSArray *mArrayCopy2 = [mArray1 copy];&&& NSLog(@"mArray1 retain count: %d",[mArray1 retainCount]);&&& NSMutableArray *mArrayMCopy1 = [mArray1 mutableCopy];&&& NSLog(@"mArray1 retain count: %d",[mArray1 retainCount]);&&& //mArrayCopy2,mArrayMCopy1和mArray1指向的都是不一样的对象,但是其中的元素都是一样的对象&&同一个指针&&& //一下做测试&&& NSMutableString *testString = [mArray1 objectAtIndex:0];&&& //testString = @"1a1";//这样会改变testString的指针,其实是将@&1a1&临时对象赋给了testString[testString appendString:@" tail"];//这样以上三个数组的首元素都被改变了由此可见,对于容器而言,其元素对象始终是指针复制。如果需要元素对象也是对象复制,就需要实现深拷贝。&&& NSArray *array = [NSArray arrayWithObjects:[NSMutableString stringWithString:@"first"],[NSStringstringWithString:@"b"],@"c",nil];&&& NSArray *deepCopyArray=[[NSArray alloc] initWithArray: array copyItems: YES];&&& NSArray* trueDeepCopyArray = [NSKeyedUnarchiver unarchiveObjectWithData:&&& [NSKeyedArchiver archivedDataWithRootObject: array]];trueDeepCopyArray是完全意义上的深拷贝,而deepCopyArray则不是,对于deepCopyArray内的不可变元素其还是指针复制。或者我们自己实现深拷贝的方法。因为如果容器的某一元素是不可变的,那你复制完后该对象仍旧是不能改变的,因此只需要指针复制即可。除非你对容器内的元素重新赋值,否则指针复制即已足够。举个例子,[[array objectAtIndex:0]appendstring:@&sd&]后其他的容器内对象并不会受影响。[[array objectAtIndex:1]和[[deepCopyArray objectAtIndex:0]尽管是指向同一块内存,但是我们没有办法对其进行修改&&因为它是不可改变的。所以指针复制已经足够。所以这并不是完全意义上的深拷贝,但是apple的官方文档将其列为deep copy了,并添加了copy和mutablity的关系说明,故在此做一说明(这边还有点疑惑,有了解的赐教啊)。或者我们自己实现深拷贝的方法(略)。3.&&&& 自定义对象如果是我们定义的对象,那么我们自己要实现NSCopying,NSMutableCopying这样就能调用copy和mutablecopy了。举个例子:@interface MyObj : NSObject&NSCopying,NSMutableCopying&{&&&&&&&& NSMutableString *&&&&&&&& NSString *imutableS&&&&&&&&}@property (nonatomic, retain) NSMutableString *@property (nonatomic, retain) NSString *imutableS@property (nonatomic)@end@implementation MyObj@@@synthesize imutableS- (id)init{&&&&&&&& if (self = [super init])&&&&&&&& {&&&&&&&&&&&&&&&&&& self.name = [[NSMutableString alloc]init];&&&&&&&&&&&&&&&&&& self.imutableStr = [[NSString alloc]init];&&&&&&&&&&&&&&&&&& age = -1;&&&&&&&& }&&&&&&&&}- (void)dealloc{&&&&&&&& [name release];&&&&&&&& [imutableStr release];&&&&&&&& [super dealloc];}- (id)copyWithZone:(NSZone *)zone{&&&&&&&& MyObj *copy = [[[self class] allocWithZone:zone] init];&&&&&&&& copy-&name = [name copy];&&&&&&&& copy-&imutableStr = [imutableStr copy];//&&&&&& copy-&name = [name copyWithZone:zone];;//&&&&&& copy-&imutableStr = [name copyWithZone:zone];//&&&&&&&& copy-&age =&&&&&&&&}- (id)mutableCopyWithZone:(NSZone *)zone{&&&&&&&& MyObj *copy = NSCopyObject(self, 0, zone);&&&&&&&& copy-&name = [self.name mutableCopy];&&&&&&&& copy-&age =&&&&&&&&}
阅读(...) 评论()ios XML,JSON,数组解析并转换成NSMutableArray(List&class&) - 推酷
ios XML,JSON,数组解析并转换成NSMutableArray(List&class&)
通过正则将JSON([{...},{...}...])分解成多个包含实体实例内容的一小节({...}),在一小节中通过Runtime(运行时)(&objc/runtime.h&)将实体所有属性值找到并赋值(正则查找实现)
({...} --& 实体的一个实例)
,遍历所有小节
将XML转换成NSMutableArray(类似:
List&class&)
通过GDataXml(也可以通过正则)将XML分解成多个包含实体实例内容的一小节XML,
在一小节中
通过Runtime(运行时)(&objc/runtime.h&)将实体所有属性值找到并赋值(正则查找实现)到实例,
遍历所有小节
将XML转换成NSMutableArray(类似:
List&class&)
将XML拼接,
通过GDataXml
将XML转换成NSMutableArray(类似:
List&string&)
(整个过程也可以通过正则实现)
已将3个解析方法写到一个公用类(
GlobalApplication)中
需注意的是实现方法中要添加2个头文件
#import &objc/runtime.h&
#import &GDataXMLNode.h&
使用说明:
// User 为一个 实体类
// xml --& NSMutableArray (List&class&)
NSMutableArray *retVal = [GlobalApplication jsonToArray:xml class:User.class];
// xml --& NSMutableArray (List&class&)
NSMutableArray *retVal = [GlobalApplication xmlToArray:xml class:User.class rowRootName:@&row&];
// xml --& NSMutableArray (List&String&)
NSMutableArray *retVal = [GlobalApplication xmlToArray:xml];
1、GlobalApplication.h
GlobalApplication.h
WebServcieBySoap
Created by fengs on 14-11-19.
Copyright (c) 2014年 fengs. All rights reserved.
#import &Foundation/Foundation.h&
@interface GlobalApplication : NSObject
#pragma mark -
#pragma mark - 将xml(数组)转换成NSMutableArray (List&String&)
* 将xml(数组)转换成NSMutableArray
* @param xml
&string&fs&/string&
&string&fs&/string&
* @return NSMutableArray (List&String&)
+(NSMutableArray*)xmlToArray:(NSString*)
#pragma mark -
#pragma mark - 将标准的xml(实体)转换成NSMutableArray (List&class&)
* 把标准的xml(实体)转换成NSMutableArray
* @param xml:
&data xmlns=&&&
&row&&UserID&ff0f0704&/UserID&&UserName&fs&/UserName&&/row&
&row&&UserID&ff0f0704&/UserID&&UserName&fs&/UserName&&/row&
* @param class:
* @param rowRootName:
* @return NSMutableArray (List&class&)
+(NSMutableArray*)xmlToArray:(NSString*)xml class:(Class)class rowRootName:rowRootN
#pragma mark -
#pragma mark - 将标准的Json(实体)转换成NSMutableArray (List&class&)
* 把标准的xml(实体)转换成NSMutableArray
* @param xml:
[{&UserID&:&ff0f0704&,&UserName&:&fs&},
{&UserID&:&ff0f0704&,&UserName&:&fs&},...]
* @param class:
* @return NSMutableArray (List&class&)
+(NSMutableArray*)jsonToArray:(NSString*)json class:(Class)
2、GlobalApplication.m
GlobalApplication.m
WebServcieBySoap
Created by fengs on 14-11-19.
Copyright (c) 2014年 fengs. All rights reserved.
#import &GlobalApplication.h&
#import &objc/runtime.h&
#import &GDataXMLNode.h&
@implementation GlobalApplication
#pragma mark -
#pragma mark - 将xml(数组)转换成NSMutableArray (List&String&)
* 将xml(数组)转换成NSMutableArray
* @param xml
&string&fs&/string&
&string&fs&/string&
* @return NSMutableArray (List&String&)
+(NSMutableArray*)xmlToArray:(NSString*)xml{
NSMutableArray *retVal = [[[NSMutableArray alloc] init] autorelease];
xml = [NSString stringWithFormat:@&&data&%@&/data&&,xml];
GDataXMLDocument *root = [[[GDataXMLDocument alloc] initWithXMLString:xml options:0 error:nil] autorelease];
GDataXMLElement *rootEle = [root rootElement];
for (int i=0; i &[rootEle childCount]; i++) {
GDataXMLNode *item = [rootEle childAtIndex:i];
[retVal addObject:item.stringValue];
return retV
#pragma mark -
#pragma mark - 将标准的xml(实体)转换成NSMutableArray (List&class&)
* 将标准的xml(实体)转换成NSMutableArray
* @param xml:
&data xmlns=&&&
&row&&UserID&ff0f0704&/UserID&&UserName&fs&/UserName&&/row&
&row&&UserID&ff0f0704&/UserID&&UserName&fs&/UserName&&/row&
* @param class:
* @param rowRootName:
* @return NSMutableArray (List&class&)
+(NSMutableArray*)xmlToArray:(NSString*)xml class:(Class)class rowRootName:rowRootName{
NSMutableArray *retVal = [[[NSMutableArray alloc] init] autorelease];
GDataXMLDocument *root = [[[GDataXMLDocument alloc] initWithXMLString:xml options:0 error:nil] autorelease];
GDataXMLElement *rootEle = [root rootElement];
NSArray *rows = [rootEle elementsForName:rowRootName];
for (GDataXMLElement *row in rows) {
id object = [[class alloc] init];
object = [self initWithXMLString:row.XMLString object:object];
[retVal addObject:object];
[object release];
return retV
* 将传递过来的实体赋值
* @param xml(忽略实体属性大小写差异):
&row&&UserID&ff0f0704&/UserID&&UserName&fs&/UserName&&/row&
* @param class:
User @property userName,userID;
* @return class
+(id)initWithXMLString:(NSString*)xml object:(id)object{
unsigned int outCount,
objc_property_t *properties = class_copyPropertyList([object class], &outCount);
for (i = 0; i&outC i++)
objc_property_t property = properties[i];
const char* char_f = property_getName(property);
NSString *propertyName = [NSString stringWithUTF8String:char_f];
NSString *value = [self setXMLProperty:xml propertyName:propertyName];
[object setValue:value forKey:propertyName];
free(properties);
* 通过正则将传递过来的实体赋值
* @param content(忽略实体属性大小写差异):
&row&&UserID&ff0f0704&/UserID&&UserName&fs&/UserName&&/row&
* @param propertyName:
* @return NSString
+(NSString*)setXMLProperty:(NSString*)value propertyName:(NSString*)propertyName {
NSString *retVal = @&&;
NSString *patternString = [NSString stringWithFormat:@&(?&=&%@&)(.*)(?=&/%@&)&,propertyName,propertyName];
// CaseInsensitive:不区分大小写比较
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:patternString options:NSRegularExpressionCaseInsensitive error:nil];
if (regex) {
NSTextCheckingResult *firstMatch = [regex firstMatchInString:value options:NSCaseInsensitiveSearch range:NSMakeRange(0, [value length])];
if (firstMatch) {
retVal = [value substringWithRange:firstMatch.range];
return retV
#pragma mark -
#pragma mark - 将标准的Json(实体)转换成NSMutableArray (List&class&)
* 将标准的Json(实体)转换成NSMutableArray
* @param xml:
[{&UserID&:&ff0f0704&,&UserName&:&fs&},
{&UserID&:&ff0f0704&,&UserName&:&fs&},...]
* @param class:
* @return NSMutableArray (List&class&)
+(NSMutableArray*)jsonToArray:(NSString*)json class:(Class)class {
NSMutableArray *retVal = [[[NSMutableArray alloc] init] autorelease];
NSString *patternString = @&\\{.*?\\}&;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:patternString options:0 error:nil];
if (regex) {
NSArray *match = [regex matchesInString:json options:0 range:NSMakeRange(0, [json length])];
if (match) {
for (NSTextCheckingResult *result in match) {
NSString *jsonRow = [json substringWithRange:result.range];
id object = [[class alloc] init];
object = [self initWithJsonString:jsonRow object:object];
[retVal addObject:object];
[object release];
return retV
* 将传递过来的实体赋值
* @param xml(忽略实体大小写差异):
{&UserID&:&ff0f0704&,&UserName&:&fs&}
* @param class:
User @property userName,userID;
* @return class
+(id)initWithJsonString:(NSString*)json object:(id)object{
unsigned int outCount,
objc_property_t *properties = class_copyPropertyList([object class], &outCount);
for (i = 0; i&outC i++)
objc_property_t property = properties[i];
const char* char_f = property_getName(property);
NSString *propertyName = [NSString stringWithUTF8String:char_f];
NSString *value = [self setJsonProperty:json propertyName:propertyName];
[object setValue:value forKey:propertyName];
free(properties);
* 通过正则将传递过来的实体赋值
* @param content(忽略实体大小写差异):
{&UserID&:&ff0f0704&,&UserName&:&fs&}
* @param propertyName:
* @return NSString
+(NSString*)setJsonProperty:(NSString*)value propertyName:(NSString*)propertyName {
NSString *retVal = @&&;
NSString *patternString = [NSString stringWithFormat:@&(?&=\&%@\&:\&)[^\&,]*&,propertyName];
// CaseInsensitive:不区分大小写比较
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:patternString options:NSRegularExpressionCaseInsensitive error:nil];
if (regex) {
NSTextCheckingResult *firstMatch = [regex firstMatchInString:value options:NSCaseInsensitiveSearch range:NSMakeRange(0, [value length])];
if (firstMatch) {
retVal = [value substringWithRange:firstMatch.range];
return retV
已发表评论数()
&&登&&&陆&&
已收藏到推刊!
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见您所在的位置: &
iOS探索:对NSArray中自定义的对象进行排序
iOS探索:对NSArray中自定义的对象进行排序
beyondvincent
我们开发的每个程序都会使用到一些数据,而这些数据一般被封装在一个自定义的类中。例如一个音乐程序可能会有一个Song类,聊天程序则又一个 Friend类,点菜程序会有一个Recipe类等。有时候我们希望在程序中显示的列表数据是按照一定顺序进行排列的,本文我们就来看看在iOS中有哪些 方法可以对NSArray中的对象进行排序。
本文译自。
我们开发的每个程序都会使用到一些数据,而这些数据一般被封装在一个自定义的类中。例如一个音乐程序可能会有一个Song类,聊天程序则又一个 Friend类,点菜程序会有一个Recipe类等。有时候我们希望在程序中显示的列表数据是按照一定顺序进行排列的,本文我们就来看看在iOS中有哪些 方法可以对NSArray中的对象进行排序。下面是目录:
使用NSComparator进行排序
使用NSDescriptor进行排序
使用selector进行排序
我们将要排序的对象是一个Persion类,如下定义:
@interface&Person&:&NSObject&@property&(nonatomic,&copy)&NSString&*&@property&(nonatomic,&copy)&NSString&*&@property&(nonatomic,&strong)&NSDate&*dateOfB&@end&
而数组中包含如下内容:
Smith&John&03/01/1984&Andersen&Jane&16/03/1979&Clark&Anne&13/09/1995&Smith&David&19/07/1981&Johnson&Rose&22/02/1989&
使用NSComparator进行排序
comparator实际上是用一个block对象作比较操作。它的定义如下所示:
typedef&NSComparisonResult&(^NSComparator)(id&obj1,&id&obj2);&
上面的参数(obj1、obj2)就是我们将要做比较的对象。block返回的结果为NSComparisonResult类型来表示两个对象的顺序。
要对整个数组做排序,则需要使用NSArray的sortArrayUsingComparator:方法,如下代码所示:
NSArray&*sortedArray&=&[self.persons&sortedArrayUsingComparator:^NSComparisonResult(Person&*p1,&Person&*p2){&&&&&return&[p1.surname&compare:p2.surname];&}];&
最终排序的结果如下所示:
Andersen&Jane&Clark&Anne&Johnson&Rose&Smith&John&Smith&David&
使用NSDescriptor进行排序
Sort descriptor不仅可以用来对数组进行排序,还能指定element在table view中的排序,以及Core
Data中对fetch request返回的数据做排序处理。通过sort
descriptor可以很方便的对数组进行多个key的排序。下面来看看如何对我们的数组做surname排序,然后在进行name排序:
NSSortDescriptor&*firstDescriptor&=&[[NSSortDescriptor&alloc]&initWithKey:@&surname&&ascending:YES];&NSSortDescriptor&*secondDescriptor&=&[[NSSortDescriptor&alloc]&initWithKey:@&name&&ascending:YES];&&NSArray&*sortDescriptors&=&[NSArray&arrayWithObjects:firstDescriptor,&secondDescriptor,&nil];&&NSArray&*sortedArray&=&[self.persons&sortedArrayUsingDescriptors:sortDescriptors];&
上面代码的排序结果如下所示:
Andersen&Jane&Clark&Anne&Johnson&Rose&Smith&David&Smith&John&
使用selector进行排序
当面,我们也可以定义自己的方法进行两个对象做比较,并将该方法用于数组排序。comparator消息会被发送到数值中的每个对象中,并携带数组中另外的一个对象当做参数。自定义的的方法的返回结果是这样的:如果本身对象小于参数中的对象,就返回NSOrederedAscending,相反,则返回NSOrderedDescending,如果相等,那么返回NSOrderedSame。如下代码所示:
-&(NSComparisonResult)compare:(Person&*)otherPerson&{&&&&&return&[self.dateOfBirth&compare:otherPerson.dateOfBirth];&}&
这个方法定义在Person类中,用来对person的生日进行排序。
上面所介绍的这些方法都是为了完成相同的事情:对数组做排序处理,你可能在想改选择使用哪个呢?当需要通过多个key进行排序,那么最简单的方法就 是使用sort descriptor。如果比较方法很复杂的话,建议在使用外面自己的selector。Block是再iOS
4之后引入的一个强大功能,用block作比较,可以不必使用任何的变量就能完成一个简单的比较方法,当然,你也可以定义一个复杂的block,来替换 selector。
最后,其实这里并没有标准答案,你可以跟着自己的感觉走:]【编辑推荐】【责任编辑: TEL:(010)】
关于&&&&&&的更多文章
Apple的操作系统被认为是在不断地演进。本书最早是针对iOS 5和Li
既然强大的Android Studio来了,有什么理由不去用呢?
Android 4.4即将发布,这对大家来说都是很期待的,当
开发者在代码开发和维护中,往往会遇到很多代码优化和
现在的天气越来越冷了,感觉跟冬天似的,小编现在在发
本书使用通俗易懂的语言,通过大量的实例,从实际应用的角度出发,全面系统地介绍了网络服务操作系统平台、电子邮件系统、Web站
Windows Phone专家
Android开发专家
51CTO旗下网站【无限互联】iPhone开发视频教程 4.3 NSArray数组的使用_土豆_高清视频在线观看

我要回帖

更多关于 ios nsarray 查找 的文章

 

随机推荐