Objective C 学习笔记
来源:互联网 发布:mysql5.7 for mac下载 编辑:程序博客网 时间:2024/06/06 13:18
前 言
终于还是选择了”挨踢”的路,经过一段时间的培训,本着自己的认识、分析和理解程度上不去做技术上的高手,记下笔记提高自己。
目 录
- 第一讲 语言简介、类和对象、NSObeject、基础语法
- 第二讲 方法(封装)、继承、多态
- 第三讲 属性(property)、语法新特性
- 第四讲 OC数据类之字符串(NSString、NSMutableString)、集合类之数组(NSArray、NSMutableArray)
- 第五讲 OC集合类之字典(NSDictionary、NSMutableDictionary)、集(NSSet、NSMutableSet)
- 拓展 NSValue\Copy\MutableCopy\NSRang
- 第六讲 NSNumber NSNumberForMatter NSValue NSDate NSDateForMatter NSTimer等
- 第七讲 内存管理
- 第八讲 类目、延展、协议
- 第九讲 单例、通知、代理引用传值
- 第十讲 Block应用、RunTime讲解
第一讲 语言简介、类和对象、NSObeject、基础语法
#import <Foundation/Foundation.h>int main(int argc, const char * argv[]) { @autoreleasepool { NSLog(@"Hello, World!"); } return 0;}
import :(保证头文件只被包含一次)
1.检测重复,防止文件的重复拷贝
2.<> 导入系统头文件 “” 导入自定义头文件
3.Foundation是一个基本库,导入他才能使用NSLog();
4.导入Foundation的头文件( Foundation.h文件 )
@autoreleasepool//称之自动释放池
NSLog(@"Hello, World!");//类似于C语言的printf函数; 1.NSLog添加了时间戳 :2016-05-20 19:44:10.366 OC第一讲[1441:158586] Hello, World! 2.打印的时候多了一个@符号 3.自动换行
类(class):对一类事物抽象的描述(抽象)
对象(object):从以类食物中具体刻画出来的一个实例(具体);
第二讲 方法(封装)、继承、多态
封装方法:封装可以隐藏实现细节,使得代码模块化
封装:只要是对成员变量的封装,例如set和get方法set方法的作用:提供一个方法给外界设置成员变量 命名规范: 1.方法必须set开头 2.set后面跟上成员变量的名称(去掉下划线,成员变量的首字母大写 3.返回值一定是void 4.一定要接收一个参数,而且参数和成员变量类型一致 5.形式参数的名称不能和成员变量一样get方法的作用:返回对象内部成员变量的值 命名规范: 1.方法名和去掉下划线的成员变量名一样 2.不能添加get关键字 3.肯定有返回值,而且返回值的类型和成员变量的类型一致 4.不接受任何参数
继承:可以扩展已存在的代码模块(类)
1.抽取重复的代码 2.建立类与类之间的关系 3.子类阔以拥有父类的所有变量和方法
封装、继承的的目的都是为了——代码重用
多态:实现接口重用,为了类在继承和派生的时候,保证使用”家谱”中任意一类实例的某一属性时的正确调用
说明: DOG 继承于 Animal (Animal 拥有eat的属性、DOG 拥有run的属性)
#pragma mark --多态 Animal *animal = [[DOG alloc]init]; [animal eat];//调用方法会检测对象的真实形象 //1.父类的指针可以指向子类的对象,但是不能指向子类的对象 //2.父类类型的变量不能调用子类的方法/*多态: 不同对象对同一消息的不同反应*///强转 DOG *dog = (DOG *)animal; [dog run];
//索引找到 继承父类的方法//如果父类定义的方法,在子类可以不用写,如在DOG类能调用Animal类中的run**************************************************************#import <Foundation/Foundation.h>@interface Animal : NSObject- (void) eat;@end*************************************************************#import "Animal.h"@interface DOG : Animal-(void)run;@end *************************************************************@implementation DOG-(void)eat{ NSLog(@"dog love bone");}-(void)run{ NSLog(@"I can run");}@end
注意:子类需重新实现父类的方法,并覆盖父类以前的做法,需要重写Setter方法
1.父类方法必须声明
2.调用方法的时候,子类优先找当前类的方法,如果找不到则寻找父类的方法
3.缺点:耦合性太高
继承使用的场合:
当A类完全拥有或者部分拥有B类中的属性和方法,可以让B类继承
-(void)sayHi{ [super sayHi];//直接调用父类中的某个方法 NSLog(@"I am a stduent,my name is %@",_name);}
super作用: 1.直接调用父类的方法 2.super在对象方法中,那么就会调用父类中的对象方法,在父类中,会调用父类的方法 3.使用场合:子类重写父类的方法同时想保留父类的一些行为 [super 方法名]//调用父类方法 self的用法: 1.谁点用了当前方法,self就代表谁 2.self在对象方法中就代表当前对象 3.self在类方法中,代表当前类 [self 方法名] //调用对象方法
实例化方法和类方法(便利构造)
‘_’(减号开头)实例化方法
1.只能由对象调用2.对象方法中能访问当前对象的成员变量
‘+’(加号开头)类方法
1.只能由类调用2.类方法中不能访问成员变量
类方法的使用场合(注:类方法可以和实例方法同名)
1.不依赖对象,执行效率高2.当方法内部不许需要成员变量的时候,阔以使用类方法
第三讲 属性(property)、语法新特性
iOS 4.4之前,只会帮助setter和getter方法的声明
在头文件中声明 @property NSString *name;
属性:在iOS5之前写属性
1.先写出带下划线的成员变量
2.使用@property关键字匹配一个不带下划线的与成员变量同名的属性
3.使用@synthesize将成员变量和属性进行合并
//@synthesize name = _name;
@property (nonatomic, strong) <#NSString#> *<#NSString#>; 属性优点: 1.自动声明一个带下划线的成员变量 2.自动声明和实现成员变量对应的setter和getter方法第一类:内存管理相关 assign:缺省值,修饰基本数据类型和delegate retain:对象类型 在MRC手动管理内存 copy:对象类型 (在遵守<NSCopying>情况下)第二类:线程相关 atomic:关心线程安全,通常用于多线程中 nonatomic:不用去关心线程安全,通常用于单线程第三类: readwrite:读写 readonly:只读,只提供getter方法,不提供setter方法第四类: nullable:表明这个属性的值可以为nil,对应swift中name? nonull:不为nil,如果传一个nil的指针,将会收到编译器的警告 null_resettable:stter 可以为空 null_unspecified:是否为nil不确定//@property (nonatomic, strong, nullable) NSString *name;//nullable 只要属性加了这个关键字,以后相同类型的属性都需要加这个关键字 stter ,getter = 重新定义setter和getter的方法名。
第四讲 OC数据类之字符串(NSString、NSMutableString)、集合类之数组(NSArray、NSMutableArray)
- pragma mark –NSString
//字符串创建 /* 1.stringWithFormat 2.stringWithString 3.stringWithCharacter:lenth */ NSString *string = [[NSString alloc] init];//不推荐使用 NSString *string1 = [[NSString alloc] initWithFormat:@"jack %@", string]; NSString *string2 = [NSString stringWithFormat:@"123%@",string1]; NSLog(@"%@",string2); =============================================================== //字符串的拼接 /* 1.stringByAppendingString 2.stringByAppendingFormat */ NSString *string = @"123"; NSString *string2 = @"456"; NSString *string3 = [string stringByAppendingString:string2]; NSLog(@"%@", string3); string3 = [string3 stringByAppendingFormat:@"%@", string3]; NSLog(@"%@", string3); =============================================================== //字符串的截取 /* *subStringFromIndex; index为截取的开始位置的下标 *subStringToIndex; *subStringWithRange; */ NSString *string = @"abcde"; //练习:将“abcde”中的de去掉 //string = [string substringToIndex:3]; NSString *string2 = [string substringToIndex:2]; NSString *string3 = [string substringFromIndex:4]; string = [string2 stringByAppendingFormat:@"%@",string3]; NSLog(@"%@", string); //练习:“hello word”的字符串通过截取变成“hd” NSString *string4 = @"hello word"; string4 = [[string4 substringToIndex:1] stringByAppendingFormat:@"%@",[string4 substringFromIndex:string4.length - 1]]; NSLog(@"%@", string4); =============================================================== //字符串查询(查找字符串cd) NSString *string = @"abcde"; NSRange range =[string rangeOfString:@"cd"]; if (range.location == NSNotFound && range.length ==0) { NSLog(@"Not Found!"); }else{ NSLog(@"Found the string!"); } BOOL result = [string containsString:@"cd"]; if (result == YES) { NSLog(@"Result=%hhd Found the string!",result); } =============================================================== NSString *str = @"baidu.com"; // 查询前缀 if ([str hasPrefix:@"http://"]) { NSLog(@"str has prefix 'http://'."); }else { NSLog(@"str has not prefix 'http://'."); } // 查询后缀 if ([str hasSuffix:@"com"]) { NSLog(@"str has suffix 'com'."); }else { NSLog(@"str has not suffix 'com'."); } =============================================================== //字符串替换(替换cd改成CD) NSString *string = @"abcdecd"; NSString *stringResult = [string stringByReplacingCharactersInRange:NSMakeRange(2, 2) withString:@"CD"];//根据范围替换 NSLog(@"%@",stringResult); NSString *stringResult1 = [string stringByReplacingOccurrencesOfString:@"cd" withString:@"CD"];//全部替换 NSLog(@"%@",stringResult1); =============================================================== // 字符串比较 /* * 字符串比较: * isEqualToString: 判断字符串是否相同 * compare: 字符串比较 * compare: option: 字符串比较(可定义比较模式) */ NSString *string = [NSString stringWithFormat:@"1232"]; NSString *string1 = [NSString stringWithFormat:@"1234"]; // 法一: BOOL resultString = [string isEqualToString:string1]; if (resultString == 1) { NSLog(@"the same"); } // 法二: NSComparisonResult result = [string compare:string1 options:NSNumericSearch | NSCaseInsensitiveSearch]; if (result == NSOrderedAscending)//升序 { NSLog(@"srtring1 is bigger than string!!"); }else if (result == NSOrderedDescending)//降序 { NSLog(@"srtring is bigger than string1!!"); }else//相等 { NSLog(@"the same!!"); } =============================================================== // NSComparisonResult:比较结果枚举类型,NSStringCompareOptions比较策略枚举类型 // NSNumericSearch :比较字符串长度 // NSCaseInsensitiveSearch: 大小写不敏感比较 // NSLiteralSearch : 完全比较,比较大小写 string1 = [NSString stringWithFormat:@"1234"]; string2 = [NSString stringWithFormat:@"123"]; NSComparisonResult result = [string1 compare:string2 options:NSNumericSearch | NSCaseInsensitiveSearch]; if (result == NSOrderedSame) { NSLog(@"the strigns are same."); }else if (result == NSOrderedAscending) { NSLog(@"string1 is less than string2."); }else if (result == NSOrderedDescending) { NSLog(@"string1 is bigger than string2."); } =============================================================== /* 1.length:获取长度 2.integerValue,floatValue,doubleValue:简单数据类型的转换 3.uppercaseString,lowercaseString,capitalzedString:字符串大小写转换 */ =============================================================== //数值转换 int a =234; NSString *numberString = [NSString stringWithFormat:@"%d",a]; int number = [numberString intValue]; NSInteger number2 = [numberString integerValue]; float number3 = [numberString floatValue]; double number4 = [numberString doubleValue]; =============================================================== // 大小写转换 NSString *string = @"hello word"; NSLog(@" string = %@",string); NSString *string1 = [string uppercaseString]; NSLog(@"string1 = %@",string1); NSString *string2 = [string1 lowercaseString]; NSLog(@"string2 = %@",string2); NSString *string3 =[string capitalizedString];//单词首字母大写 NSLog(@"string3 = %@",string3);
- pragma mark –NSMutableString可变字符串
//增、删、改、插 NSMutableString *string = [NSMutableString stringWithFormat:@"123"]; [string appendFormat:@"456"];//拼接 NSLog(@"%@",string); [string appendString:string]; NSLog(@"%@",string);//123456123456 [string insertString:@"a" atIndex:3];//在某个下标位置插入字符 NSLog(@"%@",string); [string deleteCharactersInRange:NSMakeRange(4, 3)];//删除 NSLog(@"%@",string); [string replaceCharactersInRange:NSMakeRange(0, 3) withString:@"ABC"];//更改 NSLog(@"%@",string);
- pragma mark –NSArray
//C语言//int a[5] = {1,2,3,4,5};//相同类型集合 //oc语言数组 //数组初始化 //一般初始化方式 NSArray *array = [[NSArray alloc]initWithObjects:@"123",@(34),@"567", nil]; //便利初始化 NSArray *array1 = [NSArray arrayWithObject:@"jack"];//一个对象自动添加nil NSArray *array2 = [NSArray arrayWithObjects:@"tom",@(123) ,nil]; //快速初始化(ios5以上) NSArray *array3 = @[@"2",@"5",@"nice"];//对象自动添加nil
数组取值: //objectAtIndex: //取出某一下标对应的元素 //lastObject: //取出最后一个元素 //firstObject: //取出第一个元素
NSArray *array = [NSArray arrayWithObjects:@"1",[NSString stringWithFormat:@"2"],[NSNumber numberWithInt:3], nil]; NSLog(@"%@",array);//数组外层有小括号 id object = [array objectAtIndex:1];//NSString *string = [array objectAtIndex:1] id firstObject = [array firstObject]; NSLog(@"firstObject:%@",firstObject); id lastObject = [array lastObject]; NSLog(@"lastObject:%@",lastObject); NSLog(@"object:%@",object); NSArray<NSString *> *strings = @[@"1",@"2",@"3"]; NSLog(@"%@",strings); NSLog(@"%ld",strings.firstObject.length); NSDictionary<NSString *,NSNumber *> *dict =@{@"a":@(1),@"b":@(2),@"c":@(3)}; NSLog(@"%@",dict);
- pragma mark –NSMutableArray
NSMutableArray ->数组运算: *增 *删 *改 *查 *排序 =============================================================== NSMutableArray *mutableArray = [NSMutableArray arrayWithObjects:@"1",@"2",@"3",@"4", nil]; //增加:addObject:(一定不能添加一个空对象) [mutableArray addObject:@"5"]; //删除 [mutableArray removeObject:@"4"];//删除4这个对象 [mutableArray removeObjectAtIndex:2];//删除下标对象 //查 NSInteger index = [mutableArray indexOfObject:@"2"]; //修改 [mutableArray replaceObjectAtIndex:2 withObject:@"30"]; //排序 [mutableArray sortedArrayUsingSelector:@selector(compare:)]; =============================================================== NSArray *array = [NSArray arrayWithObjects:@"1",@"13",@"4",@"56", nil]; NSLog(@"%@",array); //增加元素 NSArray *newArray = [array arrayByAddingObject:@"23"]; NSLog(@"%@",newArray); //查找某一个元素坐在的下标 NSInteger index = [array indexOfObject:@"56"]; NSLog(@"%d",(int)index); //排序 sortedArrayUsingSelector //方法选择器+方法 :@selector(compare:) NSArray *sorteArray = [array sortedArrayUsingSelector:@selector(compare:)]; NSLog(@"%@",sorteArray) =============================================================== //3种便利数组元素方式 //getter和点语法都阔以 //循环便利 for (int i = 0 ; i<array.count; i++) { NSLog(@"循环便利:%@",[sorteArray objectAtIndex:i]); } //快速枚举 for-in 适用于不需要知道元素下标 for (NSString *string in sorteArray) { NSLog(@"快速枚举:%@",string); } //block enumerateObjectsUsingBlock 两次回车符 可以将一串代码作为值 [sorteArray enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { //obj:返回的下标对应的参数 //idx:下标位置 NSLog(@"block:%@ index:%lu",obj,idx); if (idx == 2)//下标等于2中断循环 { *stop = YES; } }]; =============================================================== //Array数组元素排序(排序条件) //声明数组有年龄和姓名 // 1. (排序条件) NSSortDescriptor *sortDescriptor1 = [NSSortDescriptor sortDescriptorWithKey:@"_age" ascending:YES];//按年龄排 NSSortDescriptor *sortDescriptor2 = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES];//按名字排 // 2. 先按年龄排,再按名字排 [Array sortUsingDescriptors:@[sortDescriptor1,sortDescriptor2]];
//练习: NSArray *array1 = [NSArray arrayWithObjects:@"123",@"234",@"78",nil]; NSLog(@"array1 = %@",array1); NSArray *array2 = [NSArray arrayWithObject:array1]; NSLog(@"array2 = %@",array2); NSArray *array3 = [NSArray arrayWithObjects:@"789",array2, nil]; NSLog(@"array3 = %@",array3); NSLog(@"%@",array3[0]); NSLog(@"%@",array3[1][0][2]);//从array3种取出array1的第2个元素 array3 = ( 789, ((123,234,78))) =============================================================== //练习:举例 @[@"1",@"2",@"3",@"4",@"5"] 移除数组中大于3的元素 NSArray *array = @[@"1",@"2",@"3",@"4",@"5"]; NSMutableArray *mutableArray = [NSMutableArray arrayWithArray:array]; NSMutableArray *removeArray = [[NSMutableArray alloc]init];//用来记录要被删的元素 // 在遍历集合的时候不能对集合的对象元素进行改变 for (NSString *string in array) { if ([string integerValue] > 3) { [removeArray addObject:string]; } } [mutableArray removeObjectsInArray:removeArray]; NSLog(@"%@",mutableArray); =============================================================== //练习: NSString *string = @"123-456-789-000"; NSArray *array =[string componentsSeparatedByString:@"-"]; NSLog(@"%@",array); //(123,456,789,000) string =[array componentsJoinedByString:@"+"]; NSLog(@"%@",string); //123+456+789+000 =============================================================== //练习: 对一个已知的NSMutableArray数组进行冒泡排序 NSMutableArray *array = [NSMutableArray arrayWithObjects:@"7",@"3",@"5",@"2",@"4",@"6",@"1", nil]; for (int i = 0; i<array.count-1; i++) { for (int j = 0; j <array.count-1-i; j++) { if ([array[j] integerValue] > [array[j+1] integerValue] ) { [array exchangeObjectAtIndex:j withObjectAtIndex:j+1]; NSInteger num = [array[j] integerValue]; NSInteger num1 = [array[j+1] integerValue]; if (num >num1) { [array exchangeObjectAtIndex:j withObjectAtIndex:j+1]; } } }NSLog(@"%@",array);
第五讲 OC集合类之字典(NSDictionary、NSMutableDictionary)、集(NSSet、NSMutableSet
- pragma mark –NSDictionary
/* 字典以键值对的方式进行存储,无序 例如:key ->value 初始化方式: */ //一般初始化:alloc + initWithObjectsandKeys NSDictionary *dictionary = [[NSDictionary alloc]initWithObjectsAndKeys:@"first",@(1),@(2),@"second",@(4),@"four",nil]; NSLog(@"%@",dictionary); //便利初始化:dictionaryWithObjectAndKeys //便利构造(ios5)----快速构造方式,成对出现:前键 后值 返回的是不可变字典 NSDictionary *newdictionary = @{@"fist":@(1),@"second":@(2)}; NSLog(@"%@",newdictionary); /* 字典的常规方法 1.查询某个对象:ObjectForKey: 2.取出所有键值:allkeys 3.取出所有value:allValues数组 */ //1.查 NSString *string = [dictionary objectForKey:@"first"];//取出key做对应的对象 NSLog(@"%@",string); //2.字典里面所有键的集合 NSArray *keys = [newdictionary allKeys]; NSLog(@"%@",keys); //3.取出所有的值 NSArray *value = [newdictionary allValues]; NSLog(@"%@",value); =============================================================== 字典的遍历练习 =============================================================== NSDictionary *dictionary = @{@"name":@"jack",@"age":@(18),@"height":@"188",@"code":@"1555",@"sex":@"男"}; //for循环 取出所有的KEY值 NSArray *key = [dictionary allKeys]; for (int i = 0; i < key.count; i++) { //1.取出键值 NSString *keyString = key[i]; NSString *value = [dictionary objectForKey:keyString]; //NSString *value = dictionary[keyString]; } NSLog(@"key1:%@",key); //for-in遍历 for(NSString *key in dictionary){ NSLog(@"key2:%@",[dictionary objectForKey:key]); } // key position -- value @{@"1":@"北京",@"2":@"重庆",@"3":@"成都"} // dictionary[@"position"][@"3"];
- pragma mark –NSMutableDictionary
/* *增:setObject:forkey *删:removeObjectforKey *查:objectForKey *改:setObject:forkey 覆盖指定key对应的值 */ NSMutableDictionary *mutableDict = [[NSMutableDictionary alloc]init]; //增: [mutableDict setObject:@"jack" forKey:@"name"]; [mutableDict setObject:@"56" forKey:@"age"]; [mutableDict setObject:@"188" forKey:@"height"]; //删 [mutableDict removeAllObjects];//删除所有 [mutableDict removeObjectForKey:1];//删除KEY值对应的value key值也就不存在了 //查找 NSString *string = [mutableDict objectForKey:@"age"]; //改: [mutableDict setObject:@"45" forKey:@"age"];
- pragma mark –NSSet
NSSet简介
NSSet对象中不能存放重复对象,如果出现重复,最终只会保留一个,NSSet也常用来清除其他集合中的重复对象。
集,类似数组,但区别于数组,其特点是:无序不重复;
集分为可变集 NSSet 与不可变集 NSMutableSet;
初始化
// 1、alloc + init - (instancetype)initWithObjects:(ObjectType)firstObj, ... ;// 2、遍历构造 + (instancetype)setWithObjects:(ObjectType)firstObj, ...; ``` * 常用方法 ```1、获取元素个数- (NSUInteger)count;2、获取任意元素- (nullable ObjectType)anyObject;3、获取所有元素@property (readonly, copy) NSArray<ObjectType> *allObjects;4、查询是否包含某一元素- (BOOL)containsObject:(ObjectType)anObject; ``` * ___pragma mark --NSMutableSet___ * 常用方法
// 1、添加元素
- (void)addObject:(ObjectType)object;
// 2、删除元素
- (void)removeObject:(ObjectType)object;
拓展 NSValue\Copy\MutableCopy\NSRang
pragma mark –NSValue
数值对象,用于复杂数据类型的对象化封装,如结构体;
NSValue 对自定义结构体类型的初始化
// 1、结构体类型声明 typedef struct { char name[81]; int age; }Person;// 2、声明结构体变量并初始化 Person person = {"Charles", 21};// 3、封装 NSValue *value = [NSValue valueWithBytes:&person objCType:@encode(Person)];// 4、解封装 Person newPerson; [value getValue:&newPerson]; NSLog(@"<%p 姓名:%s 年龄:%d>", &newPerson, newPerson.name, newPerson.age); ```
简单结构体类型转换为对象类型 //便利结构初始化 NSValue *Value = [NSValue valueWithPoint:NSMakePoint(4, 5)]; NSLog(@"%@",Value); //打印:NSPoint: {4, 5} NSValue *sizeValue = [NSValue valueWithSize:NSMakeSize(34, 568)]; NSLog(@"%@",sizeValue); //打印:NSSize: {34, 568} NSValue *rectValue = [NSValue valueWithRect:NSMakeRect(3, 5, 6, 678)]; NSLog(@"%@",rectValue); //打印:NSRect: {{3, 5}, {6, 678}} //便利解封装 NSPoint point = [Value pointValue ]; NSString *str1 = NSStringFromPoint(point); NSLog(@"point is %@",str1); NSSize size = [sizeValue sizeValue]; NSString *str2 = NSStringFromSize(size); NSLog(@"point is %@",str2); NSRect rect = [rectValue rectValue]; NSString *str3 = NSStringFromRect(rect); NSLog(@"point is %@",str3);
- pragma mark –Copy
NSArray *array = [NSArray arrayWithObjects:@"1",@"2",@"3", nil]; NSArray *newArray = [array copy]; NSLog(@"%p %p",array,newArray); //结论:copy对于不可变对象,是指针复制,也成为浅复制 NSMutableString *mutableString = [NSMutableString stringWithFormat:@"34"]; NSMutableString *newMutableStr =[mutableString copy]; NSLog(@"%p %p",mutableString,newMutableStr); //结论:copy作为可变对象,是内容复制,也成为深复制。但是复制之后的字符串变成了一个不可变的字符串;
- pragma mark –MutableCopy
NSMutableArray *mutableArray = [@[@"123",@"456"] mutableCopy]; [mutableArray addObject:@"789"]; //NSLog(@"%@",mutableArray); NSString *string = [NSString stringWithFormat:@"AAA"]; //NSString *newStr = [string mutableCopy]; NSMutableString *newStr = [string mutableCopy]; [newStr appendFormat:@"BBB"]; NSLog(@"%p %p",string,newStr); NSMutableString *newStr2 = [newStr copy];// mutableCopy:对于可变或者不可变对象mutableCopy都是深复制(开辟新的内存,内容复制),且开辟的新内容都是可变的 NSMutableString *str = [@"123" mutableCopy];
- pragma mark –NSRange
- C 语言使用结构体、指针和数组来构造复杂的数据类型,而结构体和指针在iOS编程中至关重要,Cococa为我们准备了与字符串操作有关的结构体NSRange:
// NSRange:用来表示相关事物的范围 typedef struct _NSRange { unsigned int location; //location表示起始位置 unsigned int length; //length表示长度 } ```* NSRange有三种创建方式:
比如要得到字符串@“helloRIMIOnline”中@“Online”字符串,需要一个起始位置为9,6个长度的范围,它可以有三种方式创建:
它可以有三种方式创建:
第一种调用函数可以这么写:
NSRange range = NSMakeRange (9,6);第二种直接给成员赋值:
NSRange range;
range.location = 9;
range.length = 6;第三种应用C语言的聚合结构赋值机制:
NSRange range = {9,6};
第六讲 NSNumber NSNumberForMatter NSValue NSDate NSDateForMatter NSTimer等
pragma mark –NSNumber
数值对象,用于简单数据类型的对象化封装,继承与 NSValue;
NSNumber的初始化
NSNumber *number1 = [NSNumber numberWithInt:5]; NSNumber *number2 = [NSNumber numberWithFloat:5]; NSNumber *number3 = [NSNumber numberWithDouble:5.0f];
- NSNumber 比较
NSNumber *number = @(10); NSNumber *antherNumber = @(10);// 1、判断是否相等 BOOL isEqual = [number isEqualToNumber:antherNumber];// 2、比较大小 NSComparisonResult result = [number compare:antherNumber]; // NSOrderedAscending(-1):升序 // NSOrderedSame(0) :相等 // NSOrderedDescending(1):降序 if (result == NSOrderedAscending) { NSLog(@"number < antherNumber"); }else if (result == 0) { NSLog(@"number = antherNumber"); }else { NSLog(@"number > antherNumber"); }
NSNumber *number = [NSNumber numberWithInt:4]; NSLog(@"%@",number);//4 //便利写法 NSNumber *floatNumber = @(4.6); NSLog(@"%@",floatNumber);//保留有效位数 4.6 CGFloat num = floatNumber.floatValue; NSLog(@"%f",num); //4.6 NSNumber *number1 = [NSNumber numberWithFloat:3.05]; NSLog(@"%@",number1);//3.05
pragma mark –NSNumberFormatter
使用 NSNumberFormatter 对 NSNumber 与 NSString 相互转化
NSNumberFormatterStyle
1、NSNumberFormatterScientificStyle: 1.23456E5 2、NSNumberFormatterPercentStyle: 12,345,600% 3、NSNumberFormatterCurrencyStyle: ¥ 123,456.00 4、NSNumberFormatterDecimalStyle: 123,456 5、NSNumberFormatterNoStyle: 123456 ===========================================================#import <Foundation/Foundation.h>int main(int argc, const char * argv[]) { @autoreleasepool { NSNumber *number = @(12345); NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init]; // 设置样式 [formatter setNumberStyle:NSNumberFormatterCurrencyStyle]; // 据样式将 number 转换成字符串 NSString *numberString = [formatter stringFromNumber:number]; NSLog(@"number string = %@", numberString); // 输出 number string = ¥ 123,45.00 } return 0;}
NSNumber *number = @(123456);//将数字转换成文字 NSNumberFormatter *formatter = [[NSNumberFormatter alloc]init]; formatter.numberStyle = kCFNumberFormatterSpellOutStyle; NSString *string = [formatter stringFromNumber:number]; NSLog(@"%@",string);//十二万三千四百五十六
pragma mark –NSValue
数值对象,用于复杂数据类型的对象化封装,如结构体;
// 1、结构体类型声明 typedef struct { char name[81]; int age; }Person;// 2、声明结构体变量并初始化 Person person = {"Charles", 21};// 3、封装 NSValue *value = [NSValue valueWithBytes:&person objCType:@encode(Person)];// 4、解封装 Person newPerson; [value getValue:&newPerson]; NSLog(@"<%p 姓名:%s 年龄:%d>", &newPerson, newPerson.name, newPerson.age);
- pragma mark –NSdDate
//区别:NSData /* * NSDate 的初始化 * date 获取当前系统时间,默认为格林威治时间,比北京时间早8小时 * dateWithTimeInterval:3600 sinceDate: 使用一个传入的时间作为参照,加上偏移时间间隔(秒) * dateWithTimeIntervalSince1970: 使用1970-01-01的时间作为参照,加上偏移时间间隔(秒) * dateWithTimeIntervalSinceNow: 使用当前的时间作为参照,加上偏移的时间间隔(秒) * dateWithTimeIntervalSinceReferenceDate: 使用2001-01-01的时间作为参照,加上偏移的时间间隔(秒) */ //NSDate的初始化 NSDate *date = [NSDate date]; NSLog(@"date=%@",date);//date=2016-05-21 09:40:55 +0000 //传入的日期加上偏移量(时区+8) NSDate *date1 = [NSDate dateWithTimeInterval:3600*8 sinceDate:date]; NSLog(@"date1=%@",date1);//date1=2016-05-21 17:40:55 +0000 //以2001-1-1时间作为参照,在加上偏移量 date1 = [NSDate dateWithTimeIntervalSinceReferenceDate:7200]; NSLog(@"date1=%@",date1);//date1=2001-01-01 02:00:00 +0000 //使用date获取时间间隔 NSTimeInterval time = [date timeIntervalSinceDate:date1]; NSLog(@"time=%lf",time); time = [date timeIntervalSince1970]; time = [date timeIntervalSinceReferenceDate]; time = [date timeIntervalSinceNow]; //NSDate的的比较 NSComparisonResult result = [date compare:date1]; NSLog(@"%ld",(long)result); BOOL result1 = [date isEqual:date1]; NSLog(@"%d",result1); //比较2个日期,返回较小的那个 NSDate *earlierDate = [date earlierDate:date1]; NSLog(@"%ld",(long)earlierDate); //比较2个日期,返回较小那个 NSDate *laterDate = [date laterDate:date]; NSLog(@"%ld",(long)laterDate);
- pragma mark –NSDateFormatter
NSDate *date = [NSDate date]; NSLog(@"初始化:%@",date); NSDateFormatter *formatter = [[NSDateFormatter alloc]init];//创建一个格式转换器对象 [formatter setDateFormat:@"yyyy年mm月dd日 hh:mm:ss"];//设置自定义格式 [formatter setDateStyle:NSDateFormatterMediumStyle];//系统定义日期样式 [formatter setTimeStyle:NSDateFormatterMediumStyle];//系统定义时间样式 NSString *dateString = [formatter stringFromDate:date];//自定义 NSLog(@"dateString1 : %@",dateString); //类方法 获取当地时间字符串 dateString = [NSDateFormatter localizedStringFromDate:date dateStyle:NSDateFormatterMediumStyle timeStyle:NSDateFormatterMediumStyle]; NSLog(@"dateString2 : %@",dateString); //获取当前时区 NSTimeZone *zone = [NSTimeZone systemTimeZone]; NSInteger interval =[zone secondsFromGMTForDate:date]; date = [date dateByAddingTimeInterval:interval]; NSLog(@"当前时区:%@",date);=============================打印输出结果==================================2016-05-21 17:51:08.623 3.24练习[7214:232131] 初始化:2016-05-21 09:51:08 +00002016-05-21 17:51:08.624 3.24练习[7214:232131] dateString1 : 2016年5月21日 下午5:51:082016-05-21 17:51:08.624 3.24练习[7214:232131] dateString2 : 2016年5月21日 下午5:51:082016-05-21 17:51:08.624 3.24练习[7214:232131] 当前时区:2016-05-21 17:51:08 +0000
- 通过NSCalendar类来创建日期
NSDateComponents * comp = [[NSDateComponents alloc]init]; [comp setYear:1993]; // 设置年 [comp setMonth:7]; // 设置月 [comp setDay:16]; // 设置日 [comp setHour:9]; // 设置时 [comp setMinute:14]; // 设置分 [comp setSecond:0];// 设置秒 NSCalendar * myCal = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian]; NSDate * myDate = [myCal dateFromComponents:comp]; NSLog(@"%@", myDate);
第七讲 内存管理
- pragma mark –普通情况下的内存管理
Person *person = [[Person alloc]init]; NSLog(@"%ld",[person retainCount]);//1 // retainCount 用来记录对象的引用计数,所以不会对对象的引用计数产生影响 [person retain];//2 NSLog(@"%ld",[person retainCount]); [person release];//1 NSLog(@"%ld",[person retainCount]); [person release];// 0 延时调用 NSLog(@"%ld",[person retainCount]);//1? [person release];
- pragma mark –自定义初始化中的内存管理
//内存管理原则 //1.谁alloc 谁release; //2.每一个alloc 对应一个release; NSString *name = [[NSString alloc]initWithFormat:@"rimi"]; Person *person = [[Person alloc]initWithName:name code:@"234" age:34]; [name release]; [person release]; NSLog(@"%ld",[name retainCount]); NSLog(@"%ld",[person retainCount]);
- pragma mark –set方法中的内存管理
BOOK *book1 = [[BOOK alloc]init];//1 Person *person = [[Person alloc]init]; [person setBook:book1];//2 [person setBook:book1];//3 BOOK *book2 = [[BOOK alloc]init]; [person setBook:book2]; [book1 release];//1 NSLog(@"book1=%ld",[book1 retainCount]); [person release];//0 NSLog(@"book2=%ld",[book2 retainCount]); NSLog(@"person=%ld",[person retainCount]); NSMutableString *mutable = [[NSMutableString alloc]initWithFormat:@"123"]; //NSString *string = [mutable retain]; //retain关键字赋值指针 内容不变 NSString *string = [mutable copy];//copy关键字赋值内容 [mutable appendFormat:@"456"]; NSLog(@"%@ %@",mutable,string);
- pragma mark –便利构造中的内存管理
NSString *name = [NSString stringWithFormat:@"123"]; Person *person = [Person personWithName:name code:@"123" age:34]; //[person release];//错误 便利构造方法初始化对象 应减少一次release 因为在内方法中alloc已经对应一个autorelease //[name release];//错误 NSArray *array = [NSArray arrayWithObjects:@"1",@"2",nil];//便利构造方法不需要释放 //Autorelease 的基本方法 //1.会将对象放在自动释放池中 //2.当自动释放池被销毁的时候,会对池中所有的对象进行一次release //3.刚调用Autorelease的时候,引用计数是不会发生改变的 //4.Autorelease好处 不用关心对象被销毁的时间 //5.Autorelease一般用在内存较小的时候 //特别注意:便利构造方法初始化对象 应减少一次release 因为在内方法中alloc已经对应一个autorelease
- pragma mark –集合类中的内存管理
//一个对象加入到数组中 retaincount+1 不影响集合类的retaincount Person *person1 = [[Person alloc]init]; NSArray *array = [NSArray arrayWithObjects:person1, nil]; NSLog(@"person1 retainCount = %ld",[person1 retainCount]); NSLog(@"array retainCount = %ld",[array retainCount]); [array retain]; NSLog(@"array retainCount = %ld",[array retainCount]); //数组中的retaincount+1 不影响数组中的元素 [array release]; NSLog(@"array retainCount = %ld",[array retainCount]); ===================================================================== //当集合对象的呗销毁的时候,集合类的元素会进行一次release操作:releasecount-1 Person *person1 = [[Person alloc]init]; NSArray *array = [[NSArray alloc]initWithObjects:person1, nil]; [array retain]; [array release]; //[person1 release]; NSLog(@"array retainCount = %ld",[array retainCount]); NSLog(@"person1 retainCount = %ld",[person1 retainCount]);
- pragma mark –循环引用(dog类)
/* 1.循环引用解决方案 使用@class 关键字导入类,如果需要导入类的属性或者方法,在实现的。m文件里导入该类的头文件; 2.将其中的一个对象改为弱引用,dealloc方法不在释放该对象 */ Person *per1 = [[Person alloc]init];//1 Dog *dog1 = [[Dog alloc]init];//1 per1.dog = dog1;//2 dog1.person = per1;//2 [per1 release]; //per1=1 dog1=2 NSLog(@"per1 = %ld dog1 = %ld",[per1 retainCount],[dog1 retainCount]); [dog1 release]; NSLog(@"per1 = %ld dog1 =%ld",[per1 retainCount],[dog1 retainCount]);
- pragma mark –异常情况
//1.混乱释放 Person *person1 = [[Person alloc]init]; Person *person2 = person1; //[person2 release];//错误 不遵守内存管理原则 [person1 release]; //谁创建 谁release ===================================================================== //2.内存泄露 Person *per1 = [[Person alloc]init]; Person *per2 = [[[Person alloc]init]autorelease]; per2 = per1; [per1 release]; //[per2 release];//错误 造成过度释放 解决办法:增加自动释放 =================================================================== //3.过度释放 Person *person = [Person personWithName:@"rimi" code:@"1001" age:23]; //[person release]; 错误 便利构造的对象不需要多余的release ===================================================================== //4. nil 对象的引用计数为0 Person *pernson = nil; NSLog(@"%ld",[pernson retainCount]); ===================================================================== //5.常量对象的引用计数为无穷 NSString *string = @"123"; NSString *string1 = [NSString stringWithString:string]; NSLog(@"%ld",[string1 retainCount]);
第八讲 类目、延展、协议
暂无
第九讲 单例、通知、代理引用传值
- 单例
//单例在程序的运行中只会被分配一次 //可以在程序的任何一个地方都可以访问和修改它 //单例的生命周期和程序的生命周期一样的 //单例是用类方法创建 NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; [userDefaults setObject:@"no" forKey:@"取消"];//存储 NSString *string = [userDefaults objectForKey:@"取消"]; NSLog(@"---%@",string); if ([string isEqualToString:@"yes"]) { [userDefaults setObject:@"no" forKey:@"取消"]; } else { [userDefaults setObject:@"yes" forKey:@"登录"]; } NSLog(@"%@",[userDefaults objectForKey:@"登录"]); [userDefaults synchronize];//数据持久化 //单例可以在程序的任何一个地方都可以访问和修改它 [[NSUserDefaults standardUserDefaults]setObject:@"tom" forKey:@"name"];//存储 [[NSUserDefaults standardUserDefaults]removeObjectForKey:@"name"];//删除 [userDefaults synchronize];//数据持久化 // NSUserDefaults 不能存储自定义对象
- 单例的实现举例
// 简单单例的实现举例,创建一个Teacher单例 // 单例必须类方法创建 Teacher *teacher = [Teacher defaultTeacher]; 第一步:在Teacher.h文件声明 @interface Teacher : NSObject<NSCopying>//单例完整 +(Teacher *)defaultTeacher; @end 第二步:在Teacher.m文件实现 //简单单例的实现 (保证对象的唯一性) //~~~~~~~~~~~~ 方法① ~~~~~~~~~~~~~~~~~~~~~~~~~~~ static Teacher *teacher = nil; +(Teacher *)defaultTeacher { if (!teacher) { teacher = [[Teacher alloc]init]; //(保证对象只被初始化一次) } return teacher; } //~~~~~~~~~~~~ 方法② ~~~~~~~~~~~~~~~~~~~~~~~~~~~ static dispatch_once_t onceToken; static Teacher *teacher; +(Teacher *)defaultTeacher { _dispatch_once(&onceToken, ^{ teacher = [[Teacher alloc]init]; }); return teacher; } //~~~~~~~~~~~~ 方法③ ~~~~~~~~~~~~~~~~~~~~~~~~~~~ static bool token = NO; static Teacher *teacher; +(Teacher *)defaultTeacher { if (!token) { token = YES; teacher = [[Teacher alloc]init]; } return teacher; } //~~~~~~~~~~~~ 方法④ 完成单例的实现 ~~~~~~~~~~~~~~~ /* 自定义单例创建完整方法: 1.遵守<NSCopying>协议 2.覆写copyWithZone:(NSZone *)zone/retain/release/autorelease/retainCount方法 */ static Teacher *teacher; +(instancetype)allocWithZone:(struct _NSZone *)zone{ @synchronized(self) { if (!teacher) { teacher = [super allocWithZone:zone]; return teacher; } return nil; } } -(id)copyWithZone:(NSZone *)zone { return self; } -(instancetype)retain { return self; } -(instancetype)autorelease; { return self; } - (oneway void)release { } -(NSUInteger)retainCount { return NSUIntegerMax; }
- 通知
发送通知第一步:通知声明 声明两个字符串(示例) extern NSString *const TeacherAskQuestionNotification; extern NSString *const TeacherAskQuestionUserInfokey;第二步:通知赋值 NSString *const TeacherAskQuestionNotification = @"TeacherAskQuestionNotification"; NSString *const TeacherAskQuestionUserInfoKey = @"TeacherAskQuestionUserInfoKey";第三步:发送通知 //postNotificationName:通知的名称 //object:通知的发送者 //userInfo:发送的信息,是以字典的方式发送 [[NSNotificationCenter defaultCenter]postNotificationName:TeacherAskQuestionNotification//发送通知的名称(声明) object:self//发送通知的对象 userInfo:@{TeacherAskQuestionUserInfoKey:question}]; ===============================================================================接收通知:第一步:注册观察者,接收通知 - (instancetype)initWithName:(NSString *)name { self = [super init]; if (self) { _name =[name copy]; //addObserver:观察者 //selector:接受到通知之后 回调的方法(需要执行的方法) //name:通知的名称 //object:设置为空 [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(studentHasReceiveQuestion:) name:TeacherAskQuestionNotification object:nil]; } return self;}第二步:接收到通知之后,回调的方法 -(void)studentHasReceiveQuestion:(NSNotification *)notification{ //获取老师发送的问题 通知发送的内容 NSString *question = [notification.userInfo objectForKey:TeacherAskQuestionUserInfokey]; NSLog(@"student name '%@' receive this question %@",_name,question); //回答老师的问题 if (self.delegate && [self.delegate respondsToSelector:@selector(student:didFinishAnswerWithQuestionWithResult:)]) { [self.delegate student:self didFinishAnswerWithQuestionWithResult:_name]; } }第三步://移除通知 - (void)dealloc { // ARC MRC都需要移除通知 [[NSNotificationCenter defaultCenter]removeObserver:self]; [_name release]; [super dealloc]; }
- 代理、协议
第一步:在.h文件定义协议的名字和方法(示例) @class DetailViewController; // 定义协议头 @protocol DetailViewControllerDelegate <NSObject> // 协议方法(必须执行) @optional - (void)detailViewController:(DetailViewController *)Vc didClickButtonWithColor:(UIColor *)color; @end 第二步:在.h文件定义协议代理的属性(用于关联代理)定义一个遵守协议的属性,称之为代理 @property (nonatomic, weak) id<DetailViewControllerDelegate> btnDelegate; 第三步:在.m文件实现给协议代理发送消息 - (void)clickBtn:(UIButton *)btn { NSLog(@"%@",btn.backgroundColor); // 先要判断代理是否实现了协议方法 if ([self.btnDelegate respondsToSelector:@selector(detailViewController:didClickButtonWithColor:)]) { // 有实现才正式发送消息给代理 [self.btnDelegate detailViewController:self didClickButtonWithColor:btn.backgroundColor]; } // 返回 [self dismissViewControllerAnimated:YES completion:nil];} ===============================================================================代理的第一步:遵守协议 @interface ViewController ()<DetailViewControllerDelegate>代理的第二步:获得委托方(将自己作为委托方的代理) - (void)clickedNextBtn { NSLog(@"跳转到下一页"); // 初始化控制器 DetailViewController *detailVc = [[DetailViewController alloc] init]; // 设置当前控制器为代理 detailVc.btnDelegate = self; // 设置模态跳转动画模式 detailVc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal; // 显示活动指示器 [self.activityView startAnimating]; // 模拟延时 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ // 模态跳转 [self presentViewController:detailVc animated:YES completion:nil]; // 跳转后关掉活动指示器 [self.activityView stopAnimating]; }); }代理的第三步:实现代理方法,获得参数 - (void)detailViewController:(DetailViewController *)Vc didClickButtonWithColor:(UIColor *)color { // 使用传回的颜色设置当前控制器视图的背景色 self.view.backgroundColor = color; }
第十讲 Block应用、RunTime讲解
*___Block应用_
--------------------------------------------- 返回值类型 函数名 参数类型 调用 void (^print) () = ^(){} --------------------------------------------- -------------------------------------------- //无返回值 无参数类型 void (^print)()=^(){ NSLog(@"I am student!"); }; print();//调用Block //打印:I am student! -------------------------------------------- //定义一个block变量 void (^printLines)(int number)=^(int number) { for (int i = 0; i<number; i++) { NSLog(@"----------------"); } }; printLines(5); //打印:五条线 -------------------------------------------- //练习:block计算2个数的和 int (^sum1)(int,int)= ^(int a,int b) { return a+b; }; NSLog(@"sum = %d",sum1(5,6)); //打印:sum = 11 -------------------------------------------- //练习:指向函数的指针 (对比block) 注意此处sum的调用 int (*p)(int,int) = sum; int number = p(4,5); NSLog(@"number: %d",number);
- block访问外部变量
//1.对于基本数据类型,调用的时候是拷贝的,可以访问外部变量,但是不能修改局部变量 //2.若需要修改局部变量 应该加一个 __block关键字 __block int number = 12; //__block关键字 表示同一个地址内存 //int number = 12; // 两个number的地址不一样 //定义一个变量 void (^block)();// =12; block = ^(){ number = 15; NSLog(@"number = %d",number); };// =15 NSLog(@"block调用之前 number= %d",number);//=12 number = 18; NSLog(@"18 => %d",number);//=18 //调用block block(); NSLog(@"block调用之后 number= %d",number);//15 number = 28; NSLog(@" number= %d",number);
- block对于对象类型
//相当于指针复制,指向同一块内部 NSMutableArray *array = [NSMutableArray arrayWithObjects:@"1",@"2",@"3",nil]; void (^myBlock)()=^(){ [array addObject:@"4"]; NSLog(@"myBlock 里面的%@",array); }; //先为array增接一个元素 [array addObject:@"6"]; NSLog(@"%@",array); myBlock(); NSLog(@"myBlock 调用后之后的值%@",array);
- 引用Block传值
参考BlockDemo\OC阶段最后一讲
RunTime
相关练习参考OC阶段第十讲课
RunTime简称运行时,就是系统在运行的时候的一些机制,是一套比较底层的纯C语言API, 属于1个C语言库, 包含了很多底层的C语言API。 在我们平时编写的OC代码中, 程序运行过程时, 其实最终都是转成了runtime的C语言代码, runtime算是OC的幕后工作者 比如说,下面一个创建对象的方法中, 举例: OC : [[MJPerson alloc] init] runtime : objc_msgSend(objc_msgSend(“MJPerson” , “alloc”), “init”)
在程序运行过程中, 可以动态创建一个类(比如KVO的底层实现),可以动态地为某个类添加属性\方法, 修改属性值\方法,可以遍历一个类的所有成员变量(属性)\所有方法
- Objective-C学习笔记
- Objective-C 学习笔记
- Objective-C学习笔记
- objective c 学习笔记
- Objective-C 学习笔记
- Objective-C学习 笔记
- Objective-c学习笔记
- Objective-c学习笔记
- Objective-C 学习笔记
- Objective C 学习笔记
- Objective-C学习笔记
- Objective-C 学习笔记
- objective-c学习笔记
- Objective-C 学习笔记
- Objective C 学习笔记
- Objective-C学习笔记
- Objective-C学习笔记
- Objective C 学习笔记
- jar 程序发布脚本
- Python之self
- Math.Round 之关于 不同的四舍五入
- C#操作文件及文件夹
- Android 使用Mockito测试业务逻辑<unittest 之一>
- Objective C 学习笔记
- ConcurrentHashMap原理
- 【Unity Shaders】学习笔记之固定着色器命令(二)
- Path Sum
- HMM原理介绍 示例 python代码实现
- Socket原理与编程基础
- Codeforces Round #351 (VK Cup 2016 Round 3, Div. 2 Edition) B.Problems for Round
- 细谈java中的堆和栈
- hibernate一级缓存和二级缓存的区别