您的位置:首页 > 移动开发 > IOS开发

iOS 通知机制 Notifications (三)

2013-12-15 21:56 148 查看


PostingaNotification

Youcanpostnotificationswithinyourownapplicationormakethemavailabletootherapplications.See“Posting
LocalNotifications”fortheformerand“Posting
DistributedNotifications”forthelatter.


PostingLocalNotifications

发布本地通知Youcancreateanotificationobjectwith
notificationWithName:object:
or
notificationWithName:object:userInfo:
.
Youthenpostthenotificationobjecttoanotificationcenterusingthe
postNotification:
instancemethod.
NSNotification
objects
areimmutable,sooncecreated,theycannotbemodified.你可以用
notificationWithName:object:
或者
notificationWithName:object:userInfo:创建一个通知。然后你用postNotification:实例方法发布通知到通知中心。NSNotification是不可变对象,所以一旦创建,不可更改。
However,younormallydon’tcreateyourownnotificationsdirectly.Themethods
postNotificationName:object:
and
postNotificationName:object:userInfo:
of
the
NSNotificationCenter
classallowyoutoconvenientlypostanotificationwithoutcreatingitfirst.当然,你通常不需要直接创建自己的通知。
NSNotificationCenter
postNotificationName:object:
以及
postNotificationName:object:userInfo:
方法允许你直接发布一个通知,而不需要先创建它。
Ineachcase,youusuallypostthenotificationtotheprocess’sdefaultnotificationcenter.Youobtainthedefaultobjectusingthe
defaultCenter
class
method.你通常提交通知到进程默认的通知中心。你通过defaultCenter类方法获取默认的对象。Asanexampleofusingthenotificationcentertopostanotification,considertheexamplefrom“Registering
forLocalNotifications.”Youhaveaprogramthatcanperformanumberofconversionsontext(forinstance,RTFtoASCII).Theconversionsarehandledbyaclassofobjects(
Converter
)
thatcanbeaddedorremovedduringprogramexecution.Yourprogrammayhaveotherobjectsthatwanttobenotifiedwhenconvertersareaddedorremoved,butthe
Converter
objects
donotneedtoknowwhotheseobjectsareorwhattheydo.Youthusdeclaretwonotifications,
"ConverterAdded"
and
"ConverterRemoved"
,
whichyoupostwhenthegiveneventoccurs.使用通知中心发布通知的例子可以从“Registering
forLocalNotifications.”中找,]。你有个程序,执行一些文本的转换(比如,从RTF到ASCII)。对象的类(转换器)处理转化,它可以再程序执行期间被添加获取删除。你程序中可能有对象想直到转换器何时被添加何时被去除,但是转换器对象不需要这些对象的信息。于是你定义两个通知
"ConverterAdded"
"ConverterRemoved"
当事件发生时发布通知。
Whenauserinstallsorremovesaconverter,itsendsoneofthefollowingmessagestothenotificationcenter:
[[NSNotificationCenterdefaultCenter]

postNotificationName:@"ConverterAdded"object:self];

or
[[NSNotificationCenterdefaultCenter]

postNotificationName:@"ConverterRemoved"object:self];

Thenotificationcenterthenidentifieswhichobjects(ifany)areinterestedinthesenotificationsandnotifiesthem.Ifthereareotherobjectsofinteresttotheobserver(besidesthenotificationnameandobservedobject),placetheminthenotification’soptionaldictionaryoruse
postNotificationName:object:userInfo:
.如果有其他观察者感兴趣的对象,可以把他们放在通知可选的字典里,或者使用postNotificationName:object:userInfo:



DeliveringNotificationsToParticularThreads

