- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
当我在 GCD
的一个 block 中时,我总是使用 __weak
对 self
的引用。每个人都建议这样做。我知道在 GCD 中对 self
(tested) 的强引用不会产生保留周期。Apple 建议使用 __weak
对 self 的引用,然后使用 __strong
对 _week
的引用以保证 self
在 block 执行时不会是 nil
。
我有以下代码:
- (IBAction)startGCD:(id)sender {
GCDVC* __weak weakSelf = self;
[self.activityIndicator startAnimating];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ // 1
// VC2* __strong strongSelf = weakSelf;
[weakSelf.proArray addObject:@"2"];
[NSThread sleepForTimeInterval:10];
NSLog(@"%@",weakSelf.proArray);
dispatch_async(dispatch_get_main_queue(), ^{ // 2
[weakSelf.activityIndicator stopAnimating];
});
});
}
测试 1我按下按钮,指示器开始旋转。我在 GCD 完成之前按下后退按钮,GCDViewController 被释放。
测试 2然后我取消对 self 的强引用的注释并执行相同的过程。 GCDViewController 在 block 完成工作之前不会被释放。但后来发布了。
测试 3现在,如果我直接引用 self(没有 __weak
或 __strong
),我就会在测试 2 中得到准确的行为。
因此,如果我想确保在 block 执行时 self 不会为 nil,那么使用 __strong
引用到 __weak
引用的意义何在? 自己
?我在这里想念什么吗?是否有任何示例会改变测试 2 和 3 的结果?
最佳答案
I was always using __weak references to self when I was in a block in GCD. Everyone recommends that.
没有。我不知道有谁推荐这个。在某些存在循环保留的情况下,弱引用是有意义的。但是一个 block 是否应该捕获对任何对象(包括 self
指向的对象)的弱引用或强引用取决于相关代码的特定内存管理设计和
I know that strong reference to self (tested) in GCD can't produce retain cycles.
将 block 传递给全局或主队列上的 dispatch_async
永远不会产生保留周期。
Now if I refer directly to self (without __weak or __strong) I have the exact behaviour with Test 2.
在这种情况下,您可能看不出有什么不同。但它们通常有不同的行为。基本上,您的问题是捕获对 self
指向的对象的强引用或弱引用的 block 之间有什么区别。
不同之处在于,如果当前对象(self
指向的对象)已被所有其他对它拥有强引用的对象释放,除了可能的 block ,和 block 随后异步执行。
nil
,并且 block 不会对其进行任何操作(它要么检查 strongSelf
并在它看到时返回它是 nil
,否则它将向 strongSelf
发送消息,nil
什么都不做)。所以在一种情况下,事情已经完成,而在另一种情况下,什么都没做。
如果你的当前对象是一些 UI 元素,比如 View 或 View Controller ,那么只要它在 View 层次结构中,它就会被 View 层次结构中的事物保留,所以你需要退出此 View / View Controller ,以便出现没有其他任何东西对其有强引用的情况。
在您的情况下,您在 block 内所做的就是 [weakSelf.activityIndicator stopAnimating];
,即对 UI 的更改。这个命令是否运行并不重要,因为,记住,包含它的 View 已经停止显示了。没有人可以看到此事件指示器。那么停不停有什么区别呢?但这是特定于这种情况的。通常,您可以想象 block 内的命令会更改某些全局状态,或通过网络发送某些内容或其他内容,执行与否之间存在很大差异。
关于iOS - GCD 对 self 的弱引用和强引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38638904/
环境: Ubuntu 16.04 64 位 g++ 5.4.0 版 这是代码: #include ... auto g = std::gcd(10, 4); ... 我在编译命令中开启了-std=c
我正在尝试用 Python 编写欧几里得算法。它是找到两个非常大的数字的 GCD。公式是 a = bq + r 其中 a 和 b 是你的两个数,q 是 b 均分 a 的次数,r 是余数。 我可以编写代
我正在尝试创建一个处理非常大数字的 gcd 函数。因此,到目前为止我尝试过的任何事情都会导致错误。例如 : fun gcd(a : Int.toLarge, b : Int.toLarge): Int
我是 Haskell 的新手,实际上我才刚开始,我想对我将要问的问题有一点提示。 我目前正在尝试获取给定列表的 GCD。例如,列表 [3, 6, 9] 将返回 3。 目前,我想到了以下方法,我是否朝着
我有一段来自 API 黑暗时代的现有代码。它是一个基于 MPCreateTask 的线程。看起来我可以将其移至 GCG 队列,但有点复杂。当前有三个基于 MPCreateQueue 的队列用于三个优先
出于多种原因,我想让我的应用程序向后兼容 OS X 10.5。 到目前为止,我正在使用 10.6 中添加的大量 GCD 调度队列,如下所示: dispatch_async(dispatch_get_m
我有一个在一些设备上崩溃的 iOS 应用程序。鉴于发生这种情况时我在 iTunes 上看到的差评,崩溃似乎发生在代码中的同一点。 最后,一位好心人实际上联系了我,而不仅仅是留下评论,他们甚至为我安装了
我有一个定期运行的任务,它最初设计为使用 NSThread 和 NSTimer 在与主运行循环不同的单独运行循环上运行。 适应这一点以利用 GCD 的最佳方法是什么? 当前代码: -(void)ini
我想知道这两者之间的性能差异是什么。 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
我研究过 GCD 和线程安全。在苹果文档中,GCD 是线程安全的,即多线程可以访问。而且我了解了线程安全的含义,即每当多个线程访问某个对象时总是给出相同的结果。 我认为 Thread-Safe 和 G
我需要帮助来获取两个输入数字的 GCD。我不知道为什么它不会返回 GCD。例如,55 和 125 的 GCD 将为 5。任何帮助将不胜感激。它必须使用方法,而不是算法。 public static v
几天前我在编程挑战中遇到了这个问题。 在后端的 20 个测试用例中,我只得到了一个通过。这是我的解决方案 import java.util.Scanner; class TestClass {
我研究过 GCD 和线程安全。在苹果文档中,GCD 是线程安全的,即多线程可以访问。而且我了解了线程安全的含义,即每当多个线程访问某个对象时总是给出相同的结果。 我认为 Thread-Safe 和 G
我有一种方法可以帮助我将本地standardUserDefaults与Web服务同步。首先,我需要确保数据已成功同步,然后才能让该方法返回。我目前正在努力解决的问题是,我无法让GCD按特定顺序执行并完
我必须确保 3 个数字之间的 GCD 不大于 1。 这是我迄今为止该方法的代码: private int greatestCommonFactor(int a, int b, int c) {
我有两种在串行队列上运行的方法。每个方法都返回某个类的副本。我试图在保持数据完整性的同时实现线程安全解决方案。 例如: -(Users *) getAllUsers { __block
假设我们有一个 UIVewcontroller,叫它 A,在那个 VC 的 viewdidload 中我们添加两个 UIViewcontrollers(B,C)。现在为了使 A 的 Viewdidlo
我有几个任务被分派(dispatch)到串行队列,特别是一些被分派(dispatch)到组的任务。在调度这些任务后,我想给用户取消它们的选项,即使它们已经被执行。 我找不到任何方法来取消排队的任务,然
因此,我使用 dispatch_async 将 10 个任务放入并发队列中。它们不会阻塞下一个任务,并按顺序处理。我的 UI 具有响应能力。 for (int i = 0; i < 10; i++)
public static int divisor(int m, int n) { if (m == 0 || n == 0) { return m+n; } else
我是一名优秀的程序员,十分优秀!