iOS开发Block的介绍以及Block的循环引用问题

1:block的循环引用问题最主要记住两点:

如果【block内部】使用【外部声明的强引用】访问【对象A】, 那么【block内部】会自动产生一个【强引用】指向【对象A】

如果【block内部】使用【外部声明的弱引用】访问【对象A】, 那么【block内部】会自动产生一个【弱引用】指向【对象A】

2:

#import "ViewController.h"
#import "XMGPerson.h"

@interface ViewController ()
@property (nonatomic, copy) int (^sumBlock)(int, int);
@property (nonatomic, assign) int a;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    [self test5];
    /*
     如果【block内部】使用【外部声明的强引用】访问【对象A】, 那么【block内部】会自动产生一个【强引用】指向【对象A】
     如果【block内部】使用【外部声明的弱引用】访问【对象A】, 那么【block内部】会自动产生一个【弱引用】指向【对象A】
     */
}

/**
 *  不可行
 */
- (void)test6
{
    XMGPerson *p = [[XMGPerson alloc] init];

    __weak XMGPerson *weakP = p;

    p.name = @"Jack";

    p.block = ^{ // block1
        XMGPerson *strongP = weakP;
        NSLog(@"block1 -- %@", strongP.name);

        dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC));
        dispatch_after(when, dispatch_get_main_queue(), ^{ // block2
            NSLog(@"block2 -- %@", weakP.name);
        });
    };

    p.block();
}

/**
 *  可行
 */
- (void)test5
{
    XMGPerson *p = [[XMGPerson alloc] init];

    __weak XMGPerson *weakP = p;

    p.name = @"Jack";

    p.block = ^{ // block1
        NSLog(@"beign-------");
        XMGPerson *strongP = weakP;

        dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC));
        dispatch_after(when, dispatch_get_main_queue(), ^{ // block2

            // NSLog(@"block2 -- %@", weakP.name);
            NSLog(@"block2 -- %@", strongP.name);

            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ // block3
                NSLog(@"block3 -- %@", strongP.name);
            });

        });
    };

    p.block();
}

/**
 *  不可行
 */
- (void)test4
{
    XMGPerson *p = [[XMGPerson alloc] init];

    p.name = @"Jack";

    p.block = ^{ // block1
        NSLog(@"beign-------");

        dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC));
        dispatch_after(when, dispatch_get_main_queue(), ^{ // block2
            NSLog(@"after-----------%@", p.name);
        });
    };

    p.block();
}

/**
 *  不可行
 */
- (void)test3
{
    XMGPerson *p = [[XMGPerson alloc] init];
    __weak XMGPerson *weakP = p;

    p.name = @"Jack";

    p.block = ^{ // block1
        NSLog(@"beign-------");
        XMGPerson *strongP = weakP;

        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(),
                       ^{ // block2
                           NSLog(@"after-----------%@", strongP.name);
                       });
    };

    p.block();
}

/**
 *  可行
 */
- (void)test2
{
    XMGPerson *p = [[XMGPerson alloc] init];

    __weak XMGPerson *weakP = p;

    p.name = @"Jack";
    p.block = ^{ // block1
        NSLog(@"beign-------");

        XMGPerson *strongP = weakP;

        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(),
                       ^{ // block2
                           NSLog(@"after-----------%@", strongP.name);
                       });
    };

    p.block();
}

- (void)test1
{
    XMGPerson *p = [[XMGPerson alloc] init];

    __weak XMGPerson *weakP = p;

    p.name = @"Jack";
    p.block = ^{
        NSLog(@"-----------%@", weakP.name);
    };
}

#pragma mark - 其他
- (void)test:(int (^)(int, int))sumBlock
{

}

- (void)run:(int)a
{

}

- (void)testBlock
{
    [self test:^(int a, int b){
        return a + b;
    }];

    void (^block)() =  ^{
        NSLog(@"-------");
    };
    block();

    int (^sumBlock)(int, int) = ^(int num1, int num2){
        return num1 + num2;
    };
    sumBlock(10, 10);

    int a = 10;

    /*
     返回值类型 (^block的变量名)(形参类型列表) = ^(形参列表) {
     // block代码
     };
     block的变量名(实参列表);
     */
}

