Objective C speeding up animation / object creation - iphone

What kind of trick can I use to speed up and improve an image sequence animation?
I'm using the code below, but then just running through the codes below takes a couple of seconds to finish.
Once the animations have been created, my phone seems to get much slower too.
Please enlight.
Thanks,
Tee
NSMutableArray * sequenceArray;
sequenceArray = [[NSMutableArray alloc] init];
int k;
int xPos = 0;
int yPos = 50;
for (k = 1; k <= 48; k++)
{
UIImageView* dynamicView = [[UIImageView alloc] initWithFrame:self.view.frame];
[sequenceArray addObject:dynamicView];
int i;
NSMutableArray *a = [NSMutableArray array];
for (i = 1; i <= 102; i++)
{
[a addObject:[UIImage imageNamed:[NSString stringWithFormat:#"loop2 %d.png", i]]];
}
dynamicView.animationImages = a;
//[a release];
// all frames will execute in 1.75 seconds
dynamicView.animationDuration = 1.6;
// repeat the annimation forever
dynamicView.animationRepeatCount = 0;
CGRect frame1 = dynamicView.frame;
frame1.size.width = 34;
frame1.size.height = 34;
frame1.origin.x = xPos;
frame1.origin.y = yPos;
dynamicView.frame = frame1;
if (k % 8 == 0) {
xPos = 0;
yPos += 40;
}
xPos += 40;
NSLog(#"step last");
// start animating
[dynamicView startAnimating];
// add the animation view to the main window
[self.view addSubview:dynamicView];
[dynamicView release];
}

So, you're creating 48 UIImageViews, each with an animation of the same 102 frames? Am I reading that right?
The first thing that occurs to me is to pull this out of the other loop, since it's loading the same array each time, and just assign it to each view:
int i;
NSMutableArray *a = [NSMutableArray array];
for (i = 1; i <= 102; i++)
{
[a addObject:[UIImage imageNamed:[NSString stringWithFormat:#"loop2 %d.png", i]]];
}
But, really, why are you doing this?

Related

How to place arrange images dynamically in a circle

How can i dynamically arrange icons(UIButtons, with backgroundImages) in circle image.SOmething like it should like concentric circles.
I am using the following code,
UIImageView *container = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, 0.0f, 299.0f, 298.0f)];
container.image = [UIImage imageNamed:#"AR_RF004_circle.png"];
container.center = CGPointMake(self.view.bounds.size.width/2.0, self.view.bounds.size.height/2.0);
[self.view addSubview:container];
NSArray *imagesArray = [[NSArray alloc]initWithObjects:[UIImage imageNamed:#"AR1.png"],[UIImage imageNamed:#"AR2.png"],[UIImage imageNamed:#"AR3.png"],[UIImage imageNamed:#"AR4.png"],[UIImage imageNamed:#"AR5.png"], nil];
int numberOfSections = 5;
CGFloat angleSize = 2*M_PI/numberOfSections;
for (int j = 0; j < numberOfSections; ++j) {
UIButton *sectionLabel = [[UIButton alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 150.0f, 128.0f)];
[sectionLabel setBackgroundImage:[imagesArray objectAtIndex:j] forState:UIControlStateNormal];
sectionLabel.layer.anchorPoint = CGPointMake(0.9f, 0.1f);
sectionLabel.layer.position = CGPointMake(container.bounds.size.width/2.0, container.bounds.size.height/2.0); // places anchorPoint of each label directly in the center of the circle.
sectionLabel.transform = CGAffineTransformMakeRotation(angleSize*j);
[container addSubview:sectionLabel];
NSLog(#"section label x and y is %f ,%f",sectionLabel.frame.origin.x,sectionLabel.frame.origin.y);
}
[container release];
Thanks in Advance
You can use this piece of code:
UIButton *currentButton;
int buttonCount = 20;
int radius = 200;
float angleBetweenButtons = (2 * M_PI) / buttonCount;
float x = 0;
float y = 0;
CGAffineTransform rotationTransform;
for (int i = 0; i < buttonCount; i++)
{
// get your button from array or something
currentButton = ...
...
x = radius + cosf(i * angleBetweenButtons) * radius;
y = radius + sinf(i * angleBetweenButtons) * radius;
rotationTransform = CGAffineTransformIdentity;
rotationTransform = CGAffineTransformRotate(rotationTransform, (i * angleBetweenButtons));
currentButton.center = CGPointMake(x, y);
currentButton.transform = rotationTransform;
}
I think you can do something like this
sectionLabel.center = container.center;
I have not checked other code.. Simplest way for this

Access position of UIButton objects in Array

I have an array of UIButtons. What I want to do is with another button, randomly set the positions of each of the buttons in the array.
So I initialize the array with the UIButtons:
buttonArray = [[NSMutableArray alloc] initWithObjects:button1,button2,button3,button4,button5,button6,button7, nil];
Then I have a randomize method to set each of the button's positions.
this is the part where I'm stuck. I've found some threads about having to cast the type of the object in the array so the compiler understands. but I can't seem to make it work.
- (IBAction)randomizePositions:(id)sender
{
for (int i = 0; i < [buttonArray count]; ++i)
{
float xPos = arc4random() % 1000;
float yPos = arc4random() % 700;
CGRect randomPosition = CGRectMake(xPos, yPos, button1.frame.size.width, button1.frame.size.width);
(UIButton *)[buttonArray objectAtIndex:i].frame = randomPosition;
}
}
It's this part here that I can't seem to get right. It's pretty obvious by now that I'm a beginner so any help would be much appreaciated.
(UIButton *)[buttonArray objectAtIndex:i].frame = randomPosition;
You may want to grab a pointer to the UIButton in the array earlier, as it might be easier to consider what you are working with.
- (IBAction)randomizePositions:(id)sender
{
for (int i = 0; i < [buttonArray count]; ++i)
{
UIButton *currentButton = (UIButton *)[buttonArray objectAtIndex:i];
float xPos = arc4random() % 1000;
float yPos = arc4random() % 700;
[currentButton setFrame:CGRectMake(xPos, yPos, currentButton.frame.size.width, currentButton.frame.size.height)];
}
}
Unless, of course, you want to always be working with button1 size.

animation of uiimageView stops

here is what I wanna do http://www.youtube.com/watch?v=rD3MTTPaK98
and here is my code:
-(void) onTimer {
UIImage * image = [UIImage imageNamed:#"abouffer_03.png"];
imageView = [[UIImageView alloc] initWithImage:image];
[imageView setCenter:[self randomPointSquare]];
[imageViewArray addObject:imageView];
[[self view] addSubview:imageView];
[imageView release];
ix=imageView.center.x;
iy=imageView.center.y;
X=(240-ix)/230;
Y=(160-iy)/230;
coteA=(240-ix);
coteB=(160-iy);
angleDeRotation=atan(coteB/coteA);
if(ix>250||0>iy>320){
imageView.transform = CGAffineTransformMakeRotation(angleDeRotation+3.14);
}
else{
imageView.transform = CGAffineTransformMakeRotation(angleDeRotation);
}
}
-(void)onTimer2{
for(int i=0; i< [imageViewArray count];i++){
imageView = [imageViewArray objectAtIndex:i];
imageView.center = CGPointMake(imageView.center.x + X, imageView.center.y + Y);
}
onTimer is called every 2 seconds
but it doesn't work, there is no error but when a "imageView" is created after 2 seconds it sop moving and go to the same direction of the new " imageView" that has been created. How can I solve this ? sorry for my english I'm french :/
You’re adding X and Y to all of your image views, but it’a always the last-computed value. Make an array of X and Y values and use the value that corresponds with your image view.
Where you define imageViewArray, also define xArray and yArray as NSMutableArrays. Then in -onTimer, when you set X and Y, do this:
[xArray addObject:[NSNumber numberWithFloat:X]];
[yArray addObject:[NSNumber numberWithFloat:Y]];
Finally, in -onTimer2, do this:
-(void)onTimer2{
for(int i=0; i< [imageViewArray count];i++) {
float localX = [(NSNumber *)[xArray objectAtIndex:i] floatValue];
float localY = [(NSNumber *)[yArray objectAtIndex:i] floatValue];
imageView = [imageViewArray objectAtIndex:i];
imageView.center = CGPointMake(imageView.center.x + localX, imageView.center.y + localY);
}
That will use the value of X and Y that you set in -onTimer.

How to send a time-delayed message to a UIView on a timer

I am adding UIViews to a superview in the following loop:
int xValue = 0 ;
int yValue = 10;
for (NSString *element in characters) {
UIView *newCharView = [[MyChar alloc] initWithFrame:CGRectMake(xValue,yValue,100,100)];
[(MyChar *)newCharView initLayers:element];
[[self view] addSubview:newCharView];
[newCharView autorelease];
if (xValue <= 240) {
xValue+=22;
} else {
xValue = 0;
yValue += 22;
}
}
MYChar contains a method which fires an animation. I want the method to be called sequentially in my loop with a delay of, say, 0.2 seconds. How can I achieve this? I tried delaying the animation itself but obviously just get the same delay in all the UIViews.
You could try using something like this:
int xValue = 0 ;
int yValue = 10;
double delay = 0.2;
for (NSString *element in characters) {
UIView *newCharView = [[MyChar alloc] initWithFrame:CGRectMake(xValue,yValue,100,100)];
[self performSelector:#selector(delayedInitView:) withObject:element afterDelay:delay];
if (xValue <= 240) {
xValue+=22;
} else {
xValue = 0;
yValue += 22;
}
delay += 0.2;
}
-(void) delayedInitView: (id) element {
[(MyChar *) newCharView initLayers: element];
[[self view] addSubview: newCharView];
[newCharView autorelease];
}
You will have to experiment with that, as I don't know what exactly you are trying to achieve.
EDIT:
Ouch, it's definitely not a good way to go with such a large amount of views. You could try using one background loop to init all of them.
I would definitely have to think it over a lil more if I personally faced that problem, but here's a simple suggestion, you will have to tune it to your needs and probably take care of its thread/memory management safety:
[self performSelectorInBackground:#(backgroundInitViews:) withObject:characters]
-(void) backgroundInitViews: (NSArray*) elements {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
int xValue = 0 ;
int yValue = 10;
for (NSString *element in elements) {
UIView *newCharView = [[MyChar alloc] initWithFrame:CGRectMake(xValue,yValue,100,100)];
[(MyChar *) newCharView initLayers: element];
[[self view] addSubview: newCharView];
[newCharView autorelease];
if (xValue <= 240) {
xValue+=22;
} else {
xValue = 0;
yValue += 22;
}
[NSThread sleepForTimeInterval:0.2];
}
[pool drain];
}
Give this a try:
[self performSelector:#selector(postAnimationMethod) withObject:self afterDelay:0.2];

EXC_BAD_ACCESS in for loop

In this code, in the second for loop, i get an EXC_BAD_ACCESS if I use an identifier other than i and j.
if (UIDeviceOrientationIsPortrait(deviceOrientation)){
numRows = 4;
numCols = 3;
}else {
numRows = 6;
numCols = 1;
}
for (int row = 0; row < numRows; row++){
for (int col = 0; col < numCols; col++) {
keysArray[row][col] = [[[keys objectAtIndex:0] retain] autorelease];
if (col < numRows)
[keys removeObjectAtIndex:0];
}
}
//Here is the crash
for (int i = 0; i < numRows; i++) {
for (int j = 0; j < numCols; j++){
UIButton *b = [UIButton buttonWithType:UIButtonTypeCustom];
b.frame = CGRectMake(i * kKeyGap, j * kKeyGap, 57, 57);
[b setImage: [UIImage imageNamed:keysArray[j][i]]
forState:UIControlStateNormal];
[self.view addSubview:b];
}
}
Why would this cause such an error? I tried using Edit All In Scope to avoid missing one, but it still crashes.
Thanks
Your line:
keysArray[row][col] = [[[keys objectAtIndex:0] retain] autorelease];
I'm not an Objective-C expert or anything, but I'm not certain you need to autorelease that object because you haven't allocated memory for it. What happens when you try and remove that autorelease?
My suspicion is that after you autorelease the object and then attempt to assign the array value here:
[b setImage: [UIImage imageNamed:keysArray[j][i]]
forState:UIControlStateNormal];
you're getting the EXC_BAD_ACCESS.
I could be wrong, in which case I hope someone smarter than me can clear this up. :)
In your first loop you are referencing keysArray[row][col] in the second loop you seem to be using keysArray[col][row] which would cause it to crash if numRows and numCols are different