iOS Core animation and ARC - ios

I have started using CoreAnimation in my new app, i use CA to make some cool animations. But i'm new to objective C and it's difficult to me and i'm facing this big problem :
i have made a custom UIView : customView, i'm using a xib to get a user interface and set IBOutlet, custom view is a simple small view with an UIImageView inside.
In my view controller i have made a loop that insert severals customView, in this loop i set both a CAnimation for the view and for the imageView :
for (int i = 0 ; i < 8 ; i ++ )
{
CABasicAnimation *balanceAnimation = [CABasicAnimation animationWithKeyPath:#"transform.rotation.z"];
// ... set Animation here...
[customView.myImgView.layer addAnimation:balanceAnimation forKey:nil];
CABasicAnimation *moveUp3Bis;
// ... setting animation here...
moveUp3Bis.repeatCount = 1;
[customView.layer addAnimation:moveUp3Bis forKey:nil];
}
I call this loop as long as the view controller is current controller after 10 sec delay
So the views gets animate, move, and go beside the main window, but after a long time animations get slower and slower...
Of course i have understood that my loop add to the stack too many customView, the view are not released (may be because animations is still on ?)
I thought that views would be released after a while but i think the view will be moving for ever.
May be i need to set a pointer to my view and release it after a delay ?
I'm sure CA have planned something for case like that ?
But i do not know what can i do ?
Thank you for any help.

Have you tried setting -[CABasicAnimation removedOnCompletion]?
It looks like it's default value is YES, so I don't think this is your problem, but it's worth looking into.
Have you tried using Profile to see what's slowing everything down?

From the code snippet that you added is hard to tell what are you doing with your views but you definitely must remove them form their parent view otherwise they won't be released.
So what I suggest is that you should try to remove the views before you start the loop and just so you have a cool animation, you should remove a view only if is not animating, for this you will have to add a key string for your animation using your current method addAnimation:balanceAnimation forKey:nil instead of setting it to nil and check the view's layer for animationKeys if the array is empty or nil then the animation is completed if not is still animating.

Related

+[UIView transitionFromView:toView:...] with multiple views

So here's the situation:
I have let's say 20 views who are all subviews of the same view. Now I want to remove and add new views in an animated matter.
I previously did this by using regular UIView animations and fading them out or in respectively. The problem is though that the animation isn't flawless when the new subview who is to be inserted overlaps with the subviews who are fading out. So I tried using the +[UIView transitionFromView:toView:...] animation block to make the animation cross dissolve. This works well, animation looks good.
This basically solves my issue. The only problem is that it might be that I want to replace 2 subviews with one bigger subview. This doesn't really work out as I can't just pas nil to the transition method.
So my question basically is how I can simultaneously cross dissolve multiple subviews no matter how many views are animated?
Thanks for your help!
Have you tried putting the views to remove inside a transparent bigger view? So you just call transitionFromViewToView using the container with the 2 little ones inside and the big one that is entering?
You can use + [UIView transitionWithView:duration:options:animations:completion:], passing the common superview (usually self.view of your view controller) to perform all animations at once.
Excerpt from the doc:
This method applies a transition to the specified view so that you can
make state changes to it. The block you specify in the animations
parameter contains whatever state changes you want to make. You can
use this block to add, remove, show, or hide subviews of the specified
view. If you want to incorporate other animatable changes, you must
include the UIViewAnimationOptionAllowAnimatedContent key in the
options parameter.

Facebook Paper-like table cells animation

I'm trying to implement transition used in settings menu in Facebook's Paper app: http://blog.brianlovin.com/design-details-paper-by-facebook/#1. I'm using my custom UIViewControllerAnimatedTransitioning object, but I can't achieve the same effect, no matter what type of animation I'm using. So I have some questions:
1) Which animation is used? It looks like cells start to move really fast, and then halt to their final position. Looks like I need POPDecayAnimation, but the result isn't even close.
2) Is delay between animations achieved with setting animation's beginTime depending on cell's index? Or first cells have bigger velocity than last cells?
As Injectios suggested AMWaveTransition is kinda close to Paper's animation. I ended up using it with some adjustments.
I also asked this question on pop github page, you can view it here. Their answer might be useful if you want to implement this animation yourself:
Hey! I implemented that in Paper. The animations on each cell are POPSpringAnimations, and they're connected together by (every frame) updating the toValue of each animation to point to the current value of the one before. Hope that helps!
In cellForRowAtIndexPath, use UIViewAnimation block.
Set cell properties as per your requirement:
indentationLevel
indentationWidth
shouldIndentWhileEditing
Then in animation block, change frame position.
For example for first cell, indetationLevel = 1, and indentationWidth = cell.frame.size.width, then update it to indetationLevel = 0 and indentationWidth = 0 in that animation block. And for the further cells you can multiply this values by (cellIndexPath+1)
For more details visit : https://developer.apple.com/library/ios/Documentation/UIKit/Reference/UITableViewCell_Class/index.htm
P.S.: Update the logic as per your requirement

Take a snapshot of a hidden UIView

