黑马程序员—06OC内存管理_01

来源:互联网 发布:三星s5网络模式仅限2g 编辑:程序博客网 时间:2024/06/05 02:44

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------


一、description方法和SLE

1> description

包括类方法和对象方法两种 :

-description(对象方法)

使用NSLog@%输出某个对象时,会调用对象的description方法,并拿到返回值进行输出。

+description(类方法)

使用NSLog@%输出某个对象时,会调用类对象的description方法,并拿到返回值进行输出,把整个对象一次性打印出来,打印对象使用%@


使用@%打印对象如(“@%”,P)默认打印输出为<类名:内存地址>,虽然字符串也是对象,但字符串在使用@%打印时情况特殊。


2> SLE

SLE : SLE其实是对方法的一种包装,将方法包装成一个SEL类型的数据,去寻找对应的方法地址,找到方法地址后就可以调用方法。这些都是运行时特性,发消息就是发送SEL,然后根据SEL找到地址,调用方法。


SLE方法的存储位置:
* 每个类的方法列表都存储在类对象中;
* 每个方法都有一个与之对应的SEL类型的对象
* 根据一个SEL对象就可以找到方法的地址,然后调用方法;

3>举例 

Person类的声明 :

#import <Foundation/Foundation.h>@interface Person : NSObject@property int age;@property NSString *name;@end

Person类的实现 :

