Prefix Header in all source files except one? - objective-c

Is it possible to use the AppName-Prefix.pch file to import a given header file in all source files except one?
Problem:
I have followed the approach described here: https://stackoverflow.com/a/617559/1062572 to overwrite a C function call, namely the GCD dispatch_async function.
Now I need to import the header file intercept.h in all my source files and for that I tried to use the AppName-Prefix.pch file. However this also imports the header file in my implementation file intercept.m. This cause an endless call loop because I try to call the original dispatch_async in there.
Heres my header file intercept.h:
#ifdef INTERCEPT
#define dispatch_async(queue, block) my_dispatch_async(queue, block)
#endif
And heres is my implementation file 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");
});
}
Here is my Prefix.pch file:
#ifdef INTERCEPT
#import "Intercept.h"
#endif
How can I import the header file in all my sources, with the implementation file as the only exception? I hope it can be done without manually having to insert an import statement in every source file. And without writing a script to do it. ;)
One thing that confuses me even more is: Actually I have the implementation file in a compiled library (Testing.a), so why is the header file imported in it?
Even more information:
I am writing a test framework that waits until all async tasks has completed before checking the results. That why I override dispatch_async. Any other suggestion is welcome. :)
Also I have noticed this answer: https://stackoverflow.com/a/617606/1062572 However it seems that this will not work on OSX, hence not iOS which is my target.
All these approaches will only overwrite the function call in my own source code. Actually I want it to overwrite it everywhere. However for this question I am satisfied if it works for my own source code.

Unfortunately, its not possible. Prefix headers are compiled, cached and included in every file during compilation. You can't tell which files to ignore.
However you can ignore it if you already included the Intercept.h. Here's how:
1- Remove ifdef INTERCEPT condition around #import "Intercept.h" from Prefix.pch. You don't need it there.
2- Update your Intercept.h to:
#ifndef INTERCEPT_H
#define INTERCEPT_H
#define dispatch_async(queue, block) my_dispatch_async(queue, block)
#endif
What happens here is that you first checked whether INTERCEPT_H is already included/defined in current definition, if not, you defined it in the next line and then defined your macro.
Now, the #ifndef INTERCEPT_H condition will return false if it has already included its content in the same context.
Hope it helps.

