轩辕十四

探索科技与创新的个人博客

理解引用计数


Objective-C 语言使用引用计数来管理内存,也就是说,每个对象都有个可以递增或递减的计数器。如果想使某个对象继续存活,那就递增其引用计数;用完了之后,就递减其计数。计数变为 O,就表示没人关注此对象了,于是,就可以把它销毁。

引用计数工作原理

Objective-C 中,调用 alloc 方法所返回的对象由调用者所拥有。也就是说,调用者已通过 alloc 方法表达了想令该对象继续存活下去的意愿。不过请注意,这并不是说对象此时的保留计数必定是 1。在 alloc 或。initWithInt: 方法的实现代码中,也许还有其他对象也保留了此对象,所以,其保留计数可能会大于 1。能够肯定的是:保留计数至少为 1。保留计数这个概念就应该这样来理解才对。绝不应该说保留计数一定是某个值,只能说你所执行的操作是递增了该计数还是递减了该计数。

1
2
3
4
5
6
7
8
9
NSMutableArray *array = [[NSMutableArray alloc] init];
NSNumber *number = [[NSNumber alloc] initWithInt:1337];

[array addObject:number];
[number release];

// do something with 'array'

[array release];
阅读全文 »

在之前的一篇文章中【iOS 并发,锁,线程同步【一】GCD】,我们讨论了一下 GCD 的并发,锁和线程同步的问题,今天,我们来讨论一下 Operation 的并发与线程同步。

Operation 中,我们一般是将所有的 Operation 添加到 OperationQueue 中进行执行,这里需要注意一点,**Operation 添加到队列当中,默认就是执行的并发操作。我们可以设置队列的最大并发数 maxConcurrentOperationCount。如果我们在 OperationQueue 中想要执行串行任务的话,很简单,将 maxConcurrentOperationCount 设置成为1即可。 maxConcurrentOperationCount 的默认值为-1,那么默认情况下的并发数是多少呢?这个是由系统内存和 CPU 决定的,可能内存多久开多一点,内存少就开少一点。**最大并发数建议 2~3,如果并发数太多会导致 UI 卡顿。

不添加到队列当中的 Operation,我们可以调用 start() 方法开始一个操作,也可以调用 cancel() 取消等待中的操作,注意:已经开始执行的操作是没法取消的。代码示例如下:

1
2
3
4
5
let opt = BlockOperation {
print("Operation")
}
opt.start() // 开始执行任务
opt.cancel() // 取消等待中的任务
阅读全文 »

用 Objective-C 等面向对象语言编程时,“对象”(object)就是“基本构造单元”(building block),开发者可以通过对象来存储并传递数据。在对象之间传递数据并执行任务的过程就叫做“消息传递”(Messaging)。若想编写出高效且易维护的代码,就一定要熟悉这两个特性的工作原理。

当应用程序运行起来以后,为其提供相关支持的代码叫做“Objective-C 运行期环境”(Objective-C runtime),它提供了一些使得对象之间能够传递消息的重要函数,并且包含创建类实例所用的全部逻辑。在理解了运行期环境中各个部分协同工作的原理之后,你的开发水平将会进一步提升。

理解“属性”这一概念


“属性”(property)是 Objective-C 的一项特性,用于封装对象中的数据。Objective-C 对象通常会把其所需要的数据保存为各种实例变量。实例变量一般通过“存取方法”(access method)来访问,也就是 gettersetter 方法。

1
2
3
4
5
6
7
8
@interface EOCPerson: NSOjbect {
@public
NSString *_firstName;
NSString *_lastName;
@private
NSString *_someInternalData;
}
@end
阅读全文 »

Objective-C 语言的起源


Objective-C 与 C++,Java 等面向对象的语言类似,不过在很多地方还是有所差别。Objective-C 使用“消息结构”(messaging structure)而非“函数调用”(function calling)。

消息结构的语言与函数调用的语言关键区别在于:

  • 使用消息结构的语言,其运行时所应执行的代码由运行环境决定,也就是说,在运行时才会检查对象类型。接收一条消息之后,究竟应执行何种代码,由运行期环境而非编译器来决定;
  • 使用函数调用的语言,运行时所执行的代码由编译器决定;

要点:

  • Objective-C 为 C 语言添加了面向对象特性,是其超集。Objective-C 使用动态绑定的消息结构,也就是说,在运行时才会检查对象类型。接收一条消息之后,究竟应执行何种代码,由运行期环境而非编译器来决定。
  • 理解 C 语言的核心概念有助于写好 Objective-C 程序。尤其要掌握内存模型与指针。

在类的头文件中尽量少引入其他头文件


在类的头文件中(.h)我们一般不需要知道引入的某个类的全部细节,这时候,我们可以用 @class 关键字去告诉编译器,知道有一个类名为 xxx 的类就好,不需要关注细节。

