Say I have a subclass of UIView
which I will call AnimatableView
, where my implementation of layoutSubviews
lays out some internal content.
AnimatableView
also has the method commenceAnimationLoop
which looks something like this:
- (void) commenceAnimationLoop {
NSOperation *animationLoop = [[AnimationLoopOperation alloc]init];
[queue addOperation:animationLoop]; //queue is a NSOperationQueue iVar of AnimatableView
[animationLoop release];
}
The AnimationLoopOperation
is a subclass of NSOperation
whose main
method will start an infinite animation which only exits once the isCancelled
property becomes YES
.
The problem I am having is in my ViewController
where I setup and animate an instance of AnimatableView
like so:
- (void) viewDidLoad {
AnimatableView *animatableView = [AnimatableView alloc]initWithFrame:someFrame];
[self.view addSubview: animatableView];
[animatableView commenceAnimationLoop];
[animatableView release];
}
The problem is that the NSOperation
created in the commenceAnimationLoop
executes before my instance of AnimatableView
has had chance to call layoutSubviews
(meaning that it's content has not yet been generated and laid out).
I am making an educated guess that the layoutSubviews
method is called later (when the ViewController
is ready to render its view hierarchy?), but that the commenceAnimationLoop
method spawns a thread that immediately executes in the background.
To summarise - what would be the best way to make my animationLoop
operation wait for the view to layout before commencing?
To provide some high level context for what I am trying to achieve - I am using NSOperation
to start a continuous animation. The idea being that I can provide an endAnimation
method which would likely call cancelAllOperations
on my queue. All this is done in the hopes I can provide a way of starting and then interrupting an infinite animation with the two methods commenceAnimationLoop
and endAnimation
. Perhaps I am barking up the wrong tree going down the route of multi-threading?
If you need layoutSubviews
to run before your operation then you should't start the operation queue before it that. You can prevent an operation queue from starting additional operations using [myOperationQueue setSuspended:YES];
.
Since it will only prevent the queue from starting new operations you should suspend the queue before you add your operations to it.
After you view has loaded and layoutSubviews
has run you can resume the operation queue again using [myOperationQueue setSuspended:NO];
. One place to do this could be in viewDidAppear
.