Objective-C and Quartz Composer; [qcView pauseRendering] causes Bad_Access

703 views Asked by At

thanks in advance.

I have a Quartz Composer View (qcView below) and move an image (of an ant, if you were wondering of the code) in a random direction until it finds it's 'home' in the middle of the QCView. The pauseRendering is necessary so that we can see the ant move inch by inch; without it the ant will just appear at it's 'home'.

while([self distance] > acceptableOffset){
    [qcView pauseRendering];
    [self moveTowardsDestination:@"home"];
    [qcView resumeRendering];
}

This works perfectly fine for a single ant.

When I add another ant to the equation, I use a dispatch queue and two blocks.

    dispatch_async(queue, ^{
        [theAnt findCenter];
    });

    dispatch_async(queue, ^{
        [otherAnt findCenter];
    });

When this code is run, the two aunts scurry to their home's concurrently - the exact behavior we're looking for. However, when I stop the execution and build again, I immediately get a Exc_Bad_Access from somewhere within the [qcView pauseRendering] method. After a Clean & Build it will work perfectly for one more run. With the pauseRendering and resumeRendering removed, the ants will instantly appear at their home.

Apparently there is an array local to the QCView pauseRendering method which is constantly growing and shrinking, and with the single QCView and the multiple blocks accessing it you can see the root of the problem.

I've researched the QCView documentation and can't seem to find inspiration there; the documentation on pauseRendering is minimal. While I'm sure none of you has tried something as silly as this I'm hoping someone would have experience with pragmatically modifying a QCView and would be able to point me in the right (err... read "ANY!") direction.

[Edit: I've tried variations of "while (![qcView isPausedRendering])", if that helps.]

2

There are 2 answers

2
bbum On

Are you sure that QCView instances actually support concurrency?

Highly unlikely. If you are mucking w/the views from separate threads or queues -- even non-concurrently from a background queue/thread -- you are quite likely violating the concurrency rules of the QCView.

I'd suspect that you must manipulate the view from the main thread or, at the least, from one thread at a time.

(I couldn't find any specific information on this, unfortunately).

1
Rubber Duck On

Solved it.

Turns out I was vastly overestimating the problem. Simple fix of using

     usleep(10000);

Go figure.

This was originally in the code, however it was substituted in favor of dispatch_suspend(). With the sleep on the line just before the suspension, the desired activity is achieved.

If anyone encounters similar problems feel free to email me.