这叫做“向前声明”(forward declaring)该类。在实现文件(.m)中我们使用该类时就需要知道其所有细节,这时我们需要用 #import 关键字去导入 xxx 类的头文件。

将引入头文件的时机尽量延后,只有确有需要时才引入,这样就能减少类的使用者所需引入头文件的数量。这样能够一定程度上的减少编译的时间

阅读全文 »

我们都知道 Objective-C 是一门动态的语言,有的时候我们会使用 Runtime 处理一些在 Objective-C 上面无法实现或者很难实现的功能。例如:在扩展中添加属性;动态的获取属性的名称,方法名等。那么究竟什么是 Runtime

什么是 Runtime

Runtime 简称运行时。Objective-C 就是运行时机制,也就是在程序运行时候的一些机制,其中最主要的是消息机制。对于我们熟悉的C语言,函数的调用在编译的时候会决定调用哪个函数。但对于 Objective-C 的函数,属于动态调用过程,在编译的时候并不能决定真正调用哪个函数,只有在真正运行的时候才会根据函数的名称找到对应的函数来调用。

也就有了下面这两点结论:

  1. 在编译阶段,Objective-C 可以调用任何函数,即使这个函数并未实现,只要声明过就不会报错。
  2. 在编译阶段,C语言调用未实现的函数就会报错。
阅读全文 »

无并发,不编程。并发在开发中是非常重要的一个技术,运用并发技术,可以写出高性能的程序,并发能够有效地利用多核心 CPU 的优势来提高数据处理的速度。作为一个码农,学好并发是十分有必要的。iOS有四种多线程编程的技术,分别是:NSThread,Cocoa NSOperation,GCD(全称:Grand Central Dispatch), pthread。今天我们就重点讲一讲 GCD 中的并发,锁和线程同步。

GCD 中的并发


GCD 队列默认就是串行的(serial),在 GCD 中创建并发队列是如下所示:

1
let concurrent = DispatchQueue(label: "com.demo.concurrentQueue", attributes: .concurrent)

DispatchQueueattributes 参数还有一个取值:initiallyInactive,这是可以手动管理队列执行时间的参数。
当一个队列声明为 initiallyInactive 时,这个队列不会自动开始执行,必须要调用 activate() 方法。对应的还有 suspend()resume()

  • activate():开始执行队列
  • suspend():挂起队列
  • resume():继续执行队列

关于 initiallyInactive 到这里为止,我们继续说说并发队列。

阅读全文 »

但是,我仍然不明白,KVC 和属性访问(property accessor)方法有什么区别?


KVC 是调用属性访问器方法或以其他方式访问属性的一种方法。

“以其他方式访问”是什么意思?

对于 KVC 而言,没有访问器方法的实例变量会被视为非正式属性。
如果没有找到匹配的访问器对,它将直接获取或设置实例变量的值。
(是的,在现代代码中这是不值得使用的,总是为任何你想访问的任何东西声明一个 @property,反之,不要使用 KVC 来访问任何不属于公共属性的东西。)

属性访问器方法是 KVC 在其存在的情况下会调用的方法(KVC 和每个理智的程序员都倾向于直接 ivar 访问)。访问者可以获取或设置实例变量,如合成访问者所做的那样,或者访问某些其他存储。

访问器是实现,属性是接口,KVC 是使用它们的一种方式。

阅读全文 »

我在使用 Playground 的时候,喜欢将自定运行(Automatically Run)修改为手动运行(Manually Run),因为自动运行有时会导致我的 Xcode 卡住,体验非常不好。但是 Playground 并没有相应的快捷键去手动执行 Playground,这又导致手动运行的时候操作繁琐,每次都要靠鼠标去点,作为一个程序员怎么能忍受这种没有效率的操作 😂。接下来我们为手动执行 Playground 添加一个快捷键。

打开系统偏好设置中的快捷键设置


系统偏好设置 -> 键盘 -> 快捷键

选中最后一个,应用快捷键

阅读全文 »

我想要创建一个 Observable

  • 产生特定的一个元素: just
    • 经过一段延时: timer
  • 从一个序列拉取元素: from
  • 重复的产生某一个元素: repeatElement
  • 存在自定义逻辑: create
  • 每次订阅时产生: deferred
  • 每隔一段时间,发出一个元素: interval
    • 在一段延时后: timer
  • 一个空序列,只有一个完成事件: empty
  • 一个任何事件都没有产生的序列: never
阅读全文 »

just 、 from 和 of


justfrom 都能够将元素转化为 Observable 但是他们有本质的区别:

just

创建 Observable 发出唯一的一个元素just 操作符将某一个元素转换为 Observable

示例:

1
2
3
4
5
6
7
let oJust = Observable.just([1, 2, 3, 4, 5])
oJust.subscribe(onNext: {
print($0)
})
.dispose()

// [1, 2, 3, 4, 5]
阅读全文 »
0%