When I run iphone app on simulator, screen is white - iphone

I don't know what is wrong with the app it was working fine until I tried to change stuff with the textlabel to textview then it crashed. So I tried changing it back to when it worked and it still crashes. Any ideas?
#import "TestViewController.h"
#implementation TestViewController
#synthesize labelsText;
-(void)setup {
titles = [NSArray arrayWithObjects:#"Title 1",#"Title 2",#"Title 3",#"Title 4", nil];
}
-(IBAction) nextclicked:(id)sender{
titles = [NSArray arrayWithObjects:#"iology is the scientific study of life. Bam",#"This works? Wow",#"Still Works.",#"garret is the coolest awesome person awesome wowowowwwwwwwwwwwwwwwwwwwwwwwwwww", nil];
if (step<titles.count-1) {
step++;
}
else
{
step= 0;
}
labelsText.text = [titles objectAtIndex:step];
}
-(IBAction) prevClicked:(id)sender{
titles = [NSArray arrayWithObjects:#"Biology is the scientific study of life. Bam",#"This works? Wow",#"Still Works.",#"garret is the coolest awesome person awesome wowowowwwwwwwwwwwwwwwwwwwwwwwwwww", nil];
if (step>0) {
step--;
}
else
{
step =titles.count-1;
}
labelsText.text = [titles objectAtIndex:step];
}
- (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;
self.labelsText=nil;
}
- (void)dealloc {
[super dealloc];
[labelsText release];
}
#end
.h file:
#import <UIKit/UIKit.h>
#interface TestViewController : UIViewController {
UILabel *labelsText;
UIButton *btn;
int step;
NSArray *titles;
}
#property (nonatomic, retain) UILabel *labelsText;
-(IBAction) nextclicked:(id)sender;
-(IBAction) prevClicked:(id)sender;
#end

I think you missed this:
In your example it should be the labelstext and the button too.

Related

make iPhone vibrate programmatically through IF Else statement [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Making the iPhone vibrate
I have two buttons. One button adds up, one button adds down. The question is when I certain number such as lets say 22 is in the text area, the phone vibrates for a certain mount of time. Here is my code for it:
What I am trying to say is IF Label Displays "22" THEN VIBRATE PHONE... The question is how do i go about writing this.. I'm still learning so any help regarding this would be much appreciated! Here is my code so far:
#import "StartCountViewController.h"
#import "AudioToolbox/AudioServices.h"
#implementation StartCountViewController
int Count=0;
-(void)awakeFromNib {
startCount.text = #"0";
}
- (IBAction)addNumber {
if(Count >= 999) return;
NSString *numValue = [[NSString alloc] initWithFormat:#"%d", Count++];
startCount.text = numValue;
[numValue release];
}
- (IBAction)vibrate {
}
- (IBAction)subtractNumber {
if(Count <= -35) return;
NSString *numValue = [[NSString alloc] initWithFormat:#"%d", Count--];
startCount.text = numValue;
[numValue release];
}
- (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 {
[super dealloc];
}
#end
This is basically a duplicate of Programmatically make the iPhone vibrate
Having said that, I think your code is still going to have errors, and the syntax seems deprecated.
Here's an example. I didn't try this on an actual iphone which would be required to test the vibration, but it should work provided you add the AudioToolbox framework to your project, and of course your XIB file has the necessary connections:
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#property (retain, nonatomic) IBOutlet UILabel *numberLabel;
- (IBAction)addNumber:(id)sender;
- (IBAction)subtractNumber:(id)sender;
#end
ViewController.m
#import "ViewController.h"
#import "AudioToolbox/AudioServices.h"
#interface ViewController ()
{
int count;
}
#end
#implementation ViewController
#synthesize numberLabel;
- (void)viewDidLoad
{
count = 0;
[self updateCount];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[self setNumberLabel:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (void)dealloc
{
[numberLabel release];
[super dealloc];
}
- (IBAction)addNumber:(id)sender
{
if(count >= 999) {
return [self vibrate];
}; // ignore numbers larger than 999
count++;
[self updateCount];
}
- (IBAction)subtractNumber:(id)sender
{
if(count <= -35) {
return [self vibrate];
}; // ignore numbers less than -35
count--;
[self updateCount];
}
-(void)updateCount
{
NSString *countStr = [[NSString alloc] initWithFormat:#"%d",count];
[self.numberLabel setText:countStr];
[countStr release];
}
-(void)vibrate
{
NSLog(#"I'm vibrating");
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
}
#end

Give out a NSMutableArray on a texView on another Viewcontroller in objective-C?

I try to save numbers from a textfield on one viewController in a NSMutableArray when I press a button on this viewContoller. (this is working now)
Then i want the numbers give out on a textview which is on a secondViewController but this dont work. When i want to give out the array on the first Viewcontroller it work fine.
Also i cant erase the NSMutableArray with a button on the SecondviewController.
The SecondviewController have the same class like the viewController.
Can someone show me how i can give out an array on a seconviewcontroller?
Hallo,
at the moment i have this:
//ViewController.h:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController {
NSMutableArray *textViewArray;
}
#property (strong, nonatomic) IBOutlet UITextField *textLable2;
#property (strong, nonatomic) IBOutlet UITextField *textLable1;
- (IBAction)setArrayWithCurrentNumber:(id)sender;
- (IBAction)returnToTextfield:(id)sender;
#end
//this the .m file:
#import "ViewController.h"
#implementation ViewController
#synthesize textLable2;
#synthesize textLable1;
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
textViewArray = [[NSMutableArray alloc]init];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[self setTextLable2:nil];
[self setTextLable1:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (IBAction)setArrayWithCurrentNumber:(id)sender
{
NSString *string1 = self.textLable1.text;
[textViewArray addObject:string1];
NSMutableArray *array = [NSMutableArray arrayWithArray:textViewArray];
NSString *string2 = [array componentsJoinedByString:#" "];
self.textLable2.text = [NSString stringWithString:string2];
NSLog(#"%#",textViewArray);
}
- (IBAction)returnToTextfield:(id)sender
{
[textLable1 resignFirstResponder];
[textLable2 resignFirstResponder];
}
#end
If you're calling the second view controller from the first one you could set a property on the second one to hold the NSMutableArray or just send it on the initializer.
something like:
- (id)initWithArray:(NSMutableArray *)array {
if (self = [super init]) {
myArray = [array copy];
}
return self;
}
assuming your second view controller has declared NSMutableArray * myArray;
Edit: Adding some more code in here...
// I'll assume you use some kind of UINavigationController to show your content
- (void)showSecondViewController {
SecondViewController * vc = [[[SecondViewController alloc] initWithArray:yourMutableArray] autorelease];
[self.navigationController pushViewController:vc];
}

Objective-C Memory management: ViewController in a ViewController that's inside a UITabBarController

I have a UITabBarController with three ViewControllers (A, B, and C). In ViewControllerB I have a UIScrollView. The UIScrollView consists of several instances of my PhotoViewController. These PhotoViewController objects are called from ViewControllerA, not ViewController B, where they're located.
The PhotoViewController instances have a UIImage and a two buttons. And at first, when I clicked on a button in one of my PhotoViewController instances I received a 'Thread 1: Program received signal: "EXC_BAD_ACCESS"' error. Looking around on stackoverflow that error seems to appear whenever there are memory management issues.
Since I was creating the PhotoViewController objects in a loop from a method called in ViewControllerA, and releasing those objects, I figured that by the time I switched over to ViewControllerB they were already released - and hence the memory issue.
But that's just my guess. Could you tell me if I should just stop releasing the PhotoViewController objects inside of the loop code? Because that's what I did (just commented that line out) and the program "works" fine. However, I'm still not sure if this is the proper way to handle it and if it is causing unknown memory management issues.
Here is some of my code:
ViewControllerA.m
//Creating an album in ViewControllerB, the photos in the album are PhotoViewController objects
-(IBAction)showAlbum:(UIButton *)sender
{
//Go goes here to get an album and display it in the UIScrollView
albumID = #"ALBUM_ID";
NSString* graphUrl = [NSString stringWithFormat:#"%#/photos?limit=10", albumID];
[_facebook requestWithGraphPath:graphUrl andDelegate:self];
}
...
- (void)request:(FBRequest *)request didLoad:(id)result {
//Code for array of photos
NSLog(#"%#",result);
NSString *requestType = [request.url stringByReplacingOccurrencesOfString:#"https://graph.facebook.com/" withString:#""];
if ([requestType isEqualToString:[NSString stringWithFormat:#"%#/photos?limit=10", albumID]]){
NSArray *photoAlbumArray=(NSArray*)[result valueForKey:#"data"];
[self.label setText:[NSString stringWithFormat:#"%i", [photoAlbumArray count]]];
for(UIViewController *controller in self.tabBarController.viewControllers)
{
if([controller isKindOfClass:[ViewControllerB class]])
{
ViewControllerB *mtbvc = (ViewControllerB *)controller;
[mtbvc setArray:photoAlbumArray];
self.tabBarController.selectedIndex = 1;//switch over to the second view to see if it worked
}
}
}
...
#end
ViewControllerB.m
//loop where I create PhotoViewController objects
- (void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:YES];
arrayCount = [array count];
scroller.delegate=self;
scroller.pagingEnabled=YES;
scroller.directionalLockEnabled=YES;
scroller.showsHorizontalScrollIndicator=NO;
scroller.showsVerticalScrollIndicator=NO;
//should have an array of photo objects and the number of objects, correct?
scrollWidth = 0;
scroller.contentSize=CGSizeMake(arrayCount*scroller.frame.size.width, scroller.frame.size.height);
for (int i = 0; i < arrayCount;i++) {
PhotoViewController *pvc = [[PhotoViewController alloc] initWithNibName:#"PhotoViewController" bundle:nil];
UIImageView *scrollImageView = [[UIImageView alloc] initWithFrame:CGRectOffset(scroller.bounds, scrollWidth, 0)];
CGRect rect = scrollImageView.frame;
pvc.view.frame = rect;
[pvc view];
pvc.label.textColor = [UIColor whiteColor];
id individualPhoto = [array objectAtIndex:i];
NSLog(#"%#",individualPhoto);
NSArray *keys=[individualPhoto allKeys];
NSLog(#"%#",keys);
NSString *imageURL=[individualPhoto objectForKey:#"source"];
//here you can use this imageURL to get image-data and display it in imageView
NSURL *url = [NSURL URLWithString:imageURL];
NSData *data = [NSData dataWithContentsOfURL:url];
pvc.imageView.image = [[UIImage alloc] initWithData:data];
pvc.label.text = [individualPhoto objectForKey:#"id"];
//check to make sure the proper URL was passed
//I have an imageView next to the UIScrollView to test whether that works - it does.
[scroller addSubview:pvc.view];
[scrollImageView release];
//[pvc release];
scrollWidth += scroller.frame.size.width;
}
if (arrayCount > 3) {
pageControl.numberOfPages=3;
} else {
pageControl.numberOfPages=arrayCount;
}
pageControl.currentPage=0;
//[self.view addSubview:scroller];
}
PhotoViewController.m
#import "PhotoViewController.h"
#implementation PhotoViewController
#synthesize label, imageView;
-(IBAction)likeButton:(UIButton *)sender
{
//code goes here
for(UIViewController *controller in self.tabBarController.viewControllers)
{
if([controller isKindOfClass:[DemoAppViewController class]])
{
DemoAppViewController *davc = (DemoAppViewController *)controller;
[davc likePicture:self.label.text];
}
}
self.tabBarController.selectedIndex = 0;//switch over to the third view to see if it worked
}
-(IBAction)skipButton:(UIButton *)sender
{
//code goes here
}
-(IBAction)likeCommentButton:(UIButton *)sender
{
//code goes here
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)dealloc
{
[super dealloc];
}
- (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.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#end
PhotoViewController.h
#import <UIKit/UIKit.h>
#import "DemoAppViewController.h"
#import "MyTabBarViewController.h"
#interface PhotoViewController : UIViewController {
IBOutlet UILabel *label;
IBOutlet UIImageView *imageView;
UIButton *likeButton;
UIButton *skipButton;
UIButton *likeCommentButton;
}
#property (nonatomic, retain) UILabel *label;
#property (nonatomic, retain) UIImageView *imageView;
-(IBAction)likeButton:(UIButton *)sender;
-(IBAction)skipButton:(UIButton *)sender;
-(IBAction)likeCommentButton:(UIButton *)sender;
#end
To write iOS apps, it is critical that you understand the memory management rules.
In ViewControllerB, viewDidLoad, you alloc the pvc.
Further down, you add the pvc's view as a subview of the scroller. This retains the pvc's view, but not the pvc itself. Then when you release the pvc, it's retain count is zero, and when you reference it later, it's gone. Crash. It seems like you need to pass in and retain a reference to the pvc in the controller that's using it.
I am not sure why you are using PhotoViewController(Subclassing UIViewController) instead of PhotoView(subclassing UIView). As you are not using any of the facility of the viewcontroller(no life cycle method and other).
If you subclass PhotoViewController with UIView and remove the viewcontroller's methods it will work and will not cause any memory issues as you have aleready discussed in your discussion with Rayfleck. ( it will be retained by parent view controller.)
If you are thinking about the events, then these will also be handled by view itself. But if you want to handle it in your controller then you can easily delegate, or pass your controller reference and invoke the event on it.
Thanks,

Making Progress View Visible

I'm working on a very simple iOS app to get me started programming. It's a tab based application, so there is a MainWindow.xib along with a FirstView.xib and SecondView.xib. All of this is happening in the first view. I want to add a Progress bar to the First View, and when I added the object it attached itself to FirstView.xib and shows up and lets me move it around. To test, the alpha is set at 1.00 and the progress is set at 0.5. Regardless of this, it doesn't show up no matter what I do. What am I doing wrong?
AppDelegate.m:
#synthesize window=_window;
#synthesize tabBarController=_tabBarController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Add the tab bar controller's current view as a subview of the window
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application
{
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
}
- (void)applicationWillTerminate:(UIApplication *)application
{
}
- (void)dealloc
{
[_window release];
[_tabBarController release];
[super dealloc];
}
#end
FirstViewController.h:
#import <UIKit/UIKit.h>
NSTimer *stopWatchTimer;
NSDate *startDate;
#interface FirstViewController : UIViewController {
UILabel *label;
UILabel *stopWatchLabel;
UIProgressView *progressBar;
UIButton *topButton;
}
#property (nonatomic, retain) IBOutlet UILabel *stopWatchLabel;
#property (nonatomic, retain) IBOutlet UIProgressView *progressBar;
- (IBAction)onStartPressed:(id)sender;
- (IBAction)onStopPressed:(id)sender;
- (IBAction)onResetPressed:(id)sender;
#end
FirstViewController.m
#import "FirstViewController.h"
#implementation FirstViewController
#synthesize progressBar;
#synthesize stopWatchLabel;
/*
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.*/
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (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
{
[self setStopWatchLabel:nil];
[topButton release];
topButton = nil;
[super viewDidUnload];
// Release any[progress release];
progressBar = nil;
[progressBar release];
progressBar = nil;
[self setProgressBar:nil];
//retained subviews of the[self setProgressBar:nil];
// e.g. self.myOutlet = nil;
}
static NSInteger counter=0;
static NSInteger secs=0;
static NSInteger mins=0;
static NSInteger hrs=0;
- (void)dealloc
{
[stopWatchLabel release];
[label release];
[topButton release];
[super dealloc];
}
-(void)updateTimer {
//updates the timer }
-(void)clearTimer {
//clears the timer
}
-(void)stopTimer{
//stops the timer }
- (IBAction)onStartPressed:(id)sender {
//stopWatchLabel.text=#"Start Pressed";
progressBar.alpha=1.0;
//run timer }
- (IBAction)onStopPressed:(id)sender {
[self stopTimer];
}
- (IBAction)onResetPressed:(id)sender {
[self stopTimer];
[self clearTimer];
}
#end
There are two things you need to do with a view after it's been created: You have to add it as a subview of a visible view and set a proper frame.
Here's how to do that:
[self.view addSubview:progressBar];
progressBar.frame = CGRectMake(x, y, width, height);
EDIT: Probably completely unrelated to your question, but this is all wrong:
- (void)viewDidUnload
{
[self setStopWatchLabel:nil];
[topButton release];
topButton = nil;
[super viewDidUnload];
// Release any[progress release];
progressBar = nil;
[progressBar release];
progressBar = nil;
[self setProgressBar:nil];
//retained subviews of the[self setProgressBar:nil];
// e.g. self.myOutlet = nil;
}
You probably want it to look something like the following:
- (void)viewDidUnload
{
[super viewDidUnload];
[self setStopWatchLabel:nil];
[topButton release];
topButton = nil;
[label release];
label = nil;
self.progressBar = nil;
}
Make sure you understand what you did wrong. It's very important that you get this right or your app will leak and/or crash.
The rest of your code doesn't really do anything. You seem to be doing everything in IB, so I guess that's where your problem is.

iphone app with multiple views/subviews: memory is not being deallocated

I have an iPhone application that loads succesive views in a framework based on the one explained in this link (basically a main ViewController that loads/removes additional views with a displayView method). In my application I am using NIBs (the example link uses coded views) though so each of my ViewControllers has its accompanying nib.
Debugging in Instruments shows no leaks but if I enter/leave a section (ViewController with its View.xib), the nib remains in memory so after a few in/outs memory starts to accumulate.
I know the nib is not being unloaded because one is almost programmatically created (no stuff in IB) while another does have images and buttons created in IB. The large one is loaded first and the small one loads next. You would expect a reduction in allocation in Instruments.
How can I prevent this?
My structure is as follows, with a few comments below:
`MyAppDelegate.h`
#import <UIKit/UIKit.h>
#class RootViewController;
#interface MyAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
RootViewController *viewController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet RootViewController *viewController;
-(void) displayView:(int)intNewView;
#end
`MyAppDelegate.m`
#import "MyAppDelegate.h"
#import "RootViewController.h"
#implementation MyAppDelegate
#synthesize window;
#synthesize viewController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[window addSubview:viewController.view];
[window makeKeyAndVisible];
return YES;
}
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
}
-(void) displayView:(int)intNewView {
[viewController displayView:intNewView];
}
- (void)dealloc {
[viewController release];
[window release];
[super dealloc];
}
#end
This controller handles subview load/removes:
`RootViewController.h`
#import <UIKit/UIKit.h>
#interface RootViewController : UIViewController {
}
- (void) displayView:(int)intNewView;
#end
`RootViewController.m`
#import "RootViewController.h"
#import "ViewController.h"
#implementation RootViewController
UIViewController *currentView;
- (void) displayView:(int)intNewView {
NSLog(#"%i", intNewView);
[currentView.view removeFromSuperview];
[currentView release];
switch (intNewView) {
case 1:
currentView = [[ViewController alloc] initWithNibName:#"View" bundle:nil];
break;
}
[self.view addSubview:currentView.view];
}
- (void)viewDidLoad {
currentView = [[ViewController alloc]
initWithNibName:#"View" bundle:nil];
[self.view addSubview:currentView.view];
[super viewDidLoad];
}
- (void)dealloc {
[currentView release];
[super dealloc];
}
#end
There would be as many case as "detail" ViewControllers I have (right now I have 3 case but this will grow to 10 or more). The purpose of this structure is to easily move from one "section" of the application to another (NavBar controller or TabBar controller do not suit my specific needs).
`ViewController.h`
// Generic View Controller Example
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController {
UIImageView *_image1;
UIImageView *_image2;
NSTimer *_theTimer;
}
#property (nonatomic, retain) IBOutlet UIImageView *image1;
#property (nonatomic, retain) IBOutlet UIImageView *image2;
#property (nonatomic, retain) NSTimer *theTimer;
#end
`ViewController.m`
#import "ViewController.h"
#import "MyAppDelegate.h"
#synthesize image1 = _image1, image2 = _image2, theTimer = _theTimer;
- (void)loadMenu {
[self.theTimer invalidate];
self.theTimer = nil;
MyAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
[appDelegate displayView:2];
}
-(void)setView:(UIView*)aView {
if (!aView){
self.image1 = nil;
self.image2 = nil;
}
[super setView:aView];
}
- (void)viewDidLoad {
//some code
[super viewDidLoad];
}
- (void)viewDidUnload {
self.image1 = nil;
self.image2 = nil;
}
- (void)dealloc {
NSLog(#"dealloc called");
[self.theTimer invalidate];
[self.theTimer release];
[self.image1 release];
[self.image2 release];
[super dealloc];
}
Notice the NSLog in dealloc. This is being called (I can see it in the console) but the memory needed for the nib is not freed (Instruments shows an increase in memory allocation when leaving a section, because a new nib is loaded).
Any help will be greatly appreciated. I have tried a million different things and I cannot get the nibs to unload.
After a million different tries I finally ran into this forum.
It states:
Apparently images assigned in IB are loaded into image views using imageNamed. imageNamed caches the images in a way that makes them unloadable. You could load the images in viewDidLoad with initWithContentsOfFile and then assign them to the views.
Somewhere else I had read that imageNamed is the devil so I'd rather not have my images load that way.
(BTW this is iPhone OS 3.1 I'm using)
What I ended up is leaving the UIImageView intact in IB but with an empty .image value. The modified code is something like:
- (void)viewDidLoad {
NSString *path = [NSString stringWithFormat:#"%#/%#", [[NSBundle mainBundle] resourcePath], #"myImageThatBeforeWasAValueinIB.jpg"];
UIImage *image = [UIImage imageWithContentsOfFile:path];
outlet.image = image;
// do the rest of my stuff as it was
[super viewDidLoad];
}
- (void)dealloc {
outlet.image = nil;
[outlet release], outlet = nil;
[super dealloc];
}
And now everything works like a charm! Memory is recovered when I unload a nib and when I get memory warnings.
So pretty much if you have IBOutlets for UIImageViews and memory is a concern (it always is I guess), you can design all you want in IB and when the time comes to connect them to outlets, remove the image reference in IB and create it from code. IB is really good for laying out your app. It would suck to have to do all that thing by code, but I also found this nice utility that converts nibs to objective c code although I haven't tested it yet.
Did you try setting your outlet variables to nil in dealloc?
You are correctly implementing the setView method, but you are setting your outlet variables to nil in the viewDidUnload method instead of dealloc. As discussed here, you should implement dealloc as follows:
- (void)setView:(UIView *)aView {
if (!aView) { // view is being set to nil
// set outlets to nil, e.g.
self.anOutlet = nil;
}
// Invoke super's implementation last
[super setView:aView];
}
- (void)dealloc {
// release outlets and set outlet variables to nil
[anOutlet release], anOutlet = nil;
[super dealloc];
}
EDIT: if the outlets are UIImageViews, then it may be the case that you need to do
anOutlet.image = nil;
because setting the UIImage’s instance image property should increase the retain count of the UIImage’s instance by 1.