#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.自动换行
封装:只要是对成员变量的封装,例如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
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.当方法内部不许需要成员变量的时候,阔以使用类方法
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的方法名。
//字符串创建
/* 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);
//增、删、改、插
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);
//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);
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);
/* 字典以键值对的方式进行存储,无序 例如: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"];
/*
*增: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"];
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;
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);
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作为可变对象,是内容复制,也成为深复制。但是复制之后的字符串变成了一个不可变的字符串;
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];
// 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};
pragma mark –NSNumber
数值对象,用于简单数据类型的对象化封装,继承与 NSValue;
NSNumber的初始化
NSNumber *number1 = [NSNumber numberWithInt:5];
NSNumber *number2 = [NSNumber numberWithFloat:5];
NSNumber *number3 = [NSNumber numberWithDouble:5.0f];
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);
//区别: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);
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 +0000
2016-05-21 17:51:08.624 3.24练习[7214:232131] dateString1 : 2016年5月21日 下午5:51:08
2016-05-21 17:51:08.624 3.24练习[7214:232131] dateString2 : 2016年5月21日 下午5:51:08
2016-05-21 17:51:08.624 3.24练习[7214:232131] 当前时区:2016-05-21 17:51:08 +0000
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);
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];
//内存管理原则
//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]);
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);
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
//一个对象加入到数组中 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]);
/* 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]);
//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应用_
---------------------------------------------
返回值类型 函数名 参数类型 调用
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);
//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);
//相当于指针复制,指向同一块内部
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);
参考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的底层实现),可以动态地为某个类添加属性\方法, 修改属性值\方法,可以遍历一个类的所有成员变量(属性)\所有方法