所有源文件中的前缀标题除了一个?

时间:2013-10-20 18:16:46

标签: objective-c c xcode grand-central-dispatch precompiled-headers

是否可以使用 AppName -Prefix.pch文件导入除一个以外的所有源文件中的给定头文件?

问题: 我遵循了这里描述的方法:https://stackoverflow.com/a/617559/1062572来覆盖C函数调用,即GCD dispatch_async函数。

现在我需要在所有源文件中导入头文件intercept.h,为此我尝试使用 AppName -Prefix.pch文件。但是,这也会在我的实现文件intercept.m中导入头文件。这导致无限的调用循环,因为我尝试在那里调用原始的dispatch_async

继承我的头文件intercept.h

#ifdef INTERCEPT
#define dispatch_async(queue, block) my_dispatch_async(queue, block)
#endif

而heres是我的实施文件intercept.m

void my_dispatch_async(dispatch_queue_t queue, dispatch_block_t block) {
NSLog(@"\nBlock is enqueued!\n");
dispatch_async(queue, ^{
    NSLog(@"\nBlock is dequeued!\n");
    block();
    NSLog(@"\nBlock has executed!\n");
});
}

这是我的Prefix.pch文件:

#ifdef INTERCEPT
#import "Intercept.h"
#endif

如何在所有源代码中导入头文件,实现文件是唯一的例外?我希望无需手动在每个源文件中插入import语句即可完成。 并且没有编写脚本来执行此操作。 ;)

让我更加困惑的一件事是:实际上我在编译库(Testing.a)中有实现文件,为什么导入头文件?

更多信息:  我正在编写一个测试框架,等待所有异步任务完成后再检查结果。这就是为什么我重写dispatch_async。欢迎任何其他建议。 :)

我也注意到了这个答案:https://stackoverflow.com/a/617606/1062572然而,这似乎不适用于OSX,因此iOS不是我的目标。

所有这些方法只会覆盖我自己的源代码中的函数调用。实际上我希望它到处覆盖它。但是对于这个问题,我很满意它是否适用于我自己的源代码。

2 个答案:

答案 0 :(得分:1)

不幸的是,它不可能。在编译期间,前缀头被编译,缓存并包含在每个文件中。您无法分辨哪些文件会被忽略。 但是,如果已经包含Intercept.h,则可以忽略它。方法如下:

1-从Prefix.pch中移除#import "Intercept.h"周围的ifdef INTERCEPT条件。你不需要它。

2-将您的Intercept.h更新为:

#ifndef INTERCEPT_H
#define INTERCEPT_H
#define dispatch_async(queue, block) my_dispatch_async(queue, block)
#endif

这里发生的是你首先检查INTERCEPT_H是否已经包含/定义在当前定义中,如果没有,你在下一行中定义它然后定义你的宏。 现在, #ifndef INTERCEPT_H 条件如果已将其内容包含在同一上下文中,则返回false。

希望它有所帮助。

答案 1 :(得分:1)

  

更多信息:我正在编写一个测试框架,等待所有异步任务完成后再检查结果。这就是为什么我重写dispatch_async。欢迎任何其他建议。 :)

根据您的情况,这可能会以更好的方式解决。只要您可以访问使用哪些队列,就会非常简单。考虑这个API,您要传递要使用的队列:

[object doSomethingAsyncWithCompletion:block1 queue:myQueue];
[object doSomethingElseAsyncWithCompletion:block2 queue:myQueue];
[object doMoreAsyncWithCompletion:block3 queue:myQueue];

现在,你要等到所有这些结束。假设这是一个自定义并发队列(不是全局队列之一),只需使用一个屏障:

dispatch_barrier_sync(myQueue, ^{
  NSLog(@"This will not run until everything else before it on the queue finishes.");
}

但是如果你不知道正在使用什么队列怎么办?好吧,只要你控制完成块,那也没关系。 (见Waiting on Groups of Queued Tasks。)

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();

dispatch_block_t doneBlock = ^{
  dispatch_group_leave(group);
}

dispatch_group_enter(group);
[object doSomethingAsyncWithCompletion:doneBlock queue:myQueue];
dispatch_group_enter(group);
[object doSomethingElseAsyncWithCompletion:doneBlock queue:myQueue];
dispatch_group_enter(group);
[object doMoreAsyncWithCompletion:doneBlock queue:myQueue];

// Wait for all the doneBlocks to fire
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
dispatch_release(group);

当然你也可以这样做with a semaphore。如果您只想将单个操作从异步转换为同步,那么这有时会更容易。

我建议使用这些方法而不是试图劫持dispatch_async本身。