原文地址:http://blog.sunnyxx.com/2014/09/15/objc-attribute-cleanup/

编译器属性__attribute__用于向编译器描述特殊的标识、检查或优化,几个常用的用法看《mattt大神的文章》就好。今天发现一个名为cleanup的黑魔法属性,简单介绍下。


基本用法

__attribute__((cleanup(...))),用于修饰一个变量,在它的作用域结束时可以自动执行一个指定的方法,如:

1
2
3
4
5
6
7
8
9
// 指定一个cleanup方法,注意入参是所修饰变量的地址,类型要一样
// 对于指向objc对象的指针(id *),如果不强制声明__strong默认是__autoreleasing,造成类型不匹配
static void stringCleanUp(__strong NSString **string) {
NSLog(@"%@", *string);
}
// 在某个方法中:
{
__strong NSString *string __attribute__((cleanup(stringCleanUp))) = @"sunnyxx";
} // 当运行到这个作用域结束时,自动调用stringCleanUp

所谓作用域结束,包括大括号结束、return、goto、break、exception等各种情况。
当然,可以修饰的变量不止NSString,自定义Class基本类型都是可以的:

1
2
3
4
5
6
7
8
9
10
// 自定义的Class
static void sarkCleanUp(__strong Sark **sark) {
NSLog(@"%@", *sark);
}
__strong Sark *sark __attribute__((cleanup(sarkCleanUp))) = [Sark new];
// 基本类型
static void intCleanUp(NSInteger *integer) {
NSLog(@"%d", *integer);
}
NSInteger integer __attribute__((cleanup(intCleanUp))) = 1;

假如一个作用域内有若干个cleanup的变量,他们的调用顺序是先入后出的栈式顺序;
而且,cleanup是先于这个对象的dealloc调用的。

进阶用法

既然__attribute__((cleanup(...)))可以用来修饰变量,block当然也是其中之一,写一个block的cleanup函数非常有趣:

1
2
3
4
// void(^block)(void)的指针是void(^*block)(void)
static void blockCleanUp(__strong void(^*block)(void)) {
(*block)();
}

于是在一个作用域里声明一个block:

1
2
3
4
5
6
{
// 加了个`unused`的attribute用来消除`unused variable`的warning
__strong void(^block)(void) __attribute__((cleanup(blockCleanUp), unused)) = ^{
NSLog(@"I'm dying...");
};
} // 这里输出"I'm dying..."

这里不得不提万能的Reactive Cocoa中神奇的@onExit方法,其实正是上面的写法,简单定义个宏:

1
2
#define onExit\
__strong void(^block)(void) __attribute__((cleanup(blockCleanUp), unused)) = ^

用这个宏就能将一段写在前面的代码最后执行:

1
2
3
4
5
{
onExit {
NSLog(@"yo");
};
} // Log "yo"

这样的写法可以将成对出现的代码写在一起,比如说一个lock:

1
2
3
4
5
6
NSRecursiveLock *aLock = [[NSRecursiveLock alloc] init];
[aLock lock];
// 这里
// 有
// 100多万行
[aLock unlock]; // 看到这儿的时候早忘了和哪个lock对应着了

用了onExit之后,代码更集中了:

1
2
3
4
5
6
7
8
NSRecursiveLock *aLock = [[NSRecursiveLock alloc] init];
[aLock lock];
onExit {
[aLock unlock]; // 妈妈再也不用担心我忘写后半段了
};
// 这里
// 爱多少行
// 就多少行

还是那句老话:剩下的就全靠想象力了。

