[Cocoa]_[初级]_[使用NSNotificationCenter作为目标观察者实现时需要注意的事项]

场景

  1. 在开发Cocoa程序时,由于界面是用Objective-C写的。无法使用C++的目标观察者[1]类。如果是使用第二种方案2[2],那么也需要增加一个代理类。那么有没有更省事的办法?

说明

  1. 开发界面的时候,经常是需要在子界面里传递数据给主界面,主界面获得数据后跟业务逻辑交互。目前子界面和主界面的数据交互目前使用发布订阅(观察者模式)的设计模式是比较好的,因为它可以让两个界面解耦合。

  2. 之前说过在Cocoa程序里,可以使用NSNotificationCenter通知中心发布接收消息注意事项来作为消息传递的观察者实现。这里要强调一个问题,就是NSNotificationCenter注册的观察者必须要设置接收对象,也就是以下的object参数。如果参数设置为nil,当有多个地方注册同样的观察者时,目标如果发送MyNotificationChangeBackgroundColor消息,所有的观察者都有接收到这个消息,会导致该消息执行多次。特别是以下代码 self对象是多个实例时。

 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(recvNotificationMessage:) name:@(MyNotificationChangeBackgroundColor) object:subject];
  1. 发送MyNotificationChangeBackgroundColor消息, 注意要指定object参数值。
-(IBAction)onChange:(id)sender
{static int mod = 1;if(mod++ % 2){NSColor* color = [NSColor colorWithSRGBRed:255/255.0 green:255/255.0 blue:255/255.0 alpha:1];[[NSNotificationCenter defaultCenter] postNotificationName:@(MyNotificationChangeBackgroundColor) object:self userInfo:@{@"color":color}];}else{NSColor* color = [NSColor colorWithSRGBRed:240/255.0 green:122/255.0 blue:55/255.0 alpha:1];[[NSNotificationCenter defaultCenter] postNotificationName:@(MyNotificationChangeBackgroundColor) object:view1_ userInfo:@{@"color":color}];}}

例子

  1. 以下例子说明如何创建响应指定目标的观察者。点击两次Change按钮会依次更改子视图12的背景色,而它们发送的是同样的消息。

AppDelegate.h

#import <Cocoa/Cocoa.h>
#import "MyView.h"@interface AppDelegate : NSObject <NSApplicationDelegate>
{IBOutlet MyView* view1_;IBOutlet MyView* view2_;
}-(IBAction)onChange:(id)sender;-(IBAction)onReset:(id)sender;@end

AppDelegate.mm

#import "AppDelegate.h"
#include "platform.h"@interface AppDelegate ()@property (weak) IBOutlet NSWindow *window;
@end@implementation AppDelegate-(void)changeBackgroundColor:(NSView*)view withColor:(NSColor*)color1
{[view setWantsLayer:YES];CGColorSpaceRef space = [[color1 colorSpace] CGColorSpace];CGFloat components[] ={color1.redComponent,color1.greenComponent,color1.blueComponent,color1.alphaComponent};CGColorRef color_ref = CGColorCreate(space,components);[[view layer] setBackgroundColor:color_ref];CGColorRelease(color_ref);
}- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {// Insert code here to initialize your application[self onReset:nil];[view1_ registerObserver:self]; // 只接收来自self的消息[view2_ registerObserver:view1_]; // 只接收来自view1的消息
}- (void)applicationWillTerminate:(NSNotification *)aNotification {// Insert code here to tear down your application
}-(IBAction)onChange:(id)sender
{static int mod = 1;if(mod++ % 2){NSColor* color = [NSColor colorWithSRGBRed:255/255.0 green:255/255.0 blue:255/255.0 alpha:1];[[NSNotificationCenter defaultCenter] postNotificationName:@(MyNotificationChangeBackgroundColor) object:self userInfo:@{@"color":color}];}else{NSColor* color = [NSColor colorWithSRGBRed:240/255.0 green:122/255.0 blue:55/255.0 alpha:1];[[NSNotificationCenter defaultCenter] postNotificationName:@(MyNotificationChangeBackgroundColor) object:view1_ userInfo:@{@"color":color}];}}-(IBAction)onReset:(id)sender
{[self changeBackgroundColor:view1_ withColor:[NSColor redColor]];[self changeBackgroundColor:view2_ withColor:[NSColor blueColor]];
}@end

MyView.h

#import <Cocoa/Cocoa.h>NS_ASSUME_NONNULL_BEGIN@interface MyView : NSView-(void)registerObserver:(id __nullable)subject;-(void)removeObserver:(id)subject;@endNS_ASSUME_NONNULL_END

MyView.mm

#import "MyView.h"
#include "platform.h"@implementation MyView- (void)drawRect:(NSRect)dirtyRect {[super drawRect:dirtyRect];// Drawing code here.
}-(void)changeBackgroundColor:(NSView*)view withColor:(NSColor*)color1
{[view setWantsLayer:YES];CGColorSpaceRef space = [[color1 colorSpace] CGColorSpace];CGFloat components[] ={color1.redComponent,color1.greenComponent,color1.blueComponent,color1.alphaComponent};CGColorRef color_ref = CGColorCreate(space,components);[[view layer] setBackgroundColor:color_ref];CGColorRelease(color_ref);
}-(void)recvNotificationMessage:(NSNotification*) notification
{if([notification.name compare:@(MyNotificationChangeBackgroundColor)] == NSOrderedSame){NSDictionary* dict = notification.userInfo;NSColor* color = [dict objectForKey:@"color"];[self changeBackgroundColor:self withColor:color];}
}-(void)registerObserver:(id)subject
{[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(recvNotificationMessage:) name:@(MyNotificationChangeBackgroundColor) object:subject];
}-(void)removeObserver:(id)subject
{[[NSNotificationCenter defaultCenter] removeObserver:self name:@(MyNotificationChangeBackgroundColor) object:subject];
}-(void)awakeFromNib
{}@end

