iOS initializer parameter is nil - iphone

I'm fairly new to the iOS platform and I'm having some issues with the memory management. I'm passing an object (a Trial) in through an initializer of a custom UIViewController class and when the UIViewController finally receives it, the object is nil. I was hoping someone could point me in the right direction. I've included some of the source code below.
Trial.h
#interface Trial : NSObject {
NSString *IRBNumber;
NSString *PI;
NSString *Sponsor;
NSString *ContactName;
NSString *ContactPhone;
NSString *ContactEmail;
NSString *Location;
NSString *Objective;
NSString *Eligibility;
NSString *Name;
NSString *DiseaseGroup;
NSString *Age;
}
#property (retain, nonatomic) NSString *IRBNumber;
#property (retain, nonatomic) NSString *PI;
#property (retain, nonatomic) NSString *Sponsor;
#property (retain, nonatomic) NSString *ContactName;
#property (retain, nonatomic) NSString *ContactEmail;
#property (retain, nonatomic) NSString *ContactPhone;
#property (retain, nonatomic) NSString *Location;
#property (retain, nonatomic) NSString *Objective;
#property (retain, nonatomic) NSString *Eligibility;
#property (retain, nonatomic) NSString *Name;
#property (retain, nonatomic) NSString *DiseaseGroup;
#property (retain, nonatomic) NSString *Age;
#end
DiseaseControllersViewController.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
Trial *trial = (Trial *)[dataArray objectAtIndex:indexPath.row];
TrialDetailController *detailViewController = [[TrialDetailController alloc] initWithNibNameAndTrial:#"TrialDetailController" bundle:nil trial:trial];
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController release];
[trial release];
}
Here's the definition of the initializer
-(id)initWithNibNameAndTrial: (NSString*)NibNameOrNil bundle:(NSBundle*)nibBundlerOrNil trial:(Trial *)inTrial {
self = [super initWithNibName:NibNameOrNil bundle:nibBundlerOrNil];
if(self) {
self.trial = inTrial;
}
return self;
}
TrialDetailController.h
#import "Trial.h"
#interface TrialDetailController : UITabBarController {
Trial *trial;
}
#property (nonatomic, retain) Trial *trial;
-(id)initWithNibNameAndTrial: (NSString*)NibNameOrNil bundle:(NSBundle*)nibBundlerOrNil trial:(Trial *)inTrial;
-(IBAction)objectiveTabItemClick:(id)sender;
-(IBAction)detailsTabItemClick:(id)sender;
#end

You should not use self.trial within the init-method. Make that trial = [inTrial retain];.
Then you should not import Trial.h in TrialDetailController.h, do that in TrialDetailController.m. Put a #class Trial; (a forward definition) above the #interface line in TrialDetailController.h.

