OC中的那些事(太基础的东西就不写了,很感谢带我们的老大<山哥>)
(里面的代码都是可以用的,建议使用的使用跟这对应版块的代码一起使用,因为很多地方我都是用上一个列子的一些属性)
1、OC中面向对象
类:类是一组相似对象的抽象集合。例如造房子的图纸是类,房子是对象。
方法:
类方法:在该方法中不能操作成员变量。类方法使用的地方就是在没有成员变量的时候使用类方法,这个时候也建议使用类方法,因为效率高于对象方法。类方法属于类,并且也只依赖于类,与对象没有关系。(注意不能在类方法中使用self调该方法),类方法中可以调用类方法。
格式:
+ (返回值类型)方法名:(数据类型)传入参数;
对象方法:该方法属于对象和类。对象方法可以调用类方法。
格式:
- (返回值类型)方法名:(数据类型)传入参数;
对象方法和函数的区别:
1、对象方法只能声明在@interface @end中间,只能实现在@implementation @end中间。
2、函数可以放在任何位置,因为它属于整个文件。不过写在@interface @end中会无法识别。函数的声明可以在main内部和main外部。
3、对象方法与函数的调用方式不一样,对象方法的调用需要对象才能完成。
4、对象方法属于对象和类。
5、函数内部不能通过成员变量名访问对象的成员变量。
成员变量
作用域
@public 全局都可以访问
@private 只有在本类中可以访问
@protected 只能在本类以及子类中访问
对象:万物皆对象,它是存放在堆中。对象在方法中传递的时候是地址传递,它可以作为方法或函数的参数在其中进行连续的传递。
对象与对象之间的关系:
1、依赖关系
当A类的一个对象作为B类的方法形参或局部变量的时候,称B依赖于A(也称has a关系)
2、关联关系
当B类中有一个成员变量是A类的实例对象,称B拥有一个A(也称is a关系)
构造方法太简单了,这里就不总结了。
2、面向对象的特性
面向对象的思想:
面向对象强调与对象,实质就是利用模块来完成需要完成的事件。与面向过程不同,面向对象不再需要自己一点一点的去完成,而是相当于找一个代理帮忙完成。比如想吃饭,不再是自己去做饭,而是去找一个厨师帮忙做饭,自己直接等着做好了吃饭就好了。
面向对象的好处:
提高代码的灵活性和可扩展性。
提高代码的可维护性。
面向对象的三大特性(有时候也称为四大特性,因为四大特性中包含了抽象)
继承:A类继承B类,那么A类将会拥有B类中所有的成员变量和方法。即使是B类中私有的也拥有,不过它没有权限。
注意:OC中的继承是单继承,但是多层继承的。
子类中不能有与父类中同名的变量。
封装:
功能封装:把一类功能封装进一个类中供外界访问。(相当于类里面的方法)
数据封装:把一个事物的所有状态特征都封装成属性。(相当于类中的属性)
属性封装:为每一个属性提供getter|setter方法。
提供的getter|setter方法中引入@property
@property标记的属性会自动为属性生成getter|setter方法。(这里只考虑ARC中)
它里面的关键字有:
atomic:表示原子性的,它是线程安全的。被这个关键字修饰的属性在其自动生成的Set方法中都会加锁。
nonatimic:表示非原子性德,它是非线程安全的。被这个关键字修饰的属性在其自动生成的set方法中不会加锁。
assign:表示直接复制,它不会生成对象。适用于标记基本数据类型。还有就是产生循环引用的对象中,解决循环引用的问题。
strong:表示强对象,它用于OC对象。任何被创建出来的对象默认都是强指针类型。
weak:表示弱对象,它也可以用来解决循环引用的问题。
copy:表示拷贝,它用于NSString | block类型。复制赋值源所生成的对象。
readwrite:表示可读可写,生成getter何setter方法。
readonly:表示可读,只生成getter方法。
setter:定制setter方法的名称,记住要在后面加上:
getter:定制getter方法的名称。
既然有了@property,接下来是点语法
点语法的实质就是setter与getter方法调用的简写形式。
如果.在等号左边,代表setter方法。
如果.在等号右边,代表getter方法。
注意在之后的调用方法中不要把点语法调用方法与对象调用方法弄混搅,记得是set属性这个才是方法名。不过点语法就不需要了。
多态
同一个指针指向不同对象的时候,表现出不同的形态。
多态的条件:
必须存在继承的关系
子类必须重写父类的方法
父类指针指向子类对象
组合模式(一个类中包含另一个类的对象):将对象组合成树形结构以表示‘部分-整体’的层次结构。
组合模式是类与类之间的关系
3、OC中类目、延展、协议、委托(代理)
类目(category):对原有类中方法的扩充。类目的名称(原有类的名称+类目的名称)
优点:代码模块化、可以扩充系统自带的功能。
注意点:
在类目中,可以访问原类的成员变量。
只能扩充方法,但是不能扩充属性。
在分类中使用@property只能生成方法的声明,不能生成方法的实现,更不能生成属性。
分类中最好不要有与原有类同名的方法,也最好不同分类中的方法都不要同名。如果分类中出现与原有类中同名的方法它会覆盖原有类的方法(即使你没有导入这个分类)。如果不同的分类中出现了同名的方法,则使用最后编译的那个分类中的方法。
类延展(Extension):给原有类增加私有方法|私有的成员变量。
在.m文件中,给原有类增加私有的成员变量和私有方法。
协议(protocol)(规定需要实现的方法)
跟java中的接口特别像,但是OC中的协议做得非常的人性化。在OC中协议里面的方法不一定都必须去实现,根据自己的需求自己去个性化设置需要的东西。
它是对象之间的约定,只有方法声明,没有方法实现。
它与类之间是多对多得关系。
一个类可以遵守多个协议,一个协议也可以被多个类遵守。
一个协议也可以遵守其他的协议或其他的多个协议。
委托|代理(delegate)
里面的进化就是在需要代理的类中设置(id)delegate属性,该属性的作用主要是用来接受愿意代理的对象。
里面的思想是面向对象的思想
比如说:
A类要做某事,让B类去给它完成。不再是自己去完成,中间完成了一个三方的过程。
委托|代理使用的场景:
1、当A类对象发生了什么事,想通知B类对象的时候。
2、当A类对象要去做某些事,自己无法做,需要B类来帮忙做。
3、当B类对象想要监控A类对象中发生事情的时候。
4、block(块):它是一种数控类型
作用:与函数一样,用来封装代理。它摆脱了不能在函数内部定义函数的问题。
格式跟函数指针类似
数据类型 (^(记住这里必须有一个空格)名称)(参数列表) = ^返回值类型(参数列表){
代码
}
调用:
名称(参数);
自定义block类型
typedef 返回值类型(^ block名称)(参数列表)
eg:
typedef void (^SHOW)();
SHOW show = ^void(){
代码块
}
注意点:
在block中可以访问局部变量,但是不能修改局部变量。但是可以修改被__block修饰过的局部变量。
在block内部中使用对象的时候,block会给这个对象施加一个强引用。
定义block作为参数传入方法中:
在方法中参数写成这样:
(void (^)()) block
eg:
方法的定义
- (int) average:(int (^)(int,int)) sum
{
return sum(10,20) / 2;
}
方法的调用:
int avr = [person average:^int(int num1, int num2) {
return num1 * num2;
}];
感觉这方法调用与我们之前的不一样了。
来分析一下:实质是怎么样的
方法的定义
- (int) average:(int (^)(int,int)) sum
{
int sum(int num1, int num2){
return num1 * num2;
}
return sum(10,20) / 2;
}
方法的调用
int avr = [person average:^int(int num1, int num2) {
return num1 * num2;
}];
这下可以看到了把,实现了在方法中定义方法。
block使用的场景:
当发现多个方法中有很多代码是相同的时候,只有一部分代码是经常改变的时候。这个时候就可以把经常变化的代码通过block参数传入。
5、复制(拷贝)
在拷贝里面,牵扯到了可变对象和不可以变对象。
可变对象:创建后可以进行增加删除修改的对象,可以在原来的对象的基础上进行增加删除修改。
(如:NSMutableArray|NSMutableString............)
不可变对象:创建后不能进行增加删除修改的对象,只要对该对象进行增加删除修改的操作都会返回一个全新的对象,并且原对象不会受影响。
(如:NSArray | NSString.............)
深拷贝:会产生新的对象的复制。
如果是不可变对象调用mutablecopy,或者是可变对象调用copy或mutablecopy都会产生一个全新的对象。
例如:
NSString 调用mutablecopy
NSMutableNSArray 调用copy
NSMutableNSarray 调用mutablecopy
NSArray *arr = [NSArray arrayWithObjects:@1,@2,@3,nil];
NSMutableArray *arrNew = [arr mutableCopy];
NSLog(@"%p,%p",arr,arrNew);
输出结果:2014-12-06 14:48:56.218 2014-12-5(下)[4069:303] 0x100107da0,0x10010dcf0
NSArray *arr = [NSArray arrayWithObjects:@1,@2,@3,nil];
NSMutableArray *arrNew = [arr mutableCopy];
NSArray *arr2 = [arrNew mutableCopy];
NSLog(@"%p,%p,%p",arr,arrNew,arr2);
输出结果:2014-12-06 14:53:24.229 2014-12-5(下)[4109:303] 0x100103520,0x1001086c0,0x100301230
这里有个注意的地方
CZDog *dog1 = [[CZDog alloc]init];
dog1.name = @"新款";
NSArray *arr = [NSArray arrayWithObject:dog1];
NSMutableArray *arrM = [arr mutableCopy];
CZDog *dog = arrM[0];
dog.name =@"妈蛋";
NSLog(@"%@,%@",dog.name,dog1.name);
看我们这里是不是产生了一个新的对象,但是我运行的时候发现两种狗的名字都是叫妈蛋。之前我也在纳闷,最后问山哥,山哥给的解释是这里复制的是对象的指针,不是对象本身。所以当我们修改的时候,另一个对象也被修改了。我们可以这样理解,就是在新的对象里面存放被拷贝对象的地址。但是新的对象不是被拷贝的那个对象。
浅拷贝:不会产生新的对象的复制。
如果是不可变对象进行copy操作,则不会产生新的对象。
例如:
NSString调用Copy操作。
NSString *str = [NSString stringWithFormat:@"abc"];
//赋值对象
NSString *str1 = [str copy];
NSLog(@"%p,%p",str,str1);
输出结果:2014-12-06 14:48:56.216 2014-12-5(下)[4069:303] 0x100103ab0,0x100103ab0
6、内存管理
内存管理分为:MRC(手动内存管理)|ARC(自动内存管理)
引用计数器:每个对象中都有一个引用计数器,并且还有一块固定的空间。只是我们大家不知道罢了,不过它是实际存在的。
使用:每当对象被创建出来的时候,引用计数器就会+1。
每当调用retain方法的时候,引用计数器也会+1。
每当调用release方法的时候,引用计数器会-1。
当一个对象的引用计数器为0的时候,这个对象会立即被回收。(这个时候它会自动执行dealloc方法,骗你是小狗。)
在MRC中我们必须遵循黄金法则:
当一个对象调用new\alloc\init\retain\copy\mutablecopy的时候,就必须调用release\autorelease方法。
在对多个对象进行内存管理的时候(注意点)
1、setter方法,当设置新对象的时候需要对新对象进行一次retain操作。当原对象不需要的时候,需要对原对象进行一次release操作。如果在发现传进set方法中的对象时原有的对象的时候则什么都不需要做。所以在设置setter方法的时候需要注意。
我给个写列子吧:
- (void)setObject:(id)obj{
if(_obj != obj){
[_obj release];
_obj = [obj reatain];
}
}
2、dealloc方法,我们需要重写dealloc方法。因为我们它满足不了现在的我们。这个方法就相当于对象的遗言,当一个对象块被释放的时候,就会调用它。然后再进行释放。不过我们要注意,每个dealloc方法的最后面都需要有一个[supper dealloc]。不然的话,,,对象得不到释放。
写个列子:
- (void)dealloc{
self.obj = nil ;释放该对象指向的那些对象,这一句需要搭配我上面写的那一句使用。不然还是屁用没有。
[supper dealloc];
}
3、循环引用,这个是内存管理里面比较大得问题,也是比较头疼的问题。
循环引用的起因:多个对象之间形成了环状,从而导致对象不能被释放。
解决方法很简单,在环路中让一段断开,也就是破话环状。让其中的一段使用assign。
头疼的内存管理之后得到了一个提高,引进了自动释放池,让iOS程序员得到了稍微的解放。
自动释放池:它的本质是一个自动释放栈,它主要是用来延迟对象的释放。
只要让对象调用autorelease方法的时候,这个对象就会被放进离它最近的那个自动释放池中。(就近原则)当自动释放池被销毁的时候它会对池中的每一个对象进行一次release操作。因此就不用每时每刻去关心对象的释放了,也让iOS程序原得到了稍微的解救。
不过这里有一个注意点:
一个对象调用多少次autorelease操作,它在自动释放池销毁的时候就会调用多少次release操作。
但是它还是有问题的,如果当程序占用内存空间很大的时候如果不及时释放空间,会导致程序闪退的。但是释放又得等待自动释放池销毁。
因此它只使用于对象占用内存较小,使用次数比较小的地方。
在ARC中,我们就再也不用过多的担心内存问题了。所有的一切都变得这么自然,感觉回到了java的世界。
在ARC中引入了自动引用计数,它是编译器的特性,会在适当的位置自动插入内存管理的代码。
强指针:默认所有的指针都是强指针。只要是被强指针指向的对象,这个对象就不会被销毁。只要没有被强指针指向的对象,就会被立即销毁。关键词:__strong
弱指针:它不会影响对象的销毁。弱指针指向刚创建出来的对象,跟本就指不上好不好,直接被销毁了还指个毛啊。它就是克夫的,坑爹啊... 关键字__weak.
不过硬是想指的话也不是不可以,它可以指向一个强指针对象。
循环引用:不要以为只有MRC中才会遇到这个问题,ARC也好不到哪去。不然那个__weak还拿来搞毛啊,不就是现在派上用场,切断环啊,这里地切不是真正的直接弄断啊,只是说的是让它指向一个强指针对象。并不是让它死。
7、foundation
这东西最尼玛烦,东西多得要死。
还是得一个个理一下,哥是来做总结的。只能比较少间的,什么创建啊,什么简单地调用啊,全部都不搞了。
几千个API实在搞不完啊
我们宗旨是上去就是干
这里想强调一下,NSMutable与NS的区别:NS代表的时不可以变得,而NSMutable代表的是可以变的。
这里需要强调的是通过字面量创建踹的对象保存在常量区,通过对象方法和类方法创建出来的对象保存在栈中。
结尾的时候我会补充内存里面的东西,内存管理中的东西。
直接上上代码:
NSString *str = [NSString stringWithFormat:@"itcast,传智广告"];
//获取字符按的长度
int strCount = str.lenght;
//获取字符串里面的单个字符
unchar *singleChar = [str characterAtIndex:1];
//获取从开始位置到某个索引的子串
NSString *subString = [str subStringToIndex:2];
//获取从索引位置开始到字符结尾的子串
NSString *subString = [str subStringToIndex:2];
//字符串的每个单词首字母转成大写
[str capitalizedString];(capitalize的意思是用大写字母写)
//获取某个区间的字串
NSString *rangeString = [str subStringWithRange:NSMakeRange(1(索引位置), 2(长度))];
//获取一个子串所在该字符串中的区间(它查找的方式是从前往后找)
NSRange range = [str rangeOfString:@"cast"];
//rangeOfString方法还可以指定查找方式
NSRange range = [str rangeOfString:@"cast" options:NSStringCompareOptions(从下面挑一个) ]
NSStringCompareOptions:
NSCaseInsensitiveSearch不区分大小写(Insensitive的意思是莫不关心的)
NSLiteralSearch 一个字符一个字符的进行比较,严格区分打小写(Literal的意思是逐字的)
NSBackwardsSearch 从后往前查找
NSRegularExpressionSearch 使用正则方式查找
NSBackwardsSearch 从后往前查找
这里太烦了,就弄一点复杂的。以后用的时候直接查API就可以了。
这里给我的感觉是需要是,就像写对象的东西开头,一般都会有提示。也就是碰上死耗子把。
C语言的字符串转OC字符串(把NSString 写完在写string它会有提示,这样可以不用去找头文件找。)
[NSString stringWithCSString:"C语言" encoding:NSUTF8Encoding];
[[NSString alloc] initWithCString:"C语言" encoding:NSUTF8Encoding];
OC字符串转C语言字符串
NSString *str = @"继续广告itcast";
[str cStringUsingEncoding:NSUTF8StringEncoding];
这里需要注意的地方是: == | isEqualToString ==比较的是两个字符串的地址是否相等,isEqualToString比较的是两个字符串的内容是否相等。
我们来完成一个小例子:(直接写的,没测试过。不过一般应该不出意外的话,没问题)
判读字符内容相等的方法
第一步:如果两个字符串地址相等返回YES
第二步:一个字符一个字符的比较遇到不相等的字符就返回NO
第三步:返回YES
- (BOOL) compareSameStr:(NSString *)str andOtherStr:(NSString *)other{
if(str == other){
return YES;
}else{
if(str.length != other.length){//写这个的好处是如果长度不一致了就不用在去一个个比较字符了,这叫提升效率。
return NO;
}else{//这个就没得办法了,还是的继续搞起
for(int i = 0 ; i < str.length ; i++ ){
unchar *singleStrChar = [str characterAtIndex:i];
unchar *singleOtherChar = [other characterAtIndex:i];
if(singleStrChar != singleOtherChar){
return NO;
}
}
}
}
return YES;
}
判断字符串的开头和结尾
NSString *str = [NSString stringWithFormat:@"www.csdn.com"];
BOOL isWWW = [str hasPrefix:@"www"];
BOOL isCom = [str hasSuffix:@"com"];
字符串的比较
NSString *str = @"ganjuemengmengda";
NSString *str1 = @"ganjuezijimengmengda";
NSComparisonResult result = [str compare: str];
这里我是想让大家看看NSComparisonResult这个枚举里面的内容
NSOrderedAscending str > str1
NSOrderedSame str == str1
NSOrderedDescending str < str1
在compare方法里面也有option
NSString *str = @"ganjuemengmengda";
NSString *str1 = @"ganjuezijimengmengda";
NSComparisonResult result = [str compare: str options: NSStringCompareOptions];
NSStringCompareOptions枚举:
NSCaseInsensitiveSearch 不区分大小写
NSNumericSearch 用来比较数值的字符串,以数值的方式进行比较。
等等我们在NSArray排序的时候,给大家来个自定义的比较器
妈蛋好累,现在终于体会到山哥,为什么说有时候上课上太久了想吐了。但是总结还得干阿。上去就是干走起。。。
字符串的替换(在这里的话都敲stringBy开头)
不过这里有个注意点,只要我一修改NSString里面的东西都会产生一个新的对象。反正这个错误我犯了两次,现在记住了。在这里分析一下,原有是NSString是一个以NS开头的它不可以变的,只要被修改马上返回一个对象。不过这里我们有个方法可以解决这个问题。感觉就像可以被修改一样,办法就是让对象自己去指一下修改后的自己。这样就可以达到我们想要的结果了。当然这里说是不能体现的,我们直接上代码。
NSString *str = @"phome我又想到你了";
//使用某个字符串替换原来字符串中某个区间的字符串
(这个就是解决上面写的那段话)
str = [str stringByReplacingCharactersInRange:NSMakeRange(locate,length) withString:@"itcast的了" ];
//替换原有字符串中所有指定的字符
NSString *str = @"http://blog.csdn.net/jpywan";
str = [str stringByReplacingOccurrencesOfString:"." withString:@""];
这个也通过可以用来删除指定的东西,只要把后面的withString弄成空串就好了
是不是在java中又去掉空格的函数,当然oc中也是有的。不过它去掉头部很尾部的空格,不像java那样一个trim全部给你弄掉,这个就是OC的魅力所在。
NSString *str = @" d d d d ";
str = [str stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
在NSCharacterSet里面有很多方法,我们掌握一些常用的就好了。
whitespaceCharacterSet 去除首尾的空格
characterSetWithCharactersInString:@"指定字符" 去除首尾指定的字符
来看我们的代码:(刚刚吓坏了,写到这我也卡住了。记住最后要保证你去除的字符必须在首或者尾不然更没用差不多,妈蛋学习了。)
NSString *str = @" js k sd a";
str = [str stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"a"]];
NSLog(@"%@",str);
whitespaceAndNewlineCharacterSet 表示空格和换行符
NSCharacter主要使用在网络处理的时候,之后到网络处理部分我会总结出来。
接下来是一个比较好的字符串的拼接,当然这些东西很多语言中都会有。我有个朋友做了2年的C#,现在在跟我一起学iOS,它说的是C#的智能化比iOS牛多了。但是我想说的是iOS的魅力不是在智能化上,而是它跟倾向于文章和句子。
NSString *str = @"itheima";
str = [str stringByAppendingPathComponent:@"学习"];
这里我们稍微嵌入一些文件的东西,就嵌入路劲好了,因为路劲也是字符串。
之前大学弄java判断路劲是不是还是有点痛苦的,现在这里只要一行代码就搞定。虽然我的java功底也只有一年的经验,但是我从iOS感到了很多方便。也许这就为为什么Android开发需要5个月,iOS只要2-3个月就可以扫平了吧。
//判断是不是据对路径
NSString *str =@"屏幕快照 2014-12-06 上午12.19.55.png";
BOOL isAbsolute = [str isAbsolutePath];
NSLog("%d",isAbsolute);
是不是感觉很爽。爽得还在后面UI部分,特别是做刷新的时候。做过Android的就知道什么叫痛苦了,反之我是不想在痛苦了,因为我转行了。。。
//获取路径的最后一部分(应该叫资源部分)
NSString *path=@"/Users/jinpengyao/Desktop/屏幕快照 2014-12-06 上午12.19.55.png";
NSString *source = [path lastPathComponent];
NSLog(@"%@",source);
//扩展路径
NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:@"jpy.jsp"]
//获取文件的扩展名
NSString *path=@"/Users/jinpengyao/Desktop/屏幕快照 2014-12-06 上午12.19.55.png";
NSString *extension = [path pathExtension];
有获取肯定就应该有删除
//删除扩展名
NSString *path=@"/Users/jinpengyao/Desktop/屏幕快照 2014-12-06 上午12.19.55.png";
NSString *deleteExtension = [path stringByDeletingPathExtension];
有删除肯定也是会有增加的,正所谓得失的问题嘛。需要平衡。。。
//为文件末尾增加一个扩展名
NSString *path=@"/Users/jinpengyao/Desktop/屏幕快照 2014-12-06 上午12.19.55.png";
NSString *deleteExtension = [path stringByDeletingPathExtension];
NSString *insertExtension = [deleteExtension stringByAppendingPathExtension:@"jpg"];
NSString *extension = [insertExtension pathExtension];
这里我们就写一些简单地写入文件操作和读取文件操作,之后的归档在后面总结。
写入文件操作
NSError *error; 这个变量是用来保存错误信息的。
BOOL isSuccess = [path writeToFile:@"/Users/jinpengyao/Desktop/1.txt" atomically:YES encoding:NSUTF8StringEncoding error:&error];
我来解释一下里面的atomically,它表示的是原子性的。什么是原子性的,这时线程里面的问题。就是一个加锁的问题,这里我们写的是YES采用的是单线程传输。
if(isSuccess){
NSLog(@"文件写入成功");
}else{
NSLog(@"%@",error);
}
读文件
NSError *error;
NSString *str =[NSString stringWithContentsOfFile:@"/Users/jinpengyao/Desktop/1.txt" encoding:NSUTF8StringEncoding error:&error];
if(error){
NSLog(@"%@",error);
}else{
NSLog(@"%@",str);
}
好我在这里解释一下encoding,它里面的东西其实就是一个枚举类型的数据,下面是从API里面扒出来的一部分东西。反正我没怎么研究,一般都是使用UTF8
NSASCIIStringEncoding = 1,
NSJapaneseEUCStringEncoding = 3,
NSUTF8StringEncoding = 4,
NSISOLatin1StringEncoding = 5,
NSSymbolStringEncoding = 6,
NSNonLossyASCIIStringEncoding = 7,
NSShiftJISStringEncoding = 8,
NSISOLatin2StringEncoding = 9,
NSUnicodeStringEncoding = 10,
NSWindowsCP1251StringEncoding = 11,
NSWindowsCP1252StringEncoding = 12,
NSWindowsCP1253StringEncoding = 13,
NSWindowsCP1254StringEncoding = 14,
NSWindowsCP1250StringEncoding = 15,
NSISO2022JPStringEncoding = 21,
NSMacOSRomanStringEncoding = 30,
现在我们来看一个可以变的字符串
NSMUtableString(它是NSString的子类,所以它老的伙有的东西它肯定也是有的。这样我们就捡到到宝了,只要掌握上面那货,这货也会了。)
下面我们写一些它特有的东西以及重写的一些东西:
字符串的拼接
NSMutableString *mString = [NSMutableString stringWithFormat:@"德玛西亚"];
[mString appendFormat:@"潘金莲"];
在指定位置插入一个字符串
[mString insertString:@"西门庆玩" atIndex:0];
使用新的字符串替换字符串中已有的字符串
NSMutableString *mString = [NSMutableString stringWithFormat:@"东了个西"];
[mString replaceCharactersInRange:NSMakeRange(0, 2) withString:@"xixi"];
写的好累了,自己也是拼了。
NSMutableString *mString = [NSMutableString stringWithFormat:@"德玛西亚"];
[mString replaceOccurrencesOfString:@"德玛" withString:@"haha" options:NSCaseInsensitiveSearch range:NSMakeRange(0, 3)];
NSLog(@"%@",mString);
这个方法主要是多了一个查找范围NSStringCompareOptions这个枚举之前在NSString的compare里面说过。
有增加当然就会有删除
删除某个区间的字符串
NSMutableString *mString = [NSMutableString stringWithFormat:@"德玛西亚"];
[mString deleteCharactersInRange:NSMakeRange(0, 2)];
不可变字符串转可以变字符串
NSString *str = @"deldel";
NSMutableString *mStr = [str mutableCopy];
是不是有种感觉想吐的冲动,终极boss李明杰狂人,应该现在还处于兴奋状态。这些都是半个月学的东西,foundation框架两天扫平,扫平之后点脾气都没有了。就尼玛这玩意最多,烦得要死。当然不一定要全部掌握,只要有印象就好了,以后用到了再查API。在这里的话foudation框架只写了一小部分而已,还剩余几千个。东西还是得写啊,上去就是干。
接下来写集合类:
集合类的主要作用是用来保存OC对象,基本数据类、结构体、枚举是不能放进去的。这点跟java不一样,他是有严格限制的。记得之前我们写java的时候什么int啊什么float啊,直接塞。但是我们从来没有考虑过集合的感受。iOS做到了,它开始考虑集合的感受了。淡然并不是集合的感受,如果对象跟那些玩意混杂在一起,是不是很容易混乱。没有同一的规范是不好的。
集合类的话,先写数组吧
可变数组:注意这里的数组跟java里的数组不一样,这里的数组可以存放不同类型的对象。不过其他的性质还是一样的,比如有序啊,可以存放重复值。不过为了开发的方便操作数据,我们还是让数组中只存储一种类型的对象。
太基础的东西我不写了,有点扛不住了。从12点写到现在。
可以变数组的快捷创建方式
NSArray *arr = @[@"1",@"2",@"2"];//注意这里是[],不要写成{},{}是集合的东西。之前我也经常写错。
在这里我要引人一个新的东西,大家知道为什么我们要再字符串之前写@吗?@的作用就是对象,把后面的东西变成对象。 @1这个代表一个数值为1的整型变量。
访问数组的快捷方式:
NSString *str = arr[0];
判断数组中是否包含某个对象
NSArray *arr = @[@"1",@"2",@"3",@"4"];
BOOL isExist = [arr containsObject:@"3"];//这里的containsObject的内部其实是调用isEqual方法来判断的。
可变数组的遍历
普通的for|增强的for我就不写了,写一些我没遇到过的新东西。
使用block进行遍历
NSArray *arr = @[@"1",@"2",@"3",@"4"];
[arr enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
//obj是转换之后的对象,我们也可以进行修改。可以修改成自己定义的对象,或者集合对象,idx指定的是下标,而stop是用来控制遍历的。
//我们来进行一下改装在碰到2的时候结束变量
if(idx == 1){
*stop = YES;//注意这里必须给我带上*号,之前我也没带。之后发现就报个黄线,其余什么都没用。
}
NSLog(@"%@",obj);
}];
使用枚举器进行遍历(这个几乎不用,但是我觉得有点高级,所以就弄下来了。因为block遍历的原理也是枚举器)
NSArray *arr = @[@"1",@"2",@"3",@"4"];
NSEnumerator *enumerator = [arr objectEnumerator];
NSString *str ;
while(str = [enumerator nextObject]){
NSLog(@"%@",str);
}
遍历我们弄完了,现在我们来弄排序
使用选择器进行排序(记住这种排序的一半都是敲sort)
首先我们定义一个方法用来进行排序
来我们定义一个自己的排序器
这里我就不写Person类了,直接简化了。(类里面包含两个属性:age,name)
这个是写在类里面的方法( 先比较年龄,如果年龄相同就比较名子)
-(NSComparisonResult)compare:(Person(这个是自己定义的对象))other{
if(self.age == other.age){//首先我们来比较里面的age
return [self.name compare: other.name];
}else if(self.age > other.age){
return NSOrderedDescending;
}else{
return NSOrderedAscending;
}
}
NSComparisonResult是一个枚举类型:
里面的值有
NSOrderedDescending 小于的时候
NSOrderedAscending 大于的时候
NSOrderedSame 相等的时候
//看到了吗?我在用了偶。@selector
arr = [arr sortedArrayUsingSelector:@selector( compare:)];
使用比较器block感觉这个跟上面那个差不多,我还是在写一下吧。
arr = [arr sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
return [obj1 compare:obj2];
}];
使用属性描述(这里我们又借用了一下Person类,不然再这里说不清楚)
NSSortDescriptor *sdAge = [NSSortDescriptor sortDescriptorWithKey:@"age" ascending:YES ];
NSSortDescriptor *sdName = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES];
arr = [arr sortedArrayUsingDescriptors:@[sdAge,sdName]];//注意这里面的值是NSArray类型的,如果到时候我们忘记是什么类型了,我们可以查查头文件,里面写得有。
接下来这个方法碉到堡,反正我是被震撼了。太牛逼了
让数组里面所有的对象都执行一下选择器里面的方法
arr = [arr makeObjectsPerformSelector:@selector(minOne) withObject:传入参数];
(看见了没有只要是字符串转数组|数组转字符串中都是使用component,为什么要这个单词呢,component的意思的零件的意思。componentsSeparatedByString的意思就是把String才分成零件,componentsJoinedByString把零件组合成一个字符串)
字符串转数组
NSString *str =@"a,b,c,d";
NSArray *arr = [str componentsSeparatedByString:@","];
数组转字符串
NSArray *arr = @[@"1",@"2",@"3",@"4"];
NSString *str = [arr componentsJoinedByString:@"."];
这里又要来文件操作了,你们是不是很开心啊?反正我是很开心。。。编程就是这么有趣,突然我发现我的春天来了...刚跟女友分手,现在的我找到了完全的替代品。
写入文件
BOOL isSuccess = [arr writeToFile:@"/Users/jinpengyao/Desktop/arr.txt" atomically:YES];
从文件中读出
NSArray *arr = [NSArray arrayWithContentsOfFile:@"/Users/jinpengyao/Desktop/arr.txt"];
可变的数组完了,我们是不是还有不可变的数组。接着来,上去就是干...
在这里我们就没有所谓的快捷的构造方法了,但是我还想用。因此这里我们还是可以偷偷懒的。
接下来看我写(快捷创建可变数组的方式)
NSMutableArray *mArray = [NSMutableArray arrayWithCapacity:10];//这段代码的意思就是让定义一个容量为10的变数组,当然我这样定义的也是徒劳,因为这玩意可以变。不过为了规范,所我就这样写了。
mArray.array = @[@"lala",@"haha",@"dudu",@"pipi"];
向数组的尾部添加对象
[mArray addObject:@"lolo"];
既然可以在尾部添加对象,当然在其他任意位置也可以进行添加。不要问我为什么,这就是iOS的魅力
[mArray insertObject:@"doudou" atIndex:2];
既然有增加当然也有删除得了
删除指定下标的对象
[mArray removeObjectAtIndex:1];
删除指定的对象
[mArray removeObject:@"lala"];//注意这里面匹配的时候,使用的还是isEqual方法。还记得我之前进行匹配的时候吗,里面的机制也是isEqual。所以只要是匹配都与这玩意有关。
删除指定区域的对象,是不是再次体验到iOS的强大了。没错这就是iOS的魅力
[mArray removeObject:@"haha" inRange:NSMakeRange(0, 3)];//这里注意啊,不要在range里面搞越界啊。只要是使用range的地方都不要搞越界。
最后来个最大的删除,没错就是清空
[mArray removeAllObjects];
最后我们来写一个例子
遍历并删除数组
这里我们需要注意的地方是在枚举器|增强的for 中我们是无法实现的,因为在枚举器|增强的for 中我们能做的只是遍历,但是无法操作里面的元素。注意啊,不要冤枉啊。我之前弄的排序使用的是比较器,我没有使用枚举器啊,因为差点自己把自己弄混搅了。
好了现在我们开始吧,使用for的我就不写了,太简单了。写着太浪费时间了。
直接上假像的for增强把,我之所以这样说。看完代码的你就懂了
NSMutableArray *tempMArray = [NSMutableArray arrayWithCapacity:10];
for (id obj in mArray) {
[tempMArray addObject:obj];
}
[mArray removeObjectsInArray:tempMArray];
结果不负众望全部被删除了,但是这一点意义都没有。我只是把mArray里面的数据一个一个加入进tempMArray里面去了。最后使用对照数组里面的元素移除需要移除的数组而已。
这里我只想讲一下这个方法,当然仅是玩笑而已。当然这个例子没有任何意义。不过这个方法是有意义的。
NSArrat转NSMutableArray
其实在之前我们使用的那个快捷创建NSMutableArray方法里面就已经使用到了。
NSMutableArray *mArray = [NSMutableArray arrayWithCapacity:10];
mArray.array = @[@"lala",@"haha",@"dudu",@"pipi"];
反正我看见它之后整个人都好了...
接下来我们来写常用的结构体吧,在之前的数组中啊字符串中啊。我们都有接触一个叫rangge的东西。我们首先来看这玩意
这些结构体在UI里面用得比较多
NSRange 它表示的是一个区间,有两个属性一个是location表示的是当前的位置,一个是length表示的是长度
用法
NSRange的快捷构造方法
NSRange range = {(NSUInteger)locate,(NSUInteger)length};//这个是快捷方式,不要跟之前的快速定义数组的方法记混搅了。反正我是刚刚弄混搅了
再来介绍一下NSPoint
NSPoint point =NSMakePoint(double x,double x);
再是NSRect 它表示平面上的一个区域,之后用来做空间的定位
NSRect *rect = NSMakeRect(<#CGFloat x#>, <#CGFloat y#>, <#CGFloat w#>, <#CGFloat h#>);
再是NSSize 它表示的是尺寸
NSSize size = NSMakeSize(CGFloat w, <#CGFloat h#> );
或许有些枯燥,但是我们还得学啊。没办法
来看看结构体转字符串是怎么写的
在这里我就写一个range和一个rect的转换方式,因为四个结构都是一样的方法
range:
NSRange range = {10,20};
NSString *str = NSStringFromRange(range);
rect:
NSRect rect = NSMakeRect(10,20,10,10);
NSString *str = NSStringFromRect(rect);
我们继续来写集合类中的东西,有点上头了。
来我们开始写下字典:首先我们要明白什么是字典,字典在OC中其实就是用来存放对象的键值对,说白了就是跟java俩面的集合一样,有键也有值。它没有顺序,里面存放的值可以重复,但是键不能重复,因为每个键都是唯一的标示符嘛对不对。不过注意,里面的Key必须遵守NSCoping,官方使用的是NSString,并且提示也是使用NSString。之前我也在想是不是可以使用__block,不过辅导员醒哥说这个是官方的东西。最好遵守它。
快捷定义字典:
NSDictionary *dict = @{@"name" : @"哈哈" , @"age": @16 };//之前我又搞错了,就是这么幽默。注意啊,这里是花括号了,之前我一直老师记错。结果一个劲的报错,害我重启机器,删缓存,clean就差没卸载工具了。反正这里就是强调要记住
会了创建,我们来操作:
首先是查看有多少键值对吧
[dict count];/dict.count 它的返回值是ld类型的
//快速获取value
NSString *str = dict[@"name"];
学了基本用法,现在来稍微搞点有点点难度的东西
之前我们的遍历方式有for\forin\while\枚举器\block方式啊
这里面的for\while我就不写了,太浪费时间了。感觉forin也没必要,还是写一下把
forin方式
NSDictionary *dict = @{@"name" : @"哈哈" , @"age": @16 };
for (id obj in dict) {//注意obj现在时里面的键,我之前反之是弄错了,我把它当做对象了然后一个劲的obj[@"name"],反正就是死活不出来
NSLog(@"%@ = %@",obj,dict[obj]);
}
枚举器方式
//这个搞出来的键对象
NSEnumerator *enumerator =[dict keyEnumerator];
id obj = nil;
while (obj = [enumerator nextObject]) {
NSLog(@"%@",obj);//注意这里的obj现在时键对象
}
//这个搞出来的是值对象
NSEnumerator *enumerator = [dict objectEnumerator];
id obj = nil;
while (obj = [enumerator nextObject]) {
NSLog(@"%@",obj);//注意这里的obj现在是值对象
}
至于为什么有这两中方式,我们是不是看到了keyEnumerator和objectEnumerator,所有才有个这两种方式。很显然有人会问,就弄key枚举器不就好了。当然这个是可以的,我就是在逗你们啊。。
是不是现在我们还差一种枚举的方式就弄完了
来,上去就是干。
block方式
[dict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
NSLog(@"%@ = %@",key,obj);
}];
反正这种是使用得最多的一个,跟提莫一样。
好现在我们来弄排序,就是排序。你觉得你需要的话,你自己弄。反正我是不需要。
好了来进行字典的最后一项,文件操作
写入文件
好了,不想写了。感觉没意义。
从文件中读取
好了,不想写了。感觉没意义。
现在我们来弄可变得字典
创建 在这里我要强调一下,以后凡是用到NSMutable的集合的时候,初始化给我吧容量分配好。这个是规范。
NSMutableDictionary *mDitc = [NSMutableDictionary dictionaryWithCapacity:10];//不要问我为什么要这样写,这是规范
mDitc.dictionary = @{@"name":@"嘟嘟",@"age":@12};
来我们来进行操作
//插入数据
[mDitc setObject:@"KEKE" forKey:@"NICK"];//注意这个方法也可以用来修改数据
//快捷获取里面的数据
NSString *str = mDitc[@"NICK"];
//删除数据
[mDitc removeObjectForKey:@"NICK"];
//在来弄个一次性删除一个数组中与它对应的数据
[mDitc removeObjectsForKeys:@[@"name",@"age"]];
//大清空
[mDitc removeAllObjects];
接下来介绍一个不是怎么重要的东西,为什么说不重要呢。因为很少用,我记得在java中这东西也不怎么用,一般都是array|dictionary之类的东西。
set是什么呢,set也就是一个集合,一个不能有重复值并且没有顺序的集合。那么为什么有时候它还会被使用呢?它仅仅就是靠效率比数组高的这一点存在,因为没有顺序嘛,也就在数组的基础上砍去了索引。因此导致它的效率高于数组。
注意这里面没有快速创建
这里我们就学习一个方法
判断集合中是否包含某一个元素
NSSet *set1 = [NSSet setWithObjects:@1,@3,@3,nil];
BOOL isContaint = [set1 containsObject:@2];
至于NSMutableSet这里我就不写了东西都是那些,写去写来根本没意义。
集合之间的类型转换我是在啰嗦一下
NSMutable与NS之间的转换在这里就不写了,太简单了。还是写一个把
来一个NSArray转NSMutableArray的
NSArray *array = @[@1,@2,@3];
NSMutableArray *mArray = [NSMutableArray arrayWithArray:array];
反过来
NSMutableArray *mArray = [NSMutableArray arrayWithCapacity:10];
mArray.array = @[@1,@2,@3];
NSArray *array = [NSMutableArray arrayWithArray:mArray];
这里我们主要介绍的是NSArray转NSSet | NSDictionary转NSArray
NSArray *array = @[@1,@2,@3,@4];
NSSet *set = [NSSet setWithArray:array];
NSLog(@"%@",set);
注意这反过来是没有的啊
NSDictionary *dict = @{@"name":@"haha",@"age":@12};
NSArray *arrKey =[dict allKeys];
NSArray *arrValue = [dict allValues];
集合中的内存管理
MRC中:
当一个对象放在集合中的时候,集合会对这个对象进行一次retain操作。
当把一个对象从集合中移除的时候,集合会对这个对象进行一次release操作。
当集合被销毁的时候,会对集合中的每一个对象进行一次release操作。
ARC中:
当一个对象被放在集合中的时候,集合会对它又一个强引用。
当把一个对象从集合中移除的时候,集合会释放掉对这个对象的强引用。
当集合销毁的时候,会释放掉集合中的所有对象的强引用。
好了现在我们来写NSNumber(包装类)
NSNumber的作用:对象与基本数据类型之间进行转换。因为集合中只能存放对象,基本数据类型弄不进去。所以就需要借助它来包装一下。
好现在来包装
基本数据类型转包装类型
NSNumber *number = [NSNumber numberWithInt:111];
//这个我是不怎么熟悉的。所以现在写一写
unichar c = 'a';
NSNumber *number = [NSNumber numberWithUnsignedChar:c];
剩余的我就不写了
包装类型转基本数据类型
int intNum = [numberI intValue];
unichar z = [numberC charValue];
剩余的都是这样这里就不写了
基本数据类的包装有了我们是不是还缺少些东西,肯定结构体也是存在包装的。因为我们有时候需要把结构体存放进集合中。
NSValue的作用:对象与结构体之间进行转换,因为集合中只能存放对象,结构体是存放不了的,因此引入对结构体的封装。
好现在我们来包装,先包装非自定义的结构体吧。
结构体类型转包装类型
这里我们就随便写几个
NSRange range = {10,20};
NSValue *value = [NSValue valueWithRange:range];
NSRect rect = NSMakeRect(0, 0, 20, 20);
NSValue *valueRect = [NSValue valueWithRect:rect];
自定义的结构体类型转包装类型
typedef struct {
int age;
}Person;
这个结构体是定义在main函数之前的
Person person = {10};
NSValue *value = [NSValue valueWithBytes:&person objCType:@encode(Person)];
这不熟悉,多来几遍
这个结构体是定义在main函数之中
struct Person {
int age;
};
Person person = {10};
NSValue *value = [NSValue valueWithBytes:&person objCType:@encode(Person)];
NSLog(@"%d",person.age);
包装类型转常见的结构体
NSRange range1 = valueRange.rangeValue;
NSRect rect = valueRect.rectValue;
包装类型转自定义结构体(这里不方便查看,我就把全代码放这里)
struct Person {
int age;
};
Person person = {10};
NSValue *value = [NSValue valueWithBytes:&person objCType:@encode(Person)];//包装
Person person1 ;
[value getValue:&person1];//解封
这里不怎么熟悉多写一遍把
struct Person{
int age;
};
Person person = {10};
NSValue *value = [NSValue valueWithBytes:&person objCType:@encode(Person)];
Person person1 ;
[value getValue:&person1];
是不是一直在纠结时间的怎么没有,之前我也在纠结。现在来些NSDate之后再弄NSCalender,这里面我会写一个我得到的收获,包括很多人都不知道一个方法
开始:
先来介绍一下NSDate,它是一个日期类,记住不要把它与之前我们写的结构体弄混搅它是一个类与集合类一样,不是基本数据类型。
创建一个当前日期的对象
NSDate *date = [NSDate date];
创建日期类的方法我就随便介绍一个,之后要使用再查API就好了
//这个方法的创建是生产一个未来距离现在有多少秒的日期对象,后面的参数是秒数
NSDate *date = [NSDate dateWithTimeIntervalSinceNow:222022];
有了这些方法,我们是不是会想到如果我想自己定义一个时间怎么定义,不可能一点一点去算秒数吧。当然这不是我们需要关心。系统提供了一个方法解决我们的问题看我操作
这里需要用到一个日期格式化对象,之后我扩充的也是使用这个对象展开的
NSDateFormatter *formate = [[NSDateFormatter alloc]init];
formate.dateFormat=@"yyyy年MM月dd日 HH时mm分ss秒";
NSString *sTime = @"1992年3月4日 12时35分22秒";
NSDate *date = [formate dateFromString:sTime];
NSLog(@"%@",date);
这里需要注意的地方是formate.dateFormat=@"yyyy年MM月dd日 HH时mm分ss秒";
NSString *sTime = @"1992年3月4日 12时35分22秒";
这里面的格式需要保持一样,format里面是什么字符串定义的格式就应该写成什么样子,如果不遵循这个规则的话,你将永远得到的都是一个空值。
这里我还要补偿一个东西,这个东西是java中没有的东西。可能是没有吧,反正我每碰到过。我就默认它没有吧,主要是担心弄混乱。
日期比较,以后我们在按年龄排序的时候可以用到。像什么银行排队办理业务老人优先的时候,这个方法就派上用场了。当然我每做银行的系统,做了也只做了一周多一点就出来转行做iOS了。
来操作日期
首先判断两个日期是否相同
NSDateFormatter *formate = [[NSDateFormatter alloc]init];
formate.dateFormat=@"yyyy年MM月dd日 HH时mm分ss秒";
NSString *sTime = @"1992年3月4日 12时35分22秒";
NSDate *date = [formate dateFromString:sTime];
NSDate *date1 = [NSDate date];
BOOL isEqual = [date isEqualToDate:date1];
NSLog(@"%d",isEqual);
比较两个日期
NSDateFormatter *formate = [[NSDateFormatter alloc]init];
formate.dateFormat=@"yyyy年MM月dd日 HH时mm分ss秒";
NSString *sTime = @"1992年3月4日 12时35分22秒";
NSDate *date = [formate dateFromString:sTime];
NSDate *date1 = [NSDate date];
NSComparisonResult result = [date compare:date1];
if(result == NSOrderedSame){
NSLog(@"相等");
}else if(result == NSOrderedAscending){
NSLog(@"date > date1");
}else{
NSLog(@"date < date1");
}
返回较早的一个日期
NSDateFormatter *formate = [[NSDateFormatter alloc]init];
formate.dateFormat=@"yyyy年MM月dd日 HH时mm分ss秒";
NSString *sTime = @"1992年3月4日 12时35分22秒";
NSDate *date = [formate dateFromString:sTime];
NSDate *date1 = [NSDate date];
NSDate *earlyDate = [date earlierDate:date1];
NSLog(@"%@",earlyDate);
好了,我这里弄一个我收获的方法吧。因为它是NSDate部分的东西
NSDate *date = [NSDate date];
NSDateFormatter *formate = [[NSDateFormatter alloc]init];
formate.dateFormat=@"EEEE";//三个以上的是星期|三个以及三个以下是周
NSString *str = [formate stringFromDate:date];
NSLog(@"%@",str);
输出结果为:
2014-12-07 18:26:30.323 OC大总结[1824:303] 星期日
这里我们再也不用苦逼的做着什么is啊什么switch啊。
日期类写完了,我们是不是还有一个日历类啊,它主要是用来做日历的。
NSCalendar
获取当前日历对象
NSCalendar *calend = [NSCalendar currentCalendar]
获取日期的某些部分<这个是我觉得最好玩的地方,它可以把一个日期的所有东西都拆分出来,这个是相当的调啊...>
NSDate *date = [NSDate date];
NSCalendar *calend = [NSCalendar currentCalendar];
int unit =NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute |NSCalendarUnitSecond ;
NSDateComponents *cmps = [calend components:unit fromDate:date];
NSLog(@"%ld,%ld,%ld",cmps.year,cmps.month,cmps.day);
来我们再写一遍
NSDate *date = [NSDate date];
NSCalendar *calend = [NSCalendar currentCalendar];
//创建一个int类型的unit主要是用来存放要拆分出来的那些组件
int unit =NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay ;
NSDateComponents *cmps = [calend components:unit fromDate:date];
NSLog(@"%ld,%ld,%ld",cmps.year,cmps.month,cmps.day);
我们在来弄计算两个日期之间的差
NSDateFormatter *formate = [[NSDateFormatter alloc]init];
formate.dateFormat=@"yyyy年MM月dd日 HH时mm分ss秒";
NSString *sTime = @"1992年3月4日 12时35分22秒";
NSDate *date = [formate dateFromString:sTime];
NSDate *date1 = [NSDate date];
NSCalendar *calend = [NSCalendar currentCalendar];
int unit = NSCalendarUnitDay;
NSDateComponents *cmps =[calend components:unit fromDate:date toDate:date1 options:NSCalendarWrapComponents];
NSLog(@"%ld",cmps.day);
在原有时间上面添加时间(这里添加只是组件,之前我也蒙了一下,把时间塞进去,一直弄不进去。之后发现是塞组件)
NSDate *date1 = [NSDate date];
NSCalendar *calend = [NSCalendar currentCalendar];
NSDateComponents *cmps = [[NSDateComponents alloc]init];
cmps.day = 365;
NSDate *newDate = [calend dateByAddingComponents:cmps toDate:date1 options:NSCalendarMatchStrictly];
好了现在我们来些NSObject
NSObject跟java中的object一样,都是所有类的基类。
在这里我们来讲一下SEL的使用,之前我没有写。并且还在选择器中使用它,现在我来写一下SEL
SEL,我们又称他为选择器。它是一种方法签名的数据类型,主要是使用在方法中。每一个方法都有一个选择器。
我们来分析一下对象调用函数,对象调用方法的过程:先是每个对象里面都有一个isa指针,isa指针找到对应存储空间(堆中),然后通过函数头部的SEL找到与之对应找找到匹配的后,就调用SEL标记的方法。
这里我们讲了SEL我们就不写NSObject了,因为它们都是一样的。
来我们走起,我们假设现在定义了一个Person对象,里面有name和age属性还有一个introduce方法
我来判断某个对象中是否实现了我们指定的方法
Person *person = [[Person alloc]init];
person.name = @"喔喔";
person.age = 19;
BOOL isExist = [person respondsToSelector:@selector(introduce)];
NSLog(@"%d",isExist);
现在我们来使用选择器执行方法
[person performSelector:@selector(introduce)];
这个是执行不带参数的方法,接下来我来弄一个带参数的
[person performSelector:@selector(eat:) withObject:@"鱼"];
哈哈输出来的是不是它最爱吃屎啊...
这地方还有一个延迟执行的方法,但是我这边显示不出来。这个也是当然的显示不出来,因为对象被释放了。如果不相信的话,我们可以去有界面的程序中试一下,这个方法是可以。之前我也被困扰了一下,之后找到辅导员才弄明白。因为在程序进过它的时候,它延迟的过程就直接被释放。并且哪怕延迟是0秒都会被释放。不过为啥0秒也会不执行,这个问题我也没搞清楚。如果之后你们知道的,很希望你们能帮忙完善一下。谢谢了...
[person performSelector:@selector(eat:) withObject:@"哇哈哈" afterDelay:2.0];
这里在来一个用SEL作为函数参数
这个必须使用一下其他类了
这个是.h文件
@interface Person : NSObject
@property(nonatomic,copy)NSString *name;
@property(nonatomic,assign)int age;
- (void)introduce:(SEL)selector andFood:(NSString *)food;
- (void)eat:(NSString *)food;
@end
这个是.m文件
@implementation Person
- (void)introduce:(SEL)selector andFood:(NSString *)food{
NSLog(@"大家好,我叫%@,我今年%d岁",_name,_age);
[self performSelector:selector withObject:food];
}
- (void)eat:(NSString *)food{
NSLog(@"我最爱吃%@",food);
}
@end
这个是主文件
Person *person = [[Person alloc]init];
person.name = @"喔喔";
person.age = 19;
SEL selector =@selector(eat:);
[person introduce:selector andFood:@"鱼"];
好了好了,到这里的话。我们的Foundation框架也算是写完了,不过里面还有很多东西。我们有时间的话可以一个一个去套
8、文件操作
说到文件操作,这里我不得不说的是一个东西,那就是文件管理器NSFileManager。它才是大佬.它是一个单例类,主要用于操作文件的操作。
闲话不说了,直接上代码吧
我们来创建一个文件管理对象
NSFileManager *manager = [NSFileManager defaultManager];//注意这里是使用的defualtManager,不要使用alloc,出不来不要怪代码。这些代码都是我一点一点测试过的。出不来的代码在使用的前面我都带有(X)作为标记
来判断下某个路径下是否存在文件或文件夹
NSString *path = @"/Users/jinpengyao/Desktop/";
BOOL isExist = [manager fileExistsAtPath:path];
NSLog(@"%d",isExist);
判断文件权限
判断文件是否是可写文件
NSString *path = @"/Users/jinpengyao/Desktop/屏幕快照 2014-12-07 下午12.04.30.png";
BOOL isExist = [manager isWritableFileAtPath:path];
NSLog(@"%d",isExist);
有判断文件是否是可写文件,那么肯定有判断文件是否可读的方法
NSString *path = @"/Users/jinpengyao/Desktop/屏幕快照 2014-12-07 下午12.04.30.png";
BOOL isExist = [manager isReadableFileAtPath:path];
NSLog(@"%d",isExist);
我们是不是想知道文件或者目录的属性啊,没错也有方法可以获取到的,看我操作
NSFileManager *manager = [NSFileManager defaultManager];
NSString *path = @"/Users/jinpengyao/Desktop";
NSDictionary *mDict =[NSMutableDictionary dictionaryWithCapacity:10];
mDict = [manager attributesOfItemAtPath:path error:nil];
NSLog(@"%@",mDict);
//获取文件夹的大小
int size = mDict[NSFileSize];//这是从上一个程序中找到的key名称
//获取当前文件夹下的内容(以后凡是内容都敲contents)
NSString *path = @"/Users/jinpengyao/Desktop/OC大总结";
NSDictionary *mDict =[NSMutableDictionary dictionaryWithCapacity:10];
mDict = [manager contentsOfDirectoryAtPath:path error:nil ];
NSLog(@"%@",mDict);
//获取当前文件夹下以及其子文件夹的内容(以后带子的都敲sub)
NSString *path = @"/Users/jinpengyao/Desktop/OC加强考试答案";
NSDictionary *mDict =[NSMutableDictionary dictionaryWithCapacity:10];
mDict = [manager subpathsOfDirectoryAtPath:path error:nil];
NSLog(@"%@",mDict);
//拷贝文件
NSString *path = @"/Users/jinpengyao/Desktop/屏幕快照 2014 下午12.04.30.png";
NSString *path1 =@"/Users/jinpengyao/Desktop/屏幕快照 2014-12-07 下午2312.png";
BOOL isSuccess =[manager copyItemAtPath:path toPath:path1 error:nil];
NSLog(@"%d",isSuccess);
//移动文件(实质应该是剪切吧)
NSString *path = @"/Users/jinpengyao/Desktop/屏幕快照 2014 下午12.04.30.png";
NSString *path1 = @"/Users/jinpengyao/Desktop/屏幕快照 2014 下午04.30.png";
BOOL isSuccess =[manager moveItemAtPath:path toPath:path1 error:nil];
NSLog(@"%d",isSuccess);
//在来一个创建目录的方法
NSString *path = @"/Users/jinpengyao/Desktop/koko/dudud";
BOOL isSuccess = [manager createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil];
我来解释一下withIntermediateDirectories 它是问你是否要产生中间文件夹
attributes 它是问你问价的属性
NSLog(@"%d",isSuccess);
//来我们最后一个方法,创建文件的方法
NSString *path = @"/Users/jinpengyao/Desktop/koko.txt";
NSData *data = [[NSData alloc]initWithContentsOfFile:@"/Users/jinpengyao/Desktop/屏幕快照 2014-12-07 上午12.18.52.png"];
BOOL isSuccess = [manager createFileAtPath:path contents:data attributes:nil];
NSLog(@"%d",isSuccess);
是不是很纳闷为啥之前没有写NSData,利用很简单。我忘了,现在来写一下。
好我来介绍NSData
什么是NSData呢,它其实就是用来保存一些二进制文件的大小,像啥音频啊,mv之类的东西。
好我们先来把一个文件保存进NSData中,来看我操作个屁啊,上面都有,直接拉下来。
NSString *path = @"/Users/jinpengyao/Desktop/koko.txt";
NSData *data = [[NSData alloc]initWithContentsOfFile:@"/Users/jinpengyao/Desktop/屏幕快照 2014-12-07 上午12.18.52.png"];
这里我要强调的是NSData是不可变的数据类型,因此它只能加载一次文件。不要想着文件没加载完,我在用它加载一次。这个是办不到的。
好把在我来弄一个写入文件的方法
NSString *path = @"/Users/jinpengyao/Desktop/koko.txt";
NSData *data = [[NSData alloc]initWithContentsOfFile:@"/Users/jinpengyao/Desktop/屏幕快照 2014-12-07 上午12.18.52.png"];
BOOL isSuccess = [data writeToFile:path atomically:YES];
接下来是可变的data类型
这个很牛的,当我们想把多个文件都融进一个文件的时候我们可以使用它。接下来看我操作
NSString *path = @"/Users/jinpengyao/Desktop/koko1.txt";
NSData *data = [[NSData alloc]initWithContentsOfFile:@"/Users/jinpengyao/Desktop/屏幕快照 2014-12-07 上午12.18.52.png"];
NSData *data1 = [[NSData alloc]initWithContentsOfFile:@"/Users/jinpengyao/Desktop/koko.txt"];
NSMutableData *mData = [NSMutableData data];
[mData appendData:data];
[mData appendData:data1];
BOOL isSuccess = [mData writeToFile:path atomically:YES];
观察生成的文件,你可以发现生成的文件占用空间等于被融的两个文件的占用空间之和。这个我就不用多说了。
好了,OC终于弄完了。后面还有归档和KVO|KVC就全部结束。不过现在没时间弄了,进入UI了需要好好研究UI。之后我的日志会把以上的欠缺的内容写出来。