How can I view subview with an activity indicator? - iphone

I need to view a subview with an activity indicator.
This is my code but the subview doesn't appear:
#interface ProgressViewController : UIViewController {
IBOutlet UIActivityIndicatorView *myActivityIndicator;
}
#property (nonatomic, retain) IBOutlet UIActivityIndicatorView *myActivityIndicator;
#end
#implementation ProgressViewController
#synthesize myActivityIndicator;
- (void)viewDidLoad {
[myActivityIndicator startAnimating];
[super viewDidLoad];
}
- (void)viewWillDisappear:(BOOL)animated {
[myActivityIndicator stopAnimating];
}
#end
#import "ProgressViewController.h"
#interface MyViewController : UIViewController {
ProgressViewController *progressViewController;
}
#property (nonatomic, retain) ProgressViewController *progressViewController;
#end
#implementation MyViewController
#synthesize progressViewController
- (void)viewDidLoad
{
progressViewController = [[ProgressViewController alloc] initWithNibName:#"ProgressViewController" bundle:nil];
[self.view addSubview:progressViewController.view];
sleep(4);
[progressViewController.view removeFromSuperview];
[super viewDidLoad];
}
#end

There could be several causes, and it's still a bit unclear from the code you sent, which one it is.
First, you shouldn't use sleep(4) in your code - it messes up the application engine iOS runs to support user input, screen refresh, etc.
Your code could easily be changed to:
[self performSelector:#selector(removeMyProgressView:) withObject:progressViewController.view afterDelay:4.0];
and have removeFromSuperview in your removeMyProgressView: function.
Also, this line of code is buggy:
progressViewController = [[ProgressViewController alloc] initWithNibName:#"ProgressViewController" bundle:nil];
It should be
self.progressViewController = [[ProgressViewController alloc] initWithNibName:#"ProgressViewController" bundle:nil];
Otherwise you don't call the setter function (#sythesized property), and the object isn't retained. It could be that it is released, and therefore you don't see it.
If this none of this is right, we'll keep pounding at it :)
Good luck!
Oded.

Everything in your -viewDidLoad method happens in one runloop. This means that you add and remove the activity indicator without giving the system a chance to actually draw it. The 4 seconds of sleep don't help. Those just make the runloop take longer to finish.

call [super viewDidLoad] before anything in - (void)viewDidLoad methods

Related

I'm trying to initialize a UIViewController to be pushed

I began from a tutorial example that had a UIViewController connected to a nib, but now i've decided to do it all programmatically. Consequently, I deleted the nib but without knowing how to implement my controller.
I did something like this:
EventsDetailController *myChild = [[EventsDetailController alloc] init];
[self.navigationController pushViewController:myChild animated:YES];
However, it crashes when I click the specific cell.
Do I have to initWith something? Before when I had a nib it was initWithNib
#import <UIKit/UIKit.h>
#interface EventsDetailController : UIViewController {
NSString *message;
}
#property (nonatomic, copy) NSString *message;
#end
#import "EventsDetailController.h"
#implementation EventsDetailController
#synthesize message;
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
}
-(void)viewDidLoad{
UILabel *theMsg = [[UILabel alloc] initWithFrame:CGRectMake(0,0,200,30)];
theMsg.text = #"hello";
[theMsg release];
[super viewDidLoad];
}
-(void)viewDidUnload{
self.message = nil;
[super viewDidUnload];
}
-(void)dealloc{
[message release];
[super dealloc];
}
#end
Perhaps, I'll start from scratch, I think it is still looking for the nib I deleted.
I'm assuming that you have the app delegate's window.rootViewController set to a NavigationController instance, and that instance was created with a initWithRootViewController, as you mentioned that you're getting to the point where it crashes when you click on a cell.
Looking at the added code, the only thing I see that's strange is in the 'veiwDidLoad' method - you alloc and release 'theMsg', but don't use it. I'm assuming you've cut out some code for brevity.
I ended up starting from scratch when I went away from .nib files (about 5 minutes after starting my first iPhone app). I would run with that, adding in your functionality a little at a time.

Iphone : unrecognized selector sent to instance & viewDidLoad isn't running

I'm developing an application.
I used a TabBar and every tab have its Class (FirstViewController, SecondViewController, ... )
There is one AppDelegate too.
When I launch the program, the first Class is running.
When i select the second tab, the Secondview.xib 's running but the "viewDidLoad" isn't working.
When I select the third Tab, that's the same.
I've put some buttons on the third tab, and when I push it, I have a
> -[UIViewController testAuthentication:]: unrecognized selector sent to instance 0x5f16920
2011-04-08 13:46:42.511 e-mars[19501:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIViewController testAuthentication:]: unrecognized selector sent to instance 0x5f16920'
Here's the code of my classes
SecondViewController.h
#import <UIKit/UIKit.h>
#interface SecondViewController : UIViewController {
}
#end
SecondViewController.m
#import "SecondViewController.h"
#implementation SecondViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"viewDidLoad de SecondViewController");
NSURL *url = [NSURL URLWithString: #"http://iosdevelopertips.com/images/logo-iphone-dev-tips.png"];
UIImage *image = [UIImage imageWithData: [NSData dataWithContentsOfURL:url]];
[self.view addSubview:[[UIImageView alloc] initWithImage:image]];
}
- (void)dealloc {
[super dealloc];
}
#end
ThirdViewController.h
#import <UIKit/UIKit.h>
#interface ThirdViewController : UIViewController {
IBOutlet UITextField *login;
IBOutlet UITextField *motdepasse;
NSMutableData *responseData;
}
#property (retain, nonatomic) UITextField *login;
#property (retain, nonatomic) UITextField *motdepasse;
#property (retain, nonatomic) NSMutableData *responseData;
- (IBAction) testAuthentication: (id)sender;
- (IBAction) saveAuthentication: (id)sender;
#end
ThirdViewController.m
#import "ThirdViewController.h"
#implementation ThirdViewController
#synthesize login;
#synthesize motdepasse;
#synthesize responseData;
- (id)initWithFrame:(CGRect)frame {
//if ((self = [super initWithFrame:frame])) {
// Initialization code
//}
return self;
}
-(IBAction) testAuthentication: (id)sender {
//NSLog(#"testAuthentication");
}
- (IBAction) saveAuthentication: (id)sender {
NSLog(#"saveAuthentication");
}
- (void)dealloc {
[login dealloc];
[motdepasse dealloc];
[responseData dealloc];
[super dealloc];
}
#end
Your third ViewController doesn't actually create an instance, so no instance methods can be called upon it. Fix your initWithFrame: method. Remember: instance methods start with the '-' sign, class methods start with the '+' sign.
- (id)initWithFrame:(CGRect)frame {
self = [super initWithNibName:nil bundle:nil];
if (self)) {
// Initialization code
}
return self;
}
- (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle
{
return [self initWithFrame:CGRectZero];
}
- (id)init
{
return [self initWithFrame:CGRectZero];
}
After you fixed this, at least the viewDidLoad method in the third ViewController should work.
With regards to the second ViewController, could you please show the code you use to instantiate the ViewController?
Edit: I've made some changed to make sure initWithFrame: is always called upon initialization, just in case you create the instance using another method (initWithNibName:bundle: or init), now initWithFrame: has become the designated initializer.
Set class in Viewcontroller.
and then try.
Check the Object On which your are calling testAuthentication
May be you are calling testAuthentication on secondViewController's object , Just check and let us know
First time alone the viewController will come from viewDidLoad after that it does not call viewDidLoad instead it calls viewWillAppear. so you can code whatever you want in viewWillAppear.

Calling navigation controller method from background operation

I'm running a background operation using NSOperation, which gets kicked off from my AppDelegate. What I want to do is when the operation is complete, have it call a method in the RootViewController.m file.
Currently there's a property in my AppDelegate named navigationController, and I"ve been trying to set up the call like this:
AppDelegate.m:
GetRSSOperation *gro = [[GetRSSOperation alloc] initWithURL:rssURL target:self selector:#selector(dataSourceDidFinishLoadingNewData:)];
[queue addOperation:gro];
[gro release];
GetRSSOperation.m:
[target performSelectorOnMainThread:selector withObject:alerts waitUntilDone:YES];
I have tried setting the target to self, self.navigationController, self.navigationController.view but none work.
I am aware that the issue might be due to my not yet having a complete understanding of the entire ios architecture, so would appreciate any pointers please.
**Adding more code to explain:
AppDelegate.h
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#interface AppDelegate : NSObject {
NSOperationQueue *queue;
UIWindow *window;
UINavigationController *navigationController;
NSURL *rssURL;
// storage for the alert list from RSS feed
NSMutableArray *alerts;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
#property (nonatomic, retain) NSMutableArray *alerts;
#property (nonatomic, retain) NSURL *rssURL;
#property (retain) NSOperationQueue *queue;
+ (id)shared;
#end
AppDelegate.m
#import "AppDelegate.h"
#import "RootViewController.h"
#import "AlertViewController.h"
#import "RefreshTableHeader.h"
#import "GetRSSOperation.h"
#implementation AppDelegate
static AppDelegate *shared;
#synthesize window, navigationController, alerts;
- (id)init
{
if (shared) {
[self autorelease];
return shared;
}
if (![super init]) return nil;
queue = [[NSOperationQueue alloc] init];
shared = self;
return self;
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Add the navigation controller's view to the window and display.
UIImageView *imageview=[[UIImageView alloc]initWithFrame:CGRectMake(270, 3, 37, 37)];
imageview.image=[UIImage imageNamed:#"iphone.png"];
[self.navigationController.navigationBar addSubview:imageview];
[self.window addSubview:navigationController.view];
[self.window makeKeyAndVisible];
if (rssURL == nil) {
NSString *alertAddress = #"http://www.compoundstockearnings.com/com/public/selections.cfc?method=getrss&email=";
alertAddress = [alertAddress stringByAppendingString:cseLogin];
alertAddress = [alertAddress stringByAppendingString:#"&password="];
alertAddress = [alertAddress stringByAppendingString:csePass];
rssURL = [[NSURL alloc] initWithString:alertAddress];
}
GetRSSOperation *gro = [[GetRSSOperation alloc] initWithURL:rssURL target:self selector:#selector(dataSourceDidFinishLoadingNewData:)];
[queue addOperation:gro];
[gro release];
return YES;
}
return NO;
}
#end
GetRSSOperation just does the rss call, puts it in memory then tries to call the main navigation controller:
[target performSelectorOnMainThread:selector withObject:alerts waitUntilDone:YES];
The main navigation controller upon which I wish the thing to execute a selector, looks like this:
RootViewController.h
#import <UIKit/UIKit.h>
#interface RootViewController : UITableViewController {
IBOutlet RefreshTableHeader *alertTable;
UIImageView *imageView;
}
#end
RootViewController.m:
#import "RootViewController.h"
#import "AppDelegate.h"
#implementation RootViewController
- (void)dataSourceDidFinishLoadingNewData:(NSMutableArray *)tempAlerts
{
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
appDelegate.alerts = tempAlerts;
reloading = NO;
[alertTable flipImageAnimated:NO];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:.3];
[self.tableView setContentInset:UIEdgeInsetsMake(0.0f, 0.0f, 0.0f, 0.0f)];
[alertTable setStatus:kPullToReloadStatus];
[alertTable toggleActivityView:NO];
[UIView commitAnimations];
[popSound play];
}
Obviously I've shortened it a bit but that's the core of it. I just want the GetRSSOperation to be able to call RootViewController.m - dataSourceDidFinishLoadingNewData. any input appreciated.
It sounds like you're having a bit of trouble figuring out just how to format the call to performSelectorOnMainThread:withObject:waitUntilDone: correctly. It's pretty simple, really.
If you would normally call the method like this:
[target method:alerts]
you format the performSelector call like this:
[target performSelectorOnMainThread:#selector(method:) withObject:alerts waitUntilDone:YES];

How to pass a variable from one view controller to another?

I have three view controllers, one root controller, one login view controller and one customers view controller. I want to pass the entered username and password in login view controller to the customers view controller. My files and code is displayed below, could you please guide me, how can access to variables set in the login view controller? Or how can I pass variables to customers view controller?
I have these class files:
/classes/MySoftwareAppDelegate.h
/classes/MySoftwareAppDelegate.m
/classes/ViewController.h
/classes/ViewController.m
/classes/LoginController.h
/classes/LoginController.m
/classes/CustomersController.h
/classes/CustomersController.m
I have these views:
/resources/MainWindow.xib
/resources/Login.xib
/resources/Customers.xib
In the AppDelegate, I have successfully inserted the sub view "Login" and it's displayed whenever the app starts.
In the login view, I enter my username and password and then click the "Login" button. When this button is clicked, an IBAction is triggered. In this IBAction, I want to change the current subview with the Customers.
Here's the code I have used:
MySoftwareAppDelegate.h
#import <UIKit/UIKit.h>
#class ViewController;
#interface MySoftwareAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
ViewController *viewController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet ViewController *viewController;
#end
MySoftwareAppDelegate.m
#import "MySoftwareAppDelegate.h"
#import "ViewController.h"
#implementation MySoftwareAppDelegate
#synthesize window;
#synthesize viewController;
- (void)applicationDidFinishLaunching:(UIApplication *)application {
// Override point for customization after application launch
[window addSubview:viewController.view];
[window makeKeyAndVisible];
}
- (void)dealloc {
[viewController release];
[window release];
[super dealloc];
}
#end
ViewController.h
#import <UIKit/UIKit.h>
#class LoginController;
#interface ViewController : UIViewController {
LoginController *loginController;
}
#property (nonatomic, retain) LoginController *loginController;
#end
ViewController.m
#import "ViewController.h"
#import "LoginController.h"
#implementation ViewController
#synthesize loginController;
- (void)viewDidLoad {
LoginController *tmpViewController = [[LoginController alloc] initWithNibName:#"Login" bundle:nil];
self.loginController = tmpViewController;
[self.view insertSubview:loginController.view atIndex:0];
[tmpViewController release];
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
if (self.loginController.view.superview == nil) {
self.loginController = nil;
}
// 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 {
[loginController release];
[super dealloc];
}
#end
LoginController.h
#import <UIKit/UIKit.h>
#class CustomersController;
#interface LoginController : UIViewController {
UIButton *loginButton;
UITextField *usernameTextField;
UITextField *passwordTextField;
NSMutableString *available_credits;
NSString *current_xml_element;
CustomersController *customersController;
}
#property (nonatomic, retain) IBOutlet UIButton *loginButton;
#property (nonatomic, retain) IBOutlet UITextField *usernameTextField;
#property (nonatomic, retain) IBOutlet UITextField *passwordTextField;
#property (nonatomic, retain) NSMutableString *available_credits;
#property (nonatomic, retain) NSString *current_xml_element;
#property (nonatomic, retain) CustomersController *customersController;
-(IBAction)textFieldDoneEditing:(id)sender;
-(IBAction)backgroundTap:(id)sender;
-(IBAction)loginToAccount:(id)sender;
#end
LoginController.m
#import "LoginController.h"
#import "CustomersController.h"
#implementation LoginController
#synthesize loginButton;
#synthesize usernameTextField;
#synthesize passwordTextField;
#synthesize customersController;
- (void)viewDidLoad {
UIImage *buttonImageNormal = [UIImage imageNamed:#"whiteButton.png"];
UIImage *stretchableButtonImageNormal = [buttonImageNormal stretchableImageWithLeftCapWidth:12 topCapHeight:0];
UIImage *buttonImagePressed = [UIImage imageNamed:#"blueButton.png"];
UIImage *stretchableButtonImagePressed = [buttonImagePressed stretchableImageWithLeftCapWidth:12 topCapHeight:0];
[loginButton setBackgroundImage:stretchableButtonImageNormal forState:UIControlStateNormal];
[loginButton setBackgroundImage:stretchableButtonImagePressed forState:UIControlStateHighlighted];
}
- (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 {
[usernameTextField release];
[passwordTextField release];
[super dealloc];
}
-(IBAction)textFieldDoneEditing:(id)sender {
[sender resignFirstResponder];
}
-(IBAction)backgroundTap:(id)sender {
[usernameTextField resignFirstResponder];
[passwordTextField resignFirstResponder];
}
-(IBAction)loginToAccount:(id)sender {
// bla bla bla... Login check process is done here
CustomersController *tmpViewController = [[CustomersController alloc] initWithNibName:#"Customers" bundle:nil];
self.customersController = tmpViewController;
[self presentModalViewController:tmpViewController animated:YES];
[self.view removeFromSuperview];
[tmpViewController release];
}
#end
As you can see above, in LoginController.m's loginToAccount method, I am checking the login info and then setting the new view controller for the "customers" sub-view.
Then I am removing the current "Login" subview from the super view but don't know how to add the new "Customers" sub view.
In MainWindow.xib, I have one view controller which is linked to ViewController class and it's the root contoller.
Any help is appreciated. Because I am new to Objective-C and iPhone programming, please do your best to explain considering a novice programmer :)
Thanks again.
Okay, let me answer my question. I just found the answer on StackOverFlow.com
In the view controller which is going to load the next view controller, just add these lines:
NextController *tmpViewController = [[NextController alloc] initWithNibName:#"NextView" bundle:nil];
tmpViewController.enteredUsername = usernameTextField.text;
tmpViewController.enteredPassword = passwordTextField.text;
I'd say that better way is to have separate class for storing globally needed data (and that would be compliant with MVC model).
For example you can store you login information in your MySoftwareAppDelegate, which is easily accessible with [[UIApplication sharedApplication] delegate] call from any part of your application.
It all depends on how serious the data you want to pass it. For a quick variable (maybe a settings change in a modal view controller) TamTam's solution makes the most sense. You alloc/init'ed it, you got the variable, why not access it properties? That same (modally presented) view controller might pass variables back via a delegate pattern.
If you're data needs to be system wide, you can use the singleton pattern. Using "[[UIApplication sharedApplication] delegate]" gets the application delegation (which is a singleton), and many people stuff their variables there for convenience. However, your app delegate wasn't designed for this, and so it's considered bad form. Create your own singleton if your apple isn't a quickie.
If you use a persistent data store like sql, plists or coredata, you can put your system wide data there.

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.