草庐IT

objective-c - 链接完成 block

coder 2024-01-20 原文

我有两个不同类的实例,它们都需要向特定操作添加完成 block 。我将尝试笼统地解释问题,而不必解释我的应用试图执行的所有操作。

View Controller 正在调用资源管理器类的实例以保存资源。资源管理器然后调用要保存的资源的类以获得保存的网络操作。

资源的实例创建操作并为其提供一个完成 block ,该 block 将在它触发时影响资源的状态。

这就是我的问题所在 - 资源类还需要为此操作添加一个完成 block ,以便通知 View Controller 保存成功或失败。

这是管理器上保存方法的片段:

-(void)save:resource withCompletion:completion
{
.
.
.

NSOperation *operation = [resource operationForSave];

NSOperation __weak *weakOperation = operation;
void(^__weak resourceCompletion)(void)= operation.completionBlock;

[operation setCompletionBlock:^{
    if (resourceCompletion) {
        resourceCompletion();
        }

    if (completion) {
       if (weakOperation.error) {
            completion(NO, operation.error);
            }
        else {
            completion(YES, nil);
            }
        }
    }];

.
.
.
// add the operation to a network operation queue
}

虽然我认为这在技术上可行,但我并不热衷于此。感觉很时髦。我更愿意用一个 block 封装第二个 block ,但这是不可能的,因为 View Controller 和资源正在创建它们自己的完成 block ,而管理器类是必须将它们粉碎在一起的那个。

在这种情况下,是否有更优雅的方法将这两个完成 block 链接在一起,或者我目前创建一个 block 以包含原始两个 block 的方法是否是我将获得的最佳方法?

如有任何意见,我们将不胜感激。

最佳答案

您发布的代码可能 有效。当您将操作的完成 block 替换为您自己的 block 时,您可能会删除对原始完成 block (由资源设置)的唯一强引用。因此,您的 resourceCompletion 变量很弱,在 setCompletionBlock: 返回时将变为 nil。

只要使 resourceCompletion 强大就可以解决这个问题。但是,如果您想以更简洁的方式进行操作,请修改 operationForSave 消息(在资源上)以获取完成 block 本身:

__block NSNetworkOperation *operation = [resource operationForSaveWithCompletion:^{
    NSError *error = operation.error;
    completion(error == nil, error);

    // Break the retain cycle between this block and the operation object.
    operation = nil;
}];

并让资源自己的内部完成 block 调用您提供的完成 block 。

如果您不想或不能修改资源的 API,您仍然可以通过消除弱引用来简化代码:

__block NSNetworkOperation *operation = [resource operationForSave];
__block void (^priorCompletion)(void) = operation.completionBlock;
operation.completionBlock = ^{
    if (priorCompletion) {
        priorCompletion);
        // Break possible retain cycle.
        priorCompletion = nil;
    }

    NSError *error = operation.error;
    completion(error == nil, error);
    // Break the retain cycle between this block and the operation object.
    operation = nil;
};

此外,我真诚地希望您真的没有名为 NSNetworkOperation 的类,因为 Apple reserves the NS prefix (and all other two-letter prefixes) for its own use.

关于objective-c - 链接完成 block ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13830373/

有关objective-c - 链接完成 block的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby - RSpec - 使用测试替身作为 block 参数 - 2

    我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere

  3. ruby - 主要 :Object when running build from sublime 的未定义方法 `require_relative' - 2

    我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby​​1.9+ 关于ruby-主要:Objectwhenrun

  4. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  5. ruby-on-rails - Enumerator.new 如何处理已通过的 block ? - 2

    我在理解Enumerator.new方法的工作原理时遇到了一些困难。假设文档中的示例:fib=Enumerator.newdo|y|a=b=1loopdoy[1,1,2,3,5,8,13,21,34,55]循环中断条件在哪里,它如何知道循环应该迭代多少次(因为它没有任何明确的中断条件并且看起来像无限循环)? 最佳答案 Enumerator使用Fibers在内部。您的示例等效于:require'fiber'fiber=Fiber.newdoa=b=1loopdoFiber.yieldaa,b=b,a+bendend10.times.m

  6. ruby-on-rails - Ruby url 到 html 链接转换 - 2

    我正在使用Rails构建一个简单的聊天应用程序。当用户输入url时,我希望将其输出为html链接(即“url”)。我想知道在Ruby中是否有任何库或众所周知的方法可以做到这一点。如果没有,我有一些不错的正则表达式示例代码可以使用... 最佳答案 查看auto_linkRails提供的辅助方法。这会将所有URL和电子邮件地址变成可点击的链接(htmlanchor标记)。这是文档中的代码示例。auto_link("Gotohttp://www.rubyonrails.organdsayhellotodavid@loudthinking.

  7. ruby - 在匿名 block 中产生 - 2

    我没有理解以下行为(另请参阅inthisSOthread):defdef_testputs'def_test.in'yieldifblock_given?puts'def_test.out'enddef_testdoputs'def_testok'endblock_test=procdo|&block|puts'block_test.in'block.callifblockputs'block_test.out'endblock_test.calldoputs'block_test'endproc_test=procdoputs'proc_test.in'yieldifblock_gi

  8. ruby-on-rails - Prawn - 表格单元格内的链接 - 2

    我正在尝试用Prawn生成PDF。在我的PDF模板中,我有带单元格的表格。在其中一个单元格中,我有一个电子邮件地址:cell_email=pdf.make_cell(:content=>booking.user_email,:border_width=>0)我想让电子邮件链接到“mailto”链接。我知道我可以这样链接:pdf.formatted_text([{:text=>booking.user_email,:link=>"mailto:#{booking.user_email}"}])但是将这两行组合起来(将格式化文本作为内容)不起作用:cell_email=pdf.make_c

  9. ruby - Ruby 中的单 block AES 解密 - 2

    我需要尝试一些AES片段。我有一些密文c和一个keyk。密文已使用AES-CBC加密,并在前面加上IV。不存在填充,纯文本的长度是16的倍数。所以我这样做:aes=OpenSSL::Cipher::Cipher.new("AES-128-CCB")aes.decryptaes.key=kaes.iv=c[0..15]aes.update(c[16..63])+aes.final它工作得很好。现在我需要手动执行CBC模式,所以我需要单个block的“普通”AES解密。我正在尝试这个:aes=OpenSSL::Cipher::Cipher.new("AES-128-ECB")aes.dec

  10. objective-c - 在设置 Cocoa Pods 和安装 Ruby 更新时出错 - 2

    我正在尝试为我的iOS应用程序设置cocoapods但是当我执行命令时:sudogemupdate--system我收到错误消息:当前已安装最新版本。中止。当我进入cocoapods的下一步时:sudogeminstallcocoapods我在MacOS10.8.5上遇到错误:ERROR:Errorinstallingcocoapods:cocoapods-trunkrequiresRubyversion>=2.0.0.我在MacOS10.9.4上尝试了同样的操作,但出现错误:ERROR:Couldnotfindavalidgem'cocoapods'(>=0),hereiswhy:U

随机推荐