Files
knowledge-kit/Chapter1 - iOS/1.21.md
2020-02-25 17:46:51 +08:00

2.6 KiB
Raw Blame History

禅与 Objective-C 编程艺术

警告和错误

  • 警告
#warning Dude, don't compare floating point numbers like this!
  • 错误
#warning Dude, don't compare floating point numbers like this!
  • 让编译器忽略忽略你这段代码的警告

    大多数 iOS 开发者平时并没有和很多编译器选项打交道。一些选项是对控制严格检查(或者不检查)你的代码或者错误的。有时候,你想要用 pragma 直接产生一个异常,临时打断编译器的行为。

    当你使用ARC的时候编译器帮你插入了内存管理相关的调用。但是这样可能产生一些烦人的事情。比如你使用 NSSelectorFromString 来动态地产生一个 selector 调用的时候ARC不知道这个方法是哪个并且不知道应该用那种内存管理方法你会被提示 performSelector may cause a leak because its selector is unknown执行 selector 可能导致泄漏,因为这个 selector 是未知的).

    如果你知道你的代码不会导致内存泄露,你可以通过加入这些代码忽略这些警告

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"

[myObj performSelector:mySelector withObject:name];

#pragma clang diagnostic pop
  • 忽略没用使用变量的编译警告
#pragma used(foo)
- (NSInteger)giveMeFive
{
    NSString *foo;
    #pragma unused (foo)
    return 5;
}
  • 善用代码块

一个 GCC 非常模糊的特性、以及 Clang 也有的特性:代码块如果在闭合的括号内,会返回最后语句的值。

self. = ({
    NSString *urlString = [NSString stringWithFormat:@"%@/%@", baseURLString, endpoint];
    [NSURL URLWithString:urlString];
});

这个特性非常适合组织小块的代码,给代码阅读者一个重要的入口且减小相关干扰,能让读者聚焦于关键的变量和函数中,此外这个方法有个优点:变量在代码块的区域内有效,可以减小对其他作用域的命名污染。

  • 方法参数断言

你的方法可能需要一些参数来满足特定的条件(比如不能为 nil在这种情况下最好使用 NSParameterAssert()  来断言条件是否成立

括号内的条件为 false 的时候则断言抛出异常

NSParameterAssert(message.length > 0);
[self testAssert:nil];        //***  Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid parameter not satisfying: message.length > 0'
- (void)testAssert:(NSString *)message{
    NSParameterAssert(!(message.length < 1));
    NSLog(@"%@",message);
}