弱属性需要大量开销?

2024-01-08

在大约 100,000 次 setDelegate 调用后,我的 iOS 应用程序在 setDelegate 上停滞了大约 15 秒。 将委托属性从弱更改为分配可以解决该问题。知道为什么弱属性有如此多的开销并导致应用程序停止运行吗?

我怀疑弱引用被维护在一个数组中,这样运行时就可以循环它们,并在委托对象被释放时将指针设置为 nil。数组有最大大小吗?当 n 接近 100,000 时,摊位变得更长。

示例代码如下:

头文件:

#import <Foundation/Foundation.h>

@protocol GraphDataPointDelegate <NSObject>
- (BOOL)drawGraphByDistance;
@end

@interface GraphDataPoint : NSObject
- (id)initWithYValue:(NSNumber *)yValue withTime:(NSNumber *)time withDistance:(NSNumber *)distance withDelegate:(id <GraphDataPointDelegate> )delegate;
@end

@interface Graph : NSObject <GraphDataPointDelegate>
@end

M File

#import "Graph.h"

@interface GraphDataPoint ()

@property (nonatomic, weak, readwrite) id <GraphDataPointDelegate> delegate;
@property (nonatomic, strong, readwrite) NSNumber *yValue;
@property (nonatomic, strong, readwrite) NSNumber *time;
@property (nonatomic, strong, readwrite) NSNumber *distance;

@end

@implementation GraphDataPoint

- (id)initWithYValue:(NSNumber *)yValue withTime:(NSNumber *)time withDistance:(NSNumber *)distance withDelegate:(id<GraphDataPointDelegate>)delegate {
    self = [super init];
    if (self) {
        self.yValue = yValue;
        self.time = time;
        self.distance = distance;
        self.delegate = delegate;
    }
    return self;
}

- (id)graphXValue {
    if ([_delegate drawGraphByDistance]) {
        return _distance;
    } else {
        return _time;
    }
}

@end

@implementation Graph

- (id)init  {
    self = [super init];
    if (self) {

        NSMutableArray *array = [NSMutableArray array];
        NSLog(@"before");
        for (int i = 0; i < 100000; i++) {
            GraphDataPoint *graphData = [[GraphDataPoint alloc] initWithYValue:@1 withTime:@1 withDistance:@1 withDelegate:self];
            [array addObject:graphData];
        }
        NSLog(@"after");
    }
    return self;
}

- (BOOL)drawGraphByDistance {
    return YES;
}

@end

系统需要跟踪存储指向对象的弱指针的每个内存地址。为什么?因为如果要释放对象(其内存将被释放),所有这些指针必须设置为nil第一的。这就是弱指针的特殊之处:它们不保留对象(不让它们保持活动状态),但它们也永远不是悬空指针(永远不会指向以前的、现在已死的对象的内存地址);如果物体死亡,它们就会变成nil。因此,每当弱引用的值发生变化时,系统必须首先告诉全局弱指针跟踪管理器删除该内存地址过去记录的信息(如果有的话),然后在对象改变后记录新的信息。不用说,整个事情必须是线程安全的,因此涉及(稍微昂贵的)锁定。

__weak id x;
// ...
x = anObject;
// ...
x = anotherObject;
// ....
x = nil;

事实上(不是真的,只是为了让大家理解这个概念):

__weak id x;
// ...
[WeakPointerTrackingManager lock];
x = anObject;
[WeakPointerTrackingManager var:&x pointsTo:anObject];
[WeakPointerTrackingManager unlock];
// ...
[WeakPointerTrackingManager lock];
x = anotherObject;
[WeakPointerTrackingManager var:&x pointsTo:anotherObject];
[WeakPointerTrackingManager unlock];
// ...
[WeakPointerTrackingManager lock];
x = nil;
[WeakPointerTrackingManager deleteInfoForVar:&x];
[WeakPointerTrackingManager unlock];

assign没有做那样的事情。只是存储对对象的引用,而不增加对象保留计数器。然而,如果对象死亡,assign变量仍然指向对象所在的内存地址used为了活着。如果您现在向这个不存在的对象发送消息,您的应用程序可能会崩溃或可能发生其他未定义的事情。

但说实话,每个执行 100,000 次 setDelegate 调用的应用程序在设计上都被破坏了。我想不出任何有意义的严肃用例。在这里可能有更好的方法来完成您想做的任何事情。

仅供记录,访问弱变量也很昂贵。

__weak id x;
// ...
[x sendMessage];
// ...
__strong id y; // Strong is optional, 
               // vars are strong by default
y = x;

事实上(不是真的):

__weak id x;
// ...
__strong id tmp;
[WeakPointerTrackingManager lock];
tmp = [x retain];
[WeakPointerTrackingManager unlock];
[tmp sendMessage];
[tmp release];
// ...
__strong id y;
[WeakPointerTrackingManager lock];
y = [x retain];
[WeakPointerTrackingManager unlock];
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

弱属性需要大量开销? 的相关文章

