animation in xcode - xcode

when I doing animation with the next code:
NSArray *images=[NSArray arrayWithObjects:[UIImage imageNamed:#"shavit_1.png"],[UIImage imageNamed:#"shavit_1.png"],[UIImage imageNamed:#"shavit_2.png"],[UIImage imageNamed:#"shavit_3.png"],[UIImage imageNamed:#"shavit_4.png"],[UIImage imageNamed:#"shavit_5.png"],[UIImage imageNamed:#"shavit_6.png"],[UIImage imageNamed:#"shavit_7.png"],[UIImage imageNamed:#"shavit_8.png"],[UIImage imageNamed:#"shavit_9.png"],[UIImage imageNamed:#"shavit_10.png"],[UIImage imageNamed:#"shavit_11.png"],[UIImage imageNamed:#"shavit_12.png"],[UIImage imageNamed:#"shavit_13.png"],[UIImage imageNamed:#"shavit_14.png"],[UIImage imageNamed:#"shavit_15.png"],[UIImage imageNamed:#"shavit_16.png"],[UIImage imageNamed:#"shavit_17.png"],[UIImage imageNamed:#"shavit_18.png"],[UIImage imageNamed:#"shavit_19.png"],[UIImage imageNamed:#"shavit_20.png"],[UIImage imageNamed:#"shavit_21.png"],[UIImage imageNamed:#"shavit_22.png"],[UIImage imageNamed:#"shavit_23.png"],[UIImage imageNamed:#"shavit_24.png"],[UIImage imageNamed:#"shavit_25.png"],nil];
shavitimage.animationImages=images;
shavitimage.animationDuration=2.0;
shavitimage.animationRepeatCount=1;
[shavitimage startAnimating];
[images release]; //release the used array
[self performSelector:#selector(animation_ends) withObject:nil afterDelay:2.0];//after 2 seconds put astatic image
timer=[NSTimer scheduledTimerWithTimeInterval:10.0 target:self selector:#selector(timerFireMethod:) userInfo:nil repeats:NO];
}
-(void)animation_ends{
[shavitimage stopAnimating];//the UIImageView return to static mode
shavitimage.image=[UIImage imageNamed:#"shavit_25.png"];
self.view.userInteractionEnabled=YES;
}
the animation is working well,and the application working well after the end of the animation.
but when I doing animation with the next code:
NSMutableArray *images=[NSMutableArray array]; //insrt the images dynamiclly
for(int i=1;i<=25;i++)
{
NSString *file=#"shavit_";
file=[file stringByAppendingFormat:#"%d",i];
NSString *filePath = [[NSBundle mainBundle] pathForResource:file ofType:#"png"];
[images addObject:[UIImage imageWithContentsOfFile:filePath]];
[file release];
[filePath release];
}
shavitimage.animationImages=images;
shavitimage.animationDuration=2.0;
shavitimage.animationRepeatCount=1;
[shavitimage startAnimating];
[images release]; //release the used array
[self performSelector:#selector(animation_ends) withObject:nil afterDelay:2.0];//after 2 seconds put astatic image
timer=[NSTimer scheduledTimerWithTimeInterval:10.0 target:self selector:#selector(timerFireMethod:) userInfo:nil repeats:NO];
}
-(void)animation_ends{
[shavitimage stopAnimating];//the UIImageView return to static mode
shavitimage.image=[UIImage imageNamed:#"shavit_25.png"];
self.view.userInteractionEnabled=YES;
}
the animation is working well,but it stack after.why does it happen?

Do not release an autoreleased object.
That's the gist of it.
Evaluation of chain of events :–
You create an autoreleased array. Retain Count = 1 (will diminish by 1 in near future)
UIImageView object retains the array when you set animationImages. Retain Count = 2
You release the array. Retain Count = 1
Autorelease kicks in. Retain Count = 0 (object is deallocated)
Now the UIImageView still thinks that it has ownership of the array. When it tries to access it then it should result in an error. If it isn't animating and then is later deallocated, it will try to send a release message to the deallocated instance which should also crash the application. All of this is fair assumption as we don't know if the framework is adding its own memory management calls in any way.
Now both the pieces of code have the same problem and are both unreliable.
Be a good memory citizen and remove the release call.

#synthesize myImage;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSMutableArray *a = [NSMutableArray array];
//[a addObject: [UIViewController ]];
[a addObject:[UIImage imageNamed:#"1.gif"]];
[a addObject:[UIImage imageNamed:#"2.gif"]];
[a addObject:[UIImage imageNamed:#"3.gif"]];
[a addObject:[UIImage imageNamed:#"4.gif"]];
[a addObject:[UIImage imageNamed:#"5.gif"]];
[a addObject:[UIImage imageNamed:#"6.gif"]];
[a addObject:[UIImage imageNamed:#"7.gif"]];
//[myImage initWithFrame:CGRectMake(0, 0, 131, 125)];
myImage.animationImages = a;
myImage.animationDuration=5;
myImage.animationRepeatCount=0;
myImage.startAnimating;
[self.view addSubview:myImage];
}

Related

Ownership of members inside NSArray? without ARC

Is there a memory leak withOUT ARC?
NSMutableArray *array = [[NSMutableArray alloc] init];
NSNumber *numberForTest = [[NSNumber alloc] initWithInt:123456];
[array addObject: numberForTest];
[numberForTest release];
NSLog(#"number = %#", numberForTest); //safe to access "numberForTest" after calling release???
[array release];
My concern is: Did
[array addObject: numberForTest];
make "numberForTest" not qualified to be deallocated, before
[array release];
???
After using Static Analyzer, no leak is reported. And the output is consistently correct. But I don't feel comfortable.
NSArray (and NSMutableArray) retain objects.
When you release your array, all the objects in that array get released as well.

How to make second tabbarItem to be selected as default in iPhone?

I have added a UITabBarController programatically (Search,Login) and I want to set second tabbaritem(Login) and its view to be selected when Login credentials are not correct.But I m unable to do it so ..Could not understand where I m going wrong ..?
Search *first = [[Search alloc] initWithNibName:#"Search" bundle:nil];
first.title=#"Search";
Login *second=[[Login alloc]initWithNibName:#"Login" bundle:nil];
second.title=#"Login";
NSArray *viewArray= [NSArray arrayWithObjects:first,second, nil];
tabBarController=[[UITabBarController alloc] init];
[tabBarController setViewControllers:viewArray animated:NO];
[tabBarController setSelectedIndex:2];
[self presentModalViewController:tabBarController animated:NO];
But here my SearchViewController is selected and displayed as default...Where i m going wrong..?
Error is in this line:
[tabBarController setSelectedIndex:2];
Counting starts not from 1 but from 0, so in your case you have to change it to:
[tabBarController setSelectedIndex:1];

Sort a NSMutuableArray

I have a NSMutableArray that is loaded with a inforamtion from a dictionary...
[self.data removeAllObjects];
NSMutableDictionary *rows = [[NSMutableDictionary alloc] initWithDictionary:[acacheDB.myDataset getRowsForTable:#"sites"]];
self.data = [[NSMutableArray alloc] initWithArray:[rows allValues]];
There are two key value pairs in the rows dictionary.
I need to sort the self.data NSMutableArray in alphabetical order.
How is this accomplished??
thanks
tony
If the values are plain strings you can use the following to create a sorted array:
NSArray *sorted = [values sortedArrayUsingSelector:#selector(caseInsensitiveCompare:)];
This should do:
[self.data removeAllObjects];
NSArray *values = [[acacheDB.myDataset getRowsForTable:#"sites"] allValues];
NSSortDescriptor *alphaDescriptor = [[NSSortDescriptor alloc] initWithKey:#"DCFProgramName" ascending:YES selector:#selector(localizedCaseInsensitiveCompare:)];
NSArray *sortedValues = [values sortedArrayUsingDescriptors:[NSMutableArray arrayWithObjects:alphaDescriptor, nil]];
[alphaDesc release];
[self.data addObjectsFromArray:sortedValues];
There's no need to clear an NSMutableArray if you're replacing it shortly afterwards.
There's no need to create an additional NSMutableDictionary, if you're not modifying anything in it.
There's no need to create an additional NSMutableArray, if you could just as well just add the values to the existing one.
Also: There are some serious memory leaks in your code. (2x alloc + 0x release = 2x leak)
Edit: updated code snippet to reflect OP's update on data structure.

Cocoa (Snow Leopard) NSTextView's textStorage -setAttributes:range: removes characters!

I'm not sure what I'm doing wrong. I have a NSTextView and am registered as the delegate for its textStorage attribute. When I receive -textStorageDidProcessEditing:notification: I'm trying to apply attributes to ranges of characters within the text. It certainly does "something" to the characters, but not what I expect... they just disappear!
A heavily distilled code example. This should make sure the second character in the text field is always red:
-(void)textStorageDidProcessEditing:(NSNotification *)notification {
NSTextStorage *textStorage = [textView textStorage];
if ([[textStorage string] length] > 1) {
NSColor *color = [NSColor redColor];
NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:color, NSForegroundColorAttributeName, nil];
[textStorage setAttributes:attributes range:NSMakeRange(1, 1)];
}
}
Instead, as I type the sequence "abcdefg" I get "a", then when I hit "b" seemingly nothing happens, then when I hit "cdefg" typing occurs as normal, making the end result "acdefg"... the "b" is missing!
If I start hitting backspace I have to hit backspace 7 times, as if the "b" is actually there, but just not being drawn (cursor stalls as it deletes the "b", then on the next backspace deletes the "a" as expected).
If I apply attributes to some default text in the view using the same -setAttributes:range: method before the view is drawn then it does exactly as I expect.
Any clues? It seems like a fairly normal use of a NSTextStorageDelegate :)
I've tried calling -setNeedsDisplay on the text field to no avail.
Figured it out. Using NSTextStorage's -addAttribute:value:range works. I still don't fully understand why but at least I can get over it and move on.
-(void)textStorageDidProcessEditing:(NSNotification *)notification {
// ... SNIP ...
[textStorage addAttribute:NSForegroundColorAttributeName
value:[NSColor redColor]
range:NSMakeRange(1, 1)];
}
Makes the code a bit less cluttered too.
I'm not sure how relevant this is for you after so many years but I think the reason for it was that you were setting attributes with a dictionary which does not contain NSFontAttributeName, effectively removing it from the textview.
So I think this should work:
-(void)textStorageDidProcessEditing:(NSNotification *)notification {
NSTextStorage *textStorage = [textView textStorage];
if ([[textStorage string] length] > 1) {
NSColor *color = [NSColor redColor];
NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:color, NSForegroundColorAttributeName, [NSFont ...whatever...], NSFontAttributeName, nil];
[textStorage setAttributes:attributes range:NSMakeRange(1, 1)];
}
}

NSarray release

If i declare an NSArray with alloc & retain in single sentence then should i release the NSArray object twice (i.e. [arrayObject release] 2 times) ?
If you are creating an NSArray with an alloc and a retain on the same line then you are probably doing something wrong.
Objects are alloced with a retain count of +1, so there is no need to call retain on it as well.
To answer your question directly; yes, you do have to release it twice. Once because you created the object and once because you retained it. But I would question why you need to retain it an extra time in the first place.
You don't need to retain it. You already retain--or take ownership of--an object when you alloc/init. Revisit the Memory Management Programming Guide for Cocoa.
No, you have to release the object for each alloc and each retain. (And you can't alloc an object more than 1 time anyway.)
If you do
NSArray* arrayObject;
arrayObject = [[NSArray alloc] init];
arrayObject = [[NSArray alloc] init];
...
then it just wrong code. The latter assignment will cover the old one, which causes a leak. Either use 2 objects, and release each of them once:
NSArray* arrayObject1, arrayObject2;
arrayObject1 = [[NSArray alloc] init];
arrayObject2 = [[NSArray alloc] init];
...
[arrayObject1 release];
[arrayObject2 release];
or release the object before another init.
NSArray* arrayObject;
arrayObject = [[NSArray alloc] init];
...
[arrayObject release];
arrayObject = [[NSArray alloc] init];
...
[arrayObject release];

Resources