platform.h

#ifndef platform_h
#define platform_h#define MyNotificationChangeBackgroundColor "MyNotificationChangeBackgroundColor"#endif /* platform_h */

main.m

#import <Cocoa/Cocoa.h>int main(int argc, const char * argv[]) {return NSApplicationMain(argc, argv);
}

MainMenu.xib

<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct"><dependencies><plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14460.31"/><capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/></dependencies><objects><customObject id="-2" userLabel="File's Owner" customClass="NSApplication"><connections><outlet property="delegate" destination="Voe-Tx-rLC" id="GzC-gU-4Uq"/></connections></customObject><customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/><customObject id="-3" userLabel="Application"/><customObject id="Voe-Tx-rLC" customClass="AppDelegate"><connections><outlet property="view1_" destination="Gxg-KB-hXo" id="0fI-03-3v8"/><outlet property="view2_" destination="4YQ-ZK-Q0W" id="4bZ-O9-7Dg"/><outlet property="window" destination="QvC-M9-y7g" id="gIp-Ho-8D9"/></connections></customObject><customObject id="YLy-65-1bz" customClass="NSFontManager"/><menu title="Main Menu" systemMenu="main" id="AYu-sK-qS6"><items><menuItem title="NotificationTest" id="1Xt-HY-uBw"><modifierMask key="keyEquivalentModifierMask"/><menu key="submenu" title="NotificationTest" systemMenu="apple" id="uQy-DD-JDr"><items><menuItem title="About NotificationTest" id="5kV-Vb-QxS"><modifierMask key="keyEquivalentModifierMask"/><connections><action selector="orderFrontStandardAboutPanel:" target="-1" id="Exp-CZ-Vem"/></connections></menuItem><menuItem isSeparatorItem="YES" id="VOq-y0-SEH"/><menuItem title="Preferences…" keyEquivalent="," id="BOF-NM-1cW"/><menuItem isSeparatorItem="YES" id="wFC-TO-SCJ"/><menuItem title="Services" id="NMo-om-nkz"><modifierMask key="keyEquivalentModifierMask"/><menu key="submenu" title="Services" systemMenu="services" id="hz9-B4-Xy5"/></menuItem><menuItem isSeparatorItem="YES" id="4je-JR-u6R"/><menuItem title="Hide NotificationTest" keyEquivalent="h" id="Olw-nP-bQN"><connections><action selector="hide:" target="-1" id="PnN-Uc-m68"/></connections></menuItem><menuItem title="Hide Others" keyEquivalent="h" id="Vdr-fp-XzO"><modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/><connections><action selector="hideOtherApplications:" target="-1" id="VT4-aY-XCT"/></connections></menuItem><menuItem title="Show All" id="Kd2-mp-pUS"><modifierMask key="keyEquivalentModifierMask"/><connections><action selector="unhideAllApplications:" target="-1" id="Dhg-Le-xox"/></connections></menuItem><menuItem isSeparatorItem="YES" id="kCx-OE-vgT"/><menuItem title="Quit NotificationTest" keyEquivalent="q" id="4sb-4s-VLi"><connections><action selector="terminate:" target="-1" id="Te7-pn-YzF"/></connections></menuItem></items></menu></menuItem><menuItem title="File" id="dMs-cI-mzQ"><modifierMask key="keyEquivalentModifierMask"/><menu key="submenu" title="File" id="bib-Uj-vzu"><items><menuItem title="New" keyEquivalent="n" id="Was-JA-tGl"><connections><action selector="newDocument:" target="-1" id="4Si-XN-c54"/></connections></menuItem><menuItem title="Open…" keyEquivalent="o" id="IAo-SY-fd9"><connections><action selector="openDocument:" target="-1" id="bVn-NM-KNZ"/></connections></menuItem><menuItem title="Open Recent" id="tXI-mr-wws"><modifierMask key="keyEquivalentModifierMask"/><menu key="submenu" title="Open Recent" systemMenu="recentDocuments" id="oas-Oc-fiZ"><items><menuItem title="Clear Menu" id="vNY-rz-j42"><modifierMask key="keyEquivalentModifierMask"/><connections><action selector="clearRecentDocuments:" target="-1" id="Daa-9d-B3U"/></connections></menuItem></items></menu></menuItem><menuItem isSeparatorItem="YES" id="m54-Is-iLE"/><menuItem title="Close" keyEquivalent="w" id="DVo-aG-piG"><connections><action selector="performClose:" target="-1" id="HmO-Ls-i7Q"/></connections></menuItem><menuItem title="Save…" keyEquivalent="s" id="pxx-59-PXV"><connections><action selector="saveDocument:" target="-1" id="teZ-XB-qJY"/></connections></menuItem><menuItem title="Save As…" keyEquivalent="S" id="Bw7-FT-i3A"><connections><action selector="saveDocumentAs:" target="-1" id="mDf-zr-I0C"/></connections></menuItem><menuItem title="Revert to Saved" keyEquivalent="r" id="KaW-ft-85H"><connections><action selector="revertDocumentToSaved:" target="-1" id="iJ3-Pv-kwq"/></connections></menuItem><menuItem isSeparatorItem="YES" id="aJh-i4-bef"/><menuItem title="Page Setup…" keyEquivalent="P" id="qIS-W8-SiK"><modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/><connections><action selector="runPageLayout:" target="-1" id="Din-rz-gC5"/></connections></menuItem><menuItem title="Print…" keyEquivalent="p" id="aTl-1u-JFS"><connections><action selector="print:" target="-1" id="qaZ-4w-aoO"/></connections></menuItem></items></menu></menuItem><menuItem title="Edit" id="5QF-Oa-p0T"><modifierMask key="keyEquivalentModifierMask"/><menu key="submenu" title="Edit" id="W48-6f-4Dl"><items><menuItem title="Undo" keyEquivalent="z" id="dRJ-4n-Yzg"><connections><action selector="undo:" target="-1" id="M6e-cu-g7V"/></connections></menuItem><menuItem title="Redo" keyEquivalent="Z" id="6dh-zS-Vam"><connections><action selector="redo:" target="-1" id="oIA-Rs-6OD"/></connections></menuItem><menuItem isSeparatorItem="YES" id="WRV-NI-Exz"/><menuItem title="Cut" keyEquivalent="x" id="uRl-iY-unG"><connections><action selector="cut:" target="-1" id="YJe-68-I9s"/></connections></menuItem><menuItem title="Copy" keyEquivalent="c" id="x3v-GG-iWU"><connections><action selector="copy:" target="-1" id="G1f-GL-Joy"/></connections></menuItem><menuItem title="Paste" keyEquivalent="v" id="gVA-U4-sdL"><connections><action selector="paste:" target="-1" id="UvS-8e-Qdg"/></connections></menuItem><menuItem title="Paste and Match Style" keyEquivalent="V" id="WeT-3V-zwk"><modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/><connections><action selector="pasteAsPlainText:" target="-1" id="cEh-KX-wJQ"/></connections></menuItem><menuItem title="Delete" id="pa3-QI-u2k"><modifierMask key="keyEquivalentModifierMask"/><connections><action selector="delete:" target="-1" id="0Mk-Ml-PaM"/></connections></menuItem><menuItem title="Select All" keyEquivalent="a" id="Ruw-6m-B2m"><connections><action selector="selectAll:" target="-1" id="VNm-Mi-diN"/></connections></menuItem><menuItem isSeparatorItem="YES" id="uyl-h8-XO2"/><menuItem title="Find" id="4EN-yA-p0u"><modifierMask key="keyEquivalentModifierMask"/><menu key="submenu" title="Find" id="1b7-l0-nxx"><items><menuItem title="Find…" tag="1" keyEquivalent="f" id="Xz5-n4-O0W"><connections><action selector="performFindPanelAction:" target="-1" id="cD7-Qs-BN4"/></connections></menuItem><menuItem title="Find and Replace…" tag="12" keyEquivalent="f" id="YEy-JH-Tfz"><modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/><connections><action selector="performFindPanelAction:" target="-1" id="WD3-Gg-5AJ"/></connections></menuItem><menuItem title="Find Next" tag="2" keyEquivalent="g" id="q09-fT-Sye"><connections><action selector="performFindPanelAction:" target="-1" id="NDo-RZ-v9R"/></connections></menuItem><menuItem title="Find Previous" tag="3" keyEquivalent="G" id="OwM-mh-QMV"><connections><action selector="performFindPanelAction:" target="-1" id="HOh-sY-3ay"/></connections></menuItem><menuItem title="Use Selection for Find" tag="7" keyEquivalent="e" id="buJ-ug-pKt"><connections><action selector="performFindPanelAction:" target="-1" id="U76-nv-p5D"/></connections></menuItem><menuItem title="Jump to Selection" keyEquivalent="j" id="S0p-oC-mLd"><connections><action selector="centerSelectionInVisibleArea:" target="-1" id="IOG-6D-g5B"/></connections></menuItem></items></menu></menuItem><menuItem title="Spelling and Grammar" id="Dv1-io-Yv7"><modifierMask key="keyEquivalentModifierMask"/><menu key="submenu" title="Spelling" id="3IN-sU-3Bg"><items><menuItem title="Show Spelling and Grammar" keyEquivalent=":" id="HFo-cy-zxI"><connections><action selector="showGuessPanel:" target="-1" id="vFj-Ks-hy3"/></connections></menuItem><menuItem title="Check Document Now" keyEquivalent=";" id="hz2-CU-CR7"><connections><action selector="checkSpelling:" target="-1" id="fz7-VC-reM"/></connections></menuItem><menuItem isSeparatorItem="YES" id="bNw-od-mp5"/><menuItem title="Check Spelling While Typing" id="rbD-Rh-wIN"><modifierMask key="keyEquivalentModifierMask"/><connections><action selector="toggleContinuousSpellChecking:" target="-1" id="7w6-Qz-0kB"/></connections></menuItem><menuItem title="Check Grammar With Spelling" id="mK6-2p-4JG"><modifierMask key="keyEquivalentModifierMask"/><connections><action selector="toggleGrammarChecking:" target="-1" id="muD-Qn-j4w"/></connections></menuItem><menuItem title="Correct Spelling Automatically" id="78Y-hA-62v"><modifierMask key="keyEquivalentModifierMask"/><connections><action selector="toggleAutomaticSpellingCorrection:" target="-1" id="2lM-Qi-WAP"/></connections></menuItem></items></menu></menuItem><menuItem title="Substitutions" id="9ic-FL-obx"><modifierMask key="keyEquivalentModifierMask"/><menu key="submenu" title="Substitutions" id="FeM-D8-WVr"><items><menuItem title="Show Substitutions" id="z6F-FW-3nz"><modifierMask key="keyEquivalentModifierMask"/><connections><action selector="orderFrontSubstitutionsPanel:" target="-1" id="oku-mr-iSq"/></connections></menuItem><menuItem isSeparatorItem="YES" id="gPx-C9-uUO"/><menuItem title="Smart Copy/Paste" id="9yt-4B-nSM"><modifierMask key="keyEquivalentModifierMask"/><connections><action selector="toggleSmartInsertDelete:" target="-1" id="3IJ-Se-DZD"/></connections></menuItem><menuItem title="Smart Quotes" id="hQb-2v-fYv"><modifierMask key="keyEquivalentModifierMask"/><connections><action selector="toggleAutomaticQuoteSubstitution:" target="-1" id="ptq-xd-QOA"/></connections></menuItem><menuItem title="Smart Dashes" id="rgM-f4-ycn"><modifierMask key="keyEquivalentModifierMask"/><connections><action selector="toggleAutomaticDashSubstitution:" target="-1" id="oCt-pO-9gS"/></connections></menuItem><menuItem title="Smart Links" id="cwL-P1-jid"><modifierMask key="keyEquivalentModifierMask"/><connections><action selector="toggleAutomaticLinkDetection:" target="-1" id="Gip-E3-Fov"/></connections></menuItem><menuItem title="Data Detectors" id="tRr-pd-1PS"><modifierMask key="keyEquivalentModifierMask"/><connections><action selector="toggleAutomaticDataDetection:" target="-1" id="R1I-Nq-Kbl"/></connections></menuItem><menuItem title="Text Replacement" id="HFQ-gK-NFA"><modifierMask key="keyEquivalentModifierMask"/><connections><action selector="toggleAutomaticTextReplacement:" target="-1" id="DvP-Fe-Py6"/></connections></menuItem></items></menu></menuItem><menuItem title="Transformations" id="2oI-Rn-ZJC"><modifierMask key="keyEquivalentModifierMask"/><menu key="submenu" title="Transformations" id="c8a-y6-VQd"><items><menuItem title="Make Upper Case" id="vmV-6d-7jI"><modifierMask key="keyEquivalentModifierMask"/><connections><action selector="uppercaseWord:" target="-1" id="sPh-Tk-edu"/></connections></menuItem><menuItem title="Make Lower Case" id="d9M-CD-aMd"><modifierMask key="keyEquivalentModifierMask"/><connections><action selector="lowercaseWord:" target="-1" id="iUZ-b5-hil"/></connections></menuItem><menuItem title="Capitalize" id="UEZ-Bs-lqG"><modifierMask key="keyEquivalentModifierMask"/><connections><action selector="capitalizeWord:" target="-1" id="26H-TL-nsh"/></connections></menuItem></items></menu></menuItem><menuItem title="Speech" id="xrE-MZ-jX0"><modifierMask key="keyEquivalentModifierMask"/><menu key="submenu" title="Speech" id="3rS-ZA-NoH"><items><menuItem title="Start Speaking" id="Ynk-f8-cLZ"><modifierMask key="keyEquivalentModifierMask"/><connections><action selector="startSpeaking:" target="-1" id="654-Ng-kyl"/></connections></menuItem><menuItem title="Stop Speaking" id="Oyz-dy-DGm"><modifierMask key="keyEquivalentModifierMask"/><connections><action selector="stopSpeaking:" target="-1" id="dX8-6p-jy9"/></connections></menuItem></items></menu></menuItem></items></menu></menuItem><menuItem title="Format" id="jxT-CU-nIS"><modifierMask key="keyEquivalentModifierMask"/><menu key="submenu" title="Format" id="GEO-Iw-cKr"><items><menuItem title="Font" id="Gi5-1S-RQB"><modifierMask key="keyEquivalentModifierMask"/><menu key="submenu" title="Font" systemMenu="font" id="aXa-aM-Jaq"><items><menuItem title="Show Fonts" keyEquivalent="t" id="Q5e-8K-NDq"><connections><action selector="orderFrontFontPanel:" target="YLy-65-1bz" id="WHr-nq-2xA"/></connections></menuItem><menuItem title="Bold" tag="2" keyEquivalent="b" id="GB9-OM-e27"><connections><action selector="addFontTrait:" target="YLy-65-1bz" id="hqk-hr-sYV"/></connections></menuItem><menuItem title="Italic" tag="1" keyEquivalent="i" id="Vjx-xi-njq"><connections><action selector="addFontTrait:" target="YLy-65-1bz" id="IHV-OB-c03"/></connections></menuItem><menuItem title="Underline" keyEquivalent="u" id="WRG-CD-K1S"><connections><action selector="underline:" target="-1" id="FYS-2b-JAY"/></connections></menuItem><menuItem isSeparatorItem="YES" id="5gT-KC-WSO"/><menuItem title="Bigger" tag="3" keyEquivalent="+" id="Ptp-SP-VEL"><connections><action selector="modifyFont:" target="YLy-65-1bz" id="Uc7-di-UnL"/></connections></menuItem><menuItem title="Smaller" tag="4" keyEquivalent="-" id="i1d-Er-qST"><connections><action selector="modifyFont:" target="YLy-65-1bz" id="HcX-Lf-eNd"/></connections></menuItem><menuItem isSeparatorItem="YES" id="kx3-Dk-x3B"/><menuItem title="Kern" id="jBQ-r6-VK2"><modifierMask key="keyEquivalentModifierMask"/><menu key="submenu" title="Kern" id="tlD-Oa-oAM"><items><menuItem title="Use Default" id="GUa-eO-cwY"><modifierMask key="keyEquivalentModifierMask"/><connections><action selector="useStandardKerning:" target="-1" id="6dk-9l-Ckg"/></connections></menuItem><menuItem title="Use None" id="cDB-IK-hbR"><modifierMask key="keyEquivalentModifierMask"/><connections><action selector="turnOffKerning:" target="-1" id="U8a-gz-Maa"/></connections></menuItem><menuItem title="Tighten" id="46P-cB-AYj"><modifierMask key="keyEquivalentModifierMask"/><connections><action selector="tightenKerning:" target="-1" id="hr7-Nz-8ro"/></connections></menuItem><menuItem title="Loosen" id="ogc-rX-tC1"><modifierMask key="keyEquivalentModifierMask"/><connections><action selector="loosenKerning:" target="-1" id="8i4-f9-FKE"/></connections></menuItem></items></menu></menuItem><menuItem title="Ligatures" id="o6e-r0-MWq"><modifierMask key="keyEquivalentModifierMask"/><menu key="submenu" title="Ligatures" id="w0m-vy-SC9"><items><menuItem title="Use Default" id="agt-UL-0e3"><modifierMask key="keyEquivalentModifierMask"/><connections><action selector="useStandardLigatures:" target="-1" id="7uR-wd-Dx6"/></connections></menuItem><menuItem title="Use None" id="J7y-lM-qPV"><modifierMask key="keyEquivalentModifierMask"/><connections><action selector="turnOffLigatures:" target="-1" id="iX2-gA-Ilz"/></connections></menuItem><menuItem title="Use All" id="xQD-1f-W4t"><modifierMask key="keyEquivalentModifierMask"/><connections><action selector="useAllLigatures:" target="-1" id="KcB-kA-TuK"/></connections></menuItem></items></menu></menuItem><menuItem title="Baseline" id="OaQ-X3-Vso"><modifierMask key="keyEquivalentModifierMask"/><menu key="submenu" title="Baseline" id="ijk-EB-dga"><items><menuItem title="Use Default" id="3Om-Ey-2VK"><modifierMask key="keyEquivalentModifierMask"/><connections><action selector="unscript:" target="-1" id="0vZ-95-Ywn"/></connections></menuItem><menuItem title="Superscript" id="Rqc-34-cIF"><modifierMask key="keyEquivalentModifierMask"/><connections><action selector="superscript:" target="-1" id="3qV-fo-wpU"/></connections></menuItem><menuItem title="Subscript" id="I0S-gh-46l"><modifierMask key="keyEquivalentModifierMask"/><connections><action selector="subscript:" target="-1" id="Q6W-4W-IGz"/></connections></menuItem><menuItem title="Raise" id="2h7-ER-AoG"><modifierMask key="keyEquivalentModifierMask"/><connections><action selector="raiseBaseline:" target="-1" id="4sk-31-7Q9"/></connections></menuItem><menuItem title="Lower" id="1tx-W0-xDw"><modifierMask key="keyEquivalentModifierMask"/><connections><action selector="lowerBaseline:" target="-1" id="OF1-bc-KW4"/></connections></menuItem></items></menu></menuItem><menuItem isSeparatorItem="YES" id="Ndw-q3-faq"/><menuItem title="Show Colors" keyEquivalent="C" id="bgn-CT-cEk"><connections><action selector="orderFrontColorPanel:" target="-1" id="mSX-Xz-DV3"/></connections></menuItem><menuItem isSeparatorItem="YES" id="iMs-zA-UFJ"/><menuItem title="Copy Style" keyEquivalent="c" id="5Vv-lz-BsD"><modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/><connections><action selector="copyFont:" target="-1" id="GJO-xA-L4q"/></connections></menuItem><menuItem title="Paste Style" keyEquivalent="v" id="vKC-jM-MkH"><modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/><connections><action selector="pasteFont:" target="-1" id="JfD-CL-leO"/></connections></menuItem></items></menu></menuItem><menuItem title="Text" id="Fal-I4-PZk"><modifierMask key="keyEquivalentModifierMask"/><menu key="submenu" title="Text" id="d9c-me-L2H"><items><menuItem title="Align Left" keyEquivalent="{" id="ZM1-6Q-yy1"><connections><action selector="alignLeft:" target="-1" id="zUv-R1-uAa"/></connections></menuItem><menuItem title="Center" keyEquivalent="|" id="VIY-Ag-zcb"><connections><action selector="alignCenter:" target="-1" id="spX-mk-kcS"/></connections></menuItem><menuItem title="Justify" id="J5U-5w-g23"><modifierMask key="keyEquivalentModifierMask"/><connections><action selector="alignJustified:" target="-1" id="ljL-7U-jND"/></connections></menuItem><menuItem title="Align Right" keyEquivalent="}" id="wb2-vD-lq4"><connections><action selector="alignRight:" target="-1" id="r48-bG-YeY"/></connections></menuItem><menuItem isSeparatorItem="YES" id="4s2-GY-VfK"/><menuItem title="Writing Direction" id="H1b-Si-o9J"><modifierMask key="keyEquivalentModifierMask"/><menu key="submenu" title="Writing Direction" id="8mr-sm-Yjd"><items><menuItem title="Paragraph" enabled="NO" id="ZvO-Gk-QUH"><modifierMask key="keyEquivalentModifierMask"/></menuItem><menuItem id="YGs-j5-SAR"><string key="title">	Default</string><modifierMask key="keyEquivalentModifierMask"/><connections><action selector="makeBaseWritingDirectionNatural:" target="-1" id="qtV-5e-UBP"/></connections></menuItem><menuItem id="Lbh-J2-qVU"><string key="title">	Left to Right</string><modifierMask key="keyEquivalentModifierMask"/><connections><action selector="makeBaseWritingDirectionLeftToRight:" target="-1" id="S0X-9S-QSf"/></connections></menuItem><menuItem id="jFq-tB-4Kx"><string key="title">	Right to Left</string><modifierMask key="keyEquivalentModifierMask"/><connections><action selector="makeBaseWritingDirectionRightToLeft:" target="-1" id="5fk-qB-AqJ"/></connections></menuItem><menuItem isSeparatorItem="YES" id="swp-gr-a21"/><menuItem title="Selection" enabled="NO" id="cqv-fj-IhA"><modifierMask key="keyEquivalentModifierMask"/></menuItem><menuItem id="Nop-cj-93Q"><string key="title">	Default</string><modifierMask key="keyEquivalentModifierMask"/><connections><action selector="makeTextWritingDirectionNatural:" target="-1" id="lPI-Se-ZHp"/></connections></menuItem><menuItem id="BgM-ve-c93"><string key="title">	Left to Right</string><modifierMask key="keyEquivalentModifierMask"/><connections><action selector="makeTextWritingDirectionLeftToRight:" target="-1" id="caW-Bv-w94"/></connections></menuItem><menuItem id="RB4-Sm-HuC"><string key="title">	Right to Left</string><modifierMask key="keyEquivalentModifierMask"/><connections><action selector="makeTextWritingDirectionRightToLeft:" target="-1" id="EXD-6r-ZUu"/></connections></menuItem></items></menu></menuItem><menuItem isSeparatorItem="YES" id="fKy-g9-1gm"/><menuItem title="Show Ruler" id="vLm-3I-IUL"><modifierMask key="keyEquivalentModifierMask"/><connections><action selector="toggleRuler:" target="-1" id="FOx-HJ-KwY"/></connections></menuItem><menuItem title="Copy Ruler" keyEquivalent="c" id="MkV-Pr-PK5"><modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/><connections><action selector="copyRuler:" target="-1" id="71i-fW-3W2"/></connections></menuItem><menuItem title="Paste Ruler" keyEquivalent="v" id="LVM-kO-fVI"><modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/><connections><action selector="pasteRuler:" target="-1" id="cSh-wd-qM2"/></connections></menuItem></items></menu></menuItem></items></menu></menuItem><menuItem title="View" id="H8h-7b-M4v"><modifierMask key="keyEquivalentModifierMask"/><menu key="submenu" title="View" id="HyV-fh-RgO"><items><menuItem title="Show Toolbar" keyEquivalent="t" id="snW-S8-Cw5"><modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/><connections><action selector="toggleToolbarShown:" target="-1" id="BXY-wc-z0C"/></connections></menuItem><menuItem title="Customize Toolbar…" id="1UK-8n-QPP"><modifierMask key="keyEquivalentModifierMask"/><connections><action selector="runToolbarCustomizationPalette:" target="-1" id="pQI-g3-MTW"/></connections></menuItem><menuItem isSeparatorItem="YES" id="hB3-LF-h0Y"/><menuItem title="Show Sidebar" keyEquivalent="s" id="kIP-vf-haE"><modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/><connections><action selector="toggleSourceList:" target="-1" id="iwa-gc-5KM"/></connections></menuItem><menuItem title="Enter Full Screen" keyEquivalent="f" id="4J7-dP-txa"><modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/><connections><action selector="toggleFullScreen:" target="-1" id="dU3-MA-1Rq"/></connections></menuItem></items></menu></menuItem><menuItem title="Window" id="aUF-d1-5bR"><modifierMask key="keyEquivalentModifierMask"/><menu key="submenu" title="Window" systemMenu="window" id="Td7-aD-5lo"><items><menuItem title="Minimize" keyEquivalent="m" id="OY7-WF-poV"><connections><action selector="performMiniaturize:" target="-1" id="VwT-WD-YPe"/></connections></menuItem><menuItem title="Zoom" id="R4o-n2-Eq4"><modifierMask key="keyEquivalentModifierMask"/><connections><action selector="performZoom:" target="-1" id="DIl-cC-cCs"/></connections></menuItem><menuItem isSeparatorItem="YES" id="eu3-7i-yIM"/><menuItem title="Bring All to Front" id="LE2-aR-0XJ"><modifierMask key="keyEquivalentModifierMask"/><connections><action selector="arrangeInFront:" target="-1" id="DRN-fu-gQh"/></connections></menuItem></items></menu></menuItem><menuItem title="Help" id="wpr-3q-Mcd"><modifierMask key="keyEquivalentModifierMask"/><menu key="submenu" title="Help" systemMenu="help" id="F2S-fz-NVQ"><items><menuItem title="NotificationTest Help" keyEquivalent="?" id="FKE-Sm-Kum"><connections><action selector="showHelp:" target="-1" id="y7X-2Q-9no"/></connections></menuItem></items></menu></menuItem></items></menu><window title="NotificationTest" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="QvC-M9-y7g"><windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/><windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/><rect key="contentRect" x="335" y="390" width="480" height="360"/><rect key="screenRect" x="0.0" y="0.0" width="1366" height="745"/><view key="contentView" wantsLayer="YES" id="EiT-Mj-1SZ"><rect key="frame" x="0.0" y="0.0" width="480" height="360"/><autoresizingMask key="autoresizingMask"/><subviews><customView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Gxg-KB-hXo" customClass="MyView"><rect key="frame" x="31" y="193" width="183" height="124"/><autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/></customView><customView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="4YQ-ZK-Q0W" customClass="MyView"><rect key="frame" x="257" y="193" width="174" height="124"/><autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/></customView><button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="sbg-pR-7xp"><rect key="frame" x="353" y="13" width="87" height="32"/><autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/><buttonCell key="cell" type="push" title="Change" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="MHb-HO-fqR"><behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/><font key="font" metaFont="system"/></buttonCell><connections><action selector="onChange:" target="Voe-Tx-rLC" id="0CQ-0i-z8w"/></connections></button><button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="FRq-bN-yDD"><rect key="frame" x="273" y="13" width="75" height="32"/><autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/><buttonCell key="cell" type="push" title="Reset" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="JP3-gy-SnJ"><behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/><font key="font" metaFont="system"/></buttonCell><connections><action selector="onReset:" target="Voe-Tx-rLC" id="TtH-x7-6B2"/></connections></button></subviews></view></window></objects>
</document>

