TPWeakProxy 1.0.1

TPWeakProxy 1.0.1

测试已测试
语言语言 Obj-CObjective C
许可证 MIT
发布上次发布2014 年 12 月

Mark Ferlatte 维护.



  • 作者
  • Mark Ferlatte 和 Jen Leech

注意:此库已被 TPDWeakProxy 替换。此存储库将在 2015 年 9 月之后删除。

一个 NSProxy 对象,用于将强引用转换为弱引用。

使用方法

// Create a weak proxy to the object which you would like to be weakly referenced.
// For example, self.

TPWeakProxy *proxy = [[TPWeakProxy alloc] initWithObject:self];

// Now, you can use proxy anywhere you'd normally use self,
// except that self will have a weak reference to it where you use the proxy.

// As an example, NSTimer maintains a strong reference to its target. Sometimes
// this isn't what you want.

NSTimer *myWeakRefTimer = [NSTimer scheduledTimerWithTimeInterval:1.0
                                                           target:proxy
                                                         selector:@selector(myWeakRefTimerFired:)
                                                         userInfo:nil
                                                          repeats:NO];

安装

最简单的方式:使用 Cocoapods。否则,将 .h 和 .m 文件复制到您的项目中。

$ edit Podfile
platform :ios, '6.1'
pod 'TPWeakProxy', '~> 1.0.0'

$ pod install

$ open App.xcworkspace

动机

TPWeakProxy 解决了 Objective C 中对象引用循环的问题。当实例化的对象通过它的实例化对象保持对对象的强引用时,就会出现引用循环——使得第一个对象无法被回收,同时第二个对象继续存在。

这在相对常见的 iOS 模式中使用 NSTimers 的情况下可能是一个问题。

例如,假设您有一个 UIViewController,它想触发一个刷新事件。一个简单的做法

@interface

@property (strong, non-atomic) NSTimer *myTimer;

@end

@implementation

-(void)dealloc {
    [self.myTimer invalidate];
}

-(void)viewDidLoad {
    [super viewDidLoad];
    self.myTimer = [NSTimer scheduledTimerWithTimeInterval:30.0
                                                    target:self
                                                  selector:@selector(myTimerFired:)
                                                  userInfo:nil
                                                   repeats:NO];
 }

@end

这个问题在于:NSTimer 对 target: 有强引用,而目标通过 myTimer 属性对 NSTimer 有强引用。现在我们有一个引用循环,因此我们有一个内存泄漏。

我们可以通过一种相对容易的方式开始修复它;NSTimer 对它关联的 NSRunLoop 对象有强引用,因此创建它的 UIViewController 可以将其引用更改为弱引用

@property (weak, non-atomic) NSTimer *myTimer;

好的!现在我们不再有内存泄漏了,但我们仍然有一个问题。由于 NSTimer 对 UIViewController 有强引用,因此我们不会在实际释放视图控制器之前释放它,如果您的 NSTimer 在很久以后才激发,这至少浪费了资源,甚至可能引起微妙的错误。不幸的是,NSTimer API 在过去二十多年中基本没有改变;苹果不太可能很快提供具有对 target 有弱引用的 NSTimer。所以我们用 TPWeakProxy 如此修复它

-(void)viewDidLoad {
    [super viewDidLoad];
    TPWeakProxy *proxy = [[TPWeakProxy alloc] initWithObject:self];
    self.myTimer = [NSTimer scheduledTimerWithTimeInterval:30.0
                                                    target:proxy
                                                  selector:@selector(myTimerFired:)
                                                  userInfo:nil
                                                   repeats:NO];
 }

现在,NSTimer 不会阻止视图控制器在从堆栈中弹出时被销毁,销毁()现在会正确地使计时器失效。

许可证

TPWeakProxy 可在 MIT 许可证下使用。有关更多信息,请参阅 LICENSE 文件。