I'm trying to create an application that allows users to go through a set of images like a magazine. I've got one UIView class on top of the AppDelegate and on swipe to the left/right I'm either going forward or backward a page. My problem is that when I swipe and change the image source the program keeps allocating more memory, and I'm not certain where/how to release the previously allocated memory. I've looked in to the difference between imageNamed and imageWithContentsOfFile and I believe I'm using those correctly so I'm stumped. Any help would be much appreciated!
AppDelegate.h
#interface AppDelegate : NSObject {
UIWindow *window;
MagazineWebViewController *webViewController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet MagazineWebViewController *webViewController;
- (void)goToA:(NSNumber *)page;
#end
AppDelegate.m
#implementation AppDelegate
#synthesize window, webViewController;
- (void)applicationDidFinishLaunching:(UIApplication *)application {
webViewController = [[MagazineWebViewController alloc] init];
NSNumber *page = [NSNumber numberWithInt:1];
[webViewController setPage:page];
[window addSubview:webViewController.view];
[window makeKeyAndVisible];
}
- (void)goToA:(NSNumber *)page {
UIImage *image = [[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:#"%#", page] ofType:#"png"]];
webViewController.imageView.image = image;
[image release];
[webViewController setPage:page];
}
- (void)dealloc {
[webViewController release];
webViewController = nil;
[window release];
[super dealloc];
}
#end
MagazineWebViewController.h
#interface MagazineWebViewController : UIViewController {
UIImageView *imageView;
NSNumber *page;
}
#property (nonatomic, assign)NSNumber *page;
#property (nonatomic, retain)UIImageView *imageView;
- (void)swipeLeft;
- (void)swipeRight;
- (void)tableOfContents;
#end
MagazineWebViewController.m
#implementation MagazineWebViewController
#synthesize page, tocController, imageView;
- (id)init {
UINavigationBar *navBar = [[UINavigationBar alloc] initWithFrame:CGRectMake(0, 0, 768, 60)];
navBar.tintColor = [UIColor blackColor];
UIBarButtonItem *contents = [[UIBarButtonItem alloc] initWithTitle:#"Table of Contents" style:UIBarButtonItemStylePlain target:self action:#selector(tableOfContents)];
UINavigationItem *item = [[UINavigationItem alloc] initWithTitle:#"Title"];
item.leftBarButtonItem = contents;
item.hidesBackButton = YES;
[navBar pushNavigationItem:item animated:NO];
[contents release];
[item release];
[self.view addSubview:navBar];
[navBar release];
self.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 40, 768, 984)];
UIImage *image = [[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"1" ofType:#"png"]];
self.imageView.image = image;
[image release];
self.imageView.contentMode = UIViewContentModeScaleToFill;
UISwipeGestureRecognizer *swipeLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeLeft)];
swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
[self.view addGestureRecognizer:swipeLeft];
[swipeLeft release];
UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeRight)];
swipeRight.direction = UISwipeGestureRecognizerDirectionRight;
[self.view addGestureRecognizer:swipeRight];
[swipeRight release];
[self.view addSubview:self.imageView];
[self.imageView release];
return self;
}
- (void)swipeLeft {
int pageNum = [page intValue];
if (pageNum < 115) {
pageNum++;
UIViewAnimationTransition trans = UIViewAnimationTransitionCurlUp;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationTransition:trans forView:self.view.window cache:YES];
BaseballMagazine2011AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
[appDelegate goToA:[NSNumber numberWithInt:pageNum]];
[UIView commitAnimations];
}
}
- (void)swipeRight {
int pageNum = [page intValue];
if (pageNum > 1) {
pageNum--;
UIViewAnimationTransition trans = UIViewAnimationTransitionCurlDown;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationTransition:trans forView:self.view.window cache:YES];
BaseballMagazine2011AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
[appDelegate goToA:[NSNumber numberWithInt:pageNum]];
[UIView commitAnimations];
}
}
- (void)tableOfContents {
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc. that aren't in use.
}
- (void)viewDidUnload {
[imageView release];
imageView = nil;
[page release];
page = nil;
[tocController release];
tocController = nil;
[super viewDidUnload];
}
- (void)dealloc {
[imageView release];
imageView = nil;
[page release];
page = nil;
[super dealloc];
}
#end
In your AppDelegate.m, Try prefacing each reference to webViewController with 'self.'. For example:
self.webViewController = [[MagazineWebViewController alloc] init];
By not referencing the property with self, you are bypassing the properties auto generated setters and getters. And since you set this property to retain, this would bypasses some memory handling logic. I'm pretty sure that is your issue... Hope this helps!
I think it's because you alloc every time an UIImage (like said in the comments).
Did you try not doing allocations ?
self.imageView.image = [ UIImage imageNamed:#"1.png" ];
I think you won't have any problem with this.
But it's difficult to say where come from the leak without all your program ^^
Maybe a retain property or something like that.
Related
I have created two view controllers in which there is UIImage animations.Its crashing frequently and showing memory leaks in xcode instrument.
My Controllers Code-
- (void)viewDidLoad {
NSArray *firstArray;
firstArray = [NSArray arrayWithObjects:
[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"up0001" ofType:#"png"]],
[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"up0002" ofType:#"png"]],
::
::
[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"up0035" ofType:#"png"]], nil];
imgView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 1024, 768)];
imgView = UIViewContentModeScaleToFill;
[imgView setAnimationImages:firstArray];
imgView.animationDuration = 1.75;
imgView.animationRepeatCount = 0;
[imgView startAnimating];
[self.view addSubview: imgView];
}
- (void)dealloc {
[super dealloc];
[imgView release];
imgView = nil;
}
And I am changing viewcontrollers as my rootviewcontroller by getting appdelegate object and calling following appdelegate function in my Appdelegate.m(Please suggest any good approach)
- (void)changeRootViewController:(NSString *)controllerName
{
if(self.viewController){
[self.viewController.view removeFromSuperview];
self.viewController=nil;
}
if (controllerName == #"ViewController") {
ViewController *lviewController =[[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
self.viewController = (RootViewController *)lviewController;
[lviewController release];
lviewController.view = nil;
[self.window setRootViewController:self.viewController]; //LEAKS 100%
} else if (controllerName == #"MainViewController") {
// Use a different VC as roowViewController
MainViewController *lviewController =[[MainViewController alloc] initWithNibName:#"MainViewController" bundle:nil];
self.viewController = (RootViewController *)lviewController;
[lviewController release];
lviewController.view = nil;
[self.window setRootViewController:self.viewController]; //LEAKS 100%
} else if (controllerName == #"SecondViewController") {
// Use a different VC as roowViewController
SecondViewController *lviewController =[[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
self.viewController = (RootViewController *)lviewController;
[lviewController release];
lviewController.view = nil;
[self.window setRootViewController:self.viewController]; //LEAKS 100%
}
[self.window makeKeyAndVisible];
}
And calling this in my respective controlers button pressed as -
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
[appDelegate changeRootViewController:#"ViewController"];
OR
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
[appDelegate changeRootViewController:#"MainViewController"];
I want to manage view controllers from my main controller swapping controllers in and out without Navigationbar.Please help me figure out the best possible approach and avoid leaks as well.
Look at this piece of code:
if (controllerName == #"ViewController") {
ViewController *lviewController =[[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
self.viewController = (RootViewController *)lviewController;
[lviewController release];
lviewController.view = nil;
[self.window setRootViewController:self.viewController]; //LEAKS 100%
}
When you alloc "lviewController", its retain count is 1;
when you do "self.viewController" as I suppose viewController is a retained property, then lviewController retain count is increased to 2;
then you release it, balancing the previous alloc, and retain count returns to 1;
finally you assign it to rootViewController, which is a retained property, so again lviewController retain count is 2;
finally when you "swap" view controller in your window, the lviewController is released, so it retain count becomes 1. As you can see, it will never be dealloc'd. This means that each time you call this function, you make a leak.
You require to change some of your statement in your code ..
This line have no meaning ..
imgView = UIViewContentModeScaleToFill;
There is a function by using that you have to set the value of the UIImageView property to UIViewContentModeScaleToFill find that in a UIImageView documentation.
[imageView setContentMode:UIViewContentModeScaleToFill];
The same with this...
lviewController.view = nil; //Remove this from your code ..
And finally change the implmentation for the dealloc function and remember [super dealloc]; should be in the last in any implementation of dealloc .
- (void)dealloc {
[imgView release];
imgView = nil;
[super dealloc];
}
The probable leak is due to the code inside "SecondViewController", "MainViewController", "ViewController" classes. And the reason for crash is you are releasing image view after [super dealloc]
try this,
- (void)dealloc {
[imgView release];
imgView = nil;
[super dealloc];
}
I wanted to add Scroll view to my UIimage views which are created dynamically and when i click on that images i want some action to be performed but it is not working through my code.Kindly help me...
Code :-
#import <UIKit/UIKit.h>
#class AppDelegate_iPhone,Litofinter,ParsingViewController;
#interface FirstViewController : UIViewController {
NSMutableArray *array;
NSString *logoString;
AppDelegate_iPhone *appDelegate;
ParsingViewController *obj;
UIScrollView *scrollView;
}
#property (nonatomic,retain)UIScrollView *scrollView;
#end
- (void)viewDidLoad {
[super viewDidLoad];
int x=5,y=10;
appDelegate = (AppDelegate_iPhone *)[[UIApplication sharedApplication] delegate];
scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)];
scrollView.contentSize = CGSizeMake(320,460);
scrollView.showsVerticalScrollIndicator = YES;
scrollView.showsHorizontalScrollIndicator = YES;
[self.view addSubview:scrollView];
for (Litofinter *lito in appDelegate.logoArray) {
NSString * urlString = [lito.cLogo stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
NSURL * imageURL = [NSURL URLWithString:urlString];
NSData * imageData = [NSData dataWithContentsOfURL:imageURL];
UIImage * image = [UIImage imageWithData:imageData];
UIImageView *imgView = [[UIImageView alloc] initWithImage:image];
[imgView setFrame:CGRectMake(x, y, 196, 90)];
[scrollView addSubview:imgView];
UITapGestureRecognizer *tgr = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(onTapImage)];
[imgView addGestureRecognizer:tgr];
[tgr release];
[imgView release];
//Do the rest of your operations here, don't forget to release the UIImageView
x = x + 200;
}
}
-(void)onTapImage
{
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Message from mAc" message:#"Trail" delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"Ok",nil];
[alert show];
}
#end
You probably forget to set the .userInteractionEnabled property of your imageView.
Make sure you set it right.
Guys, i thought i found the solution but no.... i making app cont. from past 16 hrs, may be that's y my empty mind is not making any good sound... plz help me..
I am setting Tag to my dynamically generated imageviews and setting tapgestureReconizers on that,tags are given to UITapGestureRecognizer, i want to perform different actions on click on different images, but when ever click on any image it says very silently... :| EXC_BAD_ACCESS.
Code: -
#import <UIKit/UIKit.h>
#class AppDelegate_iPhone,Litofinter,ParsingViewController;
#interface FirstViewController : UIViewController<UIGestureRecognizerDelegate>{
NSMutableArray *array;
NSString *logoString;
AppDelegate_iPhone *appDelegate;
ParsingViewController *obj;
UIScrollView *scrollView;
NSMutableArray *idArray;
}
#property (nonatomic,retain)UIScrollView *scrollView;
-(void)onTapImage:(UITapGestureRecognizer *)recognizer;
#end
#import "FirstViewController.h"
#import "AppDelegate_iPhone.h"
#import "Litofinter.h"
#import "ParsingViewController.h"
#implementation FirstViewController
#synthesize scrollView;
-(id)init{
if(self == [super init]){
obj = [[ParsingViewController alloc] init];
array = [[NSArray alloc] initWithArray: obj.LogoMutableArray];
}
return self;
}
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
int x=20,y=10;
int a=50,b=105;
appDelegate = (AppDelegate_iPhone *)[[UIApplication sharedApplication] delegate];
scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0,500, 460)];
scrollView.contentSize = CGSizeMake(320,800);
scrollView.showsVerticalScrollIndicator = YES;
for (Litofinter *lito in appDelegate.logoArray) {
NSString * urlString = [lito.cLogo stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
NSURL * imageURL = [NSURL URLWithString:urlString];
NSData * imageData = [NSData dataWithContentsOfURL:imageURL];
UIImage * image = [UIImage imageWithData:imageData];
UIImageView *imgView = [[UIImageView alloc] initWithImage:image];
[imgView setFrame:CGRectMake(x, y, 140, 90)];
imgView.userInteractionEnabled = YES;
imgView.multipleTouchEnabled = YES;
imgView.backgroundColor = [UIColor blueColor];
// imgView.tag = lito.cId;
// NSLog(#"Tag Id = %#",imgView.tag);
NSLog(#"Tag Id = %#",lito.cId);
UITapGestureRecognizer *tgr = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(onTapImage:)];
tgr.delegate = self;
[imgView addGestureRecognizer:tgr];
[scrollView addSubview:imgView];
tgr.view.tag =(int)[NSString stringWithFormat:#"%#",lito.cId];
NSLog(#"Tag Id = %#",tgr.view.tag);
// NSLog(#"Tag Id = %#",lito.cId);
UILabel *cName = [[UILabel alloc]initWithFrame:CGRectMake(a, b, 130, 20)];
cName.text = lito.cName;
[scrollView addSubview:cName];
//Do the rest of your operations here, don't forget to release the UIImageView
x = x + 150;
a = a + 140;
if(x >300)
{
y = y +140;
x = 20;
b = b +150;
a = 50;
}
//[tgr release];
[imgView release];
}
[self.view addSubview:scrollView];
}
-(void)onTapImage:(UITapGestureRecognizer *)recognizer;
{
NSLog(#"Tapped Image tag: %#", recognizer.view.tag);
//NSLog(#"Tapped Image Id ======================== %#",scrollView.gestureRecognizers);
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Message from mAc" message:[NSString stringWithFormat:#"Tag Id : %#",recognizer.view.tag] delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"Ok",nil];
[alert show];
}
- (void)dealloc {
[super dealloc];
[scrollView release];
}
#end
This could be due to you trying to log an int as a string in your -(void)onTapImage:(UITapGestureRecognizer *)recognizer selector:
NSLog(#"Tapped Image tag: %#", recognizer.view.tag);
instead, replace %# with %i:
NSLog(#"Tapped Image tag: %i", recognizer.view.tag);
I have the following code which works fine UIScrollView. But when loading the picture can be seen only at the last subview and UIActivityIndicatorView not working for loading each picture.
How to be done for such a task?
myProject2ViewController.h
#import <UIKit/UIKit.h>
#import "PageScrollView.h"
#interface myProject2ViewController : UIViewController
{
NSMutableArray *pages;
PageScrollView *scrollView;
UIView *myOneSubview;
UIImageView *imageView;
UIActivityIndicatorView *myIndicator;
}
#property (nonatomic, retain) PageScrollView *scrollView;
#property (nonatomic, retain) UIImageView *imageView;
#property (nonatomic, retain) UIActivityIndicatorView *myIndicator;
#end
myProject2ViewController.m
#import "myProject2ViewController.h"
#implementation myProject2ViewController
#synthesize scrollView;
#synthesize imageView;
#synthesize myIndicator;
- (void)dealloc
{
[super dealloc];
}
- (void)viewDidLoad
{
[super viewDidLoad];
NSArray *imageUrls = [NSArray arrayWithObjects:
#"link_1",
#"link_2",
#"link_3",
nil];
pages = [[NSMutableArray alloc] init];
for (int i = 0; i < [imageUrls count]; i++) {
CGRect frameOne = CGRectMake(0.0f, 50.0f, 320.0f, 416.0f);
myOneSubview = [[UIView alloc] initWithFrame:frameOne];
myOneSubview.backgroundColor = [UIColor blackColor];
NSString *imageUrl = [imageUrls objectAtIndex:i];
myIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
myIndicator.center = CGPointMake(160.0f, 130.0f);
myIndicator.hidesWhenStopped = YES;
myIndicator.backgroundColor = [UIColor clearColor];
imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0f, 50.0f, 320.0f, 416.0f)];
[NSThread detachNewThreadSelector:#selector(loadImages:) toTarget:self withObject:imageUrl];
[myOneSubview addSubview:imageView];
[pages addObject:myOneSubview];
}
scrollView = [[PageScrollView alloc] initWithFrame:self.view.frame];
scrollView.pages = pages;
scrollView.delegate = self;
self.view = scrollView;
}
- (void)loadImages:(NSString *)string
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[myIndicator startAnimating];
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
NSData *imageData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:string]];
UIImage *image = [[UIImage alloc] initWithData:imageData];
[imageView setImage:image];
[image release];
[imageData release];
[self performSelectorOnMainThread:#selector(loadImageComplete) withObject:self waitUntilDone:YES];
[pool drain];
}
-(void)loadImageComplete
{
NSLog(#"Load image complete!");
[myIndicator stopAnimating];
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}
#end
When you do:
CGRectMake(0.0f, 50.0f, 320.0f, 416.0f);
Inside your for loop, you're specifying those same exact position and dimension for EVERY image you create in the for loop. In other words, every next image you create will sit ontop of the previous image, as a result, you will only see the final image you created in the for loop.
Try adding your counter "i" variable to the X and Y value in CGRectMake() to offset every image that gets subsequently created.
So let say each image was 100 pixel by 100 pixel, then something like:
CGRectMake(0.0f + (i * 100.0f), 50.0f, 320.0f, 416.0f);
Would make each image sit right after the previous one (since each image is 100 pixel wide, we offset it by 100 pixel and use that value as the starting point of the next image). If you add an extra value after (i * 100) so it becomes (i * 100 + 50) then that would give you a left padding of 50 pixels from the previous image.
If your images are different dimensions you'll need to calculate the width and height of the image before hand and factor those into your CGRectMake() method.
Hope that helps.
In addition, instead of creating so many views to add to your scroll view, you could write the code like so:
scrollView = [[UIScrollview alloc] init];
. . .
for(...)
{
UIImageView *currentImage = [[UIImageView alloc] initWithFrame:CGRectMake(0.0f + (i * 100.0f), 50.0f, 320.0f, 416.0f);
[currentImage setImage:[UIImage imageNamed:[imageUrls objectAtIndex:i]]];
. . .
[scrollView addSubview: currentImage];
[currentImage release];
}
I am programmatically adding a UIImageView and a UILabel to multiple screens in a program I'm working on. As such, I've written a UIViewController that contains the code to load up the UIImageView and UILabel in viewDidLoad, along with a timer to update the contents. I use this view controller as a superclass for any views that need the UIImageView and UILabel.
For the most part it works fine, but when transitioning from specific screens the pair seem to start with a frame of (0,0,0,0) and slowly animate to the frame I've defined. I have no idea what the issue is or even where to look. Any pointers here would be great.
Here is the code I'm using as my superclass.
FoundationViewController.h
#import
#interface FoundationViewController : UIViewController {
IBOutlet UIImageView *activeInventoryImage;
IBOutlet UILabel *activeInventoryLabel;
NSTimer *inventoryStatusTimer;
}
#property (nonatomic, retain) IBOutlet UIImageView *activeInventoryImage;
#property (nonatomic, retain) IBOutlet UILabel *activeInventoryLabel;
- (void) advanceToView:(id)nextView;
- (void) inventoryStatus;
- (BOOL) inventoryActive:(NSDate*)inventoryExpire withImage:(NSString*)imageName;
#end
FoundationViewController.m
#import "FoundationViewController.h"
#import "GameData.h"
#import "Globals.h"
#implementation FoundationViewController
#synthesize activeInventoryImage;
#synthesize activeInventoryLabel;
- (void) viewDidLoad{
// initialize the active inventory icon and label
activeInventoryImage = [[UIImageView alloc] init];
activeInventoryLabel = [[UILabel alloc] init];
// clear
activeInventoryImage.image = [UIImage imageNamed:#""];
activeInventoryLabel.text = #"";
// set the center points
activeInventoryImage.frame = CGRectMake(258, 7, 20, 20);
activeInventoryLabel.frame = CGRectMake(280, 6, 30, 20);
// set label parameters
activeInventoryLabel.backgroundColor = [UIColor clearColor];
activeInventoryLabel.font = [UIFont fontWithName:#"Helvetica" size:11.0f];
activeInventoryLabel.textColor = [UIColor colorWithRed:0.2 green:0.4 blue:0.6 alpha:1];
// add to view
[self.view addSubview:activeInventoryImage];
[self.view addSubview:activeInventoryLabel];
// start the timer if there is any active inventory
if(
[self inventoryActive:[GameData sharedGameData].player.inventory.aExpire withImage:#"a.png"] ||
[self inventoryActive:[GameData sharedGameData].player.inventory.bExpire withImage:#"b.png"] ||
[self inventoryActive:[GameData sharedGameData].player.inventory.cExpire withImage:#"c.png"]
)
inventoryStatusTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(inventoryStatus) userInfo:nil repeats:YES];
[super viewDidLoad];
}
- (BOOL) inventoryActive:(NSDate*)inventoryExpire withImage:(NSString*)imageName{
NSTimeInterval expireSeconds;
NSDateFormatter *formatter;
BOOL runTimer = FALSE;
// expire
expireSeconds = [inventoryExpire timeIntervalSinceNow];
if(expireSeconds > 0){
formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"mm:ss"];
NSDate *expireTime = [NSDate dateWithTimeIntervalSince1970:expireSeconds];
activeInventoryImage.image = [UIImage imageNamed:imageName];
activeInventoryLabel.text = [formatter stringFromDate:expireTime];
[formatter release];
runTimer = TRUE;
}
return runTimer;
}
- (void) inventoryStatus{
// if there is no active inventory kill the timer
if(
![self inventoryActive:[GameData sharedGameData].player.inventory.aExpire withImage:#"a.png"] &&
![self inventoryActive:[GameData sharedGameData].player.inventory.bExpire withImage:#"b.png"] &&
![self inventoryActive:[GameData sharedGameData].player.inventory.cExpire withImage:#"c.png"]
){
activeInventoryImage.image = [UIImage imageNamed:#""];
activeInventoryLabel.text = #"";
if(inventoryStatusTimer != nil)
[inventoryStatusTimer invalidate];
}
}
- (void) advanceToView:(id)nextView{
if([nextView isKindOfClass:[UIView class]]){
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:2.7];
[UIView setAnimationTransition:UIViewAnimationTransitionNone forView:self.view cache:YES];
[self.view addSubview:nextView];
[UIView commitAnimations];
}
else
NSLog(#" Error Loading View: %#",nextView);
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[activeInventoryImage removeFromSuperview];
[activeInventoryImage release];
[activeInventoryLabel release];
[super dealloc];
}
#end
Put a break point in advanceToView as this seems to be your only animation code. Everytime it gets called, look at the call stack in the debugger. From here, you can see what is calling this code when they are not supposed to be.
After some experimenting I've discovered using initWithFrame corrects the drifting problem.
activeInventoryImage = [[UIImageView alloc] initWithFrame:CGRectMake(258, 7, 20, 20)];
activeInventoryLabel = [[UILabel alloc] initWithFrame:CGRectMake(280, 6, 30, 20)];
I still have no idea what the root cause of the issue is. If anyone could tell me what's going on here I would love to know for future reference.