@end

总结:1:block的定义:1:block以属性定义的时候,用copy修饰,

@property (nonatomic, copy) void (^block)();无参数无返回值,因为block默认是在堆里,需要将堆中的block,copy到栈中才能使用  2:block的非属性定义:1:无参数无返回值:

其中 void (^block)() 表示声明一个名称为block的block,block的类型表示为:void (^)(),右边的为block任务的代码块,
    block();表示调用block,右边为左边的block赋值
  void (^block)() =  ^{
        NSLog(@"-------");
    };
    block();
 2:有参数有返回值的block:左边int (^sumBlock)(int, int)定义一个有参数有返回值的block:sumBlock,而右边的block给左边的block赋值,写法:参数写在^(int a,int b)其中ab为block的参数,返回值写在block的代码块中。
 sumBlock(10, 10);调用block,并未block传递参数
 ^(int num1, int num2){
        return num1 + num2;
    };
 
  int (^sumBlock)(int, int) = ^(int num1, int num2){
        return num1 + num2;
    };
    sumBlock(10, 10);
    
3:block作为参数传递:1: block作为参数传递 - (void)test:(int (^)(int, int))sumBlock,实现该方法,调用block传递参数 2:在外部调用test方法,其中ab就为传递的参数,

[self test:^(int a, int b){

NSLog(@"%d",a+b);

return a + b;

}];

- (void)test:(int (^)(int, int))sumBlock

{

sumBlock(2,1);

}

4:1:block的循环引用:XMGPerson alloc init 之后在内存中产生一个对象,name 和 block是该对象的属性(因为用copy修饰,也就相当于强引用),则该对象会对这两个属性分别有一个强引用,创建完对象之后,有一个强指针p指向该对象(指针里存放的是对象的地址,变量创建之后无论是全局变量还是局部变量都会有一个强引用),__weak那部分代码是将强指针p的地址复制给一个弱指针weakSelf,此时弱指针weakSelf会有一个弱引用指向person对象,p.name = @"JACK";此时name属性会对jack有一个强引用,block会对赋值的block有一个强引用。此时不会立即调用block代码块中的任务,但是此时会检测block代码块中有无引用外部变量(即使是外部无引用,在after中引用了,也算block中引用了外部变量,此时会对访问的该对象有一个强引用或是弱引用,代码块中有引用weakP,所以会产生一个弱引用),再执行代码调用block,执行block代码块中的任务,将一个弱引用weakP指针赋值给一个强引用,此时block代码块中的strongP会对person对象有一个强引用,在执行gcd延迟函数,此时会产生延迟函数的block块,会检测延迟函数中有无引用外界的变量,有引用了strongP,则会产生一个强引用指向person对象,此时的代码块不立即执行(但是系统会有一个强指针指向该代码块,如图2),此时会执行到方法结束,强指针p销毁,弱指针weakp销毁,strongP执行完销毁,但此时block2还指向person对象,所以person对象不会销毁,能打印出name  2:像类似于GCD的延迟函数在block中,想要保住对象使其不备销毁,就在block中定义一个强引用指向就可以了


 
				
时间: 2024-10-26 10:18:23

iOS开发Block的介绍以及Block的循环引用问题的相关文章

[翻译] iOS开发工具的介绍(第一部分)

IOS DEVELOPMENT TIPS & TRICKS - PART I http://blog.trifork.com/2013/12/19/ios-development-tips-tricks-part-i/ As you might know, I am very fond of developing apps for the iOS platform. I started back in mid-2009 by trying to create an app for the Dut

iOS开发之---block的使用(详解)

一.基本概念 block (代码块)类似C语言函数指针. 定义一个block的格式:返回值类型 (^变量名)(参数列表)--->void (^blcok)(void). 一般使用typedef重命名block,上面的block定义可以这样写--->typedef void(^MyBlock)(void),MyBlock block. 二.简单使用 block在iOS的开发中,主要用来对象之间的通信,包括值的传递(反向传递)和方法的传递.