I'm trying to take a snapshot of a hidden view but am running into several issues. If I try unhiding it quickly, taking a snapshot, and then rehiding it, I sometimes get a quick flicker on the screen that is pretty jarring.
toCollectionViewCell.hidden = NO;
UIView *toPlaceHolderSnapshot = [toCollectionViewCell resizableSnapshotViewFromRect:toCollectionViewCell.bounds afterScreenUpdates:YES withCapInsets:UIEdgeInsetsZero];
toCollectionViewCell.hidden = YES;
I'm pretty sure the flicker is caused by the afterScreenUpdates:YES, but I can't imagine that is intended behavior.
I've also tried moving the cell/view off screen instead of hiding it, but I can't be certain when that cell might be reloaded and therefore moved back into its place prematurely.
Is there a way to take a snapshot of a hidden view or a more clever way to achieve this? I need this functionality during a custom transition animation where I am pulling a collection view cell out of the collection view and then returning it back into place on dismiss. I am taking snapshots of the before/after state and then transitioning between the two during the animation.
Thanks!
Add an extra container view to your view hierarchy. Hiding the container will have the same visual effect, but you'll be able to snapshot the content of a container with ease.
I've also tried moving the cell/view off screen instead of hiding it, but I can't be certain when that cell might be reloaded and therefore moved back into its place prematurely.
This approach is probably the simplest. As long as all of your work is done on the main thread, the cell won't move during your snapshot.
You could also try archiving and then unarchiving the view (to essentially copy it):
id copyOfView =
[NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:originalView]];
UIView *viewCopy = (UIView *)copyOfView;
viewCopy.hidden = NO;
(All views in the hierarchy will need to conform to the NSCoding protocol.)
Finally, you could draw your cell to a UIImage, and then display it in a UIImageView. Sample code here.

View not updating when autolayout constraint modified programmatically

I'm having trouble getting my view to lay itself out properly after modifying a second constraint (the first works fine). I'm modifying one constraint, animating it, and then modifying another constraint in the completion block (without animation).
My reason for doing this is I don't want the second constraint change to affect the animation, but I want it to instantly take effect as soon as the initial animation completes.
The problem is the second constraint change is simply not taking effect, no matter what I try.
Here's what I'm trying (note the problem is only when toolbarVisible is YES, as I perform both animations up front when it is NO):
if ( !toolbarVisible )
self.containerViewBottomSpace.constant = toolbarVisible ? 60.f : 0;
self.toolbarBottomSpace.constant = toolbarVisible ? 0 : 60.f; // this one works fine
[self.view setNeedsUpdateConstraints];
[UIView animateWithDuration:0.3f animations:^{
[self.view layoutIfNeeded];
} completion:^(BOOL finished) {
if ( toolbarVisible )
self.containerViewBottomSpace.constant = 60.f; // this one is not taking effect
[self.view setNeedsUpdateConstraints];
[self.view layoutIfNeeded];
}];
The above method takes place inside an observeValueForKeyPath:... method. I've tried wrapping the whole above code in a dispatch_after block, but that has an even worse effect in that it is always one step behind (i.e. containerView is always in the opposite position as it should be) as if the second constraint modification isn't taking effect until the next animation.
Similarly, if I push another view onto the navigation controller (which is embedded inside the containerView), the layout corrects itself. It's as though it's just ignoring my command to lay itself out again for some reason.
Actually I just noticed that even if I make the second change initially and skip the completion block altogether, it doesn't appear to be animating the second constraint change in all cases. Something is fishy.
Update: I was using dispatch_after incorrectly thinking it accepted an NSTimeInterval. After giving it a proper dispatch_time_t and putting it inside the completion block, the layout is now sometimes updating. However, it's very flaky and this seems very hackish so I feel as though I'm missing something. If anyone knows more about this please enlighten me and I'll give you the answer.
Update 2: I decided to try logging the height of the element I am trying to change in viewDidLayoutSubviews. Interestingly, it gets called twice, first with the previous value and second with the correctly adjusted height. So I guess it is at least partially laying things out correctly, but for some reason the tableView that is inside the containerView is still not resizing itself properly. I'm not sure what I'm missing.
I'd first breakpoint and make sure you're not hitting the animation code a second time during the animation duration. If it's in observeValueForKeyPath you could hit the animation multiple times and it causes some inconsistency.
You also shouldn't need to call setNeedsUpdateConstraints or layoutIfNeeded. Setting the constant should be enough.
I'd also make sure that you've got the constraints wired up correctly and toolbarVisible is true.

Adding and Removing UIView From Springboard

I am developing a little MS tweak that adds a view on the Springboard. I want it to be constantly updated so I called it into the
- (void)showSpringBoardStatusBar
Then I create and add the view using this:
[[UIApplication sharedApplication].keyWindow addSubview:view1];
Is this the right way?
But the problem is this view uses a low alpha level to be transparent and every time the view is updated by the showSpringBoardstatus bar another UIView is added onto of it eventually just making the view solid. This also is uneconomical in terms of memory. so then I went back an added what I thought would remove the code:
view1 = nil;
[view1 removeFromSuperview];
But it seems like this doesn't make a difference as it is still there and nothing changes.
I have been searching for the last few days for anything to help me with this but got nothing out of it. All I can think of is that I can't remove an added subview from a key window like I would from a normal view or I just don't how to do it correctly.
Any help would be appreciated. Thank you.
Setting view1 to nil and than calling "removeFromSuperView" might be a bad idea. How about adding the view only once, keeping a reference and updating this reference constantly without adding it to keyWindow again?

Resources