美文网首页
读EffectiveObjective-C2.0(第三条、第四条

读EffectiveObjective-C2.0(第三条、第四条

作者: LazyLoad | 来源:发表于2020-10-20 09:28 被阅读0次

第三条:多用字面量语法,少用与之等价的方法

  • NSStringNSNumberNSArrayNSDictionary都可以使用字面量的方式创建一个对象。相比于使用alloc及init方法创建对象简单了许多。字面量语法可以缩短代码长度,十分易读。
NSString *someString = @"Effective Objective-C";
  • 字面数值(NSNumber):有些时候需要将整数、浮点数、布尔值封装成OC对象。这种情况下可以使用NSNumber类,该类提供了多种类型的包装方法。如果不使用字面量,那么就需要按照下面的方式进行对象包装:
NSNumber *someNumber = [NSNumber numberWithInt:1];

如果使用字面量,就会变得十分的简洁

NSNumber *someNumber = @1;
  • 能够使用NSNumber表示的字面量有很多:
NSNumber *intNumber = @1;
NSNumber *floatNumber = @2.1;
NSNumber *doubleNumber = @3.14159;
NSNumber *boolNumber = @YES;
NSNumber *charNumber = @'a';
  • 字面量语法也适用于表达式
int x = 5;
float y = 6.32;
NSNumber *expressionNumber = @(x * y);
  • 字面数组(NSArray):如果不使用字面量语法来创建数组,代码如下:
NSArray *animals = [NSArray arrayWithObjects:@"dog", @"cat", "mouse", @"badger", nil];

使用字面量语法创建数组:简单、易操作

NSArray *animals = @[@"dog", @"cat", @"mouse", @"badger"];
  • 通过下标获取数组中的元素,不使用字面量语法:
NSString *dog = [animals objectAtIndex:0];

使用字面量语法:

NSString *dog = animals[0];

这种方式明显更加简单,和其他语言获取元素方式相似。

注意:使用字面量语法创建的数组中的元素不能为nil,如果数组中的元素为nil,就会抛出异常

NSString *object1 = @"dog";
NSString *object2 = @"cat";
NSString *object3 = @"mouse";

NSArray *array1 = [NSArray arrayWithObjects:object1, object2, object3, nil];
NSLog(@"%@", array1);
NSArray *array2 = @[object1, object2, object3];
NSLog(@"%@", array2);

上述代码:二者打印的结果是一致的,没有任何问题。

  • 如果将object2指向nil。array1不会抛出异常,array1只会打印object1,因为arrayWithObjects:这种方式创建的数组当发现元素为nil的时候,方法会提前结束。
  • array2会抛出异常,并终止程序的运行。二者对比来说,字面量语法创建数组更加安全,帮助我们及时的发现数组中的元素存在nil的情况。而前者的方式,不容易发现数组中的元素存在nil的情况。
NSString *object1 = @"dog";
NSString *object2 = nil;
NSString *object3 = @"mouse";

NSArray *array1 = [NSArray arrayWithObjects:object1, object2, object3, nil];
NSLog(@"%@", array1);
NSArray *array2 = @[object1, object2, object3];
NSLog(@"%@", array2);
  • 字面量字典(NSDictionary):是一种映射型数据结构,相当于其他语言中的Map。可向其中添加键值对。
  • 使用非字面量语法创建字典:这种方式创建是**Value -> Key **,和通常情况理解的键值对相反,不是很方便。
NSDictionary *personData = [NSDictionary dictionaryWithObjectsAndKeys:@"Matt", @"firstName", @"Galloway", @"lastName", [NSNumber numberWithInt:28], @"age", nil];
  • 使用字面量语法创建字典:明显比上面的方式清晰,简洁
NSDictionary *personData = @{
    @"firstName": @"Matt",
    @"lastName": @"Galloway",
    @"age": @28
};

注意:字典和数组中的元素都必须是对象类型,与数组一样,使用字面量语法创建的字典,如果遇到nil,便会抛出异常,而dictionaryWithObjectsAndKeys:方法会在遇到nil之前的时候停下。

  • 字典也可以向数组一样通过字面语法进行元素的访问,字面量语法更加方便
NSString *lastName = [personData objectForKey:@"lastName"]; // 非字面语法
NSString *lastName = personData[@"lastName"]; // 字面量语法

第四条:多用类型常量,少用#define预处理指令

编写代码时经常使用到常量。例如:设置视图的动画时长,而且动画时长在多个位置都会使用到。通常会把时长抽取为常量,在需要的位置直接调用即可,方便管理。

我们也许会使用这种预处理指令来实现:

  • 使用这种预处理指令的方式会把源代码中的ANIMATION_DURATION字符串替换为0.3。这可能是我们想要的一种结果,但是这样定义出来的常量没有类型信息。动画时间与时间相关,但是在代码中没有明确指出类型。
  • 预处理过程会把碰到的所有ANIMATION_DURATION一律替换成0.3,这样的话,假设此指令声明在某个头文件中,那么所有引入这个头文件的代码,其ANIMATION_DURATION都会被替换。
#define ANIMATION_DURATION 0.3
  • 要解决此问题,可以使用类型常量:
  • 这种定义方式包含类型信息,清晰的描述了常量的含义
static const NSTimeInterval kAnimationDuration = 0.3;
  • 注意常量的名称。常用的命名法是:如果常量局限于某一个编译单元(实现文件)之内,则在前面加字母k;如果常量在类之外的多个文件可见,则通常以类名为前缀

  • 定义常量的位置很重要,不要在头文件中声明预处理指令和static const 定义的常量。当多个地方引入该头文件的时候,会将定义的常量引入,而常量不一定就是被需要的,而且,常量的名称有可能互相冲突。如果要定义全局的常量,最好加上前缀,因为OC没有命名空间的概念,不加前缀很可能导致命名的冲突。

  • 如果不打算公开某个常量,应该将其定义在使用该常量的实现文件中。比如说执行动画的时间一般情况下都是时间常量即可。

// EOCAnimatedView.h
#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface EOCAnimatedView : UIView

- (void)animate;

@end

NS_ASSUME_NONNULL_END

// EOCAnimatedView.m
#import "EOCAnimatedView.h"

static const NSTimeInterval kAnimationDuration = 0.3;

@implementation EOCAnimatedView

- (void)animate {
  [UIView animateWithDuration:kAnimationDuration animations:^{
      // do something
  }];
}

@end
  • 变量一定要使用staticconst声明。
    • 使用const修饰符声明的变量,是不允许修改的,编译器会报错。
    • 使用static修饰符声明的变量,只能在定义次变量的实现文件(.m)文件中可见。

所以kAnimationDuration变量的作用域,只在EOCAnimatedView.m中。

  • 如果声明此变量的时候没有加static,编译器会为它创建一个外部符号。此时在另一个实现文件中也声明了相同的变量,那么编译器就会报错。
duplicate symbol '_kAnimationDuration' in:
ViewController.o
EOCAnimatedView.o
ld: 1 duplicate symbol for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

所以,同时使用staticconst声明一个变量,不会创建外部符号,也保证了变量不可以被修改,还包好了类型信息,好处非常多的。

  • 有的时候我们不得不需要公开某个常量。比如说使用NSNotificationCenter的通知处理,要在多个文件中定义相同的Key。这种常量,需要放在全局符号表中,以便可以在定义该常量的实现文件之外使用。通常情况下,我的做法如下:

    • 创建一个const文件(名称可以自己起),包含声明文件和实现文件。
    • 变量在头文件中声明在实现文件中定义
    // const.h
    extern NSString *const EOCStringConstant; //!< 注释内容
    // const.m
    NSString *const EOCStringConstant = @"Value";
    
    • 编译器看到头文件中的extern关键字,就知道如何在引入头文件的代码中处理该常量了。这个关键字告诉编译器,在全局符号表中将会有一个名字叫做EOCStringConstant的符号。
  • 因为符号要放在全局符号表中,命名要格外注意。通常用相关的类名作为前缀。类似系统定义的UIApplicationDidEnterBackgroundNotification这种方式。见名知意。

相关文章

  • 读EffectiveObjective-C2.0(第三条、第四条

    第三条:多用字面量语法,少用与之等价的方法 NSString,NSNumber,NSArray,NSDiction...

  • 新教育实验专业阅读地图共读(三):路径

    五条假设里中的第三条和第四条分别如下: 第三条假设:每一门类知识的掌握,都存在着一条由浅入深的路径。 第四条假设:...

  • 《电子商务法条文释义》关键词录(4)

    第三条无关键词,第四条无关键词。 第三条 国家鼓励发展电子商务新业态,创新商业模式,促进电子商务...

  • 读书人的十个权利

    “读者权利十条 第一条 不读的权利 第二条 跳读的权利 第三条 不读完的权利 第四条 重读的权利 第五条 读不择书...

  • 如何让对读书不感兴趣的人爱上读书—读书技巧一

    读者权利十条 第一条 不读的权利 第二条 跳读的权利 第三条 不读完的权利 第四条 重读的权利 第五条 读不择...

  • 发圈第六条,下午六点,晒效果

    发圈时间: 第一条 ️:️️7~9 第二条️:️️9~11 第三条️️:️️11~13 第四条️️:️️13~...

  • 宗教活动的智慧

    第一条:忏悔 第二条: 献祭 第三条:祈祷 第四条:禁忌 第五条:礼仪 不断反复体验。

  • 偶感

    偶感 经营第三条 胸中怀有强烈的愿望――要怀有渗透到潜意识强烈而持久你愿望 经营第四条 付出不亚于任何人的努力――...

  • 7 条「反直觉」管理原则

    第一条原则: 接纳混沌 第二条原则:招聘适合当下的人,而不是强人 第三条原则: 容忍「管理不善」 第四条原则:让你...

  • 偶感

    经营第三条 胸中怀有强烈的愿望――要怀有渗透到潜意识强烈而持久你愿望 经营第四条 付出不亚于任何人的努力――一步...

网友评论

      本文标题:读EffectiveObjective-C2.0(第三条、第四条

      本文链接:https://www.haomeiwen.com/subject/njbrmktx.html