gpt4 book ai didi

ios - 在 Objective-C 中命名 block ?

转载 作者:可可西里 更新时间:2023-11-01 04:42:14 24 4
gpt4 key购买 nike

在 iOS 开发方面的建议并不少见:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// work in background
NSLog(@"%s work", __PRETTY_FUNCTION__);
dispatch_async(dispatch_get_main_queue(), ^{
// update UI on main queue
NSLog(@"%s updateUI", __PRETTY_FUNCTION__);
});
});

这很好,但是当出现问题时很难调试。查看输出:

AppName[1051:4013] __47-[Classname methodName]_block_invoke_0 work
AppName[1051:907] __block_global_0 updateUI

第一行日志有类名和方法名,所以我们有希望追踪到外部 block 中的问题(希望我们没有在该方法中定义很多 block ),但第二行日志(来自内 block )?祝你好运,尤其是如果你在你的应用中经常使用这种模式的话。

有没有办法给 block 命名,这将有助于我们在控制台输出和崩溃日志中识别它们的源位置?

最佳答案

block 一旦被复制,就成为 NSBlock 的实例,这意味着我们可以使用运行时向它添加各种美好的东西。这是一个例子:

@protocol QuietTheCompiler<NSObject>
- (NSString*) prettyBlockDescription;
@end

static id beautifyBlockDescription(id block, NSString *name)
{
static void *kAssocObjectPrettyBlockDescription = "A";
Class blockClass = [block class];

static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{

SEL descrSel = @selector(description);
SEL prettySel = @selector(prettyBlockDescription);
Method descrMethod = class_getInstanceMethod(blockClass, descrSel);
IMP originalImpl = class_getMethodImplementation(blockClass, descrSel);

IMP prettyImpl = imp_implementationWithBlock(^(id self_) {
id value = objc_getAssociatedObject(self_, kAssocObjectPrettyBlockDescription);
return (value != nil)? value : originalImpl(self_, descrSel);
});

if (class_addMethod(blockClass, prettySel, prettyImpl, method_getTypeEncoding(descrMethod))) {
IMP newImpl = imp_implementationWithBlock(^(id self_) {
return [self_ prettyBlockDescription];
});
class_replaceMethod(blockClass, descrSel, newImpl, method_getTypeEncoding(descrMethod));
}
});

NSString *description = [NSString stringWithFormat:@"<%@: %p name=%@>",NSStringFromClass(blockClass),block,name];
objc_setAssociatedObject(block, kAssocObjectPrettyBlockDescription, description, OBJC_ASSOCIATION_RETAIN);

return block;
}


int main (int argc, const char * argv[])
{
@autoreleasepool {

int (^block1)(int,NSString*) = ^(int i, NSString *fmt) {
return i;
};

id blockObject1 = beautifyBlockDescription([block1 copy], @"Hello");

int (^block2)(int,NSString*) = ^(int i, NSString *fmt) {
return i+1;
};

id blockObject2 = [block2 copy];

NSLog(@"Block 1: %@", blockObject1);
NSLog(@"Block 1: %@", blockObject2);
}
return 0;
}

这是这个程序的输出:

// Sample Output
2013-03-31 12:34:48.984 Dummy[1231:303] Block 1: <__NSGlobalBlock__: 0x1000059d0 name=Hello>
2013-03-31 12:34:48.987 Dummy[1231:303] Block 1: <__NSGlobalBlock__: 0x100005a10>

我建议您将 beautifyBlockDescription 函数包装在一个宏中,以便发布代码只返回 block 。

关于ios - 在 Objective-C 中命名 block ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14107480/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com