oc字符串处理
//获得字符串长度
NSString* str1=@"MAC OS Pro";
NSLog(@"长度是%d",[str1length]);
//两个字符串连接
NSString* str2=@"MAC OS Pro";
NSString* str3=@" Leopard";
NSString* str4=[str2stringByAppendingString:str3];
NSLog(str4,nil);
NSString* str5=[str2stringByAppendingFormat:@" %d",10];
NSLog(str5,nil);
//可修改字符串
NSMutableString* string=[NSMutableStringstring];
[stringappendString:@"Mac"];
[stringappendString:@" OS"];
[stringappendString:@" X"];
NSLog(string,nil);
//插入字符串
NSMutableString* string1=[NSMutableStringstringWithFormat:@"Mac X"];
[string1insertString:@"OS "atIndex:4];
NSLog(string1,nil);
//删除字符串
NSMutableString* string2=[NSMutableStringstringWithFormat:@"删除字符串"];
[string2deleteCharactersInRange:NSMakeRange(0,2)];
NSLog(string2,nil);
//字符串比较
BOOLresult;
result=[stringisEqualToString:string1];
NSLog(@"%d",result,nil);
//比较前置串与后置串
NSString* string3=@"Mac Pro";
NSString* string4=@"Mac OS";
//判断是否以Mac开头
result=[string3hasPrefix:@"Mac"];
NSLog(@"%d",result,nil);
//判断是否以OS结尾
result=[string4hasSuffix:@"OS"];
NSLog(@"%d",result,nil);
NSString* string5=@"This is Mac OS X";
//检索字符串
NSRangerange;
range=[string5rangeOfString:@"Mac OS"];
if(range.location!=NSNotFound)
{
//得到字符串的位置和长度
NSLog(@"%d,%d",range.location,range.length);
}
else
{
NSLog(@"没有发现",nil);
}
//抽取部分字符串
NSString* string6=@"This is Mac OS X";
NSString*nstr1,*nstr2,*nstr3;
//从开头抽取字符串
nstr1=[string6substringToIndex:4];
NSLog(nstr1,nil);
//抽取末位位置的字符串
nstr2=[string6substringFromIndex:8];
NSLog(nstr2,nil);
//抽取指定范围的字符串
nstr3=[string6substringWithRange:NSMakeRange(5,2)];
NSLog(nstr3,nil);
oc集合类型
1.OC集合类包括NSArray,NSSet,NSDictionary都是以面向对象的方式操作数组,而且OC数组不像C语言中的数组只能存放同一种数据类型,它可以存放任意类型的对象,但是不能存放非OC对象类型如基本数据类型int,struct,enum等
2.OC数组是以对象的方式存在,因此在创建的时候需要为创建的对象前面加*
3.NSArray数组一旦创建就决定了是不是可变,而且永远是可变或不可变
4.NSArray数组和子类NSMutableArray的基本操作:
1>使用NSArray的类方法arry创建个数组,创建时定义为空数组,那么array数组将永远是空数组
NSArray *array = [NSArray array];
2>创建数组对象有两种方式:
NSArray *array = [NSArray arrayWithObjects:@"Jack",nil];
// 数组中包含了两个NSString对象 nil是用来标识数组元素结束的标识
// 因此OC数组中不能存放空对象
NSArray *array1 = [NSArrayarrayWithObjects:@"Jack",@"Rose", nil];
// 第二种方式:
NSArray *array2 = @[@"Jack",@"Rose"];
// 获取数组的长度 array1.count;
NSUInteger count = [array1 count];
NSLog(@"%ld",count);
// 访问数组中的对象的两种方式
NSString *str1 = [array1 objectAtIndex:0]; //数组中索引为1的对象,OC中提供的方法 返回:Jack
NSString *str2 = array1[0]; //编译器特性其实还是转为上面的形式来访问 返回:Jack
5.遍历数组的三种方式
1>普通方式:
for (int i = 0; i
{
NSLog(@"%@",array1[i]); // 数组中存放的是对象可以用%@输出
if (i ==0)
{
break;
}
}
2>将array1数组中的每个对象拿出来赋给obj然后依次打印
for (id obj in array1)
{ // id obj 代表数组中的对象
// 获取obj对象在数组中的索引
NSUInteger index = [array1 indexOfObject:obj];
NSLog(@"%ld--%@",index,obj);
}
3>使用Block 每次从数组中遍历一个元素后就传递给block,block也相应的执行一次
// block中的id obj对应数组中的元素,NSUInteger idx对应数组中元素的索引 BOOL用来停止遍历
[array1 enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
{
NSLog(@"%ld--%@",idx,obj);
// 如果索引为0 立即停止遍历
if (idx ==0)
{
*stop = YES;
}
};
6.NSMutableArray的基本操作:
1>创建可变数组:
NSMutableArray *mutableArray = [NSMutableArray array];
NSMutableArray *mutalbeArray2 = @[@"张三",@"李斯"]; 注意:@[]返回的是不可变NSArray数组 这样会报错
// 为可变数组增加任意对象
Person *person = [[Person alloc] init];
[mutableArray addObject:person];
[mutableArray addObject:@"Jack"];
[mutableArray addObject:@"John"];
// [mutableArray addObject:10]; 数组中不可以存放基本数据类型
// 从数组中删除指定的元素
[mutableArray removeObject:@"John"];
[mutableArray removeObjectAtIndex:0];
// 将数组中的元素全部删除
[mutableArray removeAllObjects];
7.NSSet数组和子类NSMutableSet的基本操作:NSSet和NSArray都是不可变数组,一旦创建就无法改变。NSSet是无序的集合简单操作
1>创建NSSet集合:
NSSet *set = [NSSet set]; // 一旦创建为空永远为空
NSSet *set2 = [NSSet setWithObjects:@"Jack",@"Rose",@"Jim",nil];
// 随机获取NSSet集合中的元素
NSString *str = [set2 anyObject];
NSLog(@"%@",str);
NSMutableSet的简单操作:
// 创建可变set集合
NSMutableSet *mutableSet = [NSMutableSet set];
// 为set添加集合
[mutableSet addObject:@"Jack"];
[mutableSet addObject:@"Rose"];
// 删除元素
[mutableSet removeObject:@"Jack"];
8.NSArray和NSSet数组的对比:
1>都是可以存放任意类型的OC对象的集合,都不能存放基本数据类型
2>本身都是不可变的,但是子类都是可变的
3>NSArray是有序的集合,NSSet是无序的集合
9.NSDictionary和NSMutableDictionary:
1>NSDictionary和它的子类NSMutableDictionary都是以key/value的形式存在,NSDictionary本身为不可变集合
2>NSDictionary也是无序集合
3>字典集合中存储的值是以键值对的形式存在,如果存在相同的key那么后面key的值会被覆盖。但是允许vaule的重复
10.NSDictionary的基本操作
1>常见创建Dictionary集合的四种方式
// 1.创建一个空的字典集合类型
NSDictionary *dic = [NSDictionary dictionary];// 一旦为空 永久为空
// 2.创建只有一组值的字典集合
NSDictionary *dic1 = [NSDictionary dictionaryWithObject:@"Jack" forKey:@"name"];
// 3.创建多个值的字典集合
NSArray *keys = @[@"name",@"address",@"e-mail"];
NSArray *values = @[@"Jack",@"北京",@"jack@163.com"];
NSDictionary *dic3 = [NSDictionary dictionaryWithObjects:values forKeys:keys];
// 4.通过值/键的方式来创建
NSDictionary *dic4 = [NSDictionary dictionaryWithObjectsAndKeys:
@"Jack",@"name",
@"北京",@"address",
@"jack@163.com",@"e-mail",nil];
// 5.类似于数组的创建方式
NSDictionary *dic5 = @{@"name":@"Jack",
@"address":@"北京",
@"e-mail":@"jack@163.com"};
// 取值:根据相应的Key取出对应的值
NSString *name = [dic1 objectForKey:@"name"];// 返回 Jack
// 返回键值对的个数
NSUInteger count = dic5.count; // 返回 4
11.遍历NSDictionary数组用两种方式:
1>
NSArray *allKeys = [dic5 allKeys]; // 获取的键在数组中是无序的
for (int i = 0; i < dic5.count; i++)
{
NSString *key = allKeys[i];
NSString *value = dic5[key];
NSLog(@"%@-->%@",key,value);
}
2> 将字典中的键值对传递给Block中的key和obj
[dic5 enumerateKeysAndObjectsUsingBlock:^(idkey, id obj, BOOL *stop)
{
NSLog(@"%@-->%@",key,obj);
// 遍历一次立即停止 *stop = YES;
};
12.NSMutableDictionary的基本操作:
1>创建可变字典
NSMutableDictionary *mutableDic = [NSMutableDictionary dictionary];
NSMutableDictionary *mutableDic2 =@{@"name",@"Rose",@"address",@"北京"}; 错误的写法因为右边返回的是不可变的字典
2>为可变字典添加元素
[mutableDic setObject:@"Rose" forKey:@"name"];
[mutableDic setObject:@"北京"forKey:@"address"];
3>移除
[mutableDic removeAllObjects];
[mutableDic removeObjectForKey:@"name"];
4>打印
NSLog(@"%@",mutableDic);
自动引用计数ARC
过去做Objective c开发,我们需要手动管理内存,Objective c 的内存管理原理是引用计数(Reference Count-ing,简写RC),手动管理内存遵循黄金法则(有兴趣的去查一下)。
在Xcode4.2出现了新的内存管理机制,自动引用计数(Automatic Reference Count- ing,简写ARC),注意,是自动引用计数。这种自动管理内存机制跟大家所熟知的GC垃圾回收机制是不一样的,自动管理内存的原理不一样,ARC是LLVM3.0编绎器的特性之一,使用ARC,也就是使用LLVM3.0编绎器编绎程序,编绎器会在需要添加retain或release的地方自动添加(过去需要自己手动添加,有时候还惹来一大堆的内存问题)。
过去在RC机制下,对于内存管理,我们需要关心的是对象的引用计数,而在ARC机制下,也只不过换了个名称,如果我们想继续“手动”管理内存,我们需要关心的是对象的拥有者数量。在RC机制下,当对象的引用计数为0时(当然,在编绎器中去输出对象的引用计数,最小是显示是1),内存被释放回收,在ARC机制下,当对象的拥有者数为0时,系统会自动释放内存并回收,并不需要我们去release对象,这看上去很方便吧。
在ARC机制下,所谓的拥有者数,就是创建一个对象相同的指针并指向该对象即可成为该对象的拥有者, 例如:UIView*firstView=(UIView*)secondView(当然,如果该指针是弱引用则不会成为拥有者,这个概念后面会解释),一个对象可以有多个拥有者。如果要换转成RC机制的话,就变成了UIView* firstView = [(UIView*) secondView retain]。
ARC的出现,同时也产生了两个新的属性设置,Strong和Weak,在Objective c中Strong声明为强指针,强引用,而Weak则相反(弱指针,弱引用)。当一个指针被声明为Strong时,该指针可以指向某一对象并成为该对象的拥有者,而Weak只能指向对象,但不能成为拥有者,这是赤裸裸的高富帅跟屌丝的对比啊,所以在我看来,我们不妨称Strong指针为“高富帅”指针,而Weak指针,只能当屌丝指针了。好像有点跑题了,言归正传,我们来看一下强弱指针的定义。
强指针:__strong UIView*view;
弱指针:__weak UIView*view;
在前面我讲到,要注意ARC机制是自动引用计数,介绍了强弱指针,跟ARC对于内存的处理方式之后,我们就可以来讨论一下为什么强调ARC机制是自动引用计数了。一般情况下,我们会称ARC机制为自动管理内存,用了ARC就不需要理会内存问题了,妈妈再也不用担心我的内存管理,但我个人认为这是不准确的,或者说不完全的。因为一个iOSApp可以占用的内存是有限制的,虽然ARC机制可以为你自动释放内存,但是我们可以从ARC机制管理内存的原理可以看出,如果一个对象存在拥有者,编绎器就不会去释放该对象的内存,所以,当你的程序有着大量的对象一直存在拥有者时,那么,这些对象的内存就会一直不被释放,后果可想而知。由于ARC机制如此,所以,在ARC机制下,我们仍可以“手动”去管理内存。
从ARC机制管理内存的原理可以看出,编绎器释放内存的关键在于对象拥有者数,这与我们过去手动管理内理是如出一辙的,所以,抓住这原理,我们就可以在ARC机制下“手动”管理内存了。我们可以把一些不再用到的强指针设置为nil来减少对象的拥有者数。例:UIView*firstView=(UIView*)secondView; firstView=nil;当secondView这个对象的拥有者为0时,view_对象所占有的内存就会被编绎器释放并回收,对比我们过去手动管理内存,这和UIView*firstView=[(UIView*)secondView retain];[firstView release]是一样的。作为一个优秀的程序员,即使是用RC机制,我们也应该把指向已经被释放内存的指针设置为nil,防止野指针的出现。在此,我们也可以看出,Strong,Weak与retain,assign非常相似。
在编绎器的默认情况下,成员变量和局部变量为强指针(局部变量的所有权在方法结束时回收),不需要再去声明,但弱指针就需要我们去声明。ARC机制对于弱指针也是有一些处理的,当弱指针所指向的内存被释放时,该弱指针会被编绎器自动设置为nil,不需要我们手动去设置,这也减轻了我们的负担。
ARC机制管理内存是有范围限制的,ARC机制只会管理Objective c的对象,而对于C或C++的内存,则是ARC机制管理范围之外的,即,C或C++仍需要我们手动去管理内存的,当然,如果我们使用Core Fundation这个框架,也可以通过免费接桥的方式,把Core Fundation的对象的所有权转到Objective c,这样就可以转到ARC机制的管理范围内了(对于接桥这一块,有兴趣或者有需要的,可以到网上找相关的详细资料看),但不是所有都可以通过免费接桥转换。由此,我们也可以看出,ARC机制并非万能。
虽然ARC机制可以帮我们解决那些烦人的内存问题,但同时ARC机制也是有一些限制的。在使ARC机制下,不能将Objective c对象放到C的结构体中。在我们需要获取IB的对象或者自定义理代时,要把属性或者成员变量声明为Weak。ARC机制下把理代声明为Weak,这和RC机制下把理代声明为assign是一样的,目的是为了防止对象间循环引用而导致内存泄漏。由此我们也可以看出,ARC机制跟GC垃圾回收机制是不同的,GC垃圾回收机制在垃圾搜集器可以识别这种循环并释放,但ARC机制不是垃圾回收机制,仍需要手动处理所有权的循环问题,而弱指针(Weak)则可以解决这一循环问题。
ARC机制下可以重写dealloc方法,但不能添加[super dealloc];ARC机制下重写dealloc方法,有时候是很有必要的。停止计时器,反注册通知,测试内存释放等。但你所定义成员变量不再需要在dealloc方法中释放,因为ARC机制还是帮了我们不少忙的,当对象的内存被释放时,对象所有的成员变量也会被释放。
类型合同:协议
1、基本用途
1>.可以用来声明一大堆方法(不能声明成员变量)
2>.只要某个类遵守了这个协议,就相当于拥有这个协议中的所有方法声明
3>.只要父类遵守了某个协议,就相当于子类也遵守了
2、protocol协议
[objc]view plaincopy
#import
@protocolMyProtocol // 定义了一个名叫MyProtocol的协议
- (void)test;
@required// @required 要求实现,不实现就会发出警告
- (void)test1;
- (void)test2;
@optional// @optional 不要求实现
- (void)test3;
@end
: 继承父类
<> 遵守协议
[objc]view plaincopy
#import
@interfacePerson : NSObject //遵守了MyProtocol协议
@end
3、一个类可以遵守多个协议,一份协议遵守了另一份协议,就拥有了另一份协议所有声明的方法
[objc]view plaincopy
@protocol协议名称 <协议1, 协议2>
@end
4、基协议
1>.NSObject是一个基类,最根本最基本的类,任何其他类最终都要继承它
2>.其实还有一个协议,名字也叫NSObject,它是一个基协议,最根本最基本的协议
3>.NSObject协议中声明很多最基本的方法,比如description、retain、release等
4>.每个新的协议都要遵守NSObject协议
5、限制对象类型
强制要求obj保存的对象必须遵守MyProtocol协议
[objc]view plaincopy
NSObject *obj = [[Personalloc]init];
id obj = [[Personalloc]init];
类别与扩展
一、类别
OC可以为现有的类添加新的方法,并不需要通过继承的方式实现,也不需要访问原生代码,OC将这种动态特征称为类别,通过类别可以动态的为现有类添加新的方法,并且可以将类定义模块化地分布到多个相关文件中。
类别的定义方式与类有差异,类别以(类名+类别名)命名,语法格式如下:
接口部分:
@interface已有类 (类别名)
//方法定义
//...
@end
实现部分:
#import“现有类+类别名.h"
@implementation已有类 (类别名)
//方法实现
//...
@end
我们在IOS开发中也比较常用类别,比如我们有一个图片控件,但是我们需要为这个控件添加一个自动下载图片并缓存的功能,其他图片控件的功能不变,这时我们只需要使用类别就可以了。
关于类别,需要注意以下几点:
1.通过类别添加新的方法后,这个新方法不仅会影响已有类,还会影响到已有类的所有子类,所有子类都可以获得添加的方法。
2.OC允许类别重写已有类的方法,通常不推荐这么做,因为上面一条中可以知道,修改已有类,子类也会受影响。
3.如需重写已有类的方法,建议先通过已有类派生子类,子类重写父类原有方法。
4.可以根据需要为一个类定义多个类别,不同类别都可以对原有类添加方法。
5.不可以在类别中定义成员变量。
二、扩展
扩展用于临时对某个类的接口进行扩展,类实现部分同时实现类接口部分定义的方法和扩展中定义的方法,定义扩展时可以额外定义实例变量。
定义扩展的格式如下,相当于一个匿名的类别。
参考网址
http://zyc-to.blog.163.com/blog/static/17152400201111792413182/
http://www.cnblogs.com/blog-lc/p/3807273.html
http://blog.csdn.net/ollie_dannie/article/details/16886569
http://blog.csdn.net/shepqrst/article/details/44303173
http://blog.csdn.net/lingyun_blog/article/details/41822153