1. 类
首先看到类的定义的关键字是:
@interface
一般类的定义格式为:
@interface 类名:NSObject{
定义属性
}
定义方法
(返回类型) 方法名 : (参数类型)参数名称
- (void)shopping:(float)price;
- @implementation Car
- - (void)setBrand:(NSString *)brand{
- _brand = brand;
- }
- - (void)setColor:(NSString *)color{
- _color = color;
- }
Person *person = [[Person alloc] init]; //初始化
点语法 在set.get 时 直接用点语法 (@proprety 直接动态setget)
- @property NSString *userName;
2. 继承
- @interface Taxi : Car{
- NSString *_company;//所属公司
- }
3. 代理(id类型+协议+多态)
- @interface Person : NSObject{
- NSString *_name;
- }
- //- (void) printWithColor:(ColorPrinter *)colorPrint;
- //- (void) printWithBlack:(BlackPrinter *)blackPrint;
- - (void) doPrint:(Printer *)printer;
- @end
- Person *person =[[Person alloc] init];
- ColorPrinter *colorPrint = [[ColorPrinter alloc] init];
- BlackPrinter *blackPrint = [[BlackPrinter alloc] init];
- #import <Foundation/Foundation.h>
- @protocol WithProtocol <NSObject>
- //默认是必须实现的
- //必须实现
- @required
- - (void)finshTask;
- - (void)dontLate;
- //可选实现
- @optional
- - (void)wearNeat;
- @end
协议的定义格式:
@protocol 协议名 <父协议>
3.3 代理
- #import <Foundation/Foundation.h>
- @class Children;//如果没有这行代码的话,协议ChildrenDelegate中得Children类型就会查找不到,报错
- @protocol ChildrenDelegate <NSObject>
- @required
- - (void)wash:(Children *)children;
- - (void)play:(Children *)children;
- @end
- @interface Children : NSObject{
- //Nure *_nure;//保姆
- //这里可以使用多态技术实现,因为保姆,护士有共同的父类NSObject,但是这里不使用这种方式,而是使用id类型
- //但是我们还需要为这个类型添加一些方法,这里就用到了协议
- //这个代理对象必须遵从ChildrenDelegate协议
- id<ChildrenDelegate> _delegate;//这个变量就是小孩的代理对象
- NSInteger timeValue;
- }
- -(void)setDelegate:(id)delegate;
- @end
我们还定义了一个很重要的属性
_delegate
这个属性定义有点不一样,这个就是实现代理对象的精髓所在了,id是不确定类型,所以这个_delegate变量可以被赋值为的类型是:
只要实现了ChildrenDelegate协议的类就可以了。这里就记住了,以后这种定义方法后面会用到很多。相当于Java中的接口类型,只能赋值其实现类的类型。只是这里的定义格式为:id<协议名>
然后就是一个设置协议的方法了,注意参数类型也必须是id的
- #import <Foundation/Foundation.h>
- #import "Children.h"
- @interface Nure : NSObject<ChildrenDelegate>
- - (void)wash:(Children *)children;
- - (void)play:(Children *)children;
- @end
- Nure *nure = [[Nure alloc] init];
- Nanny *nanny= [[Nanny alloc] init];
- [child setDelegate:nanny];
- // [child setNure:nure];
- [[NSRunLoop currentRunLoop] run];
Tip:
- //判断wearNeat方法有没有在Student中实现了
- if([stu respondsToSelector:@selector(wearNeat)]){
- [stu wearNeat];
- }
4.类目
- #import <Foundation/Foundation.h>
- //定义类目的文件命名规则:类名+类目名称,如“NSString+Extension.h"
- @interface NSString (Extension)
- - (BOOL)validateEmail;
- //覆盖NSString中的intValue方法
- - (NSInteger)intValue;
- @end
5.Foundation框架中的NSObject
- Person *task = [[Person alloc] init];
- isBelongTo = [task respondsToSelector:@selector(demo1)];
- if(isBelongTo){
- [task performSelector:@selector(demo1)];
- NSLog(@"YES");
- }else{
- NSLog(@"NO");
- }
6.NSString
- //7.---------------------TypeXXXValue
- //数值转化方法
- NSString *string20 = @"3.14";
- float value = [string20 floatValue];
- string20 = @"1";
- BOOL values = [string20 boolValue];
- //8.---------------------subStringToIndex/subStringFromIndex/subStringWithRange
- //字符串的截取
- NSString *string21 = @"abcdefg";
- //从开始位置截取到下标为3的字串(不包括3)
- NSString *stringnews = [string21 substringToIndex:3];
- //从哪个index开始截取到尾部(包括3)
- stringnews = [string21 substringFromIndex:3];
- //截取1~(3+1)部分的字串
- NSRange range = {1,3};
- stringnews = [string21 substringWithRange:range];
- //9.----------------------stringByAppendingString/stringByAppendingFormat
- //字符串的追加
- NSString *string22 = @"Android";
- NSString *stringnew = [string22 stringByAppendingString:@"IOS"];
- stringnew = [string22 stringByAppendingFormat:@"%@",@"IOS"];
- //10.---------------------rangeOfString
- //字符串的查找
- NSString *string23 = @"www.iphonetrain.com/ios.html";
- NSRange rang = [string23 rangeOfString:@"ios"];//返回一个范围
- if(rang.location == NSNotFound){
- //没找到
- }else{
- //找到了
- }
- //11.----------------------characterAtIndex
- //取出字符串中指定的char
- NSString *string24 = @"abcdef";
- unichar c = [string24 characterAtIndex:3];
-
7.NSArray
rafd
- int main(int argc, const charchar * argv[]) {
- @autoreleasepool {
- //1.---------------------数组的创建
- NSString *s1 = @"zhangsan";
- NSString *s2 = @"lisi";
- NSString *s3 = @"wangwu";
- //最后的nil相当于结束的标记
- NSArray *array1 = [[NSArray alloc] initWithObjects:s1,s2,s3, nil nil];
- //打印的时候会调用description方法
- //相当于:array1.description
- NSLog(@"%@",array1);
- //使用类方法创建
- array1 = [NSArray arrayWithObjects:s1,s2,s3, nil nil];
- //创建一个数组,将源数组中的数据拿出来放进去
- NSArray *array2 = [NSArray arrayWithArray:array1];
- //2.----------------------objectAtIndex
- //访问数组中的数据,数组中存放的是对象的指针
- NSString *str1 = [array1 objectAtIndex:0];
- //3.----------------------count
- //获取数组元素中的个数
- NSUInteger count = [array1 count];//返回的是一个无符号数值
- //4.----------------------containsObject
- //判断数组中是否包含某一个对象,判断的是指针对象值,不是对象中的值
- BOOL isContains = [array1 containsObject:@"zhangsan"];
- //5.----------------------indexOfObject
- //返回一个对象在数组中的下标值
- NSUInteger index = [array1 indexOfObject:@"zhangsan"];
- if(index == NSNotFound){
- //没有找到
- }else{
- //找到了
- }
- //6.----------------------componentsJoinedByString
- //数组中存放的如果是字符串的话,可以使用连接符将其所有的元素进行连接
- //注意数组中的元素必须都是字符串
- NSString *content = [array1 componentsJoinedByString:@","];
- //7.----------------------lastObject
- //访问数组最后一个元素
- NSString *lastObj = [array1 lastObject];
- //8.----------------------arrayByAddingObject
- //在原来的数组后面追加元素,返回一个新的数组对象,因为他是不可变的
- NSArray *array3 = [array1 arrayByAddingObject:@"zhaoliu"];
- //数组的遍历
- for(int i=0;i<array1.count;i++){
- NSString *str = [array1 objectAtIndex:i];
- NSLog(@"%@",str);
- }
- //快速遍历
- for(NSString *s in array1){
- NSLog(@"%@",s);
- }
- //xcode4.4以后,编译器对数组的创建和访问语法做了优化
- NSArray *array7 = @[s1,s2,s3];
- NSString *s = array7[0];
- }
- return 0;
- }
8.NSDirctionary map
r
- //1.---------------------字典的创建
- NSArray *array1 = [NSArray arrayWithObjects:@"zhangsan",@"zhangfei", nil nil];
- NSArray *array2 = [NSArray arrayWithObjects:@"lisi",@"liping", nil nil];
- //第一个元素:key:@"zhang" value:array1
- //第二个元素:key:@"li" value:array2
- NSDictionary *dict = [[NSDictionary alloc] initWithObjectsAndKeys:array1,@"zhang",array2,@"li", nil nil];
- NSLog(@"%@",dict);
- //存放一个元素
- NSDictionary *dict2 = [NSDictionary dictionaryWithObject:array1 forKey:@"zhang"];
- //2.---------------------获取所有的key
- NSArray *allKeys = [dict allKeys];
- //3.---------------------获取所有的value
- //可能为二维数组
- NSArray *allValues = [dict allValues];
- //4.---------------------通过key获取value
- NSArray *values = [dict objectForKey:@"zhang"];
- //5.---------------------优化的语法
- NSDictionary *dict3 = @{@"zhangsan":array1,@"lisi":array2};
- NSLog(@"%@",dict3);
- NSArray *array4 = dict3[@"zhang"];
二、NSMutableDirctionary类
9.KVC KVO
fdgsdfgs
- //设置值
- //这里setValue方法:第一个参数是value,第二个参数是key(就是类的属性名称)
- [p setValue:@"jiangwei" forKey:@"name"];
- Dog *dog = [[Dog alloc] init];
- [p setValue:dog forKey:@"dog"];
- //KVC设置值时,如果属性有set方法,则优先调用set方法,如果没有则直接设置上去,get方法类似
- //读取值
- NSString *name = [p valueForKey:@"name"];
- //设置基本数据类型
- //这里需要将基本类型转化成NSNumber
- //在设置值的时候,会有自动解包的过程,NSNumber会解包赋值给age
- [p setValue:@22 forKey:@"age"];
下面再来看一下KVC中强大的功能:键值路径
键值路径是对于一个类中有数组对象的属性进行便捷操作。
a
- //--------------------KVC的运算
- Author *author = [[Author alloc] init];
- [author setValue:@"莫言" forKeyPath:@"name"];
- Book *book1 = [[Book alloc] init];
- book1.name = @"红高粱";
- book1.price = 9;
- Book *book2 = [[Book alloc] init];
- book2.name = @"蛙";
- book2.price = 10;
- NSArray *array = [NSArray arrayWithObjects:book1,book2, nil nil];
- [author setValue:array forKeyPath:@"issueBook"];
2、下面就开始用到KVC中键值路径了
1)获取作者类中书籍数组中所有书籍的价格
2、下面就开始用到KVC中键值路径了
1)获取作者类中书籍数组中所有书籍的价格
看到了:@"issueBook.price" 这就是键值路径的使用,issueBook是作者类中的书籍数组属性名,price是书籍类的属性,中间用点号进行连接,这样我们就可以获取到了所有书籍的价格了
- //获取数组的大小
- NSNumber *count = [author valueForKeyPath:@"issueBook.@count"];
- NSLog(@"count=%@",count);
- //获取书籍价格的总和
- NSNumber *sum = [author valueForKeyPath:@"issueBook.@sum.price"];
- NSLog(@"%@",sum);
- //获取书籍的平均值
- NSNumber *avg = [author valueForKeyPath:@"issueBook.@avg.price"];
- NSLog(@"%@",avg);
- //获取书籍的价格最大值和最小值
- NSNumber *max = [author valueForKeyPath:@"issueBook.@max.price"];
- NSNumber *min = [author valueForKeyPath:@"issueBook.@min.price"]
二、KVO操作
KVO操作在OC中也是经常会用到的,而且这种机制在java中不存在的。
它的作用就是用来监听类中属性值的变化,实现原理是观察者模式,当然我们也可以使用观察者模式在Java中实现这样的机制
看一下具体的例子:现在有一个小孩类,他有两个属性:开心值,饥饿值,然后还有一个护士类,用来监听孩子类的这两个属性值的
Chidren.h
Children.m
在初始化方法中,我们启动一个定时器,然后隔1s就去修改孩子类的值
Nure.h
定义一个孩子属性
Nure.m
看到了在这里就开始进行监听操作了
下面来具体看一下如何做到监听的
1、添加监听对象
我们使用addObserver方法给孩子添加监听对象
第一个参数:监听者,这里是Nure,所以可以直接传递self
第二个参数:监听对象的属性名
第三个参数:监听这个属性的状态:这里可以使用|进行多种组合操作,属性的新值和旧值
第四个参数:传递内容给监听方法
2、监听方法
我们上面传递的第一个参数是监听者,这个方法也是在监听者中实现的,当属性值发生变化的时候,这个方法会被回调
这个方法的参数:
第一个参数:键值路径
第二个参数:监听对象
第三个参数:变化的值
第四个参数:传递的内容
我们看到代码中有一个特殊的参数:第三个参数:NSDirctionary类型的
其实我们如果不知道是干什么的,我们可以打印一下他的结果看一下,很简单,这里就不截图说明了
我们会发现他有两个键值对
key是:new和old
他们就是分别代表这个属性值变化的前后值,同时他们的得到也和之前我们添加监听对象时设置的第三个参数有关:
NSKeyValueObservingOptionNew |NSKeyValueObservingOptionOld
那个地方设置了几种状态,这里的NSDirctionary中就会有几个键值对
3、销毁方法
这个并不属于KVO的内容了,只是在这里用到了就顺便说一下
我们在创建一个对象的时候会调用alloc方法,当对象被销毁的时候会调用dealloc这个方法,这个和C++中的析构函数一样,Java中有垃圾回收器,所以没有此类的方法,但是有一个finalize方法,其实这个方法就是在垃圾回收器回收对象的时候会调用,和这个功能差不多,但是在Java中,我们并不提倡使用这个方法。因为会造成GC的回收发生错误。
我们在销毁方法中需要移除监听者
总结
这一篇就介绍了OC中比较有特色的两个机制:KVC和KVO
KVC:就是可以暴力的去get/set类的私有属性,同时还有强大的键值路径对数组类型的属性进行操作
KVO:监听类中属性值变化的
=============================================================================