This is the code from the class within which I am trying to reference the properties from the other class(BIDDoubleComponentPickerViewController):
BIDDoubleComponentPickerViewController *dummyObject = [BIDDoubleComponentPickerViewController new];
NSString *selectedValue = [dummyObject value];
NSString *selectedSuit = [dummyObject suit];
However, whenever I attempt to access the variables selectedValue and selectedSuit, they claim that they are null, when I know for a fact that value and suit are not null within the other class. Here is the code that sets the properties in BIDDoubleComponentPickerViewController:
NSInteger valueRow = [doublePicker selectedRowInComponent:
kValueComponent];
NSInteger suitRow = [doublePicker selectedRowInComponent:
kSuitComponent];
value=[[NSString alloc]initWithString:[values objectAtIndex:valueRow]];
suit=[[NSString alloc]initWithString:[suits objectAtIndex:suitRow]];
Here is the code for the declaration of the properties:
#property (strong, nonatomic) NSString *value;
#property (strong, nonatomic) NSString *suit;
Anyone have any ideas?
When you create a new view controller, it doesn't load its view immediately. So if the code where you initialize value and suit is located in the init method, then doublePicker is still nil. Otherwise, if that code is located in viewDidLoad or loadView, then it is still not executed when you try to access value and suit using [dummyObject value]; and [dummyObject suit];
Edit: (After OP's comment)
My answer is still correct because in the line:
BIDDoubleComponentPickerViewController *dummyObject = [BIDDoubleComponentPickerViewController new];
you create a new object dummyObject that is different from the view controller where the picker view was visible. So the values value and suit that you are looking for are properties of the other view controller and not the one you just initialized.
To solve your problem, you should not create a new instance of BIDDoubleComponentPickerViewController but retrieve the instance that holds the values you are looking for.
Related
I'm trying to write an app that has two scenes in it. The first page is a UITableView that will contain a list of note entries. The second scene has 2 text fields (note summary and note description). I'm entering details on the second scene and then clicking a "Save" button which saves the data:
NoteListViewController.m
- (IBAction)saveAndGoBack:(id)sender {
NSLog(#"NoteDetailViewController.m: %#", NSStringFromSelector(_cmd));
NSString * desc = [[NSString alloc]init];
NSString * detail = [[NSString alloc]init];
desc = _noteTitle.text;
detail = _noteDesc.text;
[[NoteStore sharedStore]createNoteWithDesc:desc AndDetail:detail];
[self.navigationController popViewControllerAnimated:YES];
}
NoteStore is a static sharedStore that I am saving the data into.
NoteStore.m
-(Notes *)createNoteWithDesc:(NSString *)desc AndDetail:(NSString *)detail {
NSLog(#"NoteStore.m: %#", NSStringFromSelector(_cmd));
Notes * newNote = [[Notes alloc]initNoteWithDesc:desc AndDetail:detail];
[self.privateItems addObject:newNote];
return newNote;
}
So, the note is added to an NSMutableArray called "privateItems". I confirmed that the Note object gets added properly.
*****The problem happens when I try to retrieve the Note object (desc and detail) from the privateItems array later on using an accessor method which has a public property in the NoteStore.h file called allItems (it's an NSArray readonly, nonatomic and a copy):
NoteStore.m
-(NSArray *)allItems{
NSLog(#"NoteStore.m: %#", NSStringFromSelector(_cmd));
return [self.privateItems copy];
}
Everytime I try to retrieve it, the first property (desc) comes up as nil while the second property (detail) has the data I saved in the second text field of the second scene. Why is the first field constantly coming up as nil???
Just for clarity, a Note object is declared as follows
#interface Notes : NSObject
// What are the properties of a note?
#property (nonatomic, weak) NSString * noteDesc;
#property (nonatomic, weak) NSString * noteDetail;
#property (nonatomic, weak) NSString * test;
// Designated Initializer
-(instancetype)initNoteWithDesc:(NSString *)desc AndDetail:(NSString *)detail;
#end
Any help would be greatly appreciated.
When you call the designated initialiser you pass in two NSString objects. At this point they are owned by the method where they are created.
When they are assigned to the properties they only have a weak reference and therefor the retain count is not bumped up. Weak references are good for things like delegate objects. In this case you want your objects to stick around, so by declaring them as strong you're saying I want these properties to stick around in memory and take ownership of them.
still having problems!
I have 2 classes, and i want to access the properties of one class from the other.
I have a class called MenuViewController, which is a Facebook styled popout menu, and depending on which cell is selected, i want to load different data.
I have created a property:
#property int rowSelected;
and synthesized it:
#synthesize rowSelected;
and in my other class, i have created an instance of the class:
MenuViewController *menu = [[MenuViewController alloc] init];
NSInteger rowValue = menu.rowSelected;
and when i NSLog it, it always returns 0...
NSLog(#"%i", menu.rowSelected);
Help is much appreciated!
The call to alloc creates a new MenuViewController instance. Unless you set a value for your property in its init method, then you should expect it to be 0.
I have a textViewController class. I want to set(basically update) the corresponding textView's content from another view controller which I am pushing over the present textViewController. The way I thought I could do this was to have a shared singleton class and have a string property there to contain the text. I have been using the singleton for storing some other content as well and it worked fine till now.
But the text variable in singleton class doesn't hold the content I pass to it from the second view controller and hence the textViewController, after popping the second view controller, displays the old text even after reappearing. I am updating the textView in its viewWillAppear method which is getting called but shows old text content on NSLogging.
What am I missing here? Please suggest a solution, stuck at it for a long time now.
Declaration
Firstly, declare the NSString in your app delegate .h file. It should look something like this:
//YourAppDelegate.h
#import <UIKit/UIKit.h>
#interface YourAppDelegate : NSObject < UIApplicationDelegate >
{
NSString *sharedString; //WE ADDED THIS
}
#property (nonatomic, retain) NSString *sharedString; //AND THIS
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet SomeViewController *viewController;
#end
Now you want to synthesize the object so that the accessor and mutator methods are made for you. This means you don't have to write the setSharedString: and getSharedString methods - we can simply access and mutate the object by making a reference to it. This is how we synthesize it in the .m file:
//YourAppDelegate.m
#synthesize sharedString;
Assigning a Value
When you want to assign a value to sharedString from another class, you must first retrieve the active instance of your application delegate:
YourAppDelegate *appDelegate = (YourAppDelegate*)[[UIApplication sharedApplication] delegate];
The appDelegate object here is your running app delegate instance. To access the sharedString NSString object in the delegate and assign a value, we'd do this:
appDelegate.sharedString = #"some string we want to assign";
For the duration of our application's runtime, "some string we want to assign" is now stored in sharedString in our app delegate.
Retrieving the Value
You'll want to retrieve the value at some point. To do this, again we'll have to get the running instance of our application delegate:
YourAppDelegate *appDelegate = (YourAppDelegate*)[[UIApplication sharedApplication] delegate];
Once we have the running instance, we can then access the sharedString object stored inside it:
NSString *retrievedString = appDelegate.sharedString;
From this point, retrievedString now holds the value "some string we want to assign".
Note:
Everywhere I mention YourAppDelegate, I am referring to your app delegate - the app delegate you have in your project. It'll be related to your project name (look for the file).
How your NSString property for your Text-Variable is defined? Is it a "weak"?
I want to store a list of data records in a NSMutableArray for use in a UITableView. In other languages I would have used a simple 'type' structure to define the record structure but I understand the way to do this in Obj-C is to define a new class. I've done this as follows :
#interface CustSuppListItem : NSObject
#property (nonatomic, copy, readwrite) NSString *acCode;
#property (nonatomic, copy, readwrite) NSString *acCompany;
#property (nonatomic, copy, readwrite) NSString *acContact;
#property (nonatomic, assign, readwrite) double osBalBase;
#property (nonatomic, assign, readwrite) unsigned int acAccStatus;
#end
#implementation CustSuppListItem
#synthesize acCode, acCompany, acContact, osBalBase, acAccStatus;
#end
In the viewDidLoad of my UITableViewController I instantiate the array :
tableListDataArray = [[NSMutableArray alloc] init];
Once I have retrieved my data, I add it to the array as follows :
CustSuppListItem *custSuppItem = [[CustSuppListItem alloc] init];
[custSuppItem setAcCode:[jsonCustSuppRecord getStringForKey:#"acCode"]];
[custSuppItem setAcCompany:[jsonCustSuppRecord getStringForKey:#"acCompany"]];
[custSuppItem setAcContact:[jsonCustSuppRecord getStringForKey:#"acContact"]];
[custSuppItem setOsBalBase:[jsonCustSuppRecord getDoubleForKey:#"osBalBase"]];
[custSuppItem setAcAccStatus:[jsonCustSuppRecord getIntForKey:#"acAccStatus"]];
[tableListDataArray addObject:custSuppItem];
[custSuppItem release];
In my table cellForRowAtIndexPath method, I retrieve the data for the current cell as follows:
CustSuppListItem *listDataRecord = [tableListDataArray objectAtIndex:indexPath.row];
[cell.lblCompanyName setText:listDataRecord.acCompany]; // EXC_BAD_ACCESS here
[cell.lblAcCodeContact setText:[NSString stringWithFormat:#"%#, %#",
listDataRecord.acCode, listDataRecord.acContact]];
[cell.lblBalance setText:[Utils fmtNumber:listDataRecord.osBalBase withDecPlaces:2]];
[cell.lblStatus setText:[Utils exchAccStatusDesc:listDataRecord.acAccStatus]];
return cell;
In the dealloc method for the view controller I release the NSMutableArray :
[tableListDataArray release];
I'm very new to Obj-C so it would be great if somebody could confirm everything I've done so far makes sense and is in order. I am getting an intermittent EXC_BAD_ACCESS error when trying to read the acCompany property (see comment next to line) so something must not be right.
Any help appreciated,
Jonathan
All your code looks reasonable and correct to me at first glance.
A few things that I would look at are:
Confirm that cell definitely has a property lblCompanyName. If you're trying to assign to a property that doesn't exist then you will get this type of error. Have you defined a custom cell object type?
Confirm that it is always the acCompany property that is causing the EXC_BAD_ACCESS, and not just any property on the object. One way to do this would be to change the ordering of the lines in the cellForRowAtIndexPath method.
Confirm that the listDataRecord that's causing the crash is getting populated correctly in the first place. In other words, confirm that your jsonCustSuppRecord is always valid. What does jsonCustSuppRecord getStringForKey: return if the key doesn't exist in the jsonCustSuppRecord?
Set a breakpoint at this line: [tableListDataArray addObject:custSuppItem]; and examine the contents of the custSuppItem each time (this is an extension of point 3. above)
I have a view controller class called PresidentsViewController that sets up data in a UITableView. This data is in the form of NSMutableArray called list. I have another class, PresidentAddController, that is supposed to handle adding an object of type President to this list based on user inputted data about a president. However, I can't get the object to add to the list. I have confirmed that the user inputted data for a new president is being collected correctly, so it is adding to the list that's in another class that's causing problems. I believe the correct code to add an object to the list is:
[pvc.list addObject:newPresident];
However, I don't know how to properly create the reference/instance/? (which is what pvc would be) to PresidentsViewController inside of PresidentAddController so that I can properly add a new president to the list. I am not using Interface Builder for this because it is just a UITableView.
How do I add a president to the list in this situation?
Edit: Here is how the array is being initialized:
#property (nonatomic, retain) NSMutableArray *list;
And here is how PresidentAddController is being set up in PresidentsViewController:
PresidentAddController *childController = [[PresidentAddController alloc] initWithStyle:UITableViewStyleGrouped];
childController.title = #"Add President";
[self.navigationController pushViewController:childController animated:YES];
[childController release];
Add a pointer to PresidentAddController this way:
// in #interface
PresidentsViewController *listController;
#property (nonatomic, assign) PresidentsViewController *listController;
// in #implementation
#synthesize listController;
Then when you instantiate your PresidentAddController, set the pointer:
PresidentAddController *childController =
[[PresidentAddController alloc]
initWithStyle:UITableViewStyleGrouped];
childController.title = #"Add President";
childController.listController = self;
[self.navigationController pushViewController:childController animated:YES];
[childController release];
So then you can go [listController.list addObject:newPresident]; in PresidentAddController.
EDIT: childController.listController = self calls [childController setListController:self], which in turn reads the #synthesized method in your implementation and sets the pointer *listController to point to the current class (if you're writing code in the PresidentsViewController class, then self is going to be the current instance of PresidentsViewController).
The reason why I use assign is because if you were to use retain, then when you set listController to self it will actually keep an owning reference to the object. This can cause all sorts of problems if you ever try to deallocate PresidentsViewController, because if you have an owning reference in PresidentAddController then it will not deallocate until that reference is also released. Using assign ensures that if you ever release the PresidentsViewController before PresidentAddController disappears, it will be properly deallocated. Of course, maybe you want to keep it around in that situation, in which case using retain here is also fine.
My suspicion here would be that you have a property defined as #property (nonatomic,copy) NSMutableArray *list; Are you getting and exception trying to add the object into the array? If so, it's likely because the copy modifier is returning an immutable copy of the array. Try to create a method that takes the object and adds it to the list without using self.list ... just [list addObject] and if that works then this is your problem.