GXiOS

iOS开发--内存管理及Block

2019-05-09  本文已影响2人  Caesar_62dd

内存管理简介

引用计数器

1.什么是引用计数器

yyjsq.png

2.引用计数器的作用

3.引用计数器的操作

dealloc方法

1.dealloc方法基本概念

野指针\空指针

1.僵尸对象

zombie.png

2.野指针

3.空指针

4.如何关闭ARC功能

arc.png

内存管理原则

1.内存管理原则

2.多对象内存管理

3.set方法内存管理

- (void)setRoom:(Room *)room
{
    // 避免过度释放
    if (room != _room)
    {
        // 对当前正在使用的房间(旧房间)做一次release
        [_room release];

        // 对新房间做一次retain操作
         _room = [room retain];
    }
}

4.dealloc方法的内存管理

- (void)dealloc
{
    // 当人不在了,代表不用房间了
    // 对房间做一次release操作
    [_room release];
    [super dealloc];
}

@property参数

1.控制set方法的内存管理

2.控制需不需要生成set方法

3.多线程管理

4.控制set方法和get方法的名称

@class

1.@class基本概念

2.@class其它应用场景

#import "B.h"
@interface A : NSObject
{
    B *_b;
}
@end

#import “A.h"
@interface B : NSObject
{
    A *_a;
}
@end
@class B;
@interface A : NSObject
{
    B *_b;
}
@end

@class A;
@interface B : NSObject
{
    A *_a;
}
@end

3.@class和#import

循环retian

1.循环retian基本概念

autorelease基本使用

1.autorelease基本概念

Person *p = [Person new];
p = [p autorelease];
Person *p = [Person new];
p = [p autorelease];
NSLog(@"count = %lu", [p retainCount]); // 1

2.自动释放池

@autoreleasepool
{ //开始代表创建自动释放池

} //结束代表销毁自动释放池

3.autorelease基本使用

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

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

[autoreleasePool drain];
@autoreleasepool
{ // 创建一个自动释放池
        Person *p = [[Person new] autorelease];
} // 销毁自动释放池(会给池子中所有对象发送一条release消息)

4.autorelease使用注意

 @autoreleasepool {
    // 因为没有调用 autorelease 方法,所以对象没有加入到自动释放池
    Person *p = [[Person alloc] init];
    [p run];
}
 @autoreleasepool {
 }
 // 没有与之对应的自动释放池, 只有在自动释放池中调用autorelease才会放到释放池
 Person *p = [[[Person alloc] init] autorelease];
 [p run];

 // 正确写法
  @autoreleasepool {
    Person *p = [[[Person alloc] init] autorelease];
 }

 // 正确写法
 Person *p = [[Person alloc] init];
  @autoreleasepool {
    [p autorelease];
 }
// 内存暴涨
    @autoreleasepool {
        for (int i = 0; i < 99999; ++i) {
            Person *p = [[[Person alloc] init] autorelease];
        }
    }
// 内存不会暴涨
 for (int i = 0; i < 99999; ++i) {
        @autoreleasepool {
            Person *p = [[[Person alloc] init] autorelease];
        }
    }

5.autorelease错误用法

 @autoreleasepool {
        // 错误写法, 过度释放
    Person *p = [[[[Person alloc] init] autorelease] autorelease];
 }
 @autoreleasepool {
    Person *p = [[[Person alloc] init] autorelease];
    [p release]; // 错误写法, 过度释放
 }

ARC基本概念

1.什么是ARC

2.ARC的注意点和优点

3.ARC的判断原则

 Person *p1 = [[Person alloc] init];
 __strong  Person *p2 = [[Person alloc] init];
__weak  Person *p = [[Person alloc] init];

4.ARC机制判断

ARC下的内存管理

1.ARC下单对象内存管理

int main(int argc, const char * argv[]) {
   @autoreleasepool {
        Person *p = [[Person alloc] init];
    } // 执行到这一行局部变量p释放
    // 由于没有强指针指向对象, 所以对象也释放
    return 0;
}
int main(int argc, const char * argv[]) {
   @autoreleasepool {
        Person *p = [[Person alloc] init];
        p = nil; // 执行到这一行, 由于没有强指针指向对象, 所以对象被释放
    }
    return 0;
}
int main(int argc, const char * argv[]) {
   @autoreleasepool {
        // p1和p2都是强指针
        Person *p1 = [[Person alloc] init];
        __strong Person *p2 = [[Person alloc] init];
    }
    return 0;
}
int main(int argc, const char * argv[]) {
   @autoreleasepool {
        // p是弱指针, 创建的对象会被立即释放
        __weak Person *p1 = [[Person alloc] init];
    }
    return 0;
}