Even more information: I am writing a test framework that waits until all async tasks has completed before checking the results. That why I override dispatch_async. Any other suggestion is welcome. :)
Depending on your situation, this is likely solvable in better ways. As long as you have access to which queues are being used, it's pretty simple. Consider this API, where you are passing the queue to be used:
[object doSomethingAsyncWithCompletion:block1 queue:myQueue];
[object doSomethingElseAsyncWithCompletion:block2 queue:myQueue];
[object doMoreAsyncWithCompletion:block3 queue:myQueue];
Now, you want to wait until all those finish. Assuming this is a custom concurrent queue (not one of the global queues), just use a barrier:
dispatch_barrier_sync(myQueue, ^{
NSLog(#"This will not run until everything else before it on the queue finishes.");
}
But what if you don't know what queue is being used? Well, as long as you control the completion blocks, that's fine, too. (See 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);
Of course you could also do this with a semaphore. That's sometimes easier if you just want to convert a single operation from asynchronous to synchronous.
I'd recommend these kinds of approaches rather than trying to hijack dispatch_async itself.

Related

dispatch_async(dispatch_get_main_queue() is not working [duplicate]

This question already has an answer here:
Async request does not enter completion block
(1 answer)
Closed 3 years ago.
i am new to Objective C, i have one question regarding dispatch. Does anyone know why the block added to the queue is not run?
int main(int argc, const char * argv[]) {
#autoreleasepool {
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(#"hello world");
});
};
return 0;
}
Your program is exiting before the asynchronously dispatched block had a chance to execute. This code is basically saying “dispatch this log statement to run when the main thread for this program is free”, but is also effectively saying “dispatch that block of code run asynchronously (i.e. later) but then immediately exit”. As you can imagine, it’s just exiting before it gets around to being able to execute that dispatched block.
This pattern of dispatching code to run asynchronously makes most sense when you’re writing a full-fledged “app” (with UI where the user can do stuff and quit the app at a time of their choosing), rather than a “command line tool”. If you do this in an app, you will see your NSLog statement. So, when creating your test project, create an “app” rather than a “command line tool”. Then you’ll see your log statement fine.
This notion of dispatching code to run asynchronously (esp when you dispatch that to the main queue) doesn’t quite make sense for most command line tools. Theoretically you could create your own “run loop” to keep the command line tool alive until your dispatched block has a chance to run, but that’s not a very common pattern. Most command line tools just do something and then exit, and don’t have asynchronous blocks running.
If there’s some reason you feel like you really want to do this in a command line app, please edit your question to describe your scenario in greater detail. If you are just experimenting with GCD, it’s just simpler to do this with an “app” rather than a “command line tool”.

Long delay with NSFileCoordinator coordinateWritingItemAtURL

I'm setting up NSFileCoordinator and NSFilePresenter in my app so I can do file IO from my AppleWatch app safely. There are some places in my code where I write to a file a couple of times in quick succession. This is a problem in and of itself and I'm working to correct it, but I'm noticing some weird behavior in the process.
I wrap my writes like this:
//In a class that implements NSFilePresenter:
NSFileCoordinator *coord = [[NSFileCoordinator alloc]initWithFilePresenter:self];
[coord coordinateWritingItemAtURL:self.presentedItemUrl options:0 error:nil byAccessor:^(NSURL *url)
{
//do my writing here using CFWriteStreamRef or NSOutputStream
}];
On the first write, the write block happens within 1 ms. But after that, there's about a 0.5 second delay between calling coordinateWritingItemAtURL and the write block being executed.
Is this expected behavior?
Some of the documentation for NSFileCoordinator and NSFilePresenter says to use prepareForReadingItemsAtURLs:writingItemsAtURLs:options:error:byAccessor: for batch operations, but it seems weird to get such a long delay when I don't batch.
Update: This happens with reading too.
Update 2: Here is an example project reproducing the problem.
Update 3: Using this API for coordination between an app and its extension is apparently a bad idea. But the question still stands.
Referring to File System Programming Guide , you can read following:
you might want to avoid incorporating changes directly from your file
presenter method. Instead, dispatch a block asynchronously to a
dispatch queue and process the changes at a later time. This lets you
process the changes at your app’s convenience without causing
unnecessary delays to the file coordinator that initiated the change.
Of course, when saving or relinquishing control of a file (such as in
the relinquishPresentedItemToReader:,
relinquishPresentedItemToWriter:, or
savePresentedItemChangesWithCompletionHandler: methods) you should
perform all necessary actions immediately and not defer them.
I think this is your case where you are defering actions.
Possible Solution:
Please read this well , to properly handle multiple successive writing operations , the relinquishPresentedItemToWriter , can do the job , same will work with reading file , relinquishPresentedItemToReader , supposing that multiple different objects are trying to read and write the same file.
P.S :
I dont know what your app does exactly , but i hope you have read this :
If you are implementing a document-based app, you do not need to
incorporate file presenter semantics into your NSDocument subclasses.
The NSDocument class already conforms to the NSFilePresenter protocol
and implements the appropriate methods. Thus, all of your documents
automatically register themselves as presenters of their corresponding
file and do things like save changes and track changes to the
document.
Is it possible to use options NSFileCoordinatorReadingImmediatelyAvailableMetadataOnly for reading and NSFileCoordinatorWritingContentIndependentMetadataOnly for writing in some cases? Looks like this iOS8 options can help you.

NSTimer in command line tool

I'm getting to know the NS/Objective-C model of concurrency. Say I have a command line tool that does something like this:
#include "myLibrary.h"
void callback(void* parameter){
cout<<"callback called.\n";
//some logic...
}
int main(int argc, char* argv[]){
myLibraryInit(callback);
std::string s;
while(true){
cin>>s;
myLibrarysResponseTo(s);
}
}
In my library, I'd like to be able to have two responses. One which starts a repeating timer and one which stops it. The timer should call the callback supplied to the library by myLibraryInit.
I've used NSTimers before in iPhone/iPad apps, and I think the problem stems from the different paradigm command line tools have. The main thread goes into main and never finishes it until the program is finished. This means it's not free to run the main run loop, which is what gets the timer going. I think. So how do I make an NSTimer work in this context?
The other thing is that Apple NSTimer documentation says I need to invalidate an NSTimer on the same thread it was installed. I don't know how to figure out what thread I was on when I installed the timer, and then keep track of it (and ensure it stays alive) until I want to invalidate the timer. I'm not sure if I'm just missing an obvious mapping between threads and dispatch queues, run loops, or something else. I am using core bluetooth and I initialize a central manager like so:
_centralManager=[[CBCentralManager alloc]
initWithDelegate: self
queue: dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
];
so a callback may be triggered from here. If the callback includes some logic to call the library function that stops the timer, I can't guarantee from which thread came the invalidate. So how do I properly invalidate the timer?
I found this question but it doesn't allow a main to happen at the same time as the run loop that that the timer is on.
I hope I gave enough context. Thanks in advance for your replies.
You must call dispatch_main() or run an NSRunLoop in the main thread if any of the system frameworks [that use GCD or asynchronous operations] are to work correctly.
This can be as simple as calling [[NSRunLoop currentRunLoop] run]; at the end of your main() function (just make sure you schedule the kickoff work first as that method never returns).

C/ObjC: How to unit-test blocks?

According to this Stackoverflow post: Selectors or Blocks for callbacks in an Objective-C library ,
blocks seem to be the future of ObjC. However, much like anonymous functions, blocks feel more like "drafting" an implementation. Also, due to its "embedded" nature, I fear that overusing them will break modularity in the sense of unit-testing or "testable" OOP.
I couldn't find much guideline on how to test blocks and how to coordinate tests for blocks and regular methods. Are there good resources for this topic?
I created 3 macros that wait for the block to be executed in a unit test so the assertions can be made inside the block.
#define TestNeedsToWaitForBlock() __block BOOL blockFinished = NO
#define BlockFinished() blockFinished = YES
#define WaitForBlock() while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true) && !blockFinished)
Example:
- (void)testWaitForBlock {
TestNeedsToWaitForBlock();
[target selectorWithInlineBlock:^(id obj) {
// assertions
BlockFinished();
}];
WaitForBlock();
}
Not sure if you've already tried it, but I use Kiwi for unit testing my iOS applications. Its not amazingly documented but it can be used for testing blocks.
https://github.com/allending/Kiwi
Take a look at the 'capturing arguments' under 'mocks and stubs' on their wiki. You can use this to capture a block thats being passed. This is really useful for code thats asynchronous - you can call the method you want to test, capture some completion block and then immediately execute the block synchronously, making your asynchronous code effectively synchronous.
In reference to blocks feeling like drafting an implementation - they don't have to be like that. I define blocks as a would a method, not inline. In fact I often write a method to return the block, making the code clean and easily testable.
Not sure if thats what you were looking for.
- (void)testWaitForBlock {
[target selectorWithInlineBlock:^(id obj) {
// assertions
BlockFinished();
}];
//use this to keep runloop is alive ,you can do anything.
NSDate * date = [NSDate dateWithTimeIntervalSinceNow:10];
[[NSRunLoop currentRunLoop]runUntilDate:date];
}

Method with blocks inside NSOperation - how does it work?

I'm working on an iOS project that has to work from iOS4. I have an NSOperationQueue and I add an operation. The main method of the operation looks something like this:
-(void)main
{
[self.client getStuffSuccess:^(Stuff *s) {
//Do something on success
} failure:^(NSError *error) {
//Do something on failure
}
}
The code inside the block will only be called when getStuff calls success or failure. I thought that in the meanwhile, my operation would be removed from the NSOperationQueue and the block wouldn't be called. However, I tested it and the block was in fact called. It's called no matter if the client calls the success block on the dispatch_get_main_queue or on the thread that called it - in this case the operation above.
Before the block is called, the method isFinished is actually returning true (I overrode the isFinished method and checked the value), so can someone explain me how is it possible that the block is being called?
I'm asking all this because although this works fine for one call, when I add it in a cycle of a few hundred iterations, I get an EXC_BAD_ACCESS and understanding the above might help me on the debugging.
The code inside the block will only be called when getStuff calls success or failure. I thought that in the meanwhile, my operation would be removed from the NSOperationQueue and the block wouldn't be called.
What leads you to believe this. A block is a closure, a self-contained block of code. It does not rely on the existence of some other object (the NSOperation in this case) in order to exist. You might want it to rely on that other object, but that's up to you to enforce. Ideally, I'd make getStufSuccess:failure: synchronous. If you can't you can use an NSCondition or call NSRunLoop methods to block the thread cheaply until it's done.
You also need to consider thread safety here. Your problem might not have to do with the operation going away, but your block doing something that isn't thread-safe.
Since getStuffSuccess:failure is asynchronous, you need to use a concurrent operation. Here is a helpful blog post:
http://www.dribin.org/dave/blog/archives/2009/05/05/concurrent_operations/
If your -getStuffSuccess:failure doesn't block the thread (i.e. the method is asynchronous), then your -main will complete and your operationQueue may deallocate your operation before the success or failure blocks are called. You can block the thread by adding a:
while(notProcessed){
sleep(0.1);
//Make sure your success and failure functions update notProcessed BOOL
}
so that main never completes before you've had a chance to call the closures. Or just use a synchronous method. This is generally fine because you won't be on the UI thread anyways.