Releasing iVar IBOutlet vs Property IBOutlet - iphone

Can anyone verify my dealloc method is correct? Since my titleLabel and checkImageView are retained I am releasing them in dealloc. However, I am not releasing mainImageView, doneButton, and noteLabel, because they are not retained or alloced during the implementation.
#interface CheckMarkController : UIViewController <UIAlertViewDelegate> {
IBOutlet UIImageView *mainImageView;
IBOutlet UIButton *doneButton;
IBOutlet UILabel *noteLabel;
}
#property (nonatomic, retain) IBOutlet UILabel *titleLabel;
#property (nonatomic, retain) IBOutlet UIImageView *checkImageView;
#property (nonatomic, retain) Event *event;
#property (nonatomic, retain) Workout *workout;
#property (nonatomic, retain) NSManagedObjectContext *managedObjectContext;
#end
- (void)dealloc {
//props
[titleLabel release];
[checkImageView release];
[event release];
[workout release];
[managedObjectContext release];
[super dealloc];

If you connect these three items via Interface Builder you DO need to release them. Outlets are retained by default. KVC (Key Value Coding) is used to set outlets. This means that loadFromNib will call setValue:withKey for each outlet you have set. This uses the #property and it's setter method, but if none are set (as is your case) it retains the object by default.

Related

Memory leak vs Zombie - iPhone

My iPhone app is either crashing due to to a zombie, or leaking memory.. I've narrowed it down to 3 lines of code and can reliably get one of the two things to happen by commenting/uncommenting the code. The bugs occur when navigation between a list of results (tableView) and a details page containing a map and a few labels, memory leak happens the first time I navigation from the map back to the list of results, the zombie occurs after maybe 5/6 times navigating to different results and back.
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#define METERS_PER_MILE 1609.344
#interface ResDetailsPageVC : UIViewController <MKMapViewDelegate, UIAlertViewDelegate> {
UISegmentedControl *mapTypeSwitcher;
MKMapView *mapView;
UILabel *nameLabel;
UIButton *addressLabel;
UILabel *telephoneLabel;
NSString *address;
}
#property (nonatomic, retain) IBOutlet UISegmentedControl *mapTypeSwitcher;
#property (nonatomic, retain) IBOutlet MKMapView *mapView;
#property (nonatomic, retain) IBOutlet UILabel *nameLabel;
#property (nonatomic, retain) IBOutlet UIButton *addressLabel;
#property (nonatomic, retain) IBOutlet UILabel *telephoneLabel;
- (IBAction)segmentedControlIndexChanged;
- (IBAction)callButtonClick;
- (IBAction)addressClick;
- (void) callNumber;
#end
#synthesize mapView;
#synthesize mapTypeSwitcher;
#synthesize nameLabel, addressLabel, telephoneLabel;
- (void)dealloc {
// if these lines are commented out - memory leak
// if not - zombie?!
/*self.telephoneLabel = nil;
self.addressLabel = nil;
self.nameLabel = nil;*/
self.mapView = nil;
self.mapTypeSwitcher = nil;
[super dealloc];
}
Somewhere some other piece of code is using the same object whose address is stored in one of those three properties, but that other piece of code has not properly retained the object.
I recommend this to you:
- (void)dealloc {
[telephoneLabel release]; telephoneLabel = nil;
[addressLabel release]; addressLabel = nil;
....
[super dealloc];
}

Calling a function in viewcontroller from appdelegate