IOS开发——OC基础-ARC、BLOCK、协议

一.ARC ARC 是一种编译器特性!而不是IOS运行时特性,和JAVA中得垃圾回收机制完全不一样ARC是自iOS 5之后增加的新特性,完全消除了手动管理内存的烦琐,编译器会自动在适当的地方插入适当的retain.release.autorelease语句.你不再需要担心内存管理,因为编译器为你处理了一切ARC规则:只要还有一个强指针变量指向对象,对象就会保持在内存中弱指针指向的对象被回收后,弱指针会自动变为nil指针,不会引发野指针错误使用注意:1.不允许调用release.retain.re

iOS开发————对象间通信之block

一.block的概念: 别称:代码段,块,闭包,是苹果公司添加到OC语言中的. 作用:在程序运行的过程中保存一段代码,并且这段代码可以进行传递. 应用:用于对象间的通信. 二.block的语法: 和函数指针的语法相似 要设定block的返回值和参数个数及类型. (1)定义: 无参无返回值的block变量:void (^myBlock)(void) 有参数有返回值的block变量 int (^sumBlock)(int, int); (2)赋值: myBlock = ^{ //block中的代码

iOS内存管理(4)--Block属性用copy修饰 & 避免循环引用的问题

一.Block的类型 根据Block在内存中的位置分为三种类型NSGlobalBlock,NSStackBlock, NSMallocBlock. NSGlobalBlock:类似函数,位于text段: NSStackBlock:位于栈内存,函数返回后Block将无效: NSMallocBlock:位于堆内存. 二.Block的copy.retain.release操作 不同于NSObjec的copy.retain.release操作: Block_copy与copy等效,Block_relea

iOS开发总结(A0)- Block

1. 定义block 以返回NSInterger 接受bool 参数为例 1)作为参数 methodTakeBlockAsParamter: (NSInterger (^) (BOOL flag))blockName 2) 作为变量或者property @property(copy, nonatomic)  NSInterger (^blockName) (BOOL flag); 3)typedef typedef  NSInterger (^blockName) (BOOL flag); 2.

iOS开发多线程理论介绍

前言 线程是用来执行任务的,线程彻底执行完任务A才能去执行任务B.为了同时执行两个任务,产生了多线程. 就我们日常生活的例子来说: (1)我打开一个视频软件,我开辟一个线程A让它执行下载任务,我开辟一个线程B,用来播放视频.我开辟两个线程后,这两个任务能同时执行,如果我开辟一个线程,只有下载任务完成,才能去执行播放任务. (2)线程相当于店里的服务员,一个服务员同时只能做一件事情,多顾几个服务员,就能同时做很多事情. 在了解多线程之前我们先来介绍一下进程和线程 进程 进程是操作系统中运行的程序专

iOS开发UI—UIWindow介绍

一.简单介绍 UIWindow是一种特殊的UIView,通常在一个app中只会有一个UIWindow iOS程序启动完毕后,创建的第一个视图控件就是UIWindow,接着创建控制器的view,最后将控制器的view添加到UIWindow上,于是控制器的view就显示在屏幕上了 一个iOS程序之所以能显示到屏幕上,完全是因为它有UIWindow.也就说,没有UIWindow,就看不见任何UI界面 补充:UIWindow是创建的第一个视图控件(创建的第一个对象是UIapplication)如下图:

iOS开发>学无止境 - POP 介绍与使用实践(快速上手动画)

作者:里脊串(@里脊串) 网址:http://adad184.com/2015/03/11/intro-to-pop/   前言 动画在APP开发过程中 大家多多少少都会接触到 而且随着ios7的扁平化风格启用之后 越来越多的APP开始尝试加入各种绚丽的动画交互效果以增加APP的用户体验(当然 还是以国外的APP居多) 有过相关开发经验的同学肯定知道在iOS中 动画相关的部分都是基于Core Animation 但是今天我们不讨论Core Animation 今天的主角是POP -来自于Face