奇怪的“僵尸”中的forwardInspiration:+ getArgument:atIndex方法

2024-01-05

这是我的代码的一部分:

- (void)viewDidLoad
{
    [super viewDidLoad];

    CGRect frame = [[UIScreen mainScreen] bounds];
    _webView = [[UIWebView alloc] initWithFrame:frame];
    [_webView setHidden:NO];
    [self.view addSubview:_webView];

    _vk = [[DPVkontakteCommunicator alloc] initWithWebView:_webView];

    DPVkontakteUserAccount *user;
    NSString *accessToken = [[NSUserDefaults standardUserDefaults]
                                             objectForKey:@"accessToken"];
    NSInteger userId = [[[NSUserDefaults standardUserDefaults]
                                         objectForKey:@"userId"] integerValue];
    user = [[DPVkontakteUserAccount alloc]
                                    initUserAccountWithAccessToken:accessToken
                                                            userId:userId];

    NSLog(@"%@", user);

    [user setSuccessBlock:^(NSDictionary *dictionary)
    {
        NSLog(@"%@", dictionary);
    }];

    NSDictionary *options = @{@"uid":@"1"};
    //    [user usersGetWithCustomOptions:@{@"uid":@"1"}]; // Zombie
    [user usersGetWithCustomOptions:options]; // Not zombie

    //    __block NSDictionary *options = @{};
    //
    //    [_vk startOnCancelBlock:^{
    //        NSLog(@"Cancel");
    //    } onErrorBlock:^(NSError *error) {
    //        NSLog(@"Error: %@", error);
    //    } onSuccessBlock:^(DPVkontakteUserAccount *account) {
    //        NSLog(@"account:%@", account);
    //
    //        [account setSuccessBlock:^(NSDictionary *dictionary)
    //        {
    //            NSLog(@"%@", dictionary);
    //        }];
    //
    //        [account docsGetUploadServerWithCustomOptions:options];
    //    }];
}

这是处理 userGetWithCustomOptions: 方法的部分:

- (void)forwardInvocation:(NSInvocation *)anInvocation
{
    NSString *methodName = NSStringFromSelector([anInvocation selector]);
    NSDictionary *options;

    [anInvocation getArgument:&options
                      atIndex:2];

    NSArray *parts = [self parseMethodName:methodName];
    NSString *vkURLMethodSignature = [NSString stringWithFormat:@"%@%@.%@",
                                                                kVKONTAKTE_API_URL,
                                                                parts[0],
                                                                parts[1]];
    // appending params to URL
    NSMutableString *fullRequestURL = [vkURLMethodSignature mutableCopy];

    [fullRequestURL appendString:@"?"];

    [options enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop)
    {
        [fullRequestURL appendFormat:@"%@=%@&", key, [obj encodeURL]];
    }];

    [fullRequestURL appendFormat:@"access_token=%@", _accessToken];

    // performing HTTP GET request to vkURLMethodSignature URL
    NSURL *url = [NSURL URLWithString:fullRequestURL];
    NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
    AFJSONRequestOperation *operation;
    operation = [AFJSONRequestOperation
            JSONRequestOperationWithRequest:urlRequest
                                    success:^(NSURLRequest *request,
                                              NSHTTPURLResponse *response,
                                              id JSON)
                                    {
                                        _successBlock(JSON);
                                    }
                                    failure:^(NSURLRequest *request,
                                              NSHTTPURLResponse *response,
                                              NSError *error,
                                              id JSON)
                                    {
                                        _errorBlock(error);
                                    }];

    [operation start];
}

问题是,当我使用“选项”变量时 - 它工作正常,但是当使用直接值时 - 它失败,应用程序崩溃。使用配置文件我发现方法调用定向到已释放的对象。

为什么会出现这种情况? 没有其他代码可以提供帮助。

ViewController.m代码:https://gist.github.com/AndrewShmig/5398546 https://gist.github.com/AndrewShmig/5398546

DPVkontakteUserAccount.m:https://gist.github.com/AndrewShmig/5398557 https://gist.github.com/AndrewShmig/5398557


问题是参数getArgument:是类型void *。而你正在路过&value,即NSDictionary * __strong *(指向强引用的指针)它。强制转换是有效的,因为可以将任何非对象指针分配给或从void *没有任何警告。

当您将“指向强的指针”传递给函数时,这意味着该函数应该期望该指针指向“强引用”,并且当该函数退出时,它应该保留该指针指向“强引用”的事实。这意味着如果函数更改了引用(指针指向的),它必须首先释放以前的值,然后保留新值。

然而,什么是getArgument:atIndex:与其做void *争论?它与所指向的事物无关,只是将值复制到所指向的内存中。因此,它不执行任何保留和释放操作。基本上,它执行一个普通的 ARC 前非保留分配到您的value多变的。

那么为什么会崩溃呢?正在发生的事情是value起初是nil,然后在里面getArgument:atIndex:,它将新值分配给它,但不保留它。然而,ARC 假设它已被保留,因为value是一个强有力的参考。因此,在作用域结束时,ARC 会释放它。这是过度释放,因为它从未被保留。

解决方案是不要将“指向强的指针”传递给getArgument:,因为该方法对“强”一无所知。相反,将“指向 __unsafe_unretained 的指针”或“指向 void 的指针”传递给它,然后将其转换为强引用:

NSDictionary * __unsafe_unretained temp;
[anInvocation getArgument:&temp atIndex:2];
NSDictionary *options = temp; // or you can just use temp directly if careful

或者:

void *temp;
[anInvocation getArgument:&temp atIndex:2];
NSDictionary *options = (__bridge NSDictionary *)temp;
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

奇怪的“僵尸”中的forwardInspiration:+ getArgument:atIndex方法 的相关文章

