Skip to content

Commit 372393b

Browse files
committed
解答一些issue问题 ChenYilong#98 ChenYilong#6 ChenYilong#138
1 parent 3f64ae3 commit 372393b

File tree

2 files changed

+43
-12
lines changed

2 files changed

+43
-12
lines changed

01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(上).md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1145,7 +1145,11 @@ NSObject *foo = [[NSObject alloc] init];
11451145
11461146
参考博文: [***Fun With the Objective-C Runtime: Run Code at Deallocation of Any Object***](http://stackoverflow.com/a/31560217/3395008)
11471147
1148+
更多疑问, 可以参与issue讨论:
11481149
1150+
- [《第8题 感觉objc_storeWeak(&a, b)哪里理解有点问题 #98》]( https://github.com/ChenYilong/iOSInterviewQuestions/issues/98 )
1151+
- [《第8题 有一点说的很容易误导人 #6》]( https://github.com/ChenYilong/iOSInterviewQuestions/issues/6 )
1152+
-
11491153
### 9. @property中有哪些属性关键字?/ @property 后面可以有哪些修饰符?
11501154
属性可以拥有的特质分为四类:
11511155
@@ -1485,11 +1489,24 @@ NSMutableArray *mCopyArray = [array mutableCopy];
14851489
4 如果是 `@synthesize foo = _foo;` 就不会生成成员变量了.
14861490

14871491
假如 property 名为 foo,存在一个名为 `_foo` 的实例变量,那么还会自动合成新变量么?
1488-
不会。如下图:
1492+
1493+
<p><del>不会。如下图:</del></p>
1494+
1495+
与编译环境有关, 低版本不会, 高版本会
1496+
1497+
低版本:
14891498

14901499
![https://github.com/ChenYilong](http://i.imgur.com/t28ge4W.png)
14911500

14921501

1502+
而在 Xcode 12.5,如果存在一个名为 `_object` 实例变量,有个property名为`_object`,会合成新变量 `__object`
1503+
1504+
同时如果没有显示定义 `_objcect` 实例变量,定义属性 `_object` 也会生成 `__object` 实例变量
1505+
1506+
![](https://i.loli.net/2021/08/31/okeqdpgbRt1u74V.png)
1507+
1508+
1509+
14931510
### 15. 在有了自动合成属性实例变量之后,@synthesize还有哪些使用场景?
14941511

14951512
回答这个问题前,我们要搞清楚一个问题,什么情况下不会autosynthesis(自动合成)?

01《招聘一个靠谱的iOS》面试题参考答案/《招聘一个靠谱的iOS》面试题参考答案(下).md

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -626,14 +626,16 @@ ARC相对于MRC,不是在编译时添加retain/release/autorelease这么简单
626626
[《第33题,答案可能不是很准确 #15]( https://github.com/ChenYilong/iOSInterviewQuestions/issues/15 )
627627

628628
### 34. 不手动指定autoreleasepool的前提下,一个autorealese对象在什么时刻释放?(比如在一个vc的viewDidLoad中创建)
629+
630+
629631
分两种情况:手动干预释放时机、系统自动去释放。
630632

631633

632634
1. 手动干预释放时机--指定 `autoreleasepool`
633635
就是所谓的:当前作用域大括号结束时释放。
634636
2. 系统自动去释放--不手动指定 `autoreleasepool`
635637

636-
`__autoreleasing` 修饰的 `autorelease` 对象,是在创建好之后调用`objc_autorelease` 会被添加到最近一次创建的自动释放池中,并会在当前的 runloop 迭代结束时执行pop函数时释放
638+
`__autoreleasing` 修饰的 `autorelease` 对象,是在创建好之后调用`objc_autorelease` 会被添加到最近一次创建的自动释放池中,并且autorelease对象什么时候调用release,是由RunLoop来控制的:会在当前的 runloop 休眠之前,执行pop函数、调用 release 时释放
637639

638640
释放的时机总结起来,可以用下图来表示:
639641

@@ -648,26 +650,27 @@ ARC相对于MRC,不是在编译时添加retain/release/autorelease这么简单
648650

649651
我们都知道:
650652

651-
**所有 autorelease 的对象,在出了作用域之后,会被自动添加到最近创建的自动释放池中。**
653+
`__autoreleasing` 修饰的 `autorelease` 对象,是在创建好之后调用`objc_autorelease`加入到释放池。
652654

653655
但是如果每次都放进应用程序的 `main.m` 中的 autoreleasepool 中,迟早有被撑满的一刻。这个过程中必定有一个释放的动作。何时?
654656

655-
在一次完整的运行循环结束之前,会被销毁。
657+
在一次完整的 RunLoop 休眠之前,会被销毁。
656658

657-
那什么时间会创建自动释放池?运行循环检测到事件并启动后,就会创建自动释放池。
659+
那什么时间会创建自动释放池? RunLoop 检测到事件并启动后,就会创建自动释放池。
658660

659661
~~“子线程的 runloop 默认是不工作,无法主动创建,必须手动创建。”(表述不准确, 见 issue#82 #https://github.com/ChenYilong/iOSInterviewQuestions/issues/82)~~
660662

661-
`RunLoop` 源代码中可知,子线程默认是没有 `RunLoop` 的,如果需要在子线程开启 `RunLoop` ,则需要调用 `[NSRunLoop CurrentRunLoop]` 方法,它内部实现是先检查线程,如果发现是子线程,以懒加载的形式 创建一个子线程的 `RunLoop`。并存储在一个全局的 可变字典里。编程人员在调用 `[NSRunLoop CurrentRunLoop]` 时,是自动创建 `RunLoop` 的,而没法手动创建。
663+
`RunLoop` 源代码中可知,子线程默认是没有 `RunLoop` 的,如果需要在子线程开启 `RunLoop` ,则需要调用 `[NSRunLoop CurrentRunLoop]` 方法,它内部实现是先检查线程,如果发现是子线程,以懒加载的形式 创建一个子线程的 `RunLoop`。并存储在一个全局的 可变字典里。开发者在调用 `[NSRunLoop CurrentRunLoop]` 时,是系统自动创建 `RunLoop` 的,而没法手动创建。
662664

663665
自定义的 NSOperation 和 NSThread 需要手动创建自动释放池。比如: 自定义的 NSOperation 类中的 main 方法里就必须添加自动释放池。否则出了作用域后,自动释放对象会因为没有自动释放池去处理它,而造成内存泄露。
664666

665-
但对于 blockOperation 和 invocationOperation 这种默认的Operation ,系统已经帮我们封装好了,不需要手动创建自动释放池。
666-
667+
但对于 blockOperation 和 invocationOperation 这种默认的 Operation ,系统已经帮我们封装好了,不需要手动创建自动释放池。
667668

668669
@autoreleasepool 当自动释放池被销毁或者耗尽时,会向自动释放池中的所有对象发送 release 消息,释放自动释放池中的所有对象。
669670

670-
如果在一个vc的viewDidLoad中创建一个 Autorelease对象,那么该对象会在 viewDidAppear 方法执行前就被销毁了。
671+
举一个例子: 如果在一个vc的viewDidLoad中创建一个 Autorelease对象,那么该对象会在 viewDidAppear 方法执行前就被销毁了。
672+
673+
注意: 本次论述, 并不适用于 TaggedPointer 类型.
671674

672675
参考链接:[《黑幕背后的Autorelease》](http://blog.sunnyxx.com/2014/10/15/behind-autorelease/)
673676

@@ -1437,12 +1440,13 @@ int main(int argc, char * argv[]) {
14371440

14381441
情况二这里出现内存泄漏问题实际上是因为:
14391442

1440-
- `[NSNoficationCenter defaultCenter]` 持有了 `block`,
1443+
- `[NSNoficationCenter defaultCenter]` 持有了 `block`
14411444
- 这个 `block` 持有了 `self`;
14421445
-`[NSNoficationCenter defaultCenter]` 是一个单例,因此这个单例持有了 `self`, 从而导致 `self` 不被释放。
14431446

14441447
![https://github.com/ChenYilong](https://tva1.sinaimg.cn/large/007S8ZIlgy1gfcrlp0gn0j30z40lwag6.jpg)
14451448

1449+
这个结论可参考参考issue中讨论:[《第39题的一些疑问 #138](https://github.com/ChenYilong/iOSInterviewQuestions/issues/138)
14461450

14471451

14481452

@@ -1475,11 +1479,21 @@ addObserverForName:object:queue:usingBlock:]( https://developer.apple.com/docume
14751479
[[NSOperationQueue mainQueue] addOperationWithBlock:^{ self.someProperty = xyz; }];
14761480
```
14771481
1478-
这个因为 `[NSOperationQueue mainQueue]` 并非单例,所以并没有内存泄漏。
1482+
<p><del> 这个因为 `[NSOperationQueue mainQueue]` 并非单例,所以并没有内存泄漏。
14791483
见下图:
14801484
1481-
![https://github.com/ChenYilong](https://tva1.sinaimg.cn/large/007S8ZIlgy1gfct4s2979j30y00lq0y0.jpg)
1485+
https://tva1.sinaimg.cn/large/007S8ZIlgy1gfct4s2979j30y00lq0y0.jpg
1486+
(此图有问题, 请忽略, 请参考下文的正确描述)
14821487
1488+
</del></p>
1489+
1490+
在 Gnustep 源码中可以证实
1491+
`[NSOperationQueue mainQueue]` 是单例,然后参考 `addOperationWithBlock` 源码可知:
1492+
1493+
虽然是单例,但它并不持有 `block`,不会造成循环引用,传递完成后就销毁了,不会造成无法释放的内存泄漏问题。
1494+
1495+
参考issue中讨论:[《第39题的一些疑问 #138》](https://github.com/ChenYilong/iOSInterviewQuestions/issues/138)
1496+
14831497
-------------
14841498
14851499
针对情况四 `GCD` 的问题,实际上,self确实持有了queue; 而block也确实持有了self; 但是并没有证据或者文档表明这个queue一定会持有block; 而且即使queue持有了block, 在block执行完毕的时候,由于需要将任务从队列中移除,因此完全可以解除queue对block的持有关系,所以实际上这里也不存在循环引用。下面的测试代码可以验证这一点(其中`CYLUser`有一个属性name):

0 commit comments

Comments
 (0)