关于block的那些事

Netblock:能够阻止单个或多个目标的wifi访问的python脚本 #关于# Netblock是一个python脚本,可以阻止通过ARP欺骗从互联网访问连接到同一网关的受害者。 Netblock能够阻止同一网络上的一个,多个或所有受害者。 #如何使用# Netblock在CLI中运行。 通过执行以下命令安装脚本: sudo sh install.sh 通过在CLI中键入netblock来执行Netblock。 这是运行时netblock的外观: -------------------- Connected ips: 0) 10.12.26.1 00:00:0c:07:ac:1a 1) 10.12.26.2 c8:4c:75:6a:55:40 2) 10.12.26.3 c8:4c:75:6a:55:80 3) 10.12.26.7 d0:57:4c:53:7d:42 4) 10.12.26.9 立即下载

一,前言

在前文《深入浅出Cocoa多线程编程之block与dispatch quene》中我介绍了 block 的一些基本语法以及如何和 GCD 结合的使用示例。block 是在 iOS 4 中引入的新特性,它和 C++ 11 中的 lamba 表达式概念相似,有时候也被称为闭包。经过一段时间的使用,我发现要用对用好 block 还是有不少需要注意的地方,今天就来八一八这些值得注意的事儿。

本文源码下载:点此下载


二,block 注意事项

1,block 在实现时就会对它引用到的它所在方法中定义的栈变量进行一次只读拷贝,然后在 block 块内使用该只读拷贝。

如下代码:

- (void)testAccessVariable
{
    NSInteger outsideVariable = 10;
    //__block NSInteger outsideVariable = 10;
    NSMutableArray * outsideArray = [[NSMutableArray alloc] init];
    
    void (^blockObject)(void) = ^(void){
        NSInteger insideVariable = 20;
        KSLog(@"  > member variable = %d", self.memberVariable);
        KSLog(@"  > outside variable = %d", outsideVariable);
        KSLog(@"  > inside variable = %d", insideVariable);
        
        [outsideArray addObject:@"AddedInsideBlock"];
    };
    
    outsideVariable = 30;
    self.memberVariable = 30;

    blockObject();
    
    KSLog(@"  > %d items in outsideArray", [outsideArray count]);
}

输出结果为:

  > member variable = 30
  > outside variable = 10
  > inside variable = 20
  > 1 items in outsideArray

注意到没?outside 变量的输出值为10,虽然outside变量在定义 block 之后在定义 block 所在的方法 testAccessVariable 中被修改为 20 了。这里的规则就是:blockObject 在实现时会对 outside 变量进行只读拷贝,在 block 块内使用该只读拷贝。因此这里输出的是拷贝时的变量值 10。如果,我们想要让 blockObject 修改或同步使用 outside 变量就需要用 __block 来修饰 outside 变量。

__block NSInteger outsideVariable = 10;

 注意:

a),在上面的 block 中,我们往 outsideArray 数组中添加了值,但并未修改 outsideArray 自身,这是允许的,因为拷贝的是 outsideArray 自身。 

b),对于 static 变量,全局变量,在 block 中是有读写权限的,因为在 block 的内部实现中,拷贝的是指向这些变量的指针。

c), __block 变量的内部实现要复杂许多,__block 变量其实是一个结构体对象,拷贝的是指向该结构体对象的指针。

 

2,非内联(inline) block 不能直接访问 self,只能通过将 self 当作参数传递到 block 中才能使用,并且此时的 self 只能通过 setter 或 getter 方法访问其属性,不能使用句点式方法。但内联 block 不受此限制。

typedef NSString* (^IntToStringConverter)(id self, NSInteger paramInteger);
- (NSString *) convertIntToString:(NSInteger)paramInteger
                 usingBlockObject:(IntToStringConverter)paramBlockObject
{
    return paramBlockObject(self, paramInteger);
}

typedef NSString* (^IntToStringInlineConverter)(NSInteger paramInteger);
- (NSString *) convertIntToStringInline:(NSInteger)paramInteger
                 usingBlockObject:(IntToStringInlineConverter)paramBlockObject
{
    return paramBlockObject(paramInteger);
}

IntToStringConverter independentBlockObject = ^(id self, NSInteger paramInteger) {
    KSLog(@" >> self %@, memberVariable %d", self, [self memberVariable]);
    
    NSString *result = [NSString stringWithFormat:@"%d", paramInteger];
    KSLog(@" >> independentBlockObject %@", result);
    return result;
};

