当前位置:   article > 正文

iOS第三方库的填坑记录_refreshuisubject rac 循环引用

refreshuisubject rac 循环引用

本文是本人平时开发遇到的三方库的填坑记录,仅做保存,如果有误导嫌疑,请无视我。

一、ReactiveCocoa

1、block是被控制器持有的,如果在block中使用self,会引起循环引用,控制器不能被释放掉,所以不是所有的三方库的block都是做了处理的。

block中,会引起循环引用有以下几种情况:

  1. //(1)在block中,使用self调用方法
  2. object.delegatrSignal = [RACSubject subject];
  3. [object.delegatrSignal subscribeNext:^(id x) {
  4. //使用self调用方法
  5. [self doSomething];
  6. }];
  7. //应使用weak修饰self,避免相互循环引用
  8. __weak typeof(self) weakSelf = self;
  9. object.delegatrSignal = [RACSubject subject];
  10. [object.delegatrSignal subscribeNext:^(id x) {
  11. //使用self调用方法
  12. [weakSelf doSomething];
  13. }];
  14. //(2)在block中,使用self的成员变量
  15. object.delegatrSignal = [RACSubject subject];
  16. [object.delegatrSignal subscribeNext:^(id x) {
  17. // 注:经过测试,在block中不通过self.property的方式调用,通过_property的方式调用,都会引起循环引用
  18. self.property;
  19. _property;
  20. }];
  21. //同样应使用weak修饰self,避免相互循环引用
  22. __weak typeof(self) weakSelf = self;
  23. object.delegatrSignal = [RACSubject subject];
  24. [object.delegatrSignal subscribeNext:^(id x) {
  25. weakSelf.property;
  26. }];
  27. //(3)在block中直接使用类的私有成员变量也会造成循环引用:
  28. //例如ViewController中有一个block类型的成员属性someBlock,另外一个是私有变量_children:
  29. @interface ViewController : UIViewController
  30. {
  31. NSObject *property;
  32. }
  33. @property (copy, nonatomic) void(^someBlock)();
  34. //其实在默认情况下,ViewController中的_children是使用__strong修饰的,上述情况就等价于下面的代码:
  35. @interface ViewController : UIViewController
  36. {
  37. __strong NSObject *property;
  38. }
  39. @property (copy, nonatomic) void(^someBlock)();
  40. //这个时候,在为someBlock赋值的时候,直接使用property就会造成retain cycle:
  41. self.someBlock = ^{
  42. property;
  43. // 上面代码就等价于下面一行
  44. // self->property;
  45. };
  46. //要打破此循环引用,也要用到(1)中使用的方法,不同的是,必须在block内使用__strong的self:
  47. __weak typeof(self) weakSelf = self;
  48. self.someBlock = ^{
  49. __strong typeof(weakSelf) strongSelf = weakSelf;
  50. strongSelf->property;
  51. };
  52. // __weakSelf在block里面有可能执行完一次被释放,所有要用__strong来确保在block内weakSelf不会被释放,但是此block内只有一句话,为什么要用__strong呢?因为用weakSelf->会引发这一种错误:Dereferencing a __weak pointer is not allowed due to possible null value caused by race condition, assign it to a strong variable first. (对一个 __weak 指针的解引用不允许的,因为可能在竞态条件里面变成 null, 所以先把他定义成 strong 的属性),所以必须用__strong来确保为强引用

注:

经过查阅资料,找到RAC下避免循环引用的方法:

  1. #import "RACEXTScope.h"
  2. - (void)viewDidLoad
  3. {
  4. [super viewDidLoad];
  5. @weakify(self);
  6. [[NSNotificationCenter defaultCenter] addObserverForName:@"key" object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) {
  7. @strongify(self);
  8. [self doSomething];
  9. // 如果使用到self的属性,不能用下划线_property,必须用self.property的方式
  10. }];
  11. }


二、支付宝SDK

1、调用支付宝SDK跳转方法中的回调block中,也容易导致retain cycle,在回调block中不能直接使用self调用方法,或者直接使用成员变量和私有变量,调用方法如下:

  1. [[AlipaySDK defaultService] payOrder:orderString fromScheme:appScheme callback:^(NSDictionary *resultDic) {
  2. }];

解决方法见上方ReactiveCocoa第一条。



2018.3.15更新

三、MJRefresh 刷新提示文本变为大写英文字母

在pod过的MJRefresh的项目中,Xcode9上,刷新提示文本变为大写英文字母,没有进行本地化处理。初步估计是本地化Localizable.strings文件在项目中没有成功加载。只有自己添加一遍来解决。

解决办法:

1、添加本地化文件 Localizable.strings,确保添加中英文。 添加方法

2、将一下文本复制在简体中文的文件中:

"MJRefreshHeaderIdleText" = "下拉可以刷新";

"MJRefreshHeaderPullingText" = "松开立即刷新";

"MJRefreshHeaderRefreshingText" = "正在刷新数据中...";


"MJRefreshAutoFooterIdleText" = "点击或上拉加载更多";

"MJRefreshAutoFooterRefreshingText" = "正在加载更多的数据...";

"MJRefreshAutoFooterNoMoreDataText" = "已经全部加载完毕";


"MJRefreshBackFooterIdleText" = "上拉可以加载更多";

"MJRefreshBackFooterPullingText" = "松开立即加载更多";

"MJRefreshBackFooterRefreshingText" = "正在加载更多的数据...";

"MJRefreshBackFooterNoMoreDataText" = "已经全部加载完毕";


"MJRefreshHeaderLastTimeText" = "最后更新:";

"MJRefreshHeaderDateTodayText" = "今天";

"MJRefreshHeaderNoneLastDateText" = "无记录";



。。。未完待续






声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/229242
推荐阅读
相关标签
  

闽ICP备14008679号