例子

图1
在这里插入图片描述

参考

1.观察者模式在项目中实际使用例子

2.观察者模式在项目中实际使用例子2

3.NSNotificationCenter通知中心发布接收消息注意事项

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/440639.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Windows 搭建 Gitea

一、准备工作 1. 安装 Git&#xff1a;Gitea 依赖 Git 进行代码管理&#xff0c;所以首先需要确保系统中安装了 Git。 下载地址&#xff1a;https://git-scm.com/downloads/win 2. 安装数据库&#xff08;可选&#xff09; 默认情况下&#xff0c;Gitea 使用 SQLite 作为内…

Nginx的基础讲解之重写conf文件

一、Nginx 1、什么是nginx&#xff1f; Nginx&#xff08;engine x&#xff09;是一个高性能的HTTP和反向代理web服务器&#xff0c;同时也提供了IMAP/POP3/SMTP服务。 2、用于什么场景 Nginx适用于各种规模的网站和应用程序&#xff0c;特别是需要高并发处理和负载均衡的场…

微信步数C++

题目&#xff1a; 样例解释&#xff1a; 【样例 #1 解释】 从 (1,1) 出发将走 2 步&#xff0c;从 (1,2) 出发将走 4 步&#xff0c;从 (1,3) 出发将走 4 步。 从 (2,1) 出发将走 2 步&#xff0c;从 (2,2) 出发将走 3 步&#xff0c;从 (2,3) 出发将走 3 步。 从 (3,1) 出发将…

