优(dan)美(teng)的前奏

宏定义这个东东,估计大家在代码中应该天天用吧。

在我刚刚做的一个项目中,各种往代码里码“#define”这种预处理指令。

什么动画时长啊,cell高度啊,cell的个数啊,balabala,看得我这个心烦。

拿一个例子来讲:

A程序猿定义了一个UITableViewCell的高度为45。

#define HEIGHT_TABLEVIEWCELL 45;

B程序猿也定义了一个UITableViewCell的高度为50。

#define HEIGHT_TABLEVIEWCELL 50;

然后B在他写的.m文件中引用了A的文件,然后...然后...就没有然后了。

总结一句话就是,TMD,太乱了。

经过查找资料,发现确实有人提出过问题,并且提出了“少用#define”的建议。

(很明显没有多少人遵循这一建议,大家还在开心的#define)

提出这一观点的论据主要有以下两点:

  (1) 就是像我刚才举的例子一样,如果B引用了A的文件,并且A、B两人的文件中的预定义指令的名字相同,那么就会产生冲突,结果就是A       中的预定义指令把B中的预定义指令代替了。

  (2)没有类型定义,就像#define HEIGHT_TABLEVIEWCELL 45;这句代码中,我们只能从后边的45来推测是int类型或者float类型。但是具体      是哪一种,代码中并不能体现出来。

所以基于以上两点,我们应该尽量少的使用#define这种预定义指令。

那不使用#define,我们使啥捏?

这个问题问滴有水平!^^!

那就分为两种情况跟大家聊聊:

在一个“编译单元”中使用

在Objective-C的语境下,“编译单元”一词通常指每个类的实现文件(以.m为后缀名)。

也就是说,我们只在当前这一个.m文件中使用。

简单使用

这种情况我们就可以使用static和const来修饰变量,例如 static const NSString *kClassName = @"DemoClass";

  • static 能够限制当前变量只能在此编译单元中使用。
  • const 能够限制当前变量只要被定义之后就不能被修改。

参考以下代码:

// DemoViewController.h
#import <UIKit/UIKit.h>
@interface DemoViewController : UIViewController
@end // DemoViewController.m
#import "DemoViewController.h" static const NSString *kClassName = @"DemoViewController"; @implementation DemoViewController
@end

命名规则

根据苹果官方代码我们可以发现,定义“编译单元”内的常量都是以"k",作为前缀。

在多个“编译单元”中使用

简单使用

若要在多个“编译单元”中使用,此类常量需放在“全局符号表”(global symbol table)中,以便可以在定义该常量的编译单元之外使用。

步骤稍微复杂一下,但是比把大象装冰箱要简单一点:

  • 在.h文件中,使用extern、const关键字对变量进行声明。
  • 在.m文件中,对.h文件中声明的变量进行定义。

参考以下代码:

// DemoViewController.h
#import <Foundation/Foundation.h> extern NSString *const DemoViewControllerClassName; @interface DemoViewController : UIViewController
@end // DemoViewController.m
#import "DemoViewController.h" NSString *const DemoViewControllerClassName =
@"DemoViewController"; @implementation DemoViewController
@end

注意const关键字的位置。

命名规则

为避免名称冲突,最好是用与之相关的类名做前缀。

系统框架中一般都这样做。例如UIKit就按照这种方式来声明用作通知名称的全局常量。

其中有类似UIApplicationDidEnterBackgroundNotification与UIApplicationWillEnterForegroundNotification这样的常量名。

总之,经过这个项目蛋疼的经历,大家还是在项目中尽量少的使用预定义指令。

另外附上咱家的微信公众号的二维码,没事儿可以扫扫哈。

有啥事儿大家可以随时留言交流。

Obective-C之宏定义的更多相关文章

  1. c++宏定义命令

    在程序开始以#开头的命令,他们是预编译命令.有三类预编译命令:宏定义命令.文件包含命令.条件编译命令:今天聊聊宏定义: 宏定义命令将一个标识符定义为一个字符串,源程序中的该标识符均以指定的字符串来代替 ...

  2. dll导入导出宏定义,出现“不允许 dllimport 函数 的定义”的问题分析

    建立dll项目后,在头文件中,定义API宏 #ifndef API_S_H #define API_S_H ...... #ifndef DLL_S_20160424 #define API _dec ...

  3. iOS之常用宏定义

    下面我为大家提供一些常用的宏定义! 将这些宏定义 加入到.pch使用 再也不用 用一次写一次这么长的程序了 //-------------------获取设备大小------------------- ...

  4. linux中offsetof与container_of宏定义

    linux内核中offsetof与container_of的宏定义 #define offsetof(TYPE, MEMBER)    ((size_t) &((TYPE *)0)->M ...

  5. Linux Kernel代码艺术——系统调用宏定义

    我们习惯在SI(Source Insight)中阅读Linux内核,SI会建立符号表数据库,能非常方便地跳转到变量.宏.函数等的定义处.但在处理系统调用的函数时,却会遇到一些麻烦:我们知道系统调用函数 ...

  6. 面试问题5:const 与 define 宏定义之间的区别

    问题描述:const 与 define 宏定义之间的区别 (1) 编译器处理方式不同     define宏是在预处理阶段展开:     const常量是编译运行阶段使用: (2) 类型和安全检查不同 ...

  7. 关于Xcode8.1 / iOS10+ 真机测试系统打印或者宏定义打印不显示问题

    前言: 最近做项目时遇到了很多莫名其妙的问题,其中就有这个打印(NSLog).也不多废话了,我们先来回顾一下Xcode8发布以来,我们遇到的一些关于打印的问题,当然也有解决方法: 1.Xcode8打印 ...

  8. JDStatusBarNotification和一些宏定义

    // //  AddTopicViewController.m //  vMeet2 // //  Created by 张源海 on 16/6/30. //  Copyright © 2016年 h ...

  9. #define宏定义形式的"函数"导致的bug

    定义了一个宏定义形式的"函数": #define  SUM8(YY)\ {\ int Y = YY>>2;\ ...\ } 然后使用的时候,传入了一个同名的变量Y: i ...

  10. 黑马程序员——C语言基础 枚举 宏定义 自定义 static exterm

    Java培训.Android培训.iOS培训..Net培训.期待与您交流! (以下内容是对黑马苹果入学视频的个人知识点总结) (一)枚举 1)枚举类型的定义 枚举是C语言中的一种基本数据类型,并不是构 ...