- (void)testAccessSelf
{
    // Independent
    //
    [self convertIntToString:20 usingBlockObject:independentBlockObject];
    
    // Inline
    //
    IntToStringInlineConverter inlineBlockObject = ^(NSInteger paramInteger) {
        KSLog(@" >> self %@, memberVariable %d", self, self.memberVariable);
        
        NSString *result = [NSString stringWithFormat:@"%d", paramInteger];
        KSLog(@" >> inlineBlockObject %@", result);
        return result;
    };
    [self convertIntToStringInline:20 usingBlockObject:inlineBlockObject];
}

 

3,使用 weak–strong dance 技术来避免循环引用

在第二条中,我提到内联 block 可以直接引用 self,但是要非常小心地在 block 中引用 self。因为在一些内联 block 引用 self,可能会导致循环引用。如下例所示:

@interface KSViewController ()
{
    id _observer;
}

@end

@implementation KSViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    KSTester * tester = [[KSTester alloc] init];
    [tester run];
    
    _observer = [[NSNotificationCenter defaultCenter]
                 addObserverForName:@"TestNotificationKey"
                 object:nil queue:nil usingBlock:^(NSNotification *n) {
                     NSLog(@"%@", self);
                 }];
}

- (void)dealloc
{
    if (_observer) {
        [[NSNotificationCenter defaultCenter] removeObserver:_observer];
    }
}

在上面代码中,我们添加向通知中心注册了一个观察者,然后在 dealloc 时解除该注册,一切看起来正常。但这里有两个问题:

a) 在消息通知 block 中引用到了 self,在这里 self 对象被 block retain,而 _observer 又 retain 该 block的一份拷贝,通知中心又持有 _observer。因此只要 _observer 对象还没有被解除注册,block 就会一直被通知中心持有,从而 self 就不会被释放,其 dealloc 就不会被调用。而我们却又期望在 dealloc 中通过 removeObserver 来解除注册以消除通知中心对 _observer/block 的 retain。

b) 同时,_observer 是在 self 所在类中定义赋值,因此是被 self retain 的,这样就形成了循环引用。

上面的过程 a) 值得深入分析一下:

苹果官方文档中对 addObserverForName:object:queue:usingBlock: 中的 block 变量说明如下:

The block is copied by the notification center and (the copy) held until the observer registration is removed.

因此,通知中心会拷贝 block 并持有该拷贝直到解除 _observer 的注册。在 ARC 中,在被拷贝的 block 中无论是直接引用 self 还是通过引用 self 的成员变量间接引用 self,该 block 都会 retain self。

这两个问题,可以用 weak–strong dance 技术来解决。该技术在 WWDC 中介绍过:2011 WWDC Session #322 (Objective-C Advancements in Depth)

    __weak KSViewController * wself = self;
    //__weak typeof(self) weakSelf = self;

 _observer = [[NSNotificationCenter defaultCenter]
                 addObserverForName:@"TestNotificationKey"
                 object:nil queue:nil usingBlock:^(NSNotification *n) {
                     KSViewController * sself = wself;
                     if (sself) {
                         NSLog(@"%@", sself);
                     }
                     else {
                         NSLog(@"<self> dealloc before we could run this code.");
                     }
                 }];

下面来分析为什么该手法能够起作用。

首先,在 block 之前定义对 self 的一个弱引用 wself,因为是弱引用,所以当 self 被释放时 wself 会变为 nil;然后在 block 中引用该弱应用,考虑到多线程情况,通过使用强引用 sself 来引用该弱引用,这时如果 self 不为 nil 就会 retain self,以防止在后面的使用过程中 self 被释放;然后在之后的 block 块中使用该强引用 sself,注意在使用前要对 sself 进行了 nil 检测,因为多线程环境下在用弱引用 wself 对强引用 sself 赋值时,弱引用 wself 可能已经为 nil 了。

通过这种手法,block 就不会持有 self 的引用,从而打破了循环引用。

 

扩展:其他还需要注意避免循环引用的地方

与此类似的情况还有 NSTimer。苹果官方文档中提到"Note in particular that run loops retain their timers, so you can release a timer after you have added it to a run loop.",同时在对接口

+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)seconds target:(id)target selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)repeats

的 target 说明文档中提到:

The object to which to send the message specified by aSelector when the timer fires. The target object is retained by the timer and released when the timer is invalidated.

结合这两处文档说明,我们就知道只要重复性 timer 还没有被 invalidated,target 对象就会被一直持有而不会被释放。因此当你使用 self 当作 target 时,你就不能期望在 dealloc 中 invalidate timer,因为在 timer 没有被invalidate 之前,dealloc 绝不会被调用。因此,需要找个合适的时机和地方来 invalidate timer,但绝不是在 dealloc 中。 

 

4,block 内存管理分析