AI 激活新势能,中小企业全媒体营销绽放无限可能

什么是全媒体营销&#xff1a; 全媒体营销是一种利用多种媒介渠道进行品牌、产品或服务推广的营销策略。它结合了传统媒体&#xff08;如电视、广播、报纸、杂志&#xff09;和新媒体&#xff08;如互联网、社交媒体、移动应用等&#xff09;的优势&#xff0c;以实现信息的广…

力扣之1322.广告效果

题目&#xff1a; sql建表语句&#xff1a; Create table If Not Exists Ads (ad_id int,user_id int,action ENUM (Clicked, Viewed, Ignored) ); Truncate table Ads; insert into Ads (ad_id, user_id, action) values (1, 1, Clicked); insert into Ads (ad_id, use…

【重学 MySQL】五十八、文本字符串(包括 enum set)类型

【重学 MySQL】五十八、文本字符串&#xff08;包括 enum set&#xff09;类型 CHAR 和 VARCHARTEXT 系列ENUMSET示例注意事项 在 MySQL 中&#xff0c;文本字符串类型用于存储字符数据。这些类型包括 CHAR、VARCHAR、TEXT 系列&#xff08;如 TINYTEXT、TEXT、MEDIUMTEXT 和 L…

基于SSM的仿win10界面的酒店管理系统