随机推荐

  1. BZOJ 4127 Abs 解题报告

    这个题感觉很厉害的样子.. 首先我们注意到一点:每次加的 $d$ 都是非负的. 那么就说明一个数只可能从负数变成非负数并且只会变一次. 所以我们就可以暴力地去改变一个数的正负情况. 然后我们就可以用树 ...

  2. 团体程序设计天梯赛-练习集L2-003. 月饼

    L2-003. 月饼 时间限制 100 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 月饼是中国人在中秋佳节时吃的一种传统食品,不同地区有许多不 ...

  3. TCP长连接与短连接的区别

    http://www.cnblogs.com/liuyong/archive/2011/07/01/2095487.html 1. TCP连接 当网络通信时采用TCP协议时,在真正的读写操作之前,se ...

  4. Servlet课程0426(十二)Servlet MV模式下用户登录及查看用户表中所有用户

    Welcome.java //登录界面 package com.tsinghua; import javax.servlet.http.*; import java.io.*; import java ...

  5. Ado.Net小练习02(小项目CUID

    前台界面: 后台代码: namespace ado.net小项目cuid {     public partial class Form1 : Form     {         //连接字符串   ...

  6. Agri Net POJ1258 && Constructing Roads POJ2421

    题意,在给出的图中,使用最小花费的边,使这个图仍然连通. #include <cstdio> #include <algorithm> #include <cstring ...

  7. movzbl和movsbl

    汇编语言中最最常用的指令 -- 数据传送指令,也是我们接触的第一种类别的汇编指令.其指令的格式为:“mov 源操作数, 目的操作数”.mov系列支持从最小一个字节到最大双字的访问与传送.其中movb用 ...

  8. 不要在头文件中使用 using namespace std;

    不要在头文件中使用(using namespace std;).   若你使用了using namespace std;,在某一头文件中,那么包含这些头文件的文件就失去了"namespace ...

  9. PHP session过期时间

    如何设置一个严格30分钟过期的Session 今天在我的微博(Laruence)上发出一个问题: 我在面试的时候, 经常会问一个问题: “如何设置一个30分钟过期的Session?”, 大家不要觉得看 ...

  10. Application.CommonAppDataPath的路径

    Application.CommonAppDataPath; win7的路径 C:\ProgramData\CompanyName\ProductName\2.0.5.1 [assembly: Ass ...