block 其实也是一个 NSObject 对象,并且在大多数情况下,block 是分配在栈上面的,只有当 block 被定义为全局变量或 block 块中没有引用任何 automatic 变量时,block 才分配在全局数据段上。 __block 变量也是分配在栈上面的。

在 ARC 下,编译器会自动检测为我们处理了 block 的大部分内存管理,但当将 block 当作方法参数时候,编译器不会自动检测,需要我们手动拷贝该 block 对象。幸运的是,Cocoa 库中的大部分名称中包含”usingBlock“的接口以及 GCD 接口在其接口内部已经进行了拷贝操作,不需要我们再手动处理了。但除此之外的情况,就需要我们手动干预了。

- (id) getBlockArray
{
    int val = 10;
    return [[NSArray alloc] initWithObjects:
            ^{ KSLog(@"  > block 0:%d", val); },    // block on the stack
            ^{ KSLog(@"  > block 1:%d", val); },    // block on the stack
            nil];
    
//    return [[NSArray alloc] initWithObjects:
//            [^{ KSLog(@"  > block 0:%d", val); } copy],    // block copy to heap
//            [^{ KSLog(@"  > block 1:%d", val); } copy],    // block copy to heap
//            nil];
}

- (void)testManageBlockMemory
{
    id obj = [self getBlockArray];
    typedef void (^BlockType)(void);
    BlockType blockObject = (BlockType)[obj objectAtIndex:0];
    blockObject();
}

执行上面的代码中,在调用 testManageBlockMemory 时,程序会 crash 掉。因为从 getBlockArray 返回的 block 是分配在 stack 上的,但超出了定义 block 所在的作用域,block 就不在了。正确的做法(被屏蔽的那段代码)是在将 block 添加到 NSArray 中时先 copy 到 heap 上,这样就可以在之后的使用中正常访问。

在 ARC 下,对 block 变量进行 copy 始终是安全的,无论它是在栈上,还是全局数据段,还是已经拷贝到堆上。对栈上的 block 进行 copy 是将它拷贝到堆上;对全局数据段中的 block 进行 copy 不会有任何作用;对堆上的 block 进行 copy 只是增加它的引用记数。

如果栈上的 block 中引用了__block 类型的变量,在将该 block 拷贝到堆上时也会将 __block 变量拷贝到堆上如果该 __block 变量在堆上还没有对应的拷贝的话,否则就增加堆上对应的拷贝的引用记数。


STM32F103C8T6 + GY-906红外测温:手把手教你用CubeMX和HAL库搞定IIC驱动(附完整工程) 本文详细介绍了如何使用STM32F103C8T6和GY-906红外测温传感器(基于MLX90614芯片)实现非接触式温度测量。从STM32CubeMX工程创建、HAL库驱动适配到温度数据采集与处理,提供完整的开发流程和常见问题解决方案,帮助开发者快速掌握红外测温技术。 阅读详情

相关推荐

clock-gating整理

文章目录clock gating 理解1、latch双稳态器件常见锁存器结构SR锁存器D锁存器2、clock gating(clock low-active) latch + AND gating 电路(clock high-active)latch + OR gating 电路 clock gating 理解 1、latch 参考:https://www.cnblogs.com/IClearner/p/6443539.html 双稳态器件 稳定状态为0或1两种 举例:交叉耦合反相器 假设初始Q为1,则可

d_b_的博客 1万+

[深入浅出Cocoa]Block编程值得注意的那些事儿