I want to call a function in a viewController from my appDelegate but with the following code, it doesn't get called. What am I doing wrong?
AppDelegate.h:
#import <UIKit/UIKit.h>
#import "DetailsToTransfer.h"
#class AccountDetailTransferViewController;
#interface AccountDetailTransferAppDelegate : NSObject <UIApplicationDelegate> {
DetailsToTransfer *objDetailsToTransfer;
}
#property (nonatomic, retain) DetailsToTransfer *objDetailsToTransfer;
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet AccountDetailTransferViewController *viewController;
-(void)sendToTransferScreen:(NSArray *)detailsArray;
#end
AppDelegate.m:
....
-(void)sendToTransferScreen:(NSArray *)detailsArray {
[objDetailsToTransfer setLabels:detailsArray];
objDetailsToTransfer = [[DetailsToTransfer alloc]initWithNibName:#"DetailsToTransfer" bundle:nil];
[self.window addSubview:objDetailsToTransfer.view];
}
DetailsToTransfer.h:
#import <UIKit/UIKit.h>
#interface DetailsToTransfer : UIViewController {
NSArray *accountDetailsArray;
UILabel *nameLabel;
UILabel *accountLabel;
IBOutlet UIButton *btnTransfer;
IBOutlet UIButton *btnBack;
}
#property (nonatomic, retain) NSArray *accountDetailsArray;
#property (nonatomic, retain) IBOutlet UILabel *nameLabel;
#property (nonatomic, retain) IBOutlet UILabel *accountLabel;
-(IBAction)sendDetails;
-(IBAction)goBack;
-(void)setLabels:(NSArray *)array;
#end
DetailsToTransfer.m
....
-(void)setLabels:(NSArray *)array {
NSLog(#"Setting Labels");
self.nameLabel.text = [array objectAtIndex:0];
self.accountLabel.text = [array objectAtIndex:1];
}
....
I would like to add that all the properties have been synthesized and that I'm calling the method in the appDelegate properly (i checked using NSLogs)
In AppDelegate.m:
Looks as if you are calling a method on your object before the object has been created. Until you have alloc / init your object, there will be no labels to set text.
Try changing your method to this:
-(void)sendToTransferScreen:(NSArray *)detailsArray {
if (!objDetailsToTransfer) {
objDetailsToTransfer = [[DetailsToTransfer alloc]initWithNibName:#"DetailsToTransfer" bundle:nil];
[objDetailsToTransfer setLabels:detailsArray];
[self.window addSubview:objDetailsToTransfer.view];
}
}
The problem might be that you are trying to set the values on a object that hasn't been created yet. I also provided an if statement to prevent the object from being created multiple times.

UIPickerView not returning the correct data

I have a Main view with a landscapeview and a portraitview that gets loaded as subviews of the wrapper view. Both the landscape view and portraitview has UIPickerView objects that are linked to them. In my source I have them all as properties and I also have a wrapper for the landscape and portrait pickers. They are defined as
#property (nonatomic, retain, readonly) IBOutlet UIPickerView *pickerTown;
#property (nonatomic, retain, readonly) IBOutlet UIPickerView *pickerType;
#property (nonatomic, retain, readonly) IBOutlet UIDatePicker *pickerFrom;
#property (nonatomic, retain, readonly) IBOutlet UIDatePicker *pickerTo;
#property (nonatomic, retain) IBOutlet UIPickerView *landscapePickerTown;
#property (nonatomic, retain) IBOutlet UIPickerView *landscapePickerType;
#property (nonatomic, retain) IBOutlet UIDatePicker *landscapePickerFrom;
#property (nonatomic, retain) IBOutlet UIDatePicker *landscapePickerTo;
#property (nonatomic, retain) IBOutlet UIPickerView *portraitPickerTown;
#property (nonatomic, retain) IBOutlet UIPickerView *portraitPickerType;
#property (nonatomic, retain) IBOutlet UIDatePicker *portraitPickerFrom;
#property (nonatomic, retain) IBOutlet UIDatePicker *portraitPickerTo;
And for each of the readonly wrappers I have
- (UIPickerView *) pickerTown
{
if(self.landscapeView.superview)
{
return landscapePickerTown;
}else
{
return portraitPickerTown;
}
}
But when I am in portrait or landscape, and I try for instance to say
myHelper.selectedTown = [myHelper.towns objectAtIndex:[pickerTown selectedRowInComponent:0]];
I don't get the selected value but just the first value in the array.
The data gets added as follows:
if(pickerView == landscapePickerType || pickerView == portraitPickerType) {
return [myHelper.types objectAtIndex:row];
}else if(pickerView == landscapePickerTown || pickerView == portraitPickerTown){
return [myHelper.towns objectAtIndex:row];
}else
{
return #"";
}
and the array:
myHelper = [Helper sharedManager];
[myHelper.types addObject:#"None"];
[myHelper.types addObject:#"Food & Wine"];
[myHelper.types addObject:#"Test"];
[myHelper.towns addObject:#"None"];
[myHelper.towns addObject:#"Vanderbijlpark"];
[myHelper.towns addObject:#"Test"];
What am I doing wrong here?
If you are getting only the first element, it is indicative that [pickerTown selectedRowInComponent:0] is evaluating to zero always which will happen only if pickerTown is nil. That again is most likely due to outlet not being connected.
But in this case I think you are accessing the instance variable directly and not the value the method returns. If you are using #synthesize for pickerTown, make that #dynamic. And change the statement to [self.pickerTown selectedRowInComponent:0] to access the value of the getter.

iPhone UIImageView Array

So I'm declaring a NSMutableArray to hold 5 UIImageViews.
.h file:
#interface ImageDisplay : UIViewController {
IBOutlet UIImageView *img1;
IBOutlet UIImageView *img2;
IBOutlet UIImageView *img3;
IBOutlet UIImageView *img4;
IBOutlet UIImageView *img5;
NSMutableArray *imageHolderArray;
}
#property (nonatomic, retain) IBOutlet UIImageView *img1;
#property (nonatomic, retain) IBOutlet UIImageView *img2;
#property (nonatomic, retain) IBOutlet UIImageView *img3;
#property (nonatomic, retain) IBOutlet UIImageView *img4;
#property (nonatomic, retain) IBOutlet UIImageView *img5;
#property (nonatomic, retain) IBOutlet NSMutableArray *imageHolderArray;
#end
In the .m file:
//All objects are synthesized, just easier not to crowd the screen
- (void)viewDidLoad {
[super viewDidLoad];
imageHolderArray = [[NSMutableArray alloc] initWithObjects: img1,img2,img3,img4,img5,nil];
NSLog(#"imageHolderArray count: %i",[imageHolderArray count]); //Returns count of 1
}
So my question is, why is this happening? Why isn't it picking up all the objects in the Array? I'm not well versed in Objective-C programming so I'd appreciate it if someone could clue me in here. Thank you.
Because you didn't wire the IBOutlets to their views in Interface Builder. Looks like you probably wired img1, but didn't wire img2, so img2 is nil, which marks the end of your list of objects for -initWithObjects: even if later outlets are wired.

How can I store UIButtons in an array?

I have a method tied to four buttons. I want to create an array containing each button, and later retrieve and interact w/ a button from the array. The code I was tinkering with below. When I try to get a button from the array and send it a message, it goes kablooie.
Any thoughts on what I'm doing wrong?
Hack_DumpViewController.h
#import <UIKit/UIKit.h>
#interface Hack_DumpViewController : UIViewController {
IBOutlet UIButton *redButton;
IBOutlet UIButton *greenButton;
IBOutlet UIButton *blueButton;
IBOutlet UIButton *yellowButton;
NSArray *buttonMapping;
}
- (IBAction) changeToYo:(id)sender;
#property (nonatomic, retain) UIButton *redButton;
#property (nonatomic, retain) UIButton *greenButton;
#property (nonatomic, retain) UIButton *blueButton;
#property (nonatomic, retain) UIButton *yellowButton;
#property (nonatomic, retain) NSArray *buttonMapping;
#end
Hack_DumpViewController.m
#import "Hack_DumpViewController.h"
#implementation Hack_DumpViewController
#synthesize redButton;
#synthesize greenButton;
#synthesize yellowButton;
#synthesize blueButton;
#synthesize buttonMapping;
- (IBAction) changeToYo:(id)sender {
NSLog(#"changing numbers!");
for (UIButton *b in buttonMapping) {
[b setTitle:#"yo!"];
}
NSLog(#"changed to numbers!");
}
- (void)viewDidLoad {
buttonMapping = [[NSArray alloc] initWithObjects:greenButton, redButton, yellowButton, blueButton, nil];
}
[NSArray arrayWithObjects:...] returns an autoreleased array, so by the time you use it, it no longer exists and you end up messaging an invalid pointer. What you want is [[NSArray alloc] initWithObjects:...] (remembering to release it in your dealloc).
Why not tag the views in interface builder and then treat them like an array, much easier