My guess is that when your code does
Trial *trial = (Trial *)[dataArray objectAtIndex:indexPath.row];
the variable dataArray is nil. Then trial would be nil, too.
The [trial release]; shouldn't be there as 从善如流 is suggesting.
I cannot find any other problem.
Only you don't have to declare the property variable:
Trial *trial in your interface. A variable is created automatically when synthesizing (I expect you have #synthesize trial; somewhere).

Related

iOS - "This class is not key value coding-compliant" when using associations?

I have the following classes declared in my iOS application...
#interface UserRegistrationRequest : BaseServiceRequest
#property (nonatomic, retain) NSString *username;
#property (nonatomic, retain) NSString *password;
#property (nonatomic, retain) NSString *secretQuestionID;
#property (nonatomic, retain) NSString *secretQuestionAnswer;
#property (nonatomic, retain) UserProfile *profile;
#end
#interface UserProfile : NSObject
#property (nonatomic, retain) NSString *emailAddress;
#property (nonatomic, retain) NSString *firstName;
#property (nonatomic, retain) NSString *lastName;
#property (nonatomic, retain) NSData *profileImage;
#property (nonatomic, retain) NSNumber *dateOfBirth;
#end
As best as I can tell, these classes should be key-value coding compliant. However, when I run the following code...
NSString *propKey = #"profile.firstName";
NSString *propVal = [self.registrationRequest valueForKey:propKey];
I get an exception saying...
[<UserRegistrationRequest 0xb6187f0> valueForUndefinedKey:]: this class is not key value coding-compliant for the key profile.firstName.
Any idea why this is happening or what I should be looking for in troubleshooting this?
Use :
NSString *propVal = [self.registrationRequest valueForKeyPath:propKey];

NSMutableArray is not maintaining data [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 9 years ago.
I have created a custom class for EmployeeInfo:
#interface METEmployee : NSObject
#property (weak, nonatomic) NSString *EmpNo;
#property (weak, nonatomic) NSString *FirstName;
#property (weak, nonatomic) NSString *MiddleName;
#property (weak, nonatomic) NSString *LastName;
#property (weak, nonatomic) NSString *Department;
#property (weak, nonatomic) NSString *HireDate;
#property (weak, nonatomic) NSString *JobTitle;
#property (weak, nonatomic) NSString *SupervisorNumber;
#property (weak, nonatomic) NSString *SupLastName;
#property (weak, nonatomic) NSString *SupFirstName;
#property (weak, nonatomic) NSString *MobilePhone;
#property (weak, nonatomic) NSString *EmailAddress;
#property (weak, nonatomic) NSString *DeskPhone;
#property (weak, nonatomic) NSString *EmployeeType;
#property (weak, nonatomic) NSString *Location;
#end
Then in my view controller.h I have created:
NSMutableArray *theemplyees;
#property(nonatomic, retain) NSMutableArray *theemplyees;
Synthesize is .m:
#synthesize theemplyees
Then in ViewDidLoad, init and call to populate it:
theemplyees = [[NSMutableArray alloc] init];
[self getEmps];
In getEmps, I add the records to the array:
results = [database executeQuery:#"select * from EmpInfo order by LastName"];
while([results next]) {
METEmployee *empInfo = [METEmployee alloc];
empInfo.EmpNo = [results stringForColumn:#"EmpNo"];
empInfo.FirstName = [results stringForColumn:#"FirstName"];
empInfo.MiddleName = [results stringForColumn:#"MiddleName"];
empInfo.LastName = [results stringForColumn:#"LastName"];
empInfo.Department = [results stringForColumn:#"Department"];
empInfo.HireDate = [results stringForColumn:#"HireDate"];
empInfo.JobTitle = [results stringForColumn:#"JobTitle"];
empInfo.SupervisorNumber = [results stringForColumn:#"SupervisorNumber"];
empInfo.SupFirstName = [results stringForColumn:#"SupFirstName"];
empInfo.SupLastName = [results stringForColumn:#"SupLastName"];
empInfo.MobilePhone = [results stringForColumn:#"MobilePhone"];
empInfo.EmailAddress = [results stringForColumn:#"EmailAddress"];
empInfo.DeskPhone = [results stringForColumn:#"DeskPhone"];
empInfo.EmployeeType = [results stringForColumn:#"EmployeeType"];
empInfo.Location = [results stringForColumn:#"Location"];
[theemplyees addObject:empInfo];
}
Everything works fine for populating the table for the the first screen full of records:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
METEmpTableViewCell *cell = (METEmpTableViewCell *)[tableView dequeueReusableCellWithIdentifier:#"myCell"];
cell.lblFirstName.text = [[theemplyees objectAtIndex:indexPath.row] valueForKey:#"FirstName"];
cell.lblLastName.text = [[theemplyees objectAtIndex:indexPath.row] valueForKey:#"LastName"];
cell.lblDepartment.text = [[theemplyees objectAtIndex:indexPath.row] valueForKey:#"Department"];
NSString* picName = [NSString stringWithFormat:#"%#.jpg", [[theemplyees objectAtIndex:indexPath.row] valueForKey:#"EmpNo"]];
#try {
cell.empPicture.image = [UIImage imageNamed:picName];
}
#catch (NSException *exception) {
}
#finally {
}
return cell;
}
But if I attempt to scroll up or down on the Tableview, the array says the data is null...although it still shows the record count. If I resize my cell pn the table to smaller, it will populate more rows (that are visible) but once again any scrolling and they are gone.
Any thoughts or sugguestions is greatly appreciated. Thanks in advance for any and all help!
Geo...
You all have weak properties which means that all of the strings are instantly deallocated, since nothing is retaining them. Change it to this and try:
#property (nonatomic, strong) NSString *theString;
Also, you want to initialize your NSMutableArray like so (you're missing the init method):
NSMutableArray *array = [[NSMutableArray alloc] init];

Using a typedef enum in my object Class

I have a People class which holds various bits of into about a person. I would like to be able to identify what kind of person this is, so I thought I would try using a typedef enum for this since I have seen it done before and it seems like the cleanest solution. But, I am unsure how to declare this, then make it into a property.
.h
typedef enum {
kPersonTypeFaculty,
kPersonTypeStaff,
kPersonTypeSearch
} personType;
#interface Person : NSObject {
NSString *nameFirst;
NSString *nameLast;
NSString *email;
NSString *phone;
NSString *room;
NSString *status;
NSString *building;
NSString *department;
NSString *imageURL;
NSString *degree;
NSString *position;
NSString *bio;
NSString *education;
}
#property (nonatomic, retain) NSString *nameFirst;
#property (nonatomic, retain) NSString *nameLast;
#property (nonatomic, retain) NSString *email;
#property (nonatomic, retain) NSString *phone;
#property (nonatomic, retain) NSString *room;
#property (nonatomic, retain) NSString *status;
#property (nonatomic, retain) NSString *building;
#property (nonatomic, retain) NSString *department;
#property (nonatomic, retain) NSString *imageURL;
#property (nonatomic, retain) NSString *degree;
#property (nonatomic, retain) NSString *position;
#property (nonatomic, retain) NSString *bio;
#property (nonatomic, retain) NSString *education;
#end
.m
#import "Person.h"
#implementation Person
#synthesize nameFirst, nameLast, email, phone, room, status, building, department, imageURL, degree, position, bio, education;
- (void)dealloc {
[nameFirst release];
[nameLast release];
[email release];
[phone release];
[room release];
[status release];
[building release];
[department release];
[imageURL release];
[degree release];
[position release];
[bio release];
[education release];
[super dealloc];
}
#end
I want to be able to do something like:
Person *person = [[[Person alloc] init] autorelease];
person.nameFirst = #"Steve";
person.nameLast = #"Johnson";
person.personType = kPersonTypeStaff;
Am I missing a crucial part of this idea?
You define it like you would for any primitive type (like int or float). When you use typedef, you are telling the compiler that this name is a type which represents this. So, you would add an instance variable with that type (I capitalized the type in my post to distinguish it from the variable or property):
personType personType;
Then add a property definition:
#property (nonatomic) personType personType;
Then you synthesize it and use it:
#synthesize personType;
self.personType = kPersonTypeStaff;
A enum type is actually some type of integer which holds all of the values of the enum. By using typedef, you can specify that this integer should be one of the constants in the enum and nothing else, and the compiler can help enforce this. But, except for the variable type, you treat it exactly the same way you would an int type.
You add the following property:
#property (nonatomic) personType personType;

copy one NSString to another

How to copy one NSString to another?
#interface MyData : NSObject
{
#private
//user's private info
NSInteger uID;
NSString *name;
NSString *surname;
NSString *email;
NSString *telephone;
//user's picture
UIImage *image;
}
#property (nonatomic, assign) int uID;
#property (nonatomic, retain) NSString *name;
#property (nonatomic, retain) NSString *surname;
#property (nonatomic, retain) NSString *email;
#property (nonatomic, retain) NSString *telephone;
#property (nonatomic, retain) UIImage *image;
#end
I have two objects of this type. MyData *obj1, obj2;
First is initialized. Second I want to initialize with first.
obj2 = [obj1 copy]; //crashes
newData.surname = data.surname; //crashes to
newData.email = data.email;
newData.telephone = data.telephone;
I neeeeed a COPY of second object NOT RETAIN!!! Help please! Thanx!
you can use the NSString method stringWithString.
See also stringwithstring, what's the point? to understand when this might be preferred to simply giving it the same string.
your object should probably implement the copy itself:
#implementation MyData
-(id)copyWithZone:(NSZone *)zone
{
MyData *obj = [[[self class] alloc] init];
obj.uID = self.uId;
obj.name = self.name
...
return obj;
}
....
#end
Change your #property's to use copy instead of retain:
#property (nonatomic) int uID;
#property (nonatomic, copy) NSString *name;
#property (nonatomic, copy) NSString *surname;
#property (nonatomic, copy) NSString *email;
#property (nonatomic, copy) NSString *telephone;
#property (nonatomic, copy) UIImage *image;
Note that you also don't need the assign for the uID. Just leave that part out. Then you can easily create a copy by alloc and init-ing a second MyData object and assigning the properties :
MyData data = [[MyData alloc] init];
newData.surname = data.surname;
newData.email = data.email;
newData.telephone = data.telephone;

When is the right time to release properties?

I have a couple of properties declared in my header file, and just wondering when they have to be released. I'm currently doing them in my "dealloc" method, but getting the EXC_BAD_ACCESS error when doing so.
Here's my code
#property (nonatomic, retain) NSTimer *timer;
#property (nonatomic, retain) NSString *closeimage;
#property (nonatomic, retain) NSString *alertStyle;
#property (nonatomic, retain) NSString *phonelaunch;
#property (nonatomic, retain) NSString *resultmessage;
Here's my dealloc method
- (void)dealloc {
[super dealloc];
[timer release];
[closeimage release];
[alertStyle release];
[phonelaunch release];
[resultmessage release];
}
Thanks for any help in advance!
Put your [super dealloc] message at the end of your dealloc method.