OC语言疯狂讲义学习笔记

1、关于nil和Nil及NULL的区别:

nil: A null pointer to an Objective-C object. ( #define nil ((id)0) ) nil 是一个对象值。
Nil: A null pointer to an Objective-C class.
NULL: A null pointer to anything else. ( #define NULL ((void *)0) ) NULL是一个通用指针(泛型指针)。
NSNull: A class defines a singleton object used to represent null values in collection objects (which don't allow nil values).
[NSNull null]: The singleton instance of NSNull.
[NSNull null]是一个对象,他用在不能使用nil的场合。

2、避免使用僵尸对象的方法

为了防止不小心调用了僵尸对象,可以将对象赋值nil(对象的空值)


OC语言疯狂讲义学习笔记_第1张图片
僵尸对象.png

3、对象的内存泄露

OC语言疯狂讲义学习笔记_第2张图片
内存泄露1.png

OC语言疯狂讲义学习笔记_第3张图片
内存泄露1.png

OC语言疯狂讲义学习笔记_第4张图片
内存泄露2.png

OC语言疯狂讲义学习笔记_第5张图片
内存泄露3_1.png

OC语言疯狂讲义学习笔记_第6张图片
内存泄露3_2.png

4、@property 参数

OC语言疯狂讲义学习笔记_第7张图片
property参数.png

内存管理相关参数:


OC语言疯狂讲义学习笔记_第8张图片
内存管理相关参数.png

OC语言疯狂讲义学习笔记_第9张图片
assign.png

OC语言疯狂讲义学习笔记_第10张图片
assign_2.png

OC语言疯狂讲义学习笔记_第11张图片
retain_1.png

OC语言疯狂讲义学习笔记_第12张图片
retain_2.png

OC语言疯狂讲义学习笔记_第13张图片
retain_3.png

OC语言疯狂讲义学习笔记_第14张图片
retain_3.png

OC语言疯狂讲义学习笔记_第15张图片
retain_4.png

OC语言疯狂讲义学习笔记_第16张图片
proPerty参数二.png

OC语言疯狂讲义学习笔记_第17张图片
property_set.png

OC语言疯狂讲义学习笔记_第18张图片
property_get.png

5、@class的使用

作用

可以简单地引用一个类

简单使用

@class Dog; //类的引入
仅仅是告诉编译器: Dog是一个类; 并不会包含Dog这个类的所有内容

具体使用

在.h文件中使用@class引用一个类 在.m文件中使用#import包含这个类的.h文件

通常引用一个类有两种办法:
一种是通过#import方式引入;另一种是通过@class引入; 这两种的方式的区别在于:

1)#import方式会包含被引用类的所有信息,包括被引用类的变量和方法;@class方式只是告诉 编译器在A.h文件中 B *b 只是类的声明,具体这个类里有什么信息,这里不需要知道,等实现文 件中真正要用到时,才会真正去查看B类中信息;

2)使用@class方式由于只需要只要被引用类(B类)的名称就可以了,而在实现类由于要用到被 引用类中的实体变量和方法,所以需要使用#import来包含被引用类的头文件;

3)通过上面2点也很容易知道在编译效率上,如果有上百个头文件都#import了同一 个文件,或 者这些文件依次被#improt(A->B, B->C,C->D...),一旦最开始的头文件稍有改动,后面引用到这 个文件的所有类都需要重新编译一遍,这样的效率也是可想而知的,而相对来 讲,使用@class方 式就不会出现这种问题了;

所以:我们实际开发中尽量在.h头文件中使用@class

4)对于循环依赖关系来说,比方A类引用B类,同时B类也引用A类,B类的代码:

OC语言疯狂讲义学习笔记_第19张图片
recycle.png

作用上的区别

import会包含引用类的所有信息(内容), 包括引用类的变量和方法 @class仅仅是告诉编译器有这么一个类, 具体这个类里有什么信息, 完全不知

效率上的区别

如果有上百个头文件都#import了同一个文件,或者这些文件依次被#import,那么一旦最开始的头 文件稍有改动,后面引用到这个文件的所有类都需要重新编译一遍 , 编译效率非常低 相对来讲,使用@class方式就不会出现这种问题了

6、循环引用

循环retain的场景

OC语言疯狂讲义学习笔记_第20张图片
recycle.png

比如A对象retain了B对象,B对象retain了A对象 循环retain的弊端 这样会导致A对象和B对象永远无法释放

循环retain的解决方案

当两端互相引用时,应该一端用retain、一端用assign