随机推荐

  • AJAX 请求在大型查询字符串上中止 Elixir Plug

    我在 AJAX 请求中发送 2 个大查询字符串 它们基本上是 jpeg 的 Base64 编码 当相机不是高分辨率相机时 AJAX 请求不会中止 起初 我认为这是 Nginx 的问题 因为我收到错误如下request entity too
  • 领域 NoClassDefFoundError:rx.Observable

    我遇到了 Realm 文档中指出的问题 杰克逊数据绑定 Jackson Databind 是一个用于将 JSON 数据绑定到 Java 类的库 Jackson 使用反射来执行数据绑定 这冲突了 Realm 对 RxJava 的支持 因为 R
  • 奥利奥后台位置更新

    我发现自己对新的背景限制感到困惑 我只是在这里寻求一些清晰度 当应用程序位于前台或在后台运行前台服务时 后台服务就可以正常运行 我懂了 当应用程序在后台且没有前台服务时 后台服务将被系统停止 我对此也很满意 我的问题 该应用程序每小时仍可以
  • 当我进行编程配对时,如何避免或忽略 Android 的蓝牙配对通知?

    我有一个应用程序 可以通过编程方式控制蓝牙配对和取消配对 我可以在连接前配对并在连接后取消配对 我需要这样做的原因是特定于我的应用程序的 而不是在我的问题范围内 基本上我正在做的是 获取参考ib to IBluetooth中描述的对象这个答
  • Makefile 和 $$ 的使用

    所以我有一个 Makefile 其中包含我尝试理解的以下代码 for file exe in find name zip exe do file exe d UNZIP PATH lib done 据我了解 这段代码将尝试找到一些可执行的
  • 删除 Jumbotron Bootstrap 3 中的填充?

    如何从 jumbotron bootstrap 3 中删除默认填充 我正在尝试设置padding top 5px 在大屏幕分区 但是有一些默认的填充 如何删除它 问题是 CSS 选择器对大屏幕的特异性会大于您正在应用的选择器 您可以阅读有关
  • Rails:忽略传递给 create() 的不存在的属性

    我有以下 Rails 模型 class CreateFoo lt ActiveRecord Migration def self up create table foo do t t string a t string b t string
  • 在 x 轴上绘制时间序列时,对 ggplot 中的一个方面使用 annotate("rect")

    我正在各个方面绘制不同的时间序列 并且我想使用 annotate 仅为其中一个方面创建不同的背景颜色 一个方面代表 2018 年的最后 15 周 第 38 52 周 而另一个方面代表 2019 年的前 15 周 第 1 15 周 我只想更改
  • while 循环中的异步函数

    我有一个关于如何在 while 循环中执行异步任务直到满足某些条件的问题 这更多的是一个理论问题 但我可以看到在某些情况下这可能是一个问题 我将尝试通过示例演示该问题 我在这里使用 JavaScript 但您可以使用任何语言 我可以拥有一个
  • 调试断言失败!表达式:_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

    我知道这个问题在这些论坛上被评估过很多次 但大多数时候它们对于特定案例来说确实是独一无二的 这是一个班级项目 C 也不例外 该项目的重点是重新制作经典棋盘游戏黑白棋 我花了几个小时辛苦地编写代码 终于编写了一个可以运行的程序 至少我是这么想
  • C#:抛出自定义异常最佳实践

    我已经阅读了一些有关 C 异常处理实践的其他问题 但似乎没有人问我在寻找什么 如果我为特定类或一组类实现自己的自定义异常 是否应该使用内部异常将与这些类相关的所有错误封装到我的异常中 还是应该让它们失败 我想最好捕获所有异常 以便可以立即从
  • 如何查询SPARQL中的所有直接子类?

    I have A B and C作为通过传递属性相关的类isSubClassOf So A isSuclassOF B and B isSubClassOf C 所以通过推断我们有A isSubClassOf C 我的问题 如何编写 SPA
  • 是否允许在 iPhone 应用商店应用程序中包含 libCurl?有人做过这个吗?

    我想在应用程序中使用 libCurl 来与 Web 服务通信 不幸的是它没有包含在 iPhone SDK 中 现在我已经弄清楚如何将 Curl 作为静态库包含在我的应用程序中 但是 我想知道这是否会让我的应用程序被 Apple 拒绝 有没有
  • 如何防止 Phonegap 应用程序切换到横向视图

    这应该很简单 但事实并非如此 我试图阻止我的应用程序进入横向视图 所以我改变了config xml像这样的文件
  • Jquery 自动完成与 Jade/Pug

    我需要这个案例的帮助 即将在 Jade Pug 中实现 Jquery 自动完成 尽管现在显示错误 但自动完成的结果不会显示在表单中 Actual 没有错误 但输入时的数据未按预期显示 Expect 当我输入时 数据以 combine 形式显
  • Spring JUnit4 手动/自动装配困境

    我遇到了一个问题 这个问题只能用我对 Spring 的 IoC 容器设施和上下文设置的根本缺乏理解来解释 所以我想要求对此进行澄清 仅供参考 我维护的一个应用程序具有以下技术堆栈 Java 1 6 春季2 5 6 RichFaces 3 3
  • 如何在 Yii2 中手动在数据库中创建用户?

    我将用户从 csv 文件导入到数据库中 在 csv 文件中 我有一些用户名和密码字符串 那么如何手动创建新用户呢 据我了解我需要getPasswordHash and generateAuthKey 最后一个生成随机字符串 但可能我丢失了一
  • 如何将.fs文件编译为.exe?

    我没有找到将简单文件 fs 编译为 exe 的方法 我尝试了这个例子 但它不起作用 在文件 dolphin fs 中 let longBeaked Delphinus capensis let shortBeaked Delphinus d
  • XHTML 网站抓取指南

    我对 VBA 和 HTML XHTML 非常陌生 但是通过在线研究和这里其他优秀成员的帮助 我已经成功编写了一段代码来提取我想要的数据 我很难识别我想要的元素的 ID 因为它是 XHTML 格式的 所以我认为这是我搞砸的地方 网站 这是我想
  • 弱属性需要大量开销?

    在大约 100 000 次 setDelegate 调用后 我的 iOS 应用程序在 setDelegate 上停滞了大约 15 秒 将委托属性从弱更改为分配可以解决该问题 知道为什么弱属性有如此多的开销并导致应用程序停止运行吗 我怀疑弱引