基于SSM的仿win10界面的酒店管理系统 运行环境: jdk1.8 eclipse tomcat7 mysql5.7 项目技术: jspssm&#xff08;springspringmvcmybatis&#xff09;mysql 项目功能模块&#xff1a;基础功能、房间类型、楼层信息、附属功能

AtCoder ABC373 A-D题解

ABC372 的题解没写是因为 D 是单调栈我不会(⊙︿⊙) 比赛链接:ABC373 总结&#xff1a;wssb。听说 E 很水&#xff1f;有时间我看看。 Problem A: Code #include <bits/stdc.h> using namespace std; int mian(){int ans0;for(int i1;i<12;i){string S;cin>&g…

[Offsec Lab] ICMP Monitorr-RCE+hping3权限提升

信息收集 IP AddressOpening Ports192.168.52.218TCP:22,80 $ nmap -p- 192.168.52.218 --min-rate 1000 -sC -sV -Pn PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.9p1 Debian 10deb10u2 (protocol 2.0) | ssh-hostkey: | 2048 de:b5:23:89:bb:9f:d4:1…

表面缺陷检测系统源码分享

表面缺陷检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vision …

Redis篇(缓存机制 - 基本介绍)(持续更新迭代)

目录 一、缓存介绍 二、经典三缓存问题 1. 缓存穿透 1.1. 简介 1.2. 解决方案 1.3. 总结 2. 缓存雪崩 2.1. 简介 2.2. 解决方案 2.3. 总结 3. 缓存击穿 3.1. 简介 3.2. 解决方案 3.3. 总结 4. 经典三缓存问题出现的根本原因 三、常见双缓存方案 1. 缓存预热 1…

