What can be passed in (void *)context? - iphone

I'm doing some UIView animation stuff using
[UIView beginAnimations:nil context:nil];
// ... Animation configuration ...
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(animationEnded:finished:context:)];
[UIView commitAnimations];
Regarding the following question: Apple rejected app because of animationDidStop:finished:context: is a non-public api
I implemented my own method as the "setAnimationDidStopSelector".
My question is regarding the context:(void *)context parameter. Apple defines it as follow :
Additional application-supplied
information that is passed to the
animation delegate messages—the
selectors set using the
setAnimationWillStartSelector: and
setAnimationDidStopSelector: methods.
I'm wondering what king of thing can be passed in as a context. I'm relatively new to Objective-C and C programming and a bit lost with the void* type.
Can we pass in any sort of argument, objects, NSDictionnary, NSString, etc.
Thanks

void * is a pointer to anything. You can pass a pointer to any object or to other stuff such as a struct or a Core Foundation opaque type. To get rid of the compiler warning, cast the pointer to void *:
... context:(void *)myDictionary];
Be aware that the method has no idea what context contains and thus will not retain it or otherwise care for correct memory managemnet. You have to ensure that the thing you pass to context still exists when the animation delegate methods are called.

context:(void *)myDictionary];
When calling this method and trying to pass
(void *)[NSNumber numberWithInt:5] -
xCode proposes to make some _bridge because of invalid pointerCast from C to Objective-C ...

Related

Pointer to Pointer in Objective-C

I'm trying to learn to play with pointers here.
I have a UIImageView. I need to point its image property to another UIImageViews image property, so that whenever I change the second UIImageViews image, the first one gets updated automatically.
Some pointer manipulation here but I can't seem to get my head around it.
That is impossible. They are just pointers. For example aImageView and bImageView. You can set them's image pointer to point to the same UIImage. But change one of them does NOT change the other.
Maybe you can consider to use KVO to do what you want to do. Change one then your method will be called. Then in your method you can change the other.
you can use Key-Value Observing
from Apple Docs
Key-value observing provides a mechanism that allows objects to be notified of changes to specific properties of other objects.
KVO’s primary benefit is that you don’t have to implement your own scheme to send notifications every time a property changes.
[imageView1 addObserver:self
forKeyPath:#"image"
options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld
context:NULL];
- (void) observeValueForKeyPath:(NSString *)path ofObject:(id) object change:(NSDictionary *) change context:(void *)context
{
// this method is used for all observations, so you need to make sure
// you are responding to the right one.
}
Try to override the setter. Make a subclass of UIImageView, have a property for second UIImageView and write something like
-(void)setImage:(UIImage*)image{
_image = image;
self.secondImageView.image = image;
}
Hope this helps.

Implicit conversion from enumeration type 'UIViewAnimationCurve' to different enumeration type 'UIViewAnimationTransition'

I'm getting some warnings when I use this line of code.
[UIView setAnimationTransition:UIViewAnimationCurveEaseInOut forView:nil cache:YES];
then i am getting some warning this is following
Implicit conversion from enumeration type UIViewAnimationCurve to
different enumeration type UIViewAnimationTransition
So please suggest to me how to resolve this problem in iOS 5.0.
UIViewAnimationCurveEaseInOut is not transition type for uiview animation transition, It's the type of animation curve. Following are the valid transition as per apple developer reference.
UIViewAnimationTransitionNone,
UIViewAnimationTransitionFlipFromLeft,
UIViewAnimationTransitionFlipFromRight,
UIViewAnimationTransitionCurlUp,
UIViewAnimationTransitionCurlDown.
Please use one of them. If you want to set animation curve then do the following.
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];

iphone snow falling effect

i have been following
apps
snowfall tutorial, but i am getting some issue in iOS 5, something like this
(source: appsamuck.com)
-
(void)onAnimationComplete:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
UIImageView *flakeView = context;
****this is where the issue is: implicit conversion of a non objective c pointer type 'void *' to 'UIimageview' is disallowed when using ARC
Please suggest, how can I solve this problem.
Regards
Expanding on #fluchtpunkt 's comment which should really have been an answer ;)
ARC works by determining, at compile time, if the objects are needed or not - it then works out your retain/release for you.
If you pass an object as (void *) the compiler cannot work out that it has to retain this object so it might get released before you use it.
The __bridge explicitly tells the compiler that you are passing a 'real' object but using a void * to do it.
However, there might be a risk of a memory leak if you don't tell the compiler somewhere else that you are done with the object :)
Take a look at http://developer.apple.com/library/ios/#releasenotes/ObjectiveC/RN-TransitioningToARC/index.html and search for '_bridge' to see more details.

Objective C - Animation Blocks, multiparameters

I have a question... how is programmatically reached the Animation blocks?
[UIView beginAnimations:#"repositionAnimation" context:nil];
// -----------------------------------------------------------------------------
[view setFrame:viewRect];
[view setAlpha:0];
...
...
// -----------------------------------------------------------------------------
[UIView commitAnimations];
How the messages are stored and processed on commitAnimations ???
I just guess that the begin function invokes some kind of holder for messages, storing the messages somehow and process them in loop ?
is there a way to work with a messages some kind like in argument lists???
You are using the animation proxy when you call [UIView beginAnimations:context:]. If you want to manage animations explicitly, use Core Animation. You can monitor progress of a view's layer by periodically (using a timer) checking the layer's presentationLayer.

I need help with Animation Callbacks (iPhone)

I am creating an application in iPhone and I have several UIViews and layers in it. I am doing some animations using CAKeyframeAnimation class and since the animations have to be chained, I have overridden the animationDidStop method in UIView.
I am getting the callbacks properly, however I just couldn't figure out how I can find which animation was ended so that I can start the next one. Only parameters to the callback function is a CAAnimation object and a boolean.
I can workaround this problem by setting a property in the class and using an enum for the various animations I use. However I just wanted to know if there is any built in attributes in the callbacks which I can set in the CAKeyframeAnimation object and then refer the same in the callback.
Any help would be greatly appreciated!
You can specify a name for an animation and read it in your delegate method.
[animation setValue:"firstAnimation" forKey:#"name"];
...
- (void)animationDidStop:(CAAnimation*)animation finished:(BOOL)finished {
if([[animation valueForKey:#"name"] isEqual:#"firstAnimation"] && finished) {
...
}
}
I know that you said that you're using CAKeyframeAnimations, but if you want simple animation of UIView properties (origin, bounds, alpha, etc.), you can wrap the change of the property or properties in a begin / commit block and specify a delegate method that is called upon completion of the animation. As long as the delegate method takes three arguments, you can call it whatever you want. For example:
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:ANIMATIONDURATIONINSECONDS];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(yourAnimationHasFinished:finished:context:)];
// Change property or properties here
[UIView commitAnimations];
will cause the method
- (void)yourAnimationHasFinished:(NSString *)animationID finished:(BOOL)finished context:(void *)context;
to be called. The arbitrary naming this allows would provide you with a means of separating handling for the completion of different animations. I prefer this for simple animations.
For dealing with more complex animations that interact directly with CALayers, the animationDidStop:finished: delegate method does return the animation object that has finished. If you are making one instance that is the delegate for multiple animations, you could create an NSMutableDictionary of animations and NSNumbers for use in a switch statement within the animationDidStop:finished: method. As you create the CAKeyframeAnimation, use setObject:forKey: to assign it to its matching number, then use objectForKey: to find the number that corresponds to that animation in the completion method and feed that into a switch statement.