黑魔法__attribute__((cleanup))的更多相关文章

  1. __attribute__系列之cleanup

    cleanup属性:当变量离开它的作用域时,设置的cleanup_function函数将被调用. cleanup (cleanup_function) The cleanup attribute ru ...

  2. Objective-C 源码初探 __attribute__

    #import <Foundation/Foundation.h> //延迟执行,delayFunc函数即为延迟执行的函数 #define onExit\ __strong void (^ ...

  3. __attribute__的一些相关属性

    __attribute__((format()))  这个format有3个参数. int my(NSString *str,NSString *str1,NSArray*str2,...) __at ...

  4. 如何在 Objective-C 的环境下实现 defer

    关注仓库,及时获得更新:https://github.com/draveness/iOS-Source-Code-Analyze Follow: https://github.com/Dravenes ...

  5. GNU C/C++ __attributes__ GCC中的弱符号与强符号

    最近在看一些源代码,遇到了一些使用__attribute__修饰函数和变量的属性方面的代码,不是太了解,很是汗颜,再此做个总结:   GCC使用__attribute__关键字来描述函数,变量和数据类 ...

  6. 【原创】利用C++ RAII技术自动回收堆内存

    [说明]这篇文章本来发布在我个人网站的博客上,但由于:1,打算以cnblogs为家了:2. 关于智能指针部分需要修订,所有将修订版发在这里,作为第一篇文章. 常遇到的动态内存回收问题 在C++的编程过 ...

  7. 利用C++ RAII技术自动回收堆内存

    在C++的编程过程中,我们经常需要申请一块动态内存,然后当用完以后将其释放.通常而言,我们的代码是这样的: 1: void func() 2: { 3: //allocate a dynamic me ...

  8. libextobjc 实现的 defer

    算法沉思录:分而治之(复用): 分而治之是指把大而复杂的问题分解成若干个简单的小问题,然后逐个解决.这种朴素的思想来源于人们生活与工作的经验,也完全适合于技术领域. 要崩溃的节奏: 要崩溃的节奏: V ...

  9. Getting start with dbus in systemd (03) - sd-bus.h 使用例子 (systemd version>=221)

    sd-bus.h 例子 注意: sd-dbus 是systemd提供的lib,但是这个lib,只有在systemd>v221版本后才可以使用,centos 219版本太低,所以不能使用. 参考: ...

随机推荐

  1. .net mvc datatables中orderby动态排序

    今天在做项目中用datatables的排序来做筛选,不过人比较懒,不想写那么多的关于排序的代码,于是寻思这在度娘上找找,结果不负有心人啊,更感谢贴出此贴的哥们,来源:http://blog.csdn. ...

  2. Oracle order by case when 多条件排序

    ORACLE sql 排序 根据两个条件排序,根据id号由小到大排序,同时country字段是北京的排最前面前面,其次上海,..大连,最后是其他城市,怎么写? 写法如下:select * from p ...

  3. 《C# 并发编程 · 经典实例》读书笔记

    前言 最近在看<C# 并发编程 · 经典实例>这本书,这不是一本理论书,反而这是一本主要讲述怎么样更好的使用好目前 C#.NET 为我们提供的这些 API 的一本书,书中绝大部分是一些实例 ...

  4. SSM框架入门和搭建 十部曲

    又快到毕业设计的时候了,有的学弟说想用ssm做毕业设计,在网上找到资料看不懂,基础差.我就帮他写了一个demo,顺便也整理一下. SSM框架,顾名思义,就是Spring+SpringMVC+mybat ...

  5. STL中的set容器

    #include <iostream> #include <set> using namespace std; int main() { set<int> s; s ...

  6. (转)你知道Android也有安全模式吗?(地球人都知道了吧)

    使用PC时,我们习惯在安全模式下解决驱动的各种兼容性问题.而你是否又知道,Android手机同样存在安全模式,帮你解决APP的各种冲突问题. 很多Android手机用户都遇到过下面这种极端情况:因为第 ...

  7. Websocket 与代理服务器如何交互? How HTML5 Web Sockets Interact With Proxy Servers

    How HTML5 Web Sockets Interact With Proxy Servers Posted by Peter Lubberson Mar 16, 2010 With the re ...

  8. php把excel数值格式转成日期格式问题

    在excel中:40847对应2011-10-31,是日期的数值型表现形式. 在PHP中,echo date('Y-m-d H:i:s',40847);//结果1970-01-01 11:52:30 ...

  9. Win7-IIS7下运行PHP网站(以配置好的drupal网站为例)

    0.前提:IIS7已启用. drupal网站配置文件web.config中用到了“简洁链接”(URL重写),所以,还需要事先安装URL重写模块. URL重写模块(url rewrite)下载地址: r ...

  10. centos 下搭建 php环境(2) mysql 安装

    CentOS下的MySQL 5.1安装   01 1.下载源码包 wget http://mysql.llarian.net/Downloads/MySQL-5.1/mysql-5.1.63.tar. ...