国外媒体宣发:怎么在海外电子杂志版上发布新闻稿-时代周刊Time发布新闻稿

时代周刊Time发布新闻稿 在全球化的浪潮中&#xff0c;新闻媒体扮演着传递信息、引导舆论、塑造公众认知的重要角色。作为国际知名的媒体品牌&#xff0c;时代周刊&#xff08;Time&#xff09;以其独特的视角和深入的报道&#xff0c;为全球读者提供了一扇观察世界的窗口。近…

深度学习:GAN图像生成

GAN的诞生背景 诞生&#xff1a; 2014年由Ian Goodfellow提出 创新性&#xff1a; 无监督学习&#xff1a;GAN 提供了一种新的方法来进行无监督学习&#xff0c;即不需要对训练数据进行标注就可以学习到数据的潜在分布。对抗训练&#xff1a;通过引入对抗机制&#xff0c;G…

C语言文件操作(下)(28)

文章目录 前言一、文件的打开和关闭打开打开模式相对路径和绝对路径 关闭 二、文件操作正确流程三、文件顺序读写函数fopenfclosefputcfgetcfputsfgetsfprintffscanfsprintfsscanffwritefread 四、文件随机读写函数fseekftellrewind 五、文件读取结束时候的判断feofferror具体例…

Mysql锁机制解读(敲详细)

