new 是c++中的操做符,malloc是c 中的一个函数css
new 不止是分配内存,并且会调用类的构造函数,同理delete会调用类的析构函数,而malloc则只分配内存,不会进行初始化类成员的工做,一样free也不会调用析构函数ios
内存泄漏对于malloc或者new均可以检查出来的,区别在于new能够指明是那个文件的那一行, 而malloc没有这些信息。c++
new 和 malloc效率比较面试
new能够认为是malloc加构造函数的执行。objective-c
new出来的指针是直接带类型信息的。编程
SEL就是对方法的一种包装。包装的SEL类型数据它对应相应的方法地址,找到方法地址就能够调用方法。在内存中每一个类的方法都存储在类对象中,每一个方法都有一个与之对应的SEL类型的数据,根据一个SEL数据就能够找到对应的方法地址,进而调用方法。api
SEL s1 = @selector(test1); // 将test1方法包装成SEL对象 数组
SEL s2 = NSSelectorFromString(@"test1"); // 将一个字符串方法转换成为SEL对象安全
调用方法有两种方式:多线程
1.直接经过方法名来调用 [person text]
2.间接的经过SEL数据来调用 SEL aaa=@selector(text); [person performSelector:aaa];
继承:继承是从已有类获得继承信息建立新类的过程。提供继承信息的类被称为父类(超类、基类);获得继承信息的类被称为子类(派生类)。 继承让变化中的软件系统有了必定的延续性,同时继承也是封装程序中可变因素的重要手段。
封装:封装是把数据和操做数据的方法绑定起来,对数据的访问只能经过已定义的接口。咱们在类中编写的方法就是对实现细节的一种封装;咱们编写一个类就是对数据和数据操做的封装。能够说,封装就是隐藏一切可隐藏的东西,只向外界提供最简单的编程接口。
多态性:多态性是指容许不一样子类型的对象对同一消息做出不一样的响应。简单的说就是用一样的对象引用调用一样的方法可是作了不一样的事情。多态性分为编译时的多态性和运行时的多态性。方法重载(overload)实现的是编译时的多态性(也称为前绑定),而方法重写(override)实现的是运行时的多态性(也称为后绑定)。运行时的多态是面向对象最精髓的东西,要实现多态须要作两件事:1. 方法重写(子类继承父类并重写父类中已有的或抽象的方法);2. 对象造型(用父类型引用引用子类型对象,这样一样的引用调用一样的方法就会根据子类对象的不一样而表现出不一样的行为)。
抽象:抽象是将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象两方面。抽象只关注对象有哪些属性和行为,并不关注这些行为的细节是什么。
主要是将数据类型的肯定由编译时,推迟到了运行时。这个问题其实浅涉及到两个概念,运行时和多态。
简单来讲, 运行时机制使咱们直到运行时才去决定一个对象的类别,以及调用该类别对象指定方法。
多态:不一样对象以本身的方式响应相同的消息的能力叫作多态。
意思就是假设生物类(life)都拥有一个相同的方法-eat;那人类属于生物,猪也属于生物,都继承了life后,实现各自的eat,可是调用是咱们只需调用各自的eat方法。也就是不一样的对象以本身的方式响应了相同的消 息(响应了eat这个选择器)。所以也能够说,运行时机制是多态的基础.
KVC(Key-Value-Coding):是键值编码, 一个对象在调用setValue的时候,
检查是否存在相应key的set方法,存在就调用set方法。
set方法不存在,就查找_key的成员变量是否存在,存在就直接赋值。
若是_key没找到,就查找相同名称的key,存在就赋值。
Delegate: 一般发送者和接收者的关系是直接的一对一的关系。
代理的目的是改变或传递控制链。容许一个类在某些特定时刻通知到其余类,而不须要获取到那些类的指针。
能够减小框架复杂度。消息的发送者(sender)告知接收者(receiver)某个事件将要发生,delegate赞成然而后发送者响应事件,delegate机制使得接收者能够改变发送者的行为。
Notification: 观察者模式, 一般发送者和接收者的关系是间接的多对多关系。 消息的发送者告知接收者事件已经发生或者将要发送,仅此而已,接收者并不能反过来影响发送者的行为。
区别
浅复制(copy):只复制指向对象的指针,而不复制引用对象自己。
深复制(mutableCopy):复制引用对象自己。深复制就好理解了,内存中存在了两份独立对象自己, 当修改A时,A_copy不变。
变量的做用域不一样。
优势:1.Cateogies 2.Posing 3.动态识别 4.指标计算 5.弹性讯息传递 6.不是一个过分复杂的C衍生语言 7.Objective-C与C++可混合编程
缺点:1.不支持命名空間 2.不支持运算符重载 3.不支持多重继承 4.使用动态运行时类型,全部的方法都是函数调用,因此不少编译时优化方法都用不到。(如内联函数等),性能低劣。
谓词就是经过NSPredicate给定的逻辑条件做为约束条件,完成对数据的筛选。
//定义谓词对象,谓词对象中包含了过滤条件
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"age<%d",30];
//使用谓词条件过滤数组中的元素,过滤以后返回查询的结果
NSArray *array = [persons filteredArrayUsingPredicate:predicate];
//可使用&&进行多条件过滤
predicate = [NSPredicate predicateWithFormat:@"name='1' && age>40"];
array = [persons filteredArrayUsingPredicate:predicate];
//包含语句的使用
predicate = [NSPredicate predicateWithFormat:@"self.name IN {'1','2','4'} || self.age IN{30,40}"];
//指定字符开头和指定字符结尾,是否包含指定字符
//name以a开头的
predicate = [NSPredicate predicateWithFormat:@"name BEGINSWITH 'a'"];
//name以ba结尾的
predicate = [NSPredicate predicateWithFormat:@"name ENDSWITH 'ba'"];
//name中包含字符a的
predicate = [NSPredicate predicateWithFormat:@"name CONTAINS 'a'"];
//like进行匹配多个字符
//name中只要有s字符就知足条件
predicate = [NSPredicate predicateWithFormat:@"name like 's'"];
//?表明一个字符,下面的查询条件是:name中第二个字符是s的
predicate = [NSPredicate predicateWithFormat:@"name like '?s'"];
处理.m能够识别c和oc,.mm能够识别c c++ oc 可是cpp只能用c/c++
NSNull:NSNull是继承于NSObject的类型。它是很特殊的类,它表示是空,什么也不存储,可是它倒是对象,只是一个占位对象。使用场景就不同了,好比说服务端接口中让咱们在值为空时,传空。NSDictionry *parameters = @{@"arg1" : @"value1",@"arg2" : arg2.isEmpty ? [NSNull null] : arg2};
NULL、nil、Nil这三者对于Objective-C中值是同样的,都是(void *)0,那么为何要区分呢?又与NSNull之间有什么区别:
向nil发送消息是彻底有效的——只是在运行时不会有任何做用。
若是一个方法返回值是一个对象,那么发送给nil的消息将返回0(nil)
若是方法返回值为指针类型,其指针大小为小于或者等于sizeof(void*),float,double,long double 或者long long的整型标量,发送给nil的消息将返回0。
-若是方法返回值为结构体,正如在《Mac OS X ABI 函数调用指南》,发送给nil的消息将返回0。结构体中各个字段的值将都是0。其余的结构体数据类型将不是用0填充的。
类方法 | 实例方法 | |
---|---|---|
属于类对象 | 属于实例对象 | |
只能类对象调用 | 实例对象调用 | |
self是类对象 | self是实例对象 | |
类方法能够调用其余类方法 | 实例方法能够调用实例方法 | |
类方法不能访问成员变量 | 实例方法能够访问成员变量 | |
类方法不能直接调用对象方法 | 实例方法能够调用类方法 |
NSString *str = [[NSString alloc]initWithCString:nullTerminatedCString encoding:encoding];
extern "C" {
}
显然,头文件中的编译宏“#ifndef INCvxWorksh、#define INCvxWorksh、#endif” 的做用是防止该头文件被重复引用
@property的本质: @property = ivar(实例变量) + getter(取方法) + setter(存方法) “属性” (property)有两大概念:ivar(实例变量)、存取方法(access method = getter + setter) ivar、getter、setter如何生成并添加到类中: 这是编译器自动合成的,经过@synthesize关键字指定,若不指定,默认为@synthesize propertyName = _propertyName;若手动实现了getter/setter方法,则不会自动合成。 如今编译器已经默认为咱们添加@synthesize propertyName = _propertyName;所以再也不须要手动添加了,除非你真的要改为员变量名。 生成getter方法时,会判断当前属性名是否有_,好比声明属性为@property (nonatomic, copy) NSString *_name;那么所生成的成员变量名就会变成__name,若是咱们要手动生成getter方法,就要判断是否以_开头了。 不过,命名都要有规范,是不容许声明属性是使用_开头的,不规范的命名,在使用runtime时,会带来不少的不方便的。
• 在protocol中使用@property只会生成setter和getter方法声明,咱们使用属性的目的是但愿遵照我协议的对象能实现该属性 • category使用@property也是只会生成setter和getter方法的声明,若是咱们真的须要给category增长属性的实现,须要借助于运行时的两个函数: • objc_setAssociatedObject • objc_getAssociatedObject
原子性 (atomic,nonatomic)
读写(readwrite, readonly)
内存管理(assign, strong, weak, unsafe_unretained,copy)
getter、setter
在头文件中将属性定义为readonly,在.m文件中将属性从新定义为readwrite
meta-class 是 Class 对象的类,为这个Class类存储类方法,当一个类发送消息时,就去这个类对应的meta-class中查找那个消息,每一个Class都有不一样的meta-class,全部的meta-class都使用基类的meta-class(假如类继承NSObject,那么他所对应的meta-class也是NSObject)做为他们的类
@selector()基本能够等同C语言的中函数指针,只不过C语言中,能够把函数名直接赋给一个函数指针,而Object-C的类不能直接应用函数指针,这样只能作一个@selector语法来取.
@interface foo -(int)add:int val; @end SEL class_func ; //定义一个类方法指针 class_func = @selector(add:int);
@selector是查找当前类的方法,而[object @selector(方法名:方法参数..) ] ;是取object对应类的相应方法.
能够运行中用SEL变量反向查出方法名字字符串。NSString *变量名 = NSStringFromSelector(SEL参数);
取到selector的值之后,执行seletor。 SEL变量的执行.用performSelecor方法来执行.
[对象 performSelector:SEL变量 withObject:参数1 withObject:参数2];
- @property有两个对应的词,一个是 @synthesize,一个是 @dynamic。若是 @synthesize和 @dynamic都没写,那么默认的就是@syntheszie var = _var; - @synthesize 的语义是若是你没有手动实现 setter 方法和 getter 方法,那么编译器会自动为你加上这两个方法。 - @dynamic 告诉编译器:属性的 setter 与 getter 方法由用户本身实现,不自动生成。(固然对于 readonly 的属性只需提供 getter 便可)。假如一个属性被声明为 @dynamic var,而后你没有提供 @setter方法和 @getter 方法,编译的时候没问题,可是当程序运行到 instance.var = someVar,因为缺 setter 方法会致使程序崩溃;或者当运行到 someVar = var 时,因为缺 getter 方法一样会致使崩溃。编译时没问题,运行时才执行相应的方法,这就是所谓的动态绑定。
OC中NSString为不可变字符串的时候,用copy和strong都是只分配一次内存,可是若是用copy的时候,须要先判断字符串是不是不可变字符串,若是是不可变字符串,就再也不分配空间,若是是可变字符串才分配空间。若是程序中用到NSString的地方特别多,每一次都要先进行判断就会耗费性能,影响用户体验,用strong就不会再进行判断,因此,不可变字符串能够直接用strong。
NSString *timeStr = @"2015-04-10"; NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; formatter.dateFormat = @"yyyy-MM-dd"; formatter.timeZone = [NSTimeZone defaultTimeZone]; NSDate *date = [formatter dateFromString:timeStr]; // 2015-04-09 16:00:00 +0000 NSLog(@"%@", date);
- (id)performSelector:(SEL)aSelector; - (id)performSelector:(SEL)aSelector withObject:(id)object; - (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;
由于系统提供的performSelector的api中,并无提供三个参数。所以,咱们只能传数组或者字典,可是数组或者字典只有存入对象类型,而结构体并非对象类型,那么怎么办呢?
没有办法,咱们只能经过对象放入结构做为属性来传过去了:
ypedef struct HYBStruct { int a; int b; } *my_struct; @interface HYBObject : NSObject @property (nonatomic, assign) my_struct arg3; @property (nonatomic, copy) NSString *arg1; @property (nonatomic, copy) NSString *arg2; @end @implementation HYBObject // 在堆上分配的内存,咱们要手动释放掉 - (void)dealloc { free(self.arg3); } @end
测试:
my_struct str = (my_struct)(malloc(sizeof(my_struct))); str->a = 1; str->b = 2; HYBObject *obj = [[HYBObject alloc] init]; obj.arg1 = @"arg1"; obj.arg2 = @"arg2"; obj.arg3 = str; [self performSelector:@selector(call:) withObject:obj]; // 在回调时获得正确的数据的 - (void)call:(HYBObject *)obj { NSLog(@"%d %d", obj.arg3->a, obj.arg3->b); }
实际上,编译器在编译时会转换成objc_msgSend,大概会像这样:
((void (*)(id, SEL))(void)objc_msgSend)((id)obj, sel_registerName("foo")); 也就是说,[obj foo];在objc动态编译时,会被转换为:objc_msgSend(obj, @selector(foo));这样的形式,可是须要根据具体的参数类型及返回值类型进行相应的类型转换。
@implementation Son : Father - (id)init { self = [super init]; if (self) { NSLog(@"%@", NSStringFromClass([self class])); NSLog(@"%@", NSStringFromClass([super class])); } return self; } @end // 输出 NSStringFromClass([self class]) = Son NSStringFromClass([super class]) = Son 这个题目主要是考察关于Objective-C中对self和super的理解。咱们都知道:self是类的隐藏参数,指向当前调用方法的这个类的实例。那super呢? 不少人会想固然的认为“super和self相似,应该是指向父类的指针吧!”。这是很广泛的一个误区。其实 super是一个 Magic Keyword,它本质是一个编译器标示符,和self 是指向的同一个消息接受者!他们两个的不一样点在于:super会告诉编译器,调用class 这个方法时,要去父类的方法,而不是本类里的。 上面的例子无论调用[self class]仍是[super class],接受消息的对象都是当前 Son *xxx 这个对象。 当使用self调用方法时,会从当前类的方法列表中开始找,若是没有,就从父类中再找;而当使用super时,则从父类的方法列表中开始找。而后调用父类的这个方法。
什么是构造方法:构造方法是对象初始化并一个实例的方法。
构造方法有什么用: 通常在构造方法里 对类进行一些初始化操做
注意点:方法开头必须以init开头,接下来名称要大写 例如 initWithName ,initLayout
Get方法的做用:为调用者返回对象内部的成员变量
不能, 由于结构体当中只能是类型的声明不能进行分配空间
@implementation Person - (void)setAge:(int)newAge { self.age = newAge; } @end 会死循环,会重复调用本身!self.age 改成_age便可; 而且书写不规范:setter方法中的newAge应该为age
NSString * str = @"20 | http://www.baidu.com"; NSArray *array = [str componentsSeparatedByString:@"|"]; //这是分别输出的截取后的字符串 for (int i = 0; i<[array count]; ++i) { NSLog(@"%d=%@",i,[array objectAtIndex:i]); }
//建立 @protocol MyDelagate @required -(void)eat:(NSString *)foodName; @optional -(void)run; @end //声明 @interface person: NSObject< MyDelagate> //实现 @implementation person -(void)eat:(NSString *)foodName; { NSLog(@"吃:%@!",foodName);} -(void)run { NSLog(@"run!");} @end
isKindOfClass,做用是,某个对象属于某个类型或者继承自某类型
isMemberOfClass:某个对象确切属于某个类型
selector:经过方法名,获取在内存中的函数的入口地址
SEL是“selector”的一个类型,表示一个方法的名字-------就是一个方法的入口地址
id是一个指向任何一个继承了Object(或者NSObject)类的对象。须要注意的是id是一个指针,因此在使用id 的时候不须要加*。
int:基本整型,当字节数为2时 取值范围为-32768~32767,当字节数为4时 取值范围
负的2的31次方 到 2的31次方减1
unsigned int:无符号基本整型,当字节数为2时 取值范围为0~65535,当字节数为4时 取值范围为0到2的32次方减1
+ (void)deleteFiles:(NSString *)path;{ // 1.判断文件仍是目录 NSFileManager * fileManger = [NSFileManager defaultManager]; BOOL isDir = NO; BOOL isExist = [fileManger fileExistsAtPath:path isDirectory:&isDir]; if (isExist) { // 2. 判断是否是目录 if (isDir) { NSArray * dirArray = [fileManger contentsOfDirectoryAtPath:path error:nil]; NSString * subPath = nil; for (NSString * str in dirArray) { subPath = [path stringByAppendingPathComponent:str]; BOOL issubDir = NO; [fileManger fileExistsAtPath:subPath isDirectory:&issubDir]; [self deleteFiles:subPath]; } }else{ NSLog(@"%@",path); [manager removeItemAtPath:filePath error:nil]; } }else{ NSLog(@"你打印的是目录或者不存在"); } }
文章若有问题,请留言,我将及时更正。