• NSNotification Name 最佳写法


    本文主要借探讨NSNotificationName的最佳写法的机会,学习下extern, static, const, #define 和常量指针与指针常量等的特性和用法。

    1.NSNotification标准使用方法

    发送通知

    [[NSNotificationCenter defaultCenter] postNotificationName:QLPosterDidPostNotification object:nil];

    接收通知

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didReceive:) name:QLPosterDidPostNotification object:nil];


    还要注意在dealloc中移除通知哈

    2.通知的发送者和接收者都需要知道NSNotification name,如何保证双方统一

    在iOS中,通知是为了方便解耦,因此通知的发送者和接收者往往不在同一个类/文件中

    但是无论是发送者还是接收者,他们使用的通知名字却需要一致,如上例的QLPosterDidPostNotification在两处地方都使用到了

    那么如何保证2处地方使用的通知名字是同一个呢?

    最蠢的做法就是在各处需要用到这个通知的地方自己定义一个QLPosterDidPostNotification

    这种做法违背了DRY原则,简直忍无可忍,一旦违背了DRY原则,代码的可读性将会变得非常差,维护起来会非常恶心!

    最佳实践是一处地方定义,多处地方使用

    3.最佳写法

    QLPoster.h

    extern NSString *const QLPosterDidPostNotification;

    QLPoster.m

    NSString *const QLPosterDidPostNotification = @"QLPosterDidPostNotification";

    QLReceiver.h

    extern NSString *const QLPosterDidPostNotification;

    4.怎么用

    首先,很自然的,我们先在QLPoster.m中声明定义一个通知的名字

    NSString *const QLPosterDidPostNotification = @"QLPosterDidPostNotification";

    其次,为了让外面的人统一使用该变量,我们需要在QLPoster.h中将该变量暴露出去,并且加上extern,但不需要赋值(因为是声明)。目的就是为了告诉外部调用者,我有QLPosterDidPostNotification这个变量,它是什么内容你们别管,直接用就行了

    然后QLReceiver要来调用啦,直接把QLPoster.h中关于变量声明的这句代码直接copy到自己的.h就行啦(因为这也是声明)

    5.为什么不用#define

    static const 是十分常见的组合,这里可以先把问题转为 static const 和 #define 的区别。

    static const和#define的异同是:

    相同点:编译器根本不会创建符号,预编译时把所有遇到的变量都替换为常值

    不同点:但是static const定义的常量带有类型信息(可以指明常量是int, double, ...),便于理解

    由于#define定义的常量不含类型信息,编译器只是会在编译前据此执行查找与替换操作。即使有人重新定义了常量值,编译器也不会产生警告信息,这将导致应用程序中的常量不一致

    6.extern是什么(为什么不用static const)

    extern int a;//声明一个全局变量a
    int a; //定义一个全局变量a
    extern int a = 0 ;//定义一个全局变量a并给初值
    int a = 0;//定义一个全局变量a并给初值

    定义只能有1处,但声明可以有多处

    定义引起内存分配,声明则不会

    A.m

    NSString *hello = @"hello";

    B.m中不需要#import "A.m",直接

    extern NString *hello;
    NSLog(@"%@", hello);    //输出 hello

    非常厉害,不需要引用相关头文件就能使用其值!

    变量的声明默认就是extern

    变量的声明默认就是extern

    变量的声明默认就是extern

    重要的事情说3次了

    假如A.m不想被B用extern找到,怎么办?只需要加个static

    A.m

    static NSString *hello = @"hello";

    static表示该值只会在本文件(.m)中使用哈,别人看不到的

    假如声明此变量时不加static,则编译器会为它创建一个“外部符号”(external symbol)

    假如C.m也和A.m一样,都有一个NSString *hello = @"hello";

    那就会编译失败,因为有2个外部变量hello

    7.为什么加const

    通知名称一般是固定不可变的,且不希望外部修改其值,所以加上const无非是最正确的选择

    8.为什么是NSString *const 而不是 NSString const *

    这就是C/C++中说到的常量指针和指针常量的区别了

    const写在*前面,则该指针可被重新赋值,而指针指向的内容不可被重新赋值

    const写在*后面,则该指针指向的内容可被重新赋值,而指针本身不可被重新赋值(即不能指向其他内存)

    回到iOS中来,我们修改NSString的值,是怎么修改

    NSString *str = @"123";
    str = @"456";

    注意哦,str = @"456";相当于(不代表就一定是)str = [[NSString alloc] initWithString:"456"];

    就是说,iOS中,对NSString的修改一般都是让其指向一块新的内存

    所以为了防止外部改变通知名字的值,我们一般将const写在*后面


    9.规范的NSNotification Name命名方式

    [Name of associated class] + [Did | Will] + [UniquePartOfName] + Notification

    (1)QLPosterDidPostNotification 而不是 kDidPostNotification

    以k开头的一般是类内自己使用的static const变量,如果需要提供给外部使用,最好将自己的类名作为前缀

    通知一般都不是只给自己用的,所以需要将自己的类名作为前缀

    声明为extern的常量要出现在全局符号表中,所以其名称应加以区隔,通常用与之相关的类名做前缀。

    (2)Did/Will表示动作的已经结束或即将开始,以明确通知抛出的时机

    (3)QLPosterDidPostNotification 而不是 QLPosterDidPostNoti

    通知名称这里宁愿名字长也不要引起歧义(苹果的命名一向被吐槽太长了)

  • 相关阅读:
    linux mono环境
    【百度杯】ctf夺旗大战,16万元奖励池等你拿
    【渗透技术】渗透测试技术分析_TomCat
    成功率“99%”!截止目前史上最强大电信诈骗术
    【sql注入】浅谈sql注入中的Post注入
    通过Weeman+Ettercap配合拿下路由器管理权限
    【sql注入教程】mysql注入直接getshell
    【云盘资料】Sql注入从菜鸟到高手系列教程
    【安全开发】浅谈JSP安全开发之XSS
    Python黑帽编程2.1 Python编程哲学
  • 原文地址:https://www.cnblogs.com/chenyg32/p/5080301.html
Copyright © 2020-2023  润新知