2.ARC下多对象内存管理

@interface Person : NSObject

// MRC写法
//@property (nonatomic, retain) Dog *dog;

// ARC写法
@property (nonatomic, strong) Dog *dog;

@end

3.ARC下循环引用问题

@interface Person : NSObject

//@property (nonatomic, retain) Dog *dog;
@property (nonatomic, strong) Dog *dog;

@end

@interface Dog : NSObject

// 错误写法, 循环引用会导致内存泄露
//@property (nonatomic, strong) Person *owner;

// 正确写法, 当如果保存对象建议使用weak
//@property (nonatomic, assign) Person *owner;
@property (nonatomic, weak) Person *owner;
@end

4.ARC下@property参数

Category基本概念

1.什么是Category


2.Category的格式

@implementation ClassName(CategoryName)

NewMethod
... ...
@end
category1.png
category2.png

Category注意事项

1.分类的使用注意事项

@interface Person (NJ)
{
//    错误写法
//    int _age;
}
- (void)eat;
@end
@interface Person (NJ)
// 只会生成getter/setter方法的声明, 不会生成实现和私有成员变量
@property (nonatomic, assign) int age;
@end
@interface Person : NSObject
{
    int _no;
}
@end

@implementation Person (NJ)
- (void)say
{
    NSLog(@"%s", __func__);
    // 可以访问原有类中得成员变量
    NSLog(@"no = %i", _no);
}
@end
@implementation Person

- (void)sleep
{
    NSLog(@"%s", __func__);
}
@end

@implementation Person (NJ)
- (void)sleep
{
    NSLog(@"%s", __func__);
}
@end

int main(int argc, const char * argv[]) {
    Person *p = [[Person alloc] init];
    [p sleep];
    return 0;
}

输出结果:
-[Person(NJ) sleep]

2.分类的编译的顺序

@implementation Person

- (void)sleep
{
    NSLog(@"%s", __func__);
}
@end

@implementation Person (NJ)
- (void)sleep
{
    NSLog(@"%s", __func__);
}
@end

@implementation Person (MJ)
- (void)sleep
{
    NSLog(@"%s", __func__);
}
@end

int main(int argc, const char * argv[]) {
    Person *p = [[Person alloc] init];
    [p sleep];
    return 0;
}

输出结果:
-[Person(MJ) sleep]
category3.png
#import "NSString+GX.h"

@implementation NSString (GX)
+ (int)countWithStr:(NSString *)str
{
    int count = 0;
    for (int i = 0; i < str.length; i++) {
        unichar c = [str characterAtIndex:i];
        if (c >= '0' && c <= '9'){
            count++;
        }
    }
    return count;
}
- (int) count
{
    int num = 0;
    for (int i = 0; i < self.length; i++) {
        unichar c = [self characterAtIndex:i];
        if (c >= '0' && c <= '9'){
            num++;
        }
    }
    return num;
}
@end

类扩展(Class Extension)

1.什么是类扩展


2.类扩展书写格式

@interface 类名 ()
@end

Block基本概念

1.block的格式

返回值类型 (^block变量名)(形参列表) = ^(形参列表) {

};
Snip20150625_11.png
void (^block名)() = ^{代码块;}

例如:
void (^myBlock)() = ^{ NSLog(@"GX"); };
void (^block名称)(参数列表)
= ^ (参数列表) {  代码实现; };