#import "Person.h"@implementation Person// 决定了实例对象的输出结果- (NSString *)description{    return [NSString stringWithFormat:@"age=%d, name=%@", _age, _name];}// 决定了类对象的输出结果+ (NSString *)description{    return @"Abc";}@end
主函数 :
int main(){    // 输出行号    NSLog(@"%d", __LINE__);        // 输出源文件的名称    printf("%s\n", __FILE__);        Person *pp = [[Person alloc] init];        // 指针变量的地址    NSLog(@"%p", &pp);    // 对象的地址    NSLog(@"%p", pp);    // <类名:对象地址>    NSLog(@"%@", pp);       Class c = [Person class];        // 1.会调用类的+description方法    // 2.拿到+description方法的返回值(NSString *)显示到屏幕上    NSLog(@"%@", c);        Person *p = [[Person alloc] init];    p.age = 20;    p.name = @"Jack";    NSLog(@"%@", p);    return 0;}


4> 总结

description 下面代码会发生死循环。

- (NSString *)description{NSLog(@"%@", self);return @"0000";}</span>

SLE寻找方法的过程:

Person *p=[[Person alloc] init];[p test];

* 首先把test这个方法名包装成sel类型的数据;

* 根据SEL数据找到对应的方法地址;

* 根据方法地址调用相应的方法。

* 注意:在这个操作过程中有缓存,第一次找的时候是一个一个的找,非常耗性能,之后再用到的时候就直接使用。


关于_cmd:每个方法的内部都有一个-cmd,代表着当前方法。


二、BOLCK

1> 简介

* BOLCK :苹果推荐的类型,效率高,在运行中保存代码。用来封装和保存代码,有点像函数,BLOCK可以在任何时候执行。

* BOLCK和函数的相似性:可以保存代码;有返回值;有形参;调用方式一样。

* 标示符是^。


2> 基础使用

* 定义block变量 :

int (^sumBlock)(int, int); void (^myBlock)();

* 利用block封装代码(可以有参,亦可无参) :

^(int a, int b) {    return a - b; };  ^() {    NSLog(@"----------"); };  ^ {    NSLog(@"----------"); };

* block访问外面变量 :

int main(){       int a = 10;    __block int b = 20;        void (^block)();        block = ^{        // block内部可以访问外面的变量        //NSLog(@"a = %d", a);                // 默认情况下,block内部不能修改外面的局部变量        // a = 20;                // 给局部变量加上__block关键字,这个局部变量就可以在block内部修改        b = 25;    };        block();    return 0;}


* 利用typedef定义block类型

typedef int (^MyBlock)(int, int);

以后就可以利用MyBlock这种类型来定义block变量

MyBlock block; MyBlock b1, b2;
譬如 :

b1 = ^(int a, int b) {   return a - b; };MyBlock b3 = ^(int a, int b) {   return a - b;};


3> 举例

#import <Foundation/Foundation.h>typedef int (*SumP)(int, int);typedef int (^MyBlock)(int, int);int sum(int a, int b){    return a + b;}int main(){    MyBlock sumBlock;    sumBlock = ^(int a, int b) {        return a + b;    };        MyBlock minusBlock = ^(int a, int b) {        return a - b;    };        MyBlock multiplyBlock = ^(int a, int b) {        return a * b;    };        NSLog(@"%d - %d - %d", multiplyBlock(2, 4),  sumBlock(10 , 9), minusBlock(10, 8));         return 0;}


4> 总结


三、protocol

1> 简介

Protocol:就一个用途,用来声明一大堆的方法(不能声明成员变量),不能写实现。

只要某个类遵守了这个协议,就拥有了这个协议中的所有方法声明。

*只要父类遵守了某个协议,那么子类也遵守。

* Protocol声明的方法可以让任何类去实现,protocol就是协议。

OC不能继承多个类(单继承)但是能够遵守多个协议。继承(:),遵守协议(< >

基协议:<NSObject>是基协议,是最根本最基本的协议,其中声明了很多最基本的方法。

*协议可以遵守协议,一个协议遵守了另一个协议,就可以拥有另一份协议中的方法声明。


2> 基本使用

* 创建协议 :

#import <Foundation/Foundation.h>// 定义了一个名叫MyProtocol的协议@protocol MyProtocol <NSObject>// @required 要求实现,不实现就会发出警告// @optional 不要求实现- (void)test4;@required- (void)test;- (void)test2;@optional- (void)test3;@end

* 遵守协议 :

#import <Foundation/Foundation.h>@class Hashiqi;@protocol MyProtocol2;@protocol MyProtocol3;// 只要一个类遵守了某一份协议,就能拥有这份协议中的所有方法声明// : 继承父类// <> 遵守协议@interface Person : NSObject <MyProtocol3, MyProtocol2>@property (nonatomic, strong) id<MyProtocol2> obj;@property (nonatomic, strong) Hashiqi *dog;@end

* 完成协议中方法的实现在类的实现(@implementation)中实现。


3> 总结

* 协议的定义 :

 @protocol 协议名称 <NSObject>

 // 方法声明列表....

 @end


* 如何遵守协议 :

 1> 类遵守协议

 @interface 类名 : 父类名 <协议名称1, 协议名称2>

 @end

 2> 协议遵守协议

 @protocol 协议名称 <其他协议名称1, 其他协议名称2>

 @end

 

* 协议中方法声明的关键字

 1> @required (默认)

  要求实现,如果没有实现,会发出警告。

 2> @optional

  不要求实现,怎样不会有警告。


* 定义一个变量的时候,限制这个变量保存的对象遵守某个协议。

 类名<协议名称> *变量名;

 id<协议名称> 变量名;

 NSObject<MyProtocol> *obj;

 id<MyProtocol> obj2;

 如果没有遵守对应的协议,编译器会警告。


* @property中声明的属性也可用做一个遵守协议的限制

 @property (nonatomic, strong) 类名<协议名称> *属性名;

 @property (nonatomic, strong) id<协议名称> 属性名;

 @property (nonatomic, strong)Dog<MyProtocol> *dog;

 @property (nonatomic, strong)id<MyProtocol> dog2;

 

* 协议可用定义在单独.h文件中,也可用定义在某个类中。

 1> 如果这个协议只用在某个类中,应该把协议定义在该类中。

 2> 如果这个协议用在很多类中,就应该定义在单独文件中。


* 分类可用定义在单独.h和.m文件中,也可用定义在原来类中

 1> 一般情况下,都是定义在单独文件。

 2> 定义在原来类中的分类,只要求能看懂语法。





0 0