--Design patterns for broadcasting information and for subscribing to broadcasts.
一种关于广播信息和订阅广播信息的设计模式
♦ NSKeyValueObserving(link) //这是协议
--An informal protocol that objects adopt to be notified of changes to the specified properties of other objects.
一种非正式协议,遵循这种协议的对象都可以接收到通知,这个通知是关于 指定的 某对象的 属性 发生变化时产生的通知,牛逼的是NSObject遵循了该协议,更牛逼的是,大多数的iOS的类都继承了NSObject,所以大概率下,iOS定义的类都可以接收通知,不是绝对。也有部分并未遵循该协议。实在不行,你自己扩展遵循便是了。这个协议里有很多声明方法啊。
关于观察者模式的编程指南:Key-Value Observing Programming Guide(link)
再看一个 象征通知信息 的结构体:
♦
struct Notification(link) //这是结构体
--A container for information broadcast through a notification center to all registered observers.
就是一个结构体,这个结构体是一个容器,容纳了各种可以用来广播出去的通知信息,广播的媒介NotificationCenter ,通知信息的接收人是所有已经注册了的观察者,观察者就是用上面的NSKeyValueObserving的方法来注册成观察者,作为谁的观察者,去观察谁这些,还要继续看NotificationCenter的方法。
例如
addObserver(_:selector:name:object:)
又或者 NSObject 中实现了 NSKeyValueObserving协议的observeValue(forKeyPath:of:change:context:)的方法,反正就有各种方式成为观察者,或者被观察
♦
class NotificationCenter //这是类
--A notification dispatch mechanism that enables the broadcast of information to registered observers.
没错,这就是通知信息的媒介,一种分发信息的机制。可以通过这个类,向所有的在册的观察者发送通知。每一个app都有一个default 的 notification center,你可以自定义,没什么事,默认的就够用了。但是每一个程序只能拥有一个notification center,所以你要跨程序传递通知的话,可以用来
DistributedNotificationCenter(link)
实现。介绍一些NotificationCenter 的方法:
•
func addObserver(Any, selector: Selector, name: NSNotification.Name?, object: Any?)
--Adds an entry to the notification center's dispatch table with an observer and a notification selector, and an optional notification name and sender.
将一个条目entry添加到 notification center 的分发表中,这个条目包括了观察者、通知选择器、通知名称、以及发送者,信息选择器其实就相当于c语言的函数指针,用来进行响应的操作的,然后通知的名称是指定该观察者观察这个通知,就是通知的标识。 一个对象可以多次调用次方法,多次指定自己作为观察者,自己观察自己。selector的参数,可以根据该方法的调用者进行推断。
•
func post(name: NSNotification.Name, object: Any?)
--Creates a notification with a given name and sender and posts it to the notification center.
把你定义的notification对象推进center中,轮到它的时候,center就会把它发布出去,然后那些注册了观察者的对象就会监听通知 ,监听到了,就会进行响应的操作。还有其他一些重载的post函数,逻辑是差不多的。
官网里面有很多文档的超链接的,一个个地挖,慢慢的你就会越挖越多了。
目前计划路线:
Notification Programming Topics(link) —>
—> Key-Value Observing Programming Guide(link)—>
—> Threading Programming Guide (link) —>
—> Concurrency Programming Guide(link)—>
—> Core Bluetooth Programming Guide(link)
先看着再说。还有event要看
--These recipients of the notification, known as observers, can adjust their own appearance, behavior, and state in response
to the event. The object sending (or posting) the notification doesn’t have to know what those observers are.
notification 是一个封装通知的信息的对象,主要被设计用于通知事件的发生。你可以在你的代码中这样设计,当某事件发生时, 就发送一个notification,而这个notification会被observers接收,observer就会根据notification作出响应的行为。于是就相当于 observer响应了事件。没错,observer也是要你写代码注册的。具体又要看后面的notification center了。后面再说。
--When a notification is delivered to an interested observer, the notification object is passed in as an argument of the method handling the notification
★当center把notification传递给observer时,notification就作为处理该事件的函数的参数传进去,也就是selector的参数,可以根据类型推断。所以你定义的selector中要么参数就只有notification,要么就为空,反正notification都是要被默认传进去。
--The method must have the following signature:
- (void)myNotificationHandler:(NSNotification *)notif;
--In this handling method, you can extract information from the notification to help you in your response, especially data in the
userInfo
dictionary (if one exists).这是oc的,所以说swift的也一样,他会从你的selector方法中抽取出你的notification对象,从而获取相关信息,所以你定义响应事件的函数时,参数必须有且仅有一个notification,以便于center把notification传进去你的响应函数中,我说的。
▶ Notifications
--A message is the name of a method, and any parameters associated with it, that are sent to, and executed by, an object.
在OC中,message指的就是一个函数的名字,你send一个message给一个实例,就是你调用了该实例的该函数,换一个说法而已
--A notification encapsulates information about an event
一个notification就是压缩一些关于事件信息的通知对象。
--An
NSNotification
object (referred to as a notification) contains a name, an object, and an optional dictionary.一个
NSNotification实例包含了自己唯一的名字,发送者,和补充说明作用的字典
▶ Notification Centers
--It notifies all observers of notifications meeting specific criteria.
center 会将 规范的通知 发送给所有,是所有的观察者,至于观察者响应不响应又是另一回事了。
--A notification center delivers notifications to observers synchronously. In other words, when posting a notification, control
does not return to the poster until all observers have received and processed the notification.
通知是同步地发送到所有观察者的,也就是说,一个通知都发了个遍了,且都被处理掉了,控制权才会归还到发布者手里。
--To send notifications asynchronously use a notification queue, which is described in Notification Queues.
如果你要异步的发送信息,那就使用Notification Queues.这个类
--In a multithreaded application, notifications are always delivered in the thread in which the notification was posted, which may not be the same thread in which an observer registered itself
特别注意:在多线程的app中,notification只会在发布该notification的线程中传递,所以其他线程怎么办,我也还没看到啊。
▶ Notification Queues
--The
NSNotificationQueue
class contributes two important features to the Foundation Kit’s notification mechanism: the coalescing of notifications and asynchronous posting.
NSNotificationQueue主要是为了两个功能:合并通知,异步发布通知
-- Every thread has a default notification queue, which is associated with the default notification center for the process. You can create your own notification queues and have multiple queues per center and thread
每一个线程都有自己的notification center,所以你可以为每一个线程创建一个notification queue
--However, the invocation of the method is synchronous: before the posting object can resume its thread of execution, it must wait until the notification center dispatches the notification to all observers and returns.
center发布notification的方法仍然是同步的,但是在queue中的notification是一个一个地异步被发布的。
--These
NSNotificationQueue
’s methods immediately return to the invoking object after putting the notification in the queue.
NSNotificationQueue
的方法会立即返回值给方法的调用者,然后再异步的发布通知。--When the thread where a notification is enqueued terminates before the notification queue posts the notification to its notification center, the notification is not posted
当线程已经终止了,但是绑定该线程的notification还没有发布到 center 的情况下,这个notification不会再被发布。
--The mode argument specifies the run loop mode in which the queue will be emptied
在enqueuing方法中的mode参数,mode参数指定了notification队列在哪一种运行模式下会被清空,run loop运行模式是指线程的 运行模式,具体后面看到Threading Programming Guide (link) 会有所介绍。如果该运行模式还没清空队列,则等线程再次处于该运行模式下时,再继续之前的未完成的清空操作。
--Posting to a notification queue can occur in one of three different styles:
NSPostASAP
,NSPostWhenIdle
, andNSPostNow
.向notification queue队列里发布notification有三种方式,或者说三种状态下向队列发布通知:
NSPostASAP
,NSPostWhenIdle
, andNSPostNow,记住,仍然是center从queue里面拿notification发布给observer监听。现在是sender发布给queue而已。
▶ Registering for a Notification
--You don’t need to specify both the name and the object. If you specify only an object, the observer will receive all notifications containing that object. If you specify only a notification name, the observer will receive that notification every time it’s posted, regardless of the object associated with it.
在注册观察者时,你不需要强制指定notification中的object属性,可有可无。有name时,则observer根据name监听 notification,无name时,则根据object监听notification
--Before an object that is observing notifications is deallocated, it must tell the notification center to stop sending it notifications. Otherwise, the next notification gets sent to a nonexistent object and the program crashes.
在oc的版本中,当一个notification的所有观察者都已经被销毁了时,那么你的notification也必须要从center中移除,因为center 是等到当前的通知全部发了了个遍并且返回值时才广播下一条通知,所以如果没有observer返回的话,center会一直等待,会造成程序的崩溃。在swift版本中,好像不会等待还是怎么,反正作了优化。
▶ Posting a Notification
--
NSNotification
objects are immutable, so once created, they cannot be modified.notification是不可变的,一旦被创建,你就不可以改变notification。
--If there are other objects of interest to the observer (besides the notification name and observed object), place them in the notification’s optional dictionary or use
postNotificationName:object:userInfo:
.如果还有一些对象不是观察者,又对notification感兴趣的话,你可以把这些对象添加到notification的可选字典中,或者用
postNotificationName:object:userInfo:方法来通知该对象。
▶ Delivering Notifications To Particular Threads
--You register for a notification normally. When a notification arrives, you test whether the current thread is the thread that should handle the notification. If it is the wrong thread, you store the notification in a queue and then send a signal to the correct thread, indicating that a notification needs processing. The other thread receives the signal, removes the notification from the queue, and processes the notification.
跨线程通知的工作逻辑是:你要自定义一个a custom notification queue (not an
NSNotificationQueue
object),而不是使用默认的notification队列,然后你还是依照往常那样定义一个notification,当notification到达你定义的队列时,你会测试它是不是要在当前运行的线程中广播的,如果是,则广播出去。如果不是,你就把这个notification存储在队列中,然后告知目标线程来处理它。目标线程收到告知后,就会从队列中移除并拿出该notification,然后就进行相应的处理。
--To implement this technique, your observer object needs to have instance variables for the following values: a mutable array to hold the notifications, a communication port for signaling the correct thread (a Mach port), a lock to prevent multithreading conflicts with the notification array, and a value that identifies the correct thread (an
NSThread
object).为实现上面的工作逻辑,你的线程级别的观察者实例需要的东西有:可变的notification数组(用于储存notification,广播给当前线程的普通级别的观察者,普通与线程级别区别在于你想怎么用这个observer)、一个Mach端口实例(主要是为了给别的 线程提供访问)、一个同步锁实例(主要是为了同步notification数组,避免线程冲突)、还有该线程的唯一标识。
▶ Introduction
--Key-value observing is a mechanism that allows objects to be notified of changes to specified properties of other objects.
键值监听是一种机制,这种机制下,一个对象可以监听到另一个对象的 特定的 属性的 改变,从而作出相应的响应。
--In order to understand key-value observing, you must first understand key-value coding.
要了解 键值监听 机制,你必须要先了解 键值对编程 思想。
KVC是key-value coding , KVO是key-value observing
--Key-value observing is particularly useful for communication between model and controller layers in an application
键值监听机制 在app的model层和controller层特别好用。然后下面大概说一下MVC设计模式。
▼ MVC:
--The The Model-View-Controller (MVC) design pattern defines not only the roles objects play in the application, it defines the way objects communicate with each other.
MVC设计模式不仅定义了对象在app中扮演的角色,还定义了这些角色之间该如何进行交流。
--Model objects encapsulate the data specific to an application and define the logic and computation that manipulate and process that data
Model层对象封装了app中特定的某种数据,并且定义了操作和处理该数据的操作逻辑和计算方式。
--Because model objects represent knowledge and expertise related to a specific problem domain, they can be reused in similar problem domains.
因为Model层象征着特定行业领域的 相关知识和专业知识 ,所以Model层的对象能够在这些领域中复用,所以你应该把那些从数据库或者本地文件加载到app中的 那些persistent state的 数据储存在model层的对象中。
--Ideally, a model object should have no explicit connection to the view objects that present its data and allow users to edit that data—it should not be concerned with user-interface and presentation issues.
理想情况下,model层的对象不能与view层的对象有明确的直接联系,而是应该通过controller层进行联系,view层的对象是让客户觉得自己能在界面上编辑数据而已,并且觉得数据就展示在界面上,只是让客户感觉能直接操作数据而已。实际上还要通过 controller层才能确定客户(view层)能不能操作model层的数据,以及怎么去操作数据(交互)
--A view object knows how to draw itself and can respond to user actions. A major purpose of view objects is to display data from the application’s model objects and to enable the editing of that data.
view层的对象应该要知道怎么绘制自己的视图,然后还要让客户感觉自己在直接操作model层的数据,实际上view层和model层是解藕的,他们必须通过controller层,才可以通信。
--Controller objects are thus a conduit through which view objects learn about changes in model objects and vice versa
controller层就相当于一条管道,view层对象可以通过这条管道了解到model层数据的变化,反之亦然。
--The Cocoa frameworks offer three main controller types: coordinating controllers, view controllers (on iOS), and mediating controllers (on OS X).
Cocoa frameworks 提供了三种类型的controller,一个是面向app级别的coordinating controller,主要处理实例的生命周期,事件的响应,实例之间的连接关系的逻辑;一个是view controller,主要是处理iOS中model 层和view层之间的数据交互,OS X也有view controller,不关我事。还有一个是mediating controller,也是OS X的事情。
▲ MVC - END
-- A controller object typically observes properties of model objects, and a view object observes properties of model objects through a controller.
一个controller对象监听model对象,而view对象则监听controller对象,而model对象则监听model对象,这是基本的模式。
--KVO’s primary benefit is that you don’t have to implement your own scheme to send notifications every time a property changes.
KVO机制的主要好处在于,你不必每次都为你的 对象的 property性质制定一个发送通知的计划,就是你不用每次property发生改变时,都手动地写代码去发送通知,而是KVO机制帮你完成了这些步骤,你要做的事是注册和注销observer。
至于KVO是怎么帮你做的,看下面的Registering for Key-Value Observing。需要知道的是,property属性是遵守KVO Compliant的,而NSObject也是遵守KVO Compliant的,所以你的对象继承NSObject就好了啦。
▶ Registering Dependent Keys
--You must perform the following steps to enable an object to receive key-value observing notifications for a KVO-compliant property:
如果你要你的观察者对象能够接受到别的对象的property发生改变时的通知,那么必须包含三步:一是注册观察者,二是响应通知的方法,三是注销观察者。并非cocoa里所有的class都是KVO Compliant,只有在文档中说明它是KVO Compliant的,才是KVO Compliant的
--Register the observer with the observed object using the method
addObserver:forKeyPath:options:context:
.要注册一个观察者(包含被监听的对象),用方法
addObserver:forKeyPath:options:context:
.• 其中的option参数:
-- affects both the content of the change dictionary supplied in the notification, and the manner in which notifications are generated.
影响了 变更字典 的内容,也影响了notification的生成方式。例如:当option取值
NSKeyValueObservingOptionOld时,表示你要获取被监听对象的property的旧值;当取值NSKeyValueObservingOptionNew,表示你要取新值;当取值OR时,表示你
新旧都要;
,表示你要在被观察对象的property发生改变之前就发通知过来,一般是指被观察对象调用了以-
取值NSKeyValueObservingOptionInitial,表示你要求被观察对象的property只要发生了改变,就立马发通知过来;当取值NSKeyValueObservingOptionPriorwillChange…为前缀的方法时,用
change dictionary储存该通知,相当于willset吧,我猜的。
•
然后就是context参数:
--You may specify
NULL
and rely entirely on the key path string to determine the origin of a change notification, but this approach may cause problems for an object whose superclass is also observing the same key path for different reasons.你可以设置context参数为空,并且完全依赖于key path的变化来确定notification的来源,但是如果observer的父类也监听这个key path的话,就有可能会产生一些问题。说一下key path,就是key的完整路径名,例如com.csdn.http ,则当这三个对象中的任意一个对象的property性质发生变化,都会发布notification。
好了,context参数可以包含了任意数据类型,这些数据是用于返回给 observer 的,context是一个指针,上下文的指针,它可以用于识别该通知是给你的还是给你父类的,具体做法之一是把context赋值给你的类中的一个静态变量。好像这里的key path只是单纯的作为字符串使用,作为notification的唯一标识。
--When the value of an observed property of an object changes, the observer receives an
observeValueForKeyPath:ofObject:change:context:
message. All observers must implement this method.当被观察的property值发生变化时,所有的observer都会通
过observeValueForKeyPath:ofObject:change:context:获取
到相应的通知,所以observer必须实现这个方法。还有就是,context和observer还有observed 对象之间默认不是强引用的
,如果你要用到强引用,请自己定义。
•
然后就是change参数:
--The change dictionary entry
NSKeyValueChangeKindKey
provides information about the type of change that occurred.change dictionary的entry提供了关于变化的类型的信息,entry中的key可以是变化的种类,value可以是property的新旧值。
--If you used a single context for all observed key paths, you first test that against the notification’s context, and finding a match, use key path string comparisons to determine what specifically has changed.
如果你使用了context指针,那么observer会先匹配context,然后再匹配key path,从而确定你的notification是否是你想要的。
--If a notification propagates to the top of the class hierarchy,
NSObject
throws anNSInternalInconsistencyException
because this is a programming error: a subclass failed to consume a notification for which it registered.如果一个notification传递到了class的最顶层,即NSObject,则系统会抛出异常,因为没有子类消费这个通知。
▶ KVO Compliance
--In order to be considered KVO-compliant for a specific property, a class must ensure the following:
为了使class的property符合KVO规范,class必须遵守这三个原则:一是,property必须是KVC的,即符合key-value编程的,就是键值对啊;二是,在property发生变化时,class必须发出相应的变化通知;三是,如果是独立key,即不经过center的notification的key,则必须按照独立key的规范进行注册。
--Automatic support and Manual change notification techniques ensures the change notifications are emitted.
自动支持技术和人工通知变化的技术,保证了 关于变化的通知 能被发出去。
--Automatic key-value change notification informs observers of changes made using key-value compliant accessors, as well as the key-value coding methods.
自动通知技术,如果property是通过 accessors方法或者是KVC方法 而发生变化时,自动通知技术就会去通知监听这个property的观察者们,所以如果你要使用自动通知技术,那么你的class和property就必须遵循cocoa 的编程规范和命名规范。
--Manual change notification provides more controls of the notification process .Manual and automatic notifications are not mutually exclusive.
手动的变化通知,提供了更多的关于通知处理的控制权,而且手动通知和自动通知并不互斥,你可以同时使用。
--More typically, you may want to completely take control of the notifications for a particular property. In this case, you override the
NSObject
implementation ofautomaticallyNotifiesObserversForKey:
如果你想拥有 处理通知的 更多控制权,你可以重写父类的automaticallyNotifiesObserversForKey: 方法,从而禁止或者修改 自动通知的 处理操作,你别禁止所有的key监听啊,记得继承父类的啊,禁止你自己的key就好了。
--To implement manual observer notification, you invoke
willChangeValueForKey:
before changing the value, anddidChangeValueForKey:
after changing the value.为了实现 手动通知 observer的功能,你需要在property改变的前后分别调用
willChangeValueForKey:
和willChangeValueForKey:
方法,来向observer发送修改前后的通知。这两个方法时遵循了KVO规范的类都默认继承了的。▶Registering Dependent Keys
--If the value of one attribute changes, then the value of the derived property should also be flagged for change.
如一个属性改变,那么与这个属性有依赖关系的 其他对象的 property性质也应该被标记,说property也发生了改变,因为它的依赖发生了改变。但是如何去通知这种改变呢,就取决于依赖关系的基数了。也就是在说一对多,多对多的那种依赖。
--To trigger notifications automatically for a to-one relationship you should either override
keyPathsForValuesAffectingValueForKey:
or implement a suitable method that follows the pattern it defines for registering dependent keys为了出发一对一关系的自动通知功能,你可以重写
keyPathsForValuesAffectingValueForKey:方法,或者实现一个遵循了“依赖键注册规范”的方法,这个规范的方法名是:keyPathsForValuesAffectingPropertyName,其中方法名后面的
那个
PropertyName就是你的property的name,但要求把首字母变成大写的。其实和java的setter,getter的方法名规范
类似。这是OC版本的。
--You can't override the
keyPathsForValuesAffectingValueForKey:
method when you add a computed property to anexisting class using a category, because you're not supposed to override methods in categories.
你不能在OC的category中重写
keyPathsForValuesAffectingValueForKey:方法,OC中的category就相当于swift中的extension,OC是禁止这种行为的。所以实现依赖方法此时就很有用武之地了。
--You can‘t set up dependencies on to-many relationships by implementing
keyPathsForValuesAffectingValueForKey:
.Instead, you must observe the appropriate attribute of each of the objects in the to-many collection and respond to changes
in their values by updating the dependent key yourself.
你不能通过
重写keyPathsForValuesAffectingValueForKey:方法来实现多对多关系的通知。因为你需要通知每一个在多对多关系中有所涉及的property,这是不可取的。
--You can use key-value observing to register the parent (in this example, Department) as an observer of the relevant attribute
of all the children (Employees in this example).
在一对多关系中,例如部门和职员,你可以将 部门对象 注册为观察者,而每个 职员对象 作为被观察者。
▶ Introduction
--Although newer technologies such as operation objects and Grand Central Dispatch (GCD) provide a more modern and efficient infrastructure for implementing concurrency, OS X and iOS also provide interfaces for creating and managing threads.
虽然一些更加新的技术也提供了很好的架构来实现程序的并行,例如 operation objects 和 CGD 技术,但是,iOS同样也提供了创建和管理线程的接口技术。
--Threads are one of several technologies that make it possible to execute multiple code paths concurrently inside a single application.
线程是在一个app里执行 多个路径的代码 的技术。
--These alternative technologies simplify the amount of work you have to do to implement concurrent paths of execution and offer much better performance than traditional threads. For information about these technologies, see Concurrency Programming Guide
那些可替代线程的 新的 并行的 开发技术,可以大量简化你的工作量,并且拥有更高的效率。具体看文档:Concurrency Programming Guide(link)
▶ About Threaded Programming
--Threads are a relatively lightweight way to implement multiple paths of execution inside of an application
线程是一种 在一个app中的 实现多条执行路径的 相对轻量的 方式。
--From a technical standpoint, a thread is a combination of the kernel-level and application-level data structures needed to manage the execution of code.
从技术角度来讲,一个线程就是 内核级别和app级别的 数据结构的 结合体,用于管理代码的执行。
--The kernel-level structures coordinate the dispatching of events to the thread and the preemptive scheduling of the thread on one of the available cores.
内核级别的数据结构用于 协调事件如何分发到线程 以及 在一个可用的内核上如何抢占式地调度线程。
--The application-level structures include the call stack for storing function calls and the structures the application needs to manage and manipulate the thread’s attributes and state.
app级别的数据结构则是包含了 方法栈、管理app的数据结构,同时也管理线程的属性与状态。
--Although the underlying implementation mechanism for threads is Mach threads, you rarely (if ever) work with threads at the Mach level. Instead, you usually use the more convenient POSIX API or one of its derivatives.
虽然线程的实现机制的底层支持是Mach thread (即机器级别的线程),但是你一般不会用到Mach级别的线程,而是用到POSXI
API 或者POSIX API 的某个衍生接口;POSIX意思是:可移植的计算机操作系统接口。
--When you create a new thread, you must specify an entry-point function (or an entry-point method in the case of Cocoa threads) for that thread.
当你创建一个新的线程时,你必须指定一个入口函数;在这个入口函数中,你需要定义大量的工作或者循环的工作,因为这个入口
函数一旦返回,意味着你已经 显式地(或系统)终结了 该线程,这个线程的资源将被系统回收,也就是不复存在了。
--A run loop is a piece of infrastructure used to manage events arriving asynchronously on a thread
运行循环 是一种基础设施,该设施主要用于管理 事件 异步到达 线程 的相关事项
--As events arrive, the system wakes up the thread and dispatches the events to the run loop, which then dispatches them to the handlers you specify
当实现到达时,系统将唤醒相关的线程,并且把事件分发到 运行循环 ,运行循环再把事件分发给你定义的 处理程序中。
--To configure a run loop, all you have to do is launch your thread, get a reference to the run loop object, install your event handlers, and tell the run loop to run.
配置run loop : 启动线程,获取run loop对象的引用,安装事件处理程序,通知run loop运行起来。
--When maintaining completely separate resources is not an option though, you may have to synchronize access to the resource using locks, conditions, atomic operations, and other techniques.
当不用完全独立的拥有和维护资源时,你可能必须要通过锁、条件、原子操作和其他同步技术来对资源进行同步了。
--If you use operation objects, you can configure dependencies among your operation objects to sequence the execution of tasks, which is very similar to the behavior offered by conditions.
如果你使用 操作对象 的话,那么你可以配置 操作对象 之间的依赖关系,这样就可以对任务的执行进行排序了。这种做法非常类
似于 条件同步 的做法
--Atomic operations use special hardware instructions to ensure that modifications to a variable are completed before other threads have a chance to access it.
原子操作 使用了特殊的硬件指令,这些指令保证了 在别的线程访问该变量时,该变量已经被完整地修改完毕了。
--Rather than create a thread yourself, consider using asynchronous APIs, GCD, or operation objects to do the work
尽量不要自己显式地创建一个线程,而是使用系统提供的 异步API,GCD,或者操作对象 来实现一个线程。
--Changing your code to a transaction-based model to compensate could subsequently negate the performance advantage of having multiple threads
如果将你的代码改成基于事务模型的编程,以此来抵偿资源争夺的问题,虽然这样解决了资源争夺问题,但同时也消除了多线程模式带来的优势。所以多线程就很难啊
--A process runs until all non-detached threads have exited. By default, only the application’s main thread is created as non-detached, but you can create other threads that way as well
一个进程会一直运行到所有非分离的线程都退出为止,此时的进程才结束。非分离即是紧挨着咯。默认地,主线程都是非分离的,虽然你也可以自己创建非分离的线程。分离的线程就是独立的线程的意思咯。
--Because most high-level thread technologies do not create joinable threads by default, you may have to use the POSIX API to create your thread.
因为大多数的高级线程技术都不会默认创建非分离线程,所以你必须自己动手显示的创建。因而你需要通过高POSIX API 来创建你的非分离线程,非分离线程的作用是你的线程存在时,app不会退出,独立线程的话,app可能直接就退出了。所以非分离线程传输数据的话,可以保证了数据传输时不被终结。non-detached (also known as joinable),非分离也叫可加入的
--Because each thread has its own call stack, each thread is therefore responsible for catching its own exceptions.
每一个线程都有自己的 当前调用栈 ,所以每个线程都要自己捕捉自己抛出的异常。
--The best way for a thread to exit is naturally, by letting it reach the end of its main entry point routine
最好的终结线程的方式是 让线程自然地跑到自己的路线的尽头。
▶ Thread Management
--Each process (application) in OS X or iOS is made up of one or more threads, each of which represents a single path of execution through the application's code
OS X或iOS中的每个进程(应用程序)由一个或多个线程组成,而每个线程都代表了 单一路径的用于执行的代码。
--Each thread requires the allocation of memory in both the kernel memory space and your program’s memory space.
每一个线程都需要你给它分配 内核内存空间 和 程序内存空间 ,这是实实在在的内存成本。内核空间存储用于调度和管理的核心数据结构,程序内存空间用于储存每个线程的必要数据。
--Operation objects can often create threads more quickly,they use pools of threads already residing in the kernel to save on allocation time
操作对象 能够更快地创建线程,因为它们使用的是线程池技术,即再次利用残留的线程,而不是从头创建新线程。
--A detached thread means that the thread’s resources are automatically reclaimed by the system when the thread exits.
一个独立线程意味着 在独立线程退出后,它使用的资源会被系统自动回收。
--There are two ways to create a thread using the
NSThread
class:
Use the
detachNewThreadSelector:toTarget:withObject:
class method to spawn the new thread.Create a new
NSThread
object and call itsstart
method. (Supported only in iOS and OS X v10.5 and later.)这是创建独立线程的两种方式,一个是直接调用NSThread的类方法
detachNewThreadSelector:toTarget:withObject:
,另一种方式是创建一个新的NSThread对象
--If you have an
NSThread
object whose thread is currently running, one way you can send messages to that thread is to use theperformSelector:onThread:withObject:waitUntilDone:
method of almost any object in your application.如果有一个正在运行的NSThread甲线程,而你要从另外一个乙线程发消息给甲线程,有一种方式是,你通过调用对象中的
performSelector:onThread:withObject:waitUntilDone:
方法,你的app中几乎每一个对象中都会有这个方法。这种方式适用于线程间的偶尔通信,如果是频繁通信或者是敏感通信,则不建议使用这种方式。--OS X and iOS provide C-based support for creating threads using the POSIX thread API ; POSIX creates threads as joinable by default, this example changes the thread’s attributes to create a detached thread .
POSIX技术是基于C语言的,所以它可以创建出适用于iOS和OS X系统的线程,他默认创建的线程是非分离的,但是你可以在创建时改变线程的属性,使该线程是分离的(即独立的)。
--The
LaunchThread
function creates a new thread whose main routine is implemented in thePosixThreadMainRoutine
function好吧,POSIX创建线程是通过
LaunchThread函数创建的,而这个函数的主线程是在PosixThreadMainRoutine函数中实现的。
--The POSIX routine you use to create threads is called, appropriately enough,
pthread_create
.你用来创建线程的 POSIX例程 叫做
pthread_create
.--In iOS and OS X v10.5 and later, all objects have the ability to spawn a new thread and use it to execute one of their methods. The
performSelectorInBackground:withObject:
method creates a new detached thread and uses the specified method as the entry point for the new thread.在新版的iOS系统中,所有对象都可以新建一个分离式线程,通过
performSelectorInBackground:withObject:
方法即可,这个方法是NSOject中的。--To let Cocoa know that you intend to use multiple threads, all you have to do is spawn a single thread using the
NSThread
class and let that thread immediately exit如果要使cocoa知道你想要的是多线程编程,你只需要新建一个单线程,然后立马退出该线程。那么cocoa就明了了。POSIX技术
--If you are not sure if Cocoa thinks your application is multithreaded or not, you can use the
isMultiThreaded
method ofNSThread
to check.如果你还心存疑虑cocoa不知道你是多线程,那么你就用NSThread中的
isMultiThreaded
方法来判断吧。--In iOS and OS X v10.5 and later, allocate and initialize an
NSThread
object. Before calling thestart
method of the thread object, use thesetStackSize:
method to specify the new stack size.在新版本iOS中,你可以用NSThread创建一个线程,然后你要修改栈大小的话,你必须在调用start方法之前用
setStackSize:
方法来
修改栈大小。用 POSIX 技术 则是你可以定义一个数据结构来决定栈的大小。--Cocoa and POSIX store the thread dictionary in different ways, so you cannot mix and match calls to the two technologies
线程会维护一个 字典 作为存储机制,你可以在线程的整个run loop的任何地方访问这个字典,但是Cocoa 和 POSIX 技术储存这个字典的方式是不一样的,所以你要区分在两种技术中对 字典 访问时的访问方法不一样。
--Although they still run as independent threads, a joinable thread must be joined by another thread before its resources can be reclaimed by the system.
结合线程 虽然仍让向独立线程一样运行,但是一个结合线程在被系统回收资源之前,必须先被另外一个线程接入,即是另外一个线程对你的资源进行回收处理。
--Each joinable thread must be joined before the process is allowed to exit
在进程退出之前,它的每个结合线程都必须已经被链接了,所以 结合线程 适用于敏感的、不能被打断的工作场景。
--If you do want to create joinable threads, the only way to do so is using POSIX threads. POSIX creates threads as joinable by default.
你只能通过POSIX技术来创建结合线程。它默认就是创建结合线程。
--You initialize your data structures, do some work or optionally set up a run loop, and clean up when your thread’s code is done.
写一个 线程入口点的惯例 是:初始化数据结构、设置run loop的工作内容、清除数据。
--The app frameworks start the run loop of your application’s main thread automatically. If you create any secondary threads, you must configure the run loop and start it manually
app默认自动启动你的主线程的run loop ,如果你想创建第二个线程,那么你必须手动写它的run loop 。
▶ Run Loops