例如:
void (^myBlock)(int) = ^(int num){ NSLog(@"num = %i", num); };
返回类型 (^block名称)(参数列表)
= ^ (参数列表) { // 代码实现; }

例如:
int (^myBlock)(int, int) = ^(int num1, int num2){ return num1 + num2; };
block变量名(实参);

typedef和Block

1.函数指针回顾

int sum(int value1, int value2)
{
    return value1 + value2;
}

int minus(int value1, int value2)
{
    return value1 - value2;
}

int main(int argc, const char * argv[]) {
    int (*sumP) (int, int) = sum;
    int res = sumP(10, 20);
    NSLog(@"res = %i", res);

    int (*minusP) (int , int) = minus;
    res = minusP(10, 20);
    NSLog(@"res = %i", res);
    return 0;
}
typedef int (*calculate) (int, int);
int main(int argc, const char * argv[]) {
    calculate sumP = sum;
    int res = sumP(10, 20);
    NSLog(@"res = %i", res);
    calculate minusP = minus;
    res = minusP(10, 20);
    NSLog(@"res = %i", res);
    return 0;
}

2.block和typedef

int main(int argc, const char * argv[]) {
  int (^sumBlock) (int, int) = ^(int value1, int value2){
      return value1 + value2;
  };
  int res = sumBlock(10 , 20);
  NSLog(@"res = %i", res);

  int (^minusBlock) (int, int) = ^(int value1, int value2){
      return value1 - value2;
  };
  res = minusBlock(10 , 20);
  NSLog(@"res = %i", res);
  return 0;
}
typedef int (^calculateBlock) (int, int);
int main(int argc, const char * argv[]) {
    calculateBlock sumBlock = ^(int value1, int value2){
        return value1 + value2;
    };
    int res = sumBlock(10, 20);
    NSLog(@"res = %i", res);
    calculateBlock minusBlock = ^(int value1, int value2){
        return value1 - value2;
    };
    res = minusBlock(10, 20);
    NSLog(@"res = %i", res);

    return 0;
}

Block注意事项

1.Block注意事项

int  a = 10;
void (^myBlock)() = ^{
    NSLog(@"a = %i", a);
    }
myBlock();
输出结果: 10
int  a = 10;
void (^myBlock)() = ^{
    int a = 50;
    NSLog(@"a = %i", a);
    }
myBlock();
输出结果: 50
int b = 5;
void (^myBlock)() = ^{
    b = 20; // 报错
    NSLog(@"b = %i", b);
    };
myBlock();
__block int b = 5;
void (^myBlock)() = ^{
  b = 20;
  NSLog(@"b = %i", b);
};
myBlock();
输出结果: 2

protocol 基本概念

2.protocol 语法格式

@protocol 协议名称
// 方法声明列表
@end
@interface 类名 : 父类 <协议名称1, 协议名称2,…>
@end
@protocol SportProtocol <NSObject>
- (void)playFootball;
- (void)playBasketball;
@end

#import "SportProtocol.h" // 导入协议
@interface Studnet : NSObject<SportProtocol> // 遵守协议
@end

@implementation Student
// 实现协议方法
- (void)playBasketball
{
    NSLog(@"%s", __func__);
}
// 实现协议方法
- (void)playFootball
{
    NSLog(@"%s", __func__);
}
@end

3.protocol和继承区别

4.protocol 的使用注意

@protocol SportProtocol <NSObject>
{
    int _age; // 错误写法
}
- (void)playFootball;
- (void)playBasketball;
@end
@protocol SportProtocol <NSObject>

- (void)playFootball;
- (void)playBasketball;
@end
#import "SportProtocol.h"
@interface Student : NSObject <SportProtocol>
@end

@interface GoodStudent : Student
@end

@implementation GoodStudent
- (void)playFootball
{
    NSLog(@"%s", __func__);
}
- (void)playBasketball
{
    NSLog(@"%s", __func__);
}
@end
#import "SportProtocol.h"
#import "StudyProtocol.h"

@interface Student : NSObject <SportProtocol, StudyProtocol>

@end
@protocol A
-(void)methodA;
@end

@protocol B <A>
-(void)methodB;
@end
@interface Student : NSObject <B>
-(void)methodA; // 同时拥有A/B协议中的方法声明
-(void)methodB;
@end

5.基协议

@protocol SportProtocol <NSObject> // 基协议

- (void)playFootball;
- (void)playBasketball;
@end

6.@required和@optional关键字

@protocol SportProtocol <NSObject>

@required // 如果遵守协议的类不实现会报警告
- (void)playFootball;
@optional // 如果遵守协议的类不实现不会报警告
- (void)playBasketball;
@end

代理设计模式

协议的编写规范

上一篇下一篇

猜你喜欢

热点阅读