目录 锁的概念 全局锁 表级锁 表锁 元数据锁 意向锁 锁的概念 全局锁 表级锁 表锁 元数据锁 主要是对未提交事务&#xff0c;修改表结构造成表结构混乱&#xff0c;进行控制。 在不涉及表结构变化的情况下,元素锁可以忽略。 意向锁 避免有行级锁影响加表级锁&#xff0…

openpnp - 吸嘴校正失败的opencv参数分析

文章目录 openpnp - 吸嘴校正失败的opencv参数分析概述笔记阶段验证 - N2吸嘴校验完NT1NT2 阶段验证 - 底部相机高级校验完NT1NT2 参数比对保存 “阶段验证 - N2吸嘴校验完” 的NT1/NT2图像重建参数检测环境NT1ok的3个参数值NT1err的3个参数值NT2ok的3个参数值NT2err的3个参数值…

黑马JavaWeb开发跟学(九)MyBatis基础操作

黑马JavaWeb开发跟学九.MyBatis基础操作 1. Mybatis基础操作1.1 需求1.2 准备1.3 删除1.3.1 功能实现1.3.2 日志输入1.3.3 预编译SQL1.3.3.1 介绍1.3.3.2 SQL注入1.3.3.3 参数占位符 1.4 新增1.4.1 基本新增1.4.2 主键返回 1.5 更新1.6 查询1.6.1 根据ID查询1.6.2 数据封装1.6.…

C++引用(变量引用、数组引用与数组指针、引用本质-指针常量、常量引用)

C语言 ——对数组名进行解引用,取地址,还有sizeof和strlen进行操作解析_对数组名解引用得到什么-CSDN博客 C++引用(变量引用、数组引用与数组指针、引用本质-指针常量、常量引用)_c++11 数组引用-CSDN博客

复现文章:R语言复现文章画图

文章目录 介绍数据和代码图1图2图6附图2附图3附图4附图5附图6 介绍 文章提供画图代码和数据&#xff0c;本文记录 数据和代码 数据可从以下链接下载&#xff08;画图所需要的所有数据&#xff09;&#xff1a; 百度云盘链接: https://pan.baidu.com/s/1peU1f8_TG2kUKXftkpYq…

软考系统分析师知识点四:操作系统基本原理

前言 今年报考了11月份的软考高级&#xff1a;系统分析师。 考试时间为&#xff1a;11月9日。 倒计时&#xff1a;33天。 目标&#xff1a;优先应试&#xff0c;其次学习&#xff0c;再次实践。 复习计划第一阶段&#xff1a;扫平基础知识点&#xff0c;仅抽取有用信息&am…