传送通知到特别的线程Regularnotificationcentersdelivernotificationsonthethreadinwhichthenotificationwasposted.Distributednotificationcentersdelivernotificationsonthemainthread.Attimes,youmayrequirenotificationstobedeliveredonaparticularthread
thatisdeterminedbyyouinsteadofthenotificationcenter.Forexample,ifanobjectrunninginabackgroundthreadislisteningfornotificationsfromtheuserinterface,suchasawindowclosing,youwouldliketoreceivethenotificationsinthebackground
threadinsteadofthemainthread.Inthesecases,youmustcapturethenotificationsastheyaredeliveredonthedefaultthreadandredirectthemtotheappropriatethread.通常通知在通知被发布的线程上传递通知。分布式通知中心在主线程传递通知。有时候,你也许希望在你希望的线程上传递通知。例如,如果一个运行在后台的对象正在监听用户界面的通知,比如窗口关闭,这时候你希望在后台线程接收通知而不是在主线程。在这种情况下,你必须在默认线程截住通知,然后发送到合适的线程。Onewaytoredirectnotificationsistouseacustomnotificationqueue(notan
NSNotificationQueue
object)toholdanynotificationsthatarereceivedonincorrectthreadsandthenprocessthemon
thecorrectthread.Thistechniqueworksasfollows.Youregisterforanotificationnormally.Whenanotificationarrives,youtestwhetherthecurrentthreadisthethreadthatshouldhandlethenotification.Ifitisthewrongthread,youstorethenotification
inaqueueandthensendasignaltothecorrectthread,indicatingthatanotificationneedsprocessing.Theotherthreadreceivesthesignal,removesthenotificationfromthequeue,andprocessesthenotification.一种重新发布通知的方法是使用自定义的通知队列(注意不是NSNotificationQueue对象)去保存在不正确线程上收到的通知,然后在正确的线程上处理他们。这个技术是这样的。你正常注册一个通知。当通知到达时,你测试一下当前的线程是否应该处理通知。如果是错误的线程,你保持通知到队列。然后发送一个信号到正确的线程,告诉它一个通知需要处理。另外一个线程收到信号,从队列中移除通知,然后处理通知。Toimplementthistechnique,yourobserverobjectneedstohaveinstancevariablesforthefollowingvalues:amutablearraytoholdthenotifications,acommunication
portforsignalingthecorrectthread(aMachport),alocktopreventmultithreadingconflictswiththenotificationarray,andavaluethatidentifiesthecorrectthread(an
NSThread
object).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

Beforeregisteringforanynotifications,youneedtoinitializetheproperties.Thefollowingmethodinitializesthequeueandlockobjects,keepsareference
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];

}

Afterthismethodruns,anymessagessentto
notificationPort
arereceivedintherunloopofthethreadthatfirstranthismethod.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
notifications
array
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];

}

Whenanotificationisdeliveredtoyourobject,themethodthatreceivesthenotificationmustidentifywhetheritisrunninginthecorrectthreadornot.Ifitisthecorrectthread,thenotificationisprocessednormally.Ifitisthewrongthread,the
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;

}

}

Finally,toregisterforanotificationthatyouwantdeliveredonthecurrentthread,regardlessofthethreadinwhichitmaybeposted,youmustinitializeyourobject’snotificationpropertiesbyinvoking
setUpThreadingSupport
and
thenregisterforthenotificationnormally,specifyingthespecialnotificationprocessingmethodastheselector.
[selfsetupThreadingSupport];

[[NSNotificationCenterdefaultCenter]

addObserver:self

selector:@selector(processNotification:)

name:@"NotificationName"

object:nil];

Thisimplementationislimitedinseveralaspects.First,allthreadednotificationsprocessedbythisobjectmustpassthroughthesamemethod(
processNotification:
).
Second,eachobjectmustprovideitsownimplementationandcommunicationport.Abetter,butmorecomplex,implementationwouldgeneralizethebehaviorintoeitherasubclassof
NSNotificationCenter
or
aseparateclassthatwouldhaveonenotificationqueueforeachthreadandbeabletodelivernotificationstomultipleobserverobjectsandmethods.这个实现在某些方面。首先,对象处理的所有线程的通知必须通过相同的方法(processNotification:)传递。第二,每一个对象都必须提供自己的实现和通信端口。一个更好,但是也更复杂的实现是。。。。有空补上,这段话有点复杂
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: