《禅与Objective—C编程艺术》 阅读笔记

《禅与Objective—C编程艺术》的github地址:https://github.com/oa414/objc-zen-book-cn#swift


1. if (nil == myValue) { ...nil放左边就算少敲一个=也不会被赋值

2.条件语句多用return增加可读性,降低复杂度

3.使用长的,描述性的变量名

4.常量用 static NSString *const name = value; 不要用宏定义

5.不要将nil传进NSArray和NSDictionary,会导致崩溃

6.

NSArray *names = @[@"Brian", @"Matt", @"Chris", @"Alex", @"Steve", @"Paul"];

NSDictionary *productManagers = @{@"iPhone" : @"Kate", @"iPad" : @"Kamal", @"Mobile Web" : @"Bill"};

NSNumber *shouldUseLiterals = @YES;

NSNumber *buildingZIPCode = @10018;

7.这意味着申请分配内存和初始化被分离成两步,alloc 和 init。

alloc 负责创建对象,这个过程包括分配足够的内存来保存对象,写入 isa 指针,初始化引用计数,以及重置所有实例变量。

init 负责初始化对象,这意味着使对象处于可用状态。这通常意味着为对象的实例变量赋予合理有用的值。

8.在你希望提供你自己的初始化函数的时候,你应该遵守这三个步骤来保证获得正确的行为:

定义你的 designated initializer,确保调用了直接超类的 designated initializer。

重载直接超类的 designated initializer。调用你的新的 designated initializer。

为新的 designated initializer 写文档。

- (id)initWithNews:(ZOCNews *)news

{

// call to the immediate superclass's designated initializer (调用直接超类的 designated initializer)

self = [super initWithNibName:nil bundle:nil];

if (self) {

_news = news;

}

return self;

}

// Override the immediate superclass's designated initializer (重载直接父类的  designated initializer)

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil

{

// call the new designated initializer

return [self initWithNews:nil];

}

@end

9.单例

如果可能,请尽量避免使用单例而是依赖注入。 然而,如果一定要用,请使用一个线程安全的模式来创建共享的实例。对于 GCD,用 dispatch_once() 函数就可以咯。

+ (instancetype)sharedInstance

{

static id sharedInstance = nil;

static dispatch_once_t onceToken = 0;

dispatch_once(&onceToken, ^{

sharedInstance = [[self alloc] init];

});

return sharedInstance;

}

10.有一个例外:永远不要在 init 方法(以及其他初始化方法)里面用 getter 和 setter 方法,你应当直接访问实例变量

11.点符号

当使用 setter getter 方法的时候尽量使用点符号。应该总是用点符号来访问以及设置属性。

例子:

view.backgroundColor = [UIColor orangeColor];

[UIApplication sharedApplication].delegate;

不要这样:

[view setBackgroundColor:[UIColor orangeColor]];

UIApplication.sharedApplication.delegate;

12.任何可以用一个可变的对象设置的((比如 NSString,NSArray,NSURLRequest))属性的内存管理类型必须是 copy 的。

13.永远不要在你的私有方法前加上 _ 前缀。这个前缀是 Apple 保留的。不要冒重载苹果的私有方法的险。

14.我们应该要在我们的 category 方法前加上自己的小写前缀以及下划线,比如- (id)zoc_myCategoryMethod。 这种实践同样被苹果推荐。

14.

NSNotification

当你定义你自己的 NSNotification 的时候你应该把你的通知的名字定义为一个字符串常量,就像你暴露给其他类的其他字符串常量一样。你应该在公开的接口文件中将其声明为 extern 的, 并且在对应的实现文件里面定义。

因为你在头文件中暴露了符号,所以你应该按照统一的命名空间前缀法则,用类名前缀作为这个通知名字的前缀。

同时,用一个 Did/Will 这样的动词以及用 "Notifications" 后缀来命名这个通知也是一个好的实践。

// Foo.h

extern NSString * const ZOCFooDidBecomeBarNotification

// Foo.m

NSString * const ZOCFooDidBecomeBarNotification = @"ZOCFooDidBecomeBarNotification”;

15.推荐:

if (user.isHappy) {

//Do something

}

else {

//Do something else

}

16.

关于 pragma

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

#pragma clang diagnostic push

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

[myObj performSelector:mySelector withObject:name];

#pragma clang diagnostic pop

注意我们是如何在相关代码上下文中用 pragma 停用 -Warc-performSelector-leaks 检查的。这确保我们没有全局禁用。如果全局禁用,可能会导致错误。

17.

self 的循环引用

当使用代码块和异步分发的时候,要注意避免引用循环。 总是使用 weak 来引用对象,避免引用循环。(译者注:这里更为优雅的方式是采用影子变量@weakify/@strongify 这里有更为详细的说明) 此外,把持有 block 的属性设置为 nil (比如self.completionBlock = nil) 是一个好的实践。它会打破 block 捕获的作用域带来的引用循环。

例子:

__weak __typeof(self) weakSelf = self;

[self executeBlock:^(NSData *data, NSError *error) {

[weakSelf doSomethingWithData:data];

}];

不要这样:

[self executeBlock:^(NSData *data, NSError *error) {

[self doSomethingWithData:data];

}];

多个语句的例子:

__weak __typeof(self)weakSelf = self;

[self executeBlock:^(NSData *data, NSError *error) {

__strong __typeof(weakSelf) strongSelf = weakSelf;

if (strongSelf) {

[strongSelf doSomethingWithData:data];

[strongSelf doSomethingWithData:data];

}

}];

不要这样:

__weak __typeof(self)weakSelf = self;

[self executeBlock:^(NSData *data, NSError *error) {

[weakSelf doSomethingWithData:data];

[weakSelf doSomethingWithData:data];

}];

你可能感兴趣的:(《禅与Objective—C编程艺术》 阅读笔记)