7、NSString 类的内存管理问题

1)、NSString 等Foundation框架中类的内存管理

OC语言疯狂讲义学习笔记_第21张图片
内存管理.png

先看看以下这几种写法:

NSString *testStr1 = @"a";
NSString *testStr2 = [NSString stringWithString:@"a"];
NSString *testStr3 = [NSString stringWithFormat:@"b"];
NSString *testStr4 = [[NSString alloc] initWithString:@"c"];
NSString *testStr5 = [[NSString alloc] initWithFormat:@"d"];
NSString *testStr6 = [[NSString alloc] init];

NSLog(@"testStr1 ->%p",testStr1);
NSLog(@"testStr2 ->%p",testStr2);
NSLog(@"testStr3 ->%p",testStr3);
NSLog(@"testStr4 ->%p",testStr4);
NSLog(@"testStr5 ->%p",testStr5);
NSLog(@"testStr6 ->%p",testStr6);

OC语言疯狂讲义学习笔记_第22张图片
内存管理_2.png

通过对比地址可以看到,从上可以看出,testStr1,testStr2,testStr4都是在一个内存区域,也 就是常量内存区,

1---> NSString *str = [[NSString alloc] initWithString:@"ABC"]; 
2---> str = @"123";
3---> [str release];
4---> NSLog(@"%@",str);

首先,咱们先对这段代码进行分析。
第一句 声明了一个NSString类型的实例 str, 并将其初始化init后赋值为@"ABC" 第二行,将str的指针指向了一个常量@"123"。 理论上讲在第一行初始化的@"ABC"没有任何任何 指针指向了。 所以造成了内存泄露
然后第三行, 将str的引用计数-1
第四行输出str的值 为123.
首先回答为什么不会崩溃, 因为第三行的release 实际上是release了一个常量@"123" 而作为 常量,其默认的引用计数值是很大的(100k+)
NSLog(@"retainCount = %tu",[@"123" retainCount]);
最终的输出值会是一个很大很大的数。 所以单单一个release是不会将其释放掉的。
然后再回答这样会不会造成内存泄露。
其实............理论上讲 会!
但是实际上,Objective-C对NSString类型有特殊照顾。所有的NSString的引用计数器默认初始值 都会非常非常大。

2)、危险的用法

while ([a retainCount] > 0) {
         [a release];
} 

如果运行结果正确,那么这是多么幸运的一个人啊!

8、自动释放池及autorelease介绍

自动释放池

(1)在iOS程序运行过程中,会创建无数个池子,这些池子都是以栈结构(先进后出)存在的。 (2)当一个对象调用autorelease时,会将这个对象放到位于栈顶的释放池中

自动释放池的创建方式

(1)iOS 5.0以前的创建方式

NSAutoreleasePool *pool=[[NSAutoreleasePool alloc] init];

[pool release];//[pool drain];用于mac


(2)iOS5.0以后 

@autoreleasepool
{//开始代表创建自动释放池
·······
}//结束代表销毁自动释放池

####  autorelease

是一种支持引用计数的内存管理方式 
它可以暂时的保存某个对象(object),然后在内存池自己的排干(drain)的时候对其中的每个 对象发送release消息 注意,这里只是发送release消息,如果当时的引用计数(reference-counted)依然不为0,则该 对象依然不会被释放。可以用该方法来保存某个对象,也要注意保存之后要释放该对象。

####  为什么会有autorelease?
(1)不需要再关心对象释放的时间 
(2)不需要再关心什么时候调用release

####  autorelease何时释放?
对于autorelease pool本身,会在如下两个条件发生时候被释放
1)手动释放Autorelease pool
2)Runloop结束后自动释放
对于autorelease pool内部的对象
在引用计数的retain == 0的时候释放。release和autorelease pool 的 drain都会触发retain-- 事件。

### 9、Block
一、静态变量和全局变量 在加和不加 __block都会直接引用变量地址。也就意味着可以修
改变量的值。在没有加__block 参数的情况下。
• 全局block和栈block区别为是否引用了外部变量,堆block则是对栈block copy得来。对全局block
copy 不会有任何作用,返回的依然是全局block。
二, 常量变量(NSString *a = @"hello";a 为常量变量,@“hello”为常量。)-----不 加__block类型 block 会引用常量的地址(浅拷贝)。加__block类型 block会去引用常量变 量(如:a变量,a = @"abc".可以任意修改a 指向的内容。)的地址。

你可能感兴趣的:(OC语言疯狂讲义学习笔记)