随机推荐

  • 使用 HttpURLConnection 发送 UTF-8 字符串

    到目前为止 我已经使用以下代码片段来发送和接收 JSON 字符串 static private String sendJson String json String url HttpClient httpClient new Default
  • 未捕获错误:ReCAPTCHA 占位符元素必须是元素或 id

    我正在将 ReCAPTCHA 添加到具有多个联系表单的 Bootstrap Jekyll 网站 页脚中有一个弹出模式 偶尔有一个 立即联系我们 部分 还有几个页面上有一个 请求有关 的更多信息 由于我在一个页面上有多个联系表单 因此我需要显
  • 将 Python 最小化到系统托盘并生成通知? [复制]

    这个问题在这里已经有答案了 我环顾四周 但找不到任何可以接近做我想做的事的东西 我想让我的 Python 脚本作为最小化的系统托盘应用程序启动 或者能够最小化到系统托盘 并且能够发出系统托盘通知 有人有任何想法 库或示例吗 谢谢 海福莱克斯
  • 从 Swift 中的 Eureka Forms 获取值

    我是 Swift 编程新手 我正在尝试使用 Eureka 库创建一个表单 该表格已经可以使用 但我无法从表格中获取数据 我试图将数据一一存储到全局变量中 以便在按下按钮时打印 问题是代码总是被破坏 我不知道如何纠正它 这是我的代码 impo
  • 如何在没有支持表的情况下在 Rails 中创建只读模型

    我想创建只读模型 这可能是一些复杂的结果 与任何直接表模型类关系不大的联接或聚合查询 我已经定义了 例如想象中的 ActiveRecord View 类 class B lt ActiveRecord View default scope
  • 用Java编写一个mode方法来查找数组中出现次数最多的元素

    问题是 编写一个名为 mode 的方法 该方法返回整数数组中最常出现的元素 假设数组至少有一个元素 并且数组中的每个元素的值都在 0 到 100 之间 含 0 和 100 通过选择较低的值来打破平局 例如 如果传递的数组包含值 27 15
  • 使用mysql递归调用存储过程

    enter image description here https i stack imgur com h5aNM pngget legside from binary https i stack imgur com sJvWh png
  • TextAreaFor 无法设置宽度

    我无法设置文本区域中的列宽度 行 高度效果很好 有人可以帮忙吗谢谢 using Html BeginForm Html AntiForgeryToken Html ValidationSummary true Html TextAreaFo
  • 如何在Powershell中输出多个哈希表

    我有一个键 值对哈希表的哈希表 来自 ini 文件 它看起来像这样 Name Value global Variables
  • TableModel 火灾方法如果不可见则昂贵

    在java swing表模型中 我们能够触发表更改 添加 删除等 我想知道如果组件不可见 这些方法调用是否会很昂贵 例如 另一扇窗户覆盖着它 或者它位于非活动选项卡中 为了最大限度地减少触发大量更新事件的影响 JTable 渲染 http
  • 如何在 ContainerRequestFilter 中检索请求的匹配资源

    我正在使用 JAX RS Jersey 开发 Web 服务 我已经设置了一个容器请求过滤器其目的是验证用户身份 我只需要通过身份验证保护某些路径 其余的路径可供所有人使用 我想通过 ContainerRequestFilter 中的 Ext
  • Dancer 与 Catalyst [Perl Web 框架] [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 在 C++ 中声明可变长度二维数组的正确方法

    我想要一个二维 int 数组arr我可以通过 arr i j 访问 据我了解我可以声明int arr 10 15 得到这样一个数组 然而 就我而言 大小是可变的 据我了解 如果数组的大小没有硬编码 则此语法不起作用 但我使用像这样的变量in
  • Lua加载文件找不到文件

    我有一些带有以下行的 lua 代码 JSON loadfile JSON lua 文件 JSON lua 与该行来自的 lua 代码位于同一目录中 这段代码对我有用了一段时间 然后 在我不更改 lua 源 JSON lua 任何文件的权限或
  • WPF 单击 ListBoxItem 内的控件不会选择 ListBoxItem

    您好 我找不到任何类似的问题 所以我发布了新问题 在下面的代码中 我使用 ListBoxItems 创建 ListBox 控件 每个 ListBoxItems 内部都包含单选按钮 当我单击单选按钮时 它会进行选择 但父 ListBoxIte
  • 访问本地隐藏的全局变量[重复]

    这个问题在这里已经有答案了 可能的重复 如何在 C 中访问隐藏的全局变量 https stackoverflow com questions 618769 how can i access a shadowed global variabl
  • git fork repo 到同一组织

    如何将我的组织中的存储库分叉到same组织 以便我可以定期将前叉与upstream存储库 在这个 StackOverflow 问题中将 github 上的 git 存储库复制 分叉到同一组织中 https stackoverflow com
  • 在Python中从二进制文件中读取整数

    我正在尝试阅读BMP http en wikipedia org wiki BMP file formatPython 中的文件 我知道前两个字节 表示 BMP 公司 接下来的 4 个字节是文件大小 当我执行时 fin open hi bm
  • pandas 使用 fill_method 重新采样:需要知道从哪一行复制数据?

    我正在尝试使用重新采样方法来填补时间序列数据中的空白 但我也想知道哪一行被用来填充丢失的数据 这是我的输入系列 In 28 data Out 28 Date 2002 09 09 233 25 2002 09 11 233 05 2002
  • 奇怪的“僵尸”中的forwardInspiration:+ getArgument:atIndex方法

    这是我的代码的一部分 void viewDidLoad super viewDidLoad CGRect frame UIScreen mainScreen bounds webView UIWebView alloc initWithFr