ObjC 中的循环引用
iOS App 国际化的那些事儿
iOS 多线程基础知识
多线程注意点: 不要同时开太多线程,耗时操作不要再主线程执行,放到子线程执行
线程概念
a. 主线程:UI线程,显示、刷新UI界面,处理UI控件的事件
b. 子线程:后台线程,异步线程
一、NSThread
- 1.1 创建和启动线程的三种方式
|
|
- 1.2 常见用法
|
|
二、线程同步
- 本质: 防止多个线程访问同一个资源造成数据安全问题
- 实现: 加一个互斥锁(同步锁)
|
|
三、GCD(Grand Central Dispatch)
队列和任务
- 1.1 任务: 需要执行的操作block
1.2 队列: 存放任务
1.2.1 全局并发队列(系统提供)
1dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);1.2.2 串行队列(手动创建)
1dispatch_queue_t queue = dispatch_queue_create("aQueue”, NULL);1.2.3 主队列(主线程中执行)
1dispatch_queue_t queue = dispatch_get_main_queue();
2 执行任务的函数
dispatch_sync… 同步执行: 不具备开启新线程的能力
dispatch_async… 异步执行: 具备开启新线程的能力
- 3 常用组合
dispatch_async… + 并发队列
dispatch_async… + 串行队列
- 4 线程间通信
|
|
- 5 GCD的所有API都在 libdispatch.dylib, Xcode会自动导入主头文件:
#import \
- 6 延迟执行
|
|
- 7 只执行一次
|
|
- 8 队列组
dispatch_group_async \ dispatch_group_notify
四、单例模式
|
|
五、NSOperation
NSOperation 是一个抽象的基类, 一般使用子类 NSBlockOperation 或 NSOperationQueue
- 1 队列的类型
|
|
- 2 添加任务到队列
|
|
- 3 常见用法
|
|
- 4 设置依赖
|
|
- 5 线程之间的通信
|
|
六、从其他线程回到主线程的三种方式
|
|
七、判断编译器的环境
|
|
八、类的初始化方法
|
|
ObjC 中的@符号
我们在写 OC 代码时, 最常用到的一个特殊符号可能就是 @ 了吧, 下面总结一下, OC 中使用到 @ 符号的场景.
@””
快速创建一个由引号内内容初始化的 NSString 对象.
@42, @3.14, @YES, @’Z’
创建一个由对应类型初始化的 NSNumber 对象.
例如 :
|
|
@[]
创建一个由 , 分隔的对象列表作为内容的 NSArray 对象.
例如 :
|
|
@{}
创建一个由特定 键-值 对作为内容的 NSDictionary 对象.
例如 :
|
|
@()
自动装箱, 返回基于其值的合适的对象.
例如 :
|
|
ObjC Style Guide
Objective-C Style Guide
最近看了很多OC方面的编码风格推荐, 个人认为编码规范不管对于个人开发还是团队开发都是非常重要的, 这里总结出来, 给大家提供一个参考.
语言
使用美式英语.
|
|
组织代码
使用 #pragma mark -
组织代码.
|
|
条件语句
|
|
方法
方法声明中, 应该在(-/+ 符号)的后面留一个空格.
|
|
变量
变量应该尽可能的用描述性的语言命名, 应该避免使用单字母来命名变量除了用于
for()
循环里.*表示变量是一个指针, 例如
NSString *text
不要写成NSString* text
, 也不要写成NSString * text
, 除非是在定义常量的情况下.属性定义无论在何时都应该是用来代替实例变量定义, 应该避免直接使用实例变量, 除非在初始化方法中(
init
,initWithCoder:
等),dealloc
方法中和实例变量对应的setter
和getter
方法中.
|
|
命名
遵循 Apple 命名规范
|
|
字母前缀(例如SR
)应该用于类名和常量, 但是 Core Data 的实体名应该忽略前缀.
常量应该使用驼峰式命名规范, 要与类名有相关性要见面知意.
|
|
- 属性和局部变量应该使用开头字母小写的驼峰式命名规范.
- 实例变量应该使用开头字母小写的驼峰式命名规范,并且前缀是下划线.
- 局部变量不应该包含下划线.
注释
注释应该是用来解释为什么, 而不是用来说明是什么.
init 和 deallocdealloc
方法应该放在 implementation
的上面, init
应该直接放在 dealloc
方法的下面.
|
|
文字变量
NSString
,NSDictionary
,NSArray
, 和NSNumber
这些文字变量无论在何时都应该被用来创建不可变的实例对象.- 注意不要把
nil
传入到了NSArray
和NSDictionary
中,因为这样会导致c程序崩溃.
|
|
CGRect 函数
当访问 x
, y
, width
,height
,应该使用 CGGeometry
函数,而不应该直接访问结构的成员.
|
|
常量
常量和宏都可以的情况下, 推荐使用常量.
|
|
枚举类型
|
|
Case 语句
当在switch
中使用枚举类型的时候 default
并不需要.
|
|
布尔值判断
- 既然
nil
等同于NO
那就没有必要在条件语句中进行比较 - 永远不要直接把某些东西与
YES
相比较.
|
|
BOOL
的例子
|
|
BOOL
属性的名字应该取名为形容词, 属性名可以忽略 ‘is’ 前缀, 但 getter
方法要使用传统的命名.
|
|
单例
单例对象应该使用安全线程机制来创建它们的共享实例.
|
|
这能够防止某些时候可能出现各种程序崩溃的问题
(未完持续更新)
参考
官方 OC Style Guides:
- The Objective-C Programming Language
- Cocoa Fundamentals Guide
- Coding Guidelines for Cocoa
- iOS App Programming Guide
其他 OC Style Guides:
ObjC 中可变参数的原理
最近写了一个自定义的 ActionSheet, 参考系统的 UIActionSheet 的创建方式设计 API. 我们知道系统的 UIAlertView 是使用可变参数来接收最后一个参数的, 我一直也只是知道怎么用, 于是这次查资料了解了可变参数的实现原理.
cocoa的API里使用到可变参数的地方
|
|
首先我们来看看C语言中常用的哨兵参数的实现
###哨兵参数
上面我们注意到, 哨兵参数实际上就是指定一个结束参数, 当遇到这个参数时停止接收参数.
我们再来看看OC里的可变参数的实现
|
|
上面我们主要用到了以下几个函数:
va_list argumentList : 定义一个指向可变参数列表的指针argumentList.
va_start(argumentList, last_determine_param) : 使用argumentList指针指向函数参数列表中的第一个参数.
- 说明 : 可变参数之前必须有一个或多个确定参数, last_determine_param是位于可变参数之前的最后一个固定参数( … 之前的最后一个参数). 调用va_start()时last_determine_param被用作第二个参数传入.
- 函数参数列表中参数在内存中的顺序与函数声明时的顺序是一致的, 比如有一个可变参数函数的声明是: void va_test(char a, char b, char c, …), 则它的固定参数依次是a, b, c, last_determine_param为c, 因此就是 va_start(arg_ptr, c).
va_arg(argList, type) : 返回argumentList所指的当前可变参数, 返回类型为type, 并使指针argumentList指向可变参数列表中的下一个参数.
va_end(argList) : 必须调用va_end()确保堆栈的正确恢复.
上述宏的原型如下:
- void va_start(va_list argptr, last_parm);
- type va_arg(va_list argptr, type);
- void va_end(va_list argptr);
它们都包含在头文件stdarg.h.
下面是自定义ActionSheet中可变参数的实际使用方式
|
|
|
|
传送门
本文Demo:VariableArgument
自定义ActionSheet:SRActionSheet
Have Fun.