Objective C: How to get values of selected UIPickerView from one class to another - objective-c

I set the UIPickerView value in one class, implemented the delegate and everything else, and also didSelectRow.
In another ViewController of another class, I set the delegate for dataSource. But, when I try to call it, it is null.
How can this issue be fixed? I appreciate your help.
Code in didSelectRow:
NSInteger distRow = [self.distPicker selectedRowInComponent:
pickerViewComponent];
NSString *distance = self.dist[distRow];
I'm calling both of following methods from another ViewController, but it doesn't work:
NSString *distance = self.dist[[self.distPicker selectedRowInComponent:
pickerViewComponent]];
NSLog(#"picker %#",self.distPicker.dataSource);
NSLog(#"%#", distance);
NSLong for the picker is null and for time is 0.

Related

Passing value from ViewController to NSObject in Objective-C

I need to pass value from a ViewController to NSObject as soon as the view loaded using Xcode with Objective c.
I am using the code below but the value is null.
-(void)viewDidAppear:(BOOL)animated
{
MyHomeModelNSObject *nsOb;
nsOb = [[MyHomeModelNSObject alloc] init];
nsOb.myString = self.userName.text;
}
The above code is working between Views when using segue, but it does not work with when passing the value to NSObject.
Thanks
The above code is working between Views when using segue, but it does not work with when passing the value to NSObject.
You're not using a real object. You're declaring a pointer to an object, but never allocating the object itself:
MyHomeModelNSObject *nsOb;
nsOb.myString = self.userName.text;
See? You're missing the bit where you do:
nsOb = [[MyHomeModelNSObject alloc] init];
What's more, even if you added that, the object would be deallocated as soon as viewDidAppear exits because it's a local variable. If you want it to hand around, you'll need to 1) create it and then 2) assign it to some property of your view controller or another object.

Adding 'data' to an NSMutable Array - Xcode

I want to add 'email' data to my NSMutableArray so every time the button is pushed it adds another email to the array, so I end up with an array of email addresses but can't seem to get it working.
I think my problem is I am reinitialising the array so clearing it out and maybe need to put the initialisation somewhere else..which I have tried.
The below code lets me add an address but each time the IBAction is called I think I am clearing the array, any pointers or help would be great
#property (strong, nonatomic) NSMutableArray *mutable;
#synthesize mutable;
- (IBAction)array:(id)sender {
mutable = [[NSMutableArray alloc]initWithObjects:self.person.email, nil];
[mutable addObject:self.person.email];
NSLog(#"ARRAY OF EMAILS %#",mutable);
}
You are right - you are initializing the array each time the array: method is called. You can change the code to initialize it only once:
- (IBAction)array:(id)sender {
if(!self.mutable) {
self.mutable = [[NSMutableArray alloc]initWithObjects:self.person.email, nil];
}
[self.mutable addObject:self.person.email];
}
As a side note - you don't have to use #synthesize for this property. Read "Adopting Modern Objective-C" for more details.
Did you use UIViewController? If yes then reset the array in viewDidAppear method.
If you are using the UIView, then create the custom method to reset the array and call from the parent viewController.

(Beginner)Trying to pass an array from ViewController to DetailController

I have loaded an array (recordArray) in RootViewController class which I need to pass to the DetailViewController class so that I can access any variable within it. I can pass a single value successfully, but I cannot get how to pass the whole array across.
I have created a second NSMutableArray recordArray in DetailsViewController.h, added the #property statement (with retain), and synthesized in DetailsViewController.m. I then added the following line in DetailsViewController.m
recordArray = [[NSMutableArray alloc] initWithArray:self.recordArray];
but that just gives me an empty array in the detail view.
I have read through some of the posts on this, but have not found anything which I understand sufficiently to be able to implement. I expect I'm going about this all wrong....
Thanks in advance for your help guys.
Please refer to this code:
iPhone SDK: How do I pass an array of values from a ViewController onto other ViewController?
There you can refer to Satya's answer.
Let me know if you need more help
EDIT:
Let us assume that there is an NSArray called secondArray declared in SecondViewController
Define a method in SecondViewController which says:
-(void)setValue:(NSArray *)array
{
secondArray = array;
}
Hope this helps.
The problem is that here:
recordArray = [[NSMutableArray alloc] initWithArray:self.recordArray];
You are just assigning the same property recordArray, which is probably nil at this point, what you want to do is dependency injection. So whenever you instantiate your DetailController, you can do:
myDetailController.recordArray = myRecordArray
Where myRecordArray is the value you want to pass or "inject" in the detailview controller.

Typecasting return value of methods when returned value is parent class of the typecast?

I have code similar to this.
MySubclassOfUIView *view = [aUIPickerView viewForRow:4 forComponent:0];
The viewForRow:forComponent method of UIPickerView returns a UIView. MySubclassOfUIView is exactly that: a subclass of UIView.
The UIPickerView delegate (not mentioned here) uses an array of MySubclassOfUIView objects to populate the rows of the UIPickerView components. Thus, I know the viewForRow:forComponent method is really going to be returning a pointer to an object of type MySubclassOfUIView.
Xcode gives me this warning.
Incompatible pointer types initializing 'MySubclassOfUIView*' with an expression of type 'UIView*'.
So I figure that I'll typecast it to fix the warning, which gives me this code.
MySubclassOfUIView *view = (MySubclassOfUIView*)[aUIPickerView viewForRow:4 forComponent:0];
And the warning goes away.
Please forgive my shaky C and Objective-C skills, but am I doing the right thing (as far as the context given so far)? Is there some other better way to handle this situation?
If you are absolutely sure that it will return a MySubclassOfUIView, then it is OK to do this. If there is any chance that it could return something else (such as you made a mistake and added the wrong thing to the array), then you should check the type and use a temporary variable.
UIView *temp = [aUIPickerView viewForRow:4 forComponent:0];
NSAssert([temp isMemberOfClass:[MySubclassOfUIView class]],[NSString stringWIthFormat:#"aUIPickerView returned the wrong class (%#)",[temp class]]);
MySubclassOfUIView *theView = (MySubclassOfUIView*)temp;
What you can do is:
MySubclass* subFoo = [[MySubclass alloc] init];
MySuperclass* superFoo = subFoo;
What you shouldn't do is:
MySuperclass* superFoo = [[MySuperclass alloc] init];
MySubclass* subFoo = superFoo;
This is, because your Subclass will have all properties, selectors, etc from the Superclass. But the Superclass won't have all (..) of the Subclass.
For the rest, see ughoavgfhw's answer.

Using int datatype in objective-c

First, I'm very new with objective-c and memory management, pointers, etc. No doubt my problem lies in a simple point I'm missing.
I've got a class which contains a property for an integer:
// Device.H file
#interface Device : NSObject {
#private int nodeLevel;
}
#property (readwrite, assign, nonatomic) int nodeLevel;
// Device.m file
#implementation Device
#synthesize nodeLevel;
- (id)init {
self.nodeLevel = 0;
return self;
}
I create an NSMutableArray of many Device objects, assigning the node Id:
-(NSMutableArray *)getDevices {
...
NSMutableArray *devices = [[NSMutableArray alloc] initWithCapacity:[rDevices count]];
for (NSDictionary *d in rDevices) {
Device *newDevice = [[Device alloc] init] autorelease];
newDevice.nodeLevel = d.nodeLevel;
[devices addObject: newDevice];
}
return [devices autorelease];
}
My devices array is stored on the main app delegate where I've got a property assigned to hold it:
#property (nonatomic, retain) NSMutableArray *devices;
Now here's where my problem is manifest. I'm using a tableView in another controller class to access my app delegate, pull a device from its array then set values with the int, but 'strange' things happen:
EDIT: Min/Max values for the slider are set in another part of the code to 0 and 100 respectively.
// In method cellForRowAtIndex
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
Device *d = (Device *)[[appDelegate.devices objectAtIndex:indexPath.row]];
// cell is a custom cell with a UISlider object
cell.sliderLevel.value = [d nodeLevel];
When I assign value to the device's nodeLevel, the slider is always maxed out, even if nodeLevel only equals 1 or 2.
If I do this instead, the slider is at the correct position, but I'll eventually get a "EXC_BAD_ACCESS" signal when scrolling up and down through my tableView:
// cell is a custom cell with a UISlider object
cell.sliderLevel.value = [[d nodeLevel] intValue];
I suspect that I must be assigning the value to a memory location in the first instance? In the second case it works, but I assume that my BAD_ACCESS is a result of the nodeLevel becoming "released" or something? One final note, I've also got an NSString object associated with the Device class. I access the string and assign it to a label in my cell and it never causes me problems.
Thanks in advance for taking a look.
What type is returned by the nodeLevel property in this line: "newDevice.nodeLevel = d.nodeLevel;"? The nodeLevel property in Device is an int, so you need to ensure that d.nodeLevel is returning an int, and not an NSNumber object.
If d.nodeLevel is returning an NSNumber, that would explain why calling intValue on it gets you a reasonable value, and you get a huge number if you don't call intValue on it (the huge value would be the pointer value for the NSNumber object). It would also explain why you get an EXC_BAD_ACCESS crash later on, because your NSNumber object isn't being retained.
You should probably just change this line:
newDevice.nodeLevel = d.nodeLevel;
to
newDevice.nodeLevel = [d.nodeLevel intValue];
and don't call intValue on it later on, so you would change this:
cell.sliderLevel.value = [[d nodeLevel] intValue];
to this:
cell.sliderLevel.value = [d nodeLevel];
[d nodeLevel] returns an integer, a primitive type, not an Objective-C object. Therefore, you cannot call -intValue on it, and that's why you get an EXC_BAD_ACCESS.
Further, the reason your slider is maxed out is because you haven't set its maximum value to 2.0. Because it defaults to 1.0, when you set it to any value 1.0 or higher, it will appear maxed out (in your case, both 1 and 2 appear the same). At some point, you need to call cell.sliderLevel.maximumValue = 2.0; to make the maximum value possible high enough.