[深入浅出Cocoa]Block编程值得注意的那些事儿 罗朝辉 (http://blog.youkuaiyun.com/kesalin/) 本文遵循“署名-非商业用途-保持一致”创作公用协议 一,前言 在前文《深入浅出Cocoa多线程编程之block与dispatch quene》中我介绍了 block 的一些基本语法以及如何和 GCD 结合的使用示例。block 是在 iOS 4 中...

dawuafang 216

3dsMax高效导入OSGB倾斜模型的3个关键步骤与插件应用

本文详细解析了在3dsMax中高效导入OSGB倾斜模型的三个核心步骤:建立索引、处理贴图路径以及选择合适的插件。针对导入过程中常见的模型崩溃、贴图丢失和操作卡顿问题,提供了从数据结构理解到插件选型的实战解决方案,帮助用户实现大规模实景模型在3dsMax中的流畅导入与编辑。

weixin_29238147的博客 468

ext4 ext4_map_blocks

struct ext4_map_blocks { ext4_fsblk_t m_pblk; ext4_lblk_t m_lblk; unsigned int m_len; unsigned int m_flags; }; /*  * The ext4_map_blocks() function tries to look up the reques

星空探索 1545

局域网ip冲突检测工具_python 小工具实现 windows笔记本与 ipad数据互传

宅在家没事的时候就开始琢磨ipad的进阶使用,由于没有mac无法隔空投送,ipad与windows的数据交互表现极差,所以设计了这个ftp小工具。当然,这个工具不仅仅能用于windows与ipad,还可以用于局域网任意两台设备之间程序源码与下载见文章末尾使用说明windows端:biubiubiu.exeipad端: appsotre下载 FE文件管理器windows端操作在c盘下创建ftp目录...

weixin_39866265的博客 4435

一文搞定 ST22 短转储 MEMORY_NO_MORE_PAGING:看懂 SAP Paging 机制,参数 rdisp/PG_SHM 与 rdisp/PG_MAXFS 怎么设才稳

SAP系统MEMORY_NO_MORE_PAGING错误通常源于Paging资源耗尽而非物理内存不足。关键排查点包括:通过ST22确认错误类型,ST02监控Paging使用情况,检查工作进程trace中的"no more free blocks"提示。解决方案建议将rdisp/PG_SHM和rdisp/PG_MAXFS设为相同值(如250000块≈2GB),使Paging完全在内存中运行。同时需优化易耗Paging的代码逻辑,如避免滥用EXTRACT命令和超大内存对象传输。典型案例如月末

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 334

使用内存文件映射MappedByteBuffer读超大文件可能会遇到的问题

使用内存文件映射MappedByteBuffer读超大文件可能会遇到的问题 这种方式存在一个致命问题就是依然没法读取超大文件(大于 Integer.MAX_VALUE),因为 FileChannel 的 map 方法中 size 参数会有大小限制,源码中发现该参数值大于Integer.MAX_VALUE 时会直接抛出IllegalArgumentException("Size exceeds Integer.MAX_VALUE") 异常,所以对于特别大的文件其依然不适合。本质上是由于 java.nio..

liinux-Talk is cheap,show me the code. 1989

08-StarRocks性能调优FAQ

StarRocks性能调优摘要 本文提供了StarRocks数据库性能调优的常见问题解答,涵盖查询优化、索引设计、分区策略和系统配置等关键方面。主要内容包括:查询优化技巧(使用EXPLAIN分析、避免全表扫描、优化JOIN和聚合查询);索引选择与维护建议(高频查询列索引、复合索引);分区策略设计(时间分区、范围分区)及其管理方法;以及系统内存配置优化(JVM参数调整、查询内存限制设置)。这些优化措施可显著提升StarRocks的查询性能和系统效率。

欢迎来到我的博客,一起探索代码里的世界! 541

常见的闭包代码陷阱

闭包深入理解 如果一个函数在定义的词法环境外运行并记住了定义时的词法环境,这样的现象就可以称作函数闭包 function f(x=0){ var count=x; function getCount(){ return count++; } return getCount } var func = f(10); console.log(func()); // 10 代码如下 let f = ()=

yiyueqinghui的博客 865

置顶必读(1) |《YOLOv11实战:从入门到深度优化》专栏导读,带你一文了解本专栏!

🏆 本文收录于 《YOLOv8实战:从入门到深度优化》 专栏,该专栏专注于分享我在YOLOv8目标检测模型中的实战经验,涵盖从入门基础到深度优化的全方位解决方案。无论你是计算机视觉的新手,还是具有多年深度学习经验的专家,本专栏都将为你提供高效、可复现的技术方案,助你掌握YOLOv8的核心技术,提升目标检测性能,突破瓶颈,优化模型,并加速项目开发🚀!

**My Coding Family** 12万+

量化之趋势跟踪策略

趋势跟踪策略 import numpy as np import pandas as pd import matplotlib as mpl import matplotlib.pyplot as plt import seaborn as sns from finance import GetData import warnings; warnings.filterwarnings('ignore') data = GetData.get_data('../data/002236.csv') .

木头大左的博客 2533

Block的那些事

这篇文章主要是用来学习Block的原理和一些Block的用法,相信有很多小伙伴每天都在用Block,但是对于它在MRC和ARC中的运行模式,包括Block在内存中的位置并不是很清楚,所以咱还是赶紧看我摘取过来的资料吧。

司小文的专栏 2256

芒果YOLOv8改进160:姿态估计Head篇:即插即用|轻量化非对称多级压缩LOADH旋转检测头,原创改进适配YOLOv8高效检测头,检测头新颖改进,全网首发独一份

芒果YOLOv8改进159:OBB旋转检测头Head篇:即插即用|轻量化非对称多级压缩LOADH旋转检测头,原创改进适配YOLOv8高效检测头,检测头新颖改进,全网首发独一份

包括YOLOv5、YOLOv7、YOLOv8等模型改进 812

关于block change tracking的那些事

1.block change tracking介绍Block chage tracking是Oracle10g的一个新特性,Block change tracking进程记录自从上一次备份以来数据块的变化,并把这些信息记录在跟踪文件中。RMAN使用这个文件判断增量备份中需要备份的变更数据。这极大的促进了备份性能,RMAN可以不再扫描整个文件以查找变更数据。为此Oracle引入了一个新的后台进程,CTWR,其全称为Change Tracking Writer,用于记录变化的块并将变化写入相应的日志文件中。 2

Makaveli的专栏 5993

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

block底层那些你不知道的事

如果block只掌握了怎么去应用,那了解了block的皮毛。若想要精通block,非得了解block的本质不行! ####block的实质 block对象本质是一个结构体,里面主要信息有:isa指针指向自己的类(三类:global程序的数据区域、 malloc堆、 stack栈),desc结构体描述block的信息,__forwarding指向自己或堆上自己的地址。 如果block对象截获变量,...

John_5555的博客 7485

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

block才会执行 mono_Block与GCD的那些事

BlocksBlocks是C语言的扩充功能,是带用自动变量的匿名函数(不带有名称的函数)1.Block语法//C语言为例 int countAdd(int count) { return count + 1; } //标准格式 // ^ 返回值类型 参数列表 表达式 ^int (int count) { return count + 1; } //可省略返回值类型 ^(int count)...

weixin_31727937的博客 399

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

iOS block中使用self的那么事

我们在使用block的时候,如果在block是引用self有可能会循环引用,产生内存泄漏的问题。通常,我们如果遇到这种情况,我们会将self转换成weak automatic的变量,这样就避免了block对self强引用。

driftAxe的专栏 3119

IOS ARC跟block那点事

【ARC的特性】   ARC下,所有NSObject类型指针,   1. 默认为__strong类型   2. 可以显示的指定为__weak类型,__weak类型指针在所指向对象销毁后会自动置为nil   3. __autorelesing类型用于inout参数类型   ARC下,当一个函数返回一个NSObject指针时,编译器会帮我们实现autorelease调用。

a330416020—my_start的专栏 7787

iOS--Block的那些事

假设我们熟悉代理递值的话,对代理我们可能又爱有恨!我们先建立模型A页面 push B页面,如果把A页面的值传递到B页面,属性和单例传值可以搞定!但是如果Pop过程中把B页面的值传递到A页面,那就可以用单例或者代理了!说到代理,我们要先声明协议,创建代理,很是麻烦。常常我们传递一个数值需要在两个页面间写很多代码,这些代码改变页面的整体顺序,可读性也打了折扣。所以,此时,Block是一种优化...

aocuy600466的博客 126

也谈block 编程那些事

转:http://sealedace.com/blog/2014/01/23/block-retain-cycle/ 我们知道在使用block时,必须避免出现retain cycle。如果写代码不仔细造成了retain cycle,就会出现内存泄露。即使Xcode有静态代码分析工具,但很多时候Xcode也不太靠谱,根本什么提示都没有,所以还是自己写代码多注意比较好。 (下文译自Th

songhongri的专栏 1236

iOS打基础之Block二三事

iOS 学习之Block学习

Ambrosedream的博客 644

f2fs二三事 block map 1

f2fs_map_blocks函数主要作用是为写入inode的数据分配内存空间(包括node block,data block),四个参数: 1) struct inode * inode: 操作的inode结构 2) struct f2fs_map_blocks * map:要写入的block相关信息的参数 3) int create: 如果为true, 表示如果内中不存在相应的bloc...

tianweishuiguo的专栏 1215

block 二三事

Programming with C Blocks   On Apple Devices   by Joachim Bengtsson What are Blocks?What are Blocks Good For?Getting Started On and for Mac OS X 10.6 Snow Leopard, or for iOS 4On Mac OS X 10.5

yohohohoho的专栏 1279

OC学习那些事:Block

1.Block Block封装了一段代码,可以在任何时候执行。 Block可以作为函数的参数,或者函数的返回值,而其本身又可以带输入参数或返回值。它和传统的函数指针类似,但是有区别:block是inline(内联函数)的,并且默认情况下它对具备变量是可读的。 苹果官方建议尽量多用block。在多线程、异步任务、集合遍历、集合排序、动画转场的很多。 2.B...

jishublog 181
上一篇: 使用GCD时的内存管理问题
下一篇: iOS开发--地图与定位
Allen_iOS
博客等级 码龄12年 3粉丝 4原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值