iOS 通知机制 Notifications (三)
2013-12-15 21:56
148 查看
PostingaNotification
Youcanpostnotificationswithinyourownapplicationormakethemavailabletootherapplications.See“PostingLocalNotifications”fortheformerand“Posting
DistributedNotifications”forthelatter.
PostingLocalNotifications
发布本地通知YoucancreateanotificationobjectwithnotificationWithName:object:or
notificationWithName:object:userInfo:.
Youthenpostthenotificationobjecttoanotificationcenterusingthe
postNotification:instancemethod.
NSNotificationobjects
areimmutable,sooncecreated,theycannotbemodified.你可以用
notificationWithName:object:或者
notificationWithName:object:userInfo:创建一个通知。然后你用postNotification:实例方法发布通知到通知中心。NSNotification是不可变对象,所以一旦创建,不可更改。However,younormallydon’tcreateyourownnotificationsdirectly.Themethods
postNotificationName:object:and
postNotificationName:object:userInfo:of
the
NSNotificationCenterclassallowyoutoconvenientlypostanotificationwithoutcreatingitfirst.当然,你通常不需要直接创建自己的通知。
NSNotificationCenter的
postNotificationName:object:以及
postNotificationName:object:userInfo: 方法允许你直接发布一个通知,而不需要先创建它。Ineachcase,youusuallypostthenotificationtotheprocess’sdefaultnotificationcenter.Youobtainthedefaultobjectusingthe
defaultCenterclass
method.你通常提交通知到进程默认的通知中心。你通过defaultCenter类方法获取默认的对象。Asanexampleofusingthenotificationcentertopostanotification,considertheexamplefrom“Registering
forLocalNotifications.”Youhaveaprogramthatcanperformanumberofconversionsontext(forinstance,RTFtoASCII).Theconversionsarehandledbyaclassofobjects(
Converter)
thatcanbeaddedorremovedduringprogramexecution.Yourprogrammayhaveotherobjectsthatwanttobenotifiedwhenconvertersareaddedorremoved,butthe
Converterobjects
donotneedtoknowwhotheseobjectsareorwhattheydo.Youthusdeclaretwonotifications,
"ConverterAdded"and
"ConverterRemoved",
whichyoupostwhenthegiveneventoccurs.使用通知中心发布通知的例子可以从“Registering
forLocalNotifications.”中找,]。你有个程序,执行一些文本的转换(比如,从RTF到ASCII)。对象的类(转换器)处理转化,它可以再程序执行期间被添加获取删除。你程序中可能有对象想直到转换器何时被添加何时被去除,但是转换器对象不需要这些对象的信息。于是你定义两个通知
"ConverterAdded"和
"ConverterRemoved"
当事件发生时发布通知。Whenauserinstallsorremovesaconverter,itsendsoneofthefollowingmessagestothenotificationcenter:
[[NSNotificationCenterdefaultCenter] |
postNotificationName:@"ConverterAdded"object:self]; |
[[NSNotificationCenterdefaultCenter] |
postNotificationName:@"ConverterRemoved"object:self]; |
postNotificationName:object:userInfo:.如果有其他观察者感兴趣的对象,可以把他们放在通知可选的字典里,或者使用postNotificationName:object:userInfo:
DeliveringNotificationsToParticularThreads
传送通知到特别的线程Regularnotificationcentersdelivernotificationsonthethreadinwhichthenotificationwasposted.Distributednotificationcentersdelivernotificationsonthemainthread.Attimes,youmayrequirenotificationstobedeliveredonaparticularthreadthatisdeterminedbyyouinsteadofthenotificationcenter.Forexample,ifanobjectrunninginabackgroundthreadislisteningfornotificationsfromtheuserinterface,suchasawindowclosing,youwouldliketoreceivethenotificationsinthebackground
threadinsteadofthemainthread.Inthesecases,youmustcapturethenotificationsastheyaredeliveredonthedefaultthreadandredirectthemtotheappropriatethread.通常通知在通知被发布的线程上传递通知。分布式通知中心在主线程传递通知。有时候,你也许希望在你希望的线程上传递通知。例如,如果一个运行在后台的对象正在监听用户界面的通知,比如窗口关闭,这时候你希望在后台线程接收通知而不是在主线程。在这种情况下,你必须在默认线程截住通知,然后发送到合适的线程。Onewaytoredirectnotificationsistouseacustomnotificationqueue(notan
NSNotificationQueueobject)toholdanynotificationsthatarereceivedonincorrectthreadsandthenprocessthemon
thecorrectthread.Thistechniqueworksasfollows.Youregisterforanotificationnormally.Whenanotificationarrives,youtestwhetherthecurrentthreadisthethreadthatshouldhandlethenotification.Ifitisthewrongthread,youstorethenotification
inaqueueandthensendasignaltothecorrectthread,indicatingthatanotificationneedsprocessing.Theotherthreadreceivesthesignal,removesthenotificationfromthequeue,andprocessesthenotification.一种重新发布通知的方法是使用自定义的通知队列(注意不是NSNotificationQueue对象)去保存在不正确线程上收到的通知,然后在正确的线程上处理他们。这个技术是这样的。你正常注册一个通知。当通知到达时,你测试一下当前的线程是否应该处理通知。如果是错误的线程,你保持通知到队列。然后发送一个信号到正确的线程,告诉它一个通知需要处理。另外一个线程收到信号,从队列中移除通知,然后处理通知。Toimplementthistechnique,yourobserverobjectneedstohaveinstancevariablesforthefollowingvalues:amutablearraytoholdthenotifications,acommunication
portforsignalingthecorrectthread(aMachport),alocktopreventmultithreadingconflictswiththenotificationarray,andavaluethatidentifiesthecorrectthread(an
NSThreadobject).You
alsoneedmethodstosetupthevariables,toprocessthenotifications,andtoreceivetheMachmessages.Herearethenecessarydefinitionstoaddtotheclassofyourobserverobject.为了实现这个技术,你的观察者对象需要以下值的实例变量:一个保存通知的可变数组,一个通知正确线程的通信端口(aMachport),一个防止通知数组内多线程处理冲突的锁,一个标示正确线程(一个NSThread对象)的值。你也需要方法去设置变量,去处理通知,去接收Mach消息。下面是要添加到你观察者对象中的必要的定义。
@interfaceMyThreadedClass:NSObject |
/*Threadednotificationsupport.*/ |
@propertyNSMutableArray*notifications; |
@propertyNSThread*notificationThread; |
@propertyNSLock*notificationLock; |
@propertyNSMachPort*notificationPort; |
-(void)setUpThreadingSupport; |
-(void)handleMachMessage:(void*)msg; |
-(void)processNotification:(NSNotification*)notification; |
@end |
tothecurrentthreadobject,andcreatesaMachcommunicationport,whichitaddstothecurrentthread’srunloop.
在注册通知之前,你需要初始化这些属性,下面的方法初始化了队列和锁对象,保持了一个对当前线程对象的引用,以及创建了一个Mach通信端口,它将被添加到当前线程的runloop中。
-(void)setUpThreadingSupport{ |
if(self.notifications){ |
return; |
} |
self.notifications=[[NSMutableArrayalloc]init]; |
self.notificationLock=[[NSLockalloc]init]; |
self.notificationThread=[NSThreadcurrentThread]; |
self.notificationPort=[[NSMachPortalloc]init]; |
[self.notificationPortsetDelegate:self]; |
[[NSRunLoopcurrentRunLoop]addPort:self.notificationPort |
forMode:(NSString__bridge*)kCFRunLoopCommonModes]; |
} |
notificationPortarereceivedintherunloopofthethreadthatfirstranthismethod.Ifthereceivingthread’srunloopisnot
runningwhentheMachmessagearrives,thekernelholdsontothemessageuntilthenexttimetherunloopisentered.Thereceivingthread’srunloopsendstheincomingmessagestothe
handleMachMessage:method
oftheport’sdelegate.在这个方法运行之后,任何发送到notificationPort的消息将会在首先运行这个方法的线程的runloop中被收到。如果Mach消息到达时,接收者线程的runloop没有运行,内核被保持这个消息直到下次runloop进入。接收者线程的runloop发送未到达的消息到端口代理的handleMachMessage:方法。Inthisimplementation,noinformationiscontainedinthemessagessentto
notificationPort.Instead,theinformationpassedbetweenthreadsiscontainedinthenotification
array.WhenaMachmessagearrives,the
handleMachMessage:methodignoresthecontentsofthemessageandjustchecksthe
notificationsarray
foranynotificationsthatneedprocessing.Thenotificationsareremovedfromthearrayandforwardedtotherealnotificationprocessingmethod.Becauseportmessagesmaygetdroppediftoomanyaresentsimultaneously,the
handleMachMessage:methoditeratesover
thearrayuntilitisempty.Themethodmustacquirealockwhenaccessingthenotificationarraytopreventconflictsbetweenonethreadaddingnotificationsandanotherremovingnotificationsfromthearray.在这个实现中,发送到notificationPort的消息没有包含任何信息。相反,通知数组包含线程间传递的信息。当Mach信息到达时,handleMachMessage:方法忽略了消息的内容,只是检查通知数组中需要处理的通知。通知从数组中移除,然后传到真正处理通知的方法中。因为如果同时发送太多端口信息,信息可能会丢失。handleMachMessage:方法会遍历数组,直到它为空。当访问通知数组时必须获取一个锁,以防止一个线程添加通知而另一个线程把通知从数组移除。
-(void)handleMachMessage:(void*)msg{ |
[self.notificationLocklock]; |
while([self.notificationscount]){ |
NSNotification*notification=[self.notificationsobjectAtIndex:0]; |
[self.notificationsremoveObjectAtIndex:0]; |
[self.notificationLockunlock]; |
[selfprocessNotification:notification]; |
[self.notificationLocklock]; |
}; |
[self.notificationLockunlock]; |
} |
notificationisaddedtothequeueandthenotificationportsignaled.
-(void)processNotification:(NSNotification*)notification{ |
if([NSThreadcurrentThread]!=notificationThread){ |
//Forwardthenotificationtothecorrectthread. |
[self.notificationLocklock]; |
[self.notificationsaddObject:notification]; |
[self.notificationLockunlock]; |
[self.notificationPortsendBeforeDate:[NSDatedate] |
components:nil |
from:nil |
reserved:0]; |
} |
else{ |
//Processthenotificationhere; |
} |
} |
setUpThreadingSupportand
thenregisterforthenotificationnormally,specifyingthespecialnotificationprocessingmethodastheselector.
[selfsetupThreadingSupport]; |
[[NSNotificationCenterdefaultCenter] |
addObserver:self |
selector:@selector(processNotification:) |
name:@"NotificationName" |
object:nil]; |
processNotification:).
Second,eachobjectmustprovideitsownimplementationandcommunicationport.Abetter,butmorecomplex,implementationwouldgeneralizethebehaviorintoeitherasubclassof
NSNotificationCenteror
aseparateclassthatwouldhaveonenotificationqueueforeachthreadandbeabletodelivernotificationstomultipleobserverobjectsandmethods.这个实现在某些方面。首先,对象处理的所有线程的通知必须通过相同的方法(processNotification:)传递。第二,每一个对象都必须提供自己的实现和通信端口。一个更好,但是也更复杂的实现是。。。。有空补上,这段话有点复杂
相关文章推荐
- iOS 通知机制 Notifications (二)
- iOS 通知机制 Notifications (二)
- iOS 通知机制 Notifications (一)
- iOS 通知机制 Notifications (一)
- iOS 10新的通知机制中添加图片的方法详解
- ios中的通知机制
- iOS开发系列--通知与消息机制
- iOS开发中的两种消息通知机制详解
- iOS中通知机制
- iOS中的通知机制
- iOS开发系列--通知与消息机制
- [iOS基础控件 - 6.10] Notification 通知机制
- iOS开发系列--通知与消息机制----转
- iOS开发系列--通知与消息机制
- ios学习路线—Objective-C(通知机制)
- iOS开发系列--通知与消息机制--转
- iOS开发系列--通知与消息机制
- iOS开发之通知机制(一)本地通知(UILocalNotification)
- iOS开发系列--通知与消息机制
- iOS开发-消息通知机制(NSNotification和NSNotificationCenter)