i have 2 classes . in my first class i have one label. now i have to give input for that label from my second class.
here is my code.
IBOutlet UILabel *label1;
#property(nonatomic, retain) IBOutlet UILabel *label1;
#synthesize label1;
I call this label like this.
I import my class1 and create object like classone.
I checked(NSLog print)class and that method will be called but that input won't come.i checked that label its also connected to my class.because i give same input in my viewDidLoad that time its working fine.
NSString *ram= #":13123123312";
classone.label1.text= ram;
guide me where i'm doing wrong.
Setting values of previous views is trickier than this. What it the view has been removed by the OS under memory pressure?
The proper way of setting these values is to use the MVC pattern that is used throughout the Cocoa frameworks. Your second view controller sets a property of the previous view controller. And when the previous view needs to be shown, it takes its value from this property.
The usual way to correctly hook up a view controller to talk back to a another view controller lower in the stack is to use a delegate protocol.
I wrote an example of this, DelegationExample,a while ago which shows how a textfield in the first view is populated by a textfield's value in the second view controller using a delegate protocol. You might find it useful to see how I have done this as an example.
Update
I've updated the link to a new project for iOS6 with ARC and Storyboards
Take one NSString variable in AppDelegate class and synthesize it properly. And store the value of the second class's variable to that like:
appDelegate.strLbl = [NSString stringWithformat:#"%#",strVal];
and then copy that value to the label in first class like:
lblVal.text = [NSString stringWithformat:#"%#",appDelegate.strLbl];
Hope that helps you. Thanks.
Actually you should have the reference of the first class in the second class. You should not allocate a new instance. If you create new instance, then the instance for which you have set the label value is different from the actual one which you will see on clicking back.
I guess you got this.
Aadhira was right, when u create a new instance of class1 in class2 its wrong,
You have to get the original instance of class1, this can be achieved by creating a static function which returns current instance of class1, as shown below
static classone* sInstance;
#implementation classone
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization.
}
sInstance = self;
return self;
}
+(classone*) getInstance {
// NSAssert (sInstance!=nil, #"classone:getInstance: called when singleton was not initialized!");
return sInstance;
}
Related
i've been doing a thing here using objective-c, but i'm a beginner in this language, and that's what i did:
there is a class, named "firstviewclass", that is in the control of my first view, in this view there is a textfield that the user puts a number. the textfield is in the firstviewclass.h named "setNumber". There is another class, named "secondviewclass" that is in control of the second view, in this view there is a label that is in the secondviewclass.h, and i want that this label recive the value that the user put in the textfield from the first view, but when i test it on the iOS simulator any number that i put in the textfield it appears in the label as 0... I really don't know what to do!
My codes:
firstviewclass.h:
#import <UIKit/UIKit.h>
#interface firstviewclass : UIViewController
#property (strong, nonatomic) IBOutlet UITextField *setNumber;
- (IBAction)gotonextview:(id)sender;
#end
secondviewclass.h:
#import <UIKit/UIKit.h>
#import "firstviewclass.h"
#interface secondviewclass : UIViewController
#property (weak, nonatomic) IBOutlet UILabel *labelthatrecivesthetextfieldvalue;
#end
secondviewclass.m:
#import "secondviewclass.h"
#import "firstviewclass.h"
#implementation secondviewclass
#synthesize labelthatrecivesthetextfieldvalue;
-(void)viewDidLoad{
[super viewDidLoad];
firstviewclass *object = [[firstviewclass alloc] init];
NSString *string = [[NSString alloc] initWithFormat:#"%i", [object.setNumber.text intValue]];
labelthatrecivesthetextfieldvalue.text = string;
}
#end
First of all, I would strongly recommend not naming a property or instance variable setSomething. It will cause headaches for anyone reading your code because it will always look like you're trying to call a setter. Also, please do capitalize your class names.
Your actual problem is that in viewDidLoad you're creating an instance of firstviewclass, and then trying to get the value from setNumber. That is before the user had any chance to enter anything.
Also, the setNumber outlet in firstviewclass will probably be going nowhere anyway, since you're instantiating that class yourself, instead of loading the NIB.
Edit (ah, Storyboard, d'oh):
For Storyboard, you need to pass the setNumber text field's value to the second view.
First of all, remove the firstviewclass *object = [[firstviewclass alloc] init]; line.
Then, in your first view controller's prepareForSegue method, you can pass the value of the setNumber text field to a property in your your second view controller, and use it from there (e.g. in configureView).
I recommend working through Apple's Storyboard tutorial, it shows exactly what you need to do, step by step. The step you're having issues with right now, passing data to your next view controller, is here.
How are you initiating the setting of the label? From viewDidLoad? If so, then 0 would be correct because you have not set object.setNumber.text to anything. Also, you aren't carrying over the data from your first viewController. You need to let the second viewController know what the number is. Try setting this value in your NSUserDefaults, then in your second viewController, load that value from your defaults.
in the viewDidLoad of secondviewclass, you are creating a new instance of firstviewclass, and then accessing the property of the label. Since you haven't set that to be anything, it will always return zero.
Can you post the implementation of the gotonextview method?
EDIT:
I think you need to be setting the label property from the first view controller. so in your gotonextview method, add this line:
secondviewclass.labelthatrecivesthetextfieldvalue.text = self.setNumber.text;
I admit I'm a little lost in your naming scheme but that might work.
I want to have a custom initWithNibName, basically passing in another NSString as a type to determine some logic inside this UIViewController based on the type. So I set is as follows:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil andFeedType:(NSString *)feedType
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
Does this even make sense? As I don't see this type of init's quite often. If not then what is the best way to do this?
It makes perfectly sense to me. This is the way you would override an initializer to add some custom initialization in Objective-C. What do you think is wrong with it ?
Yes it makes sense. In addition, if you want to keep clean your init you could do the following:
- (id)initWithFeedType:(NSString *)feedType
{
self = [super initWithNibName:#"YourNibName" bundle:nil]; // nil is ok if the nib is included in the main bundle
if (self) {
// Set your feed here (copy it since you are using a string)
// see the edit
myFeedType = [feedType copy];
}
return self;
}
For further info see the post initWithNibName-bundle-breaks-encapsulation by Ole Begemann.
Hope that helps.
Edit
If that feed property cannot be accessed by external objects, create a class extension for your controller like the following:
//.m
#interface YourController ()
#property (nonatomic, copy) NSString* myFeedType;
#end
#implementation YourController
#synthesize myFeedType;
#end
It does make sense. You are creating you own initializer, tailored to your needs. Also, you are doing what you should, which is calling the designated initializer (in the case of UIViewController initWithNibName:bundle:) inside your custom init method.
Wait!
There is one reason why it may not be best: this method is not called when your view controller is loaded from a storyboard. For this reason I recommend using viewDidLoad: instead for the custom logic, and setting your custom string as a property.
I'm reasonably new at the iPhone SDK, so please forgive me if this answer's ridiculously obvious.
I have a ViewController connected to a .xib file (they are called FirstViewController)
I also have a custom class called MyCustomClass. In this class, I have a method like this:
- (void)setTheText {
[myLabel setText:#"foo"];
}
I want to call this method to set the text in a label in FirstViewController.xib
So far, I have done this:
Dragged in an "Object" into Interface Builder, and set the class to: MyCustomClass
Connected up the IBOutlet 'myLabel' from MyCustomClass to a UILabel in the view.
However, when I run the program, and press the button to set the label (which is in FirstViewController.m), something like:
- (IBAction)doSomething:(id)sender {
MyCustomClass *customClass = [MyCustomClass alloc] init];
[customClass setTheText];
}
This doesn't set though. NSLog(#"%#",[myLabel text]); returns (null)
Xcode shows no errors or warnings, what could be wrong?
Thanks,
Michael
Additional Info:
Interface to MyCustomClass.h:
#import <UIKit/UIKit.h>
#interface MyCustomClass : NSObject {
UILabel *myLabel;
}
#property (nonatomic, retain) IBOutlet UILabel *myLabel;
- (void)setTheText;
#end
You don't want to create a new instance of your custom class in your action method.
There are a couple of ways to do what you want.
Option 1 is to give your view controller a reference to your custom object. To do this, create an outlet of type MyCustomClass * in your view controller, connect that outlet to the new object that you created in your XIB file, and then get rid of the allocation in your action method:
- (IBAction)doSomething:(id)sender {
[customClass setTheText];
}
Option 2 is to let your CustomClass handle both the label and the action method. To do this, you can simplify things even further. Put an outlet for the UILabel into your CustomClass, and then simply convert your setTheText method into an action:
- (IBAction)setTheText:(id)sender {
[myLabel setText:#"foo"];
}
Now, connect that action up to your button, and everything should work like a charm.
Note: You should probably use a method name that does not start with "set", since those are commonly used for property setters as part of Cocoa's KVC/KVO system. Instead, I would call it something like changeLabel, or equivalent.
Your instance of customClass here is completely unrelated to the NIB. You've instantiated a new object using +alloc. If you want to modify the specific MyCustomClass in your NIB, then FirstViewController needs an IBOutlet that points to it.
UILabel also have a property called text to set the value, you might find that easier.
myObject.myLabel.text = #"Your text";
well you called your label two things, first a non-ibaction then an ibaction in the property.
I have a NSString member variable declared in the header file of the view controller:
#interface MyApprViewController : UIViewController {
NSString *var;
...
}
#property (retain) NSString *var;
...
-(IBAction)buttonPressed: (id)sender;
Inside the implementation, I use #synthesize var and try to use that var from within the implementation of the buttonPressed method, but it does not work properly and I assume it is because var was never initialized. Where can I initialize this variable? I do not want to do it inside the method; I want to do it once of course, because I will keep appending text to it:
-(IBAction)buttonPressed: (id)sender {
NSString *input = ((UIButton *)sender).currentTitle;
var = [var stringByAppendingString:input];
textField.text = var;
}
[input release];
}
I tried overriding the init method inside the view controller class, but it never gets called (maybe because there is no explicit initialization of the view controller class?) So, where should I initialize var so that I can use it inside the view controller class (inside the buttonPressed method)?
Thanks,
Mihai
There are several places to initialize:
- (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle
This is the designated initializer. You said you overloaded "init" which is not the designated initializer for UIViewController.
- (void)awakeFromNib
If your view controller is itself inside of a parent NIB, this method is called once the parent NIB is fully loaded and the parent NIB's outlets have all been wired.
- (void)viewDidLoad
If your view controller has a NIB, this is called when its NIB has been loaded.
- (void)loadView
If your view controller doesn't have a NIB, this is called when its view is first requested.
The best place would be inside your viewDidLoad or any init method you use. If you have neither, just add a method -(void)viewDidLoad to your UIViewController.
Of course this will not work, stringByAppendingString is an instance method, and var is never allocated. The best way to initialize ,if you have a nib file (as this example appera to have) is on viewDidLoad, but check before initialize if is allready nil, to avoid every time this method is called a new object is allocated. finally remember release
I have two properties setup as ViewControllers that each use different NIB file. (Male and Female Models, will function the same but are setup visually different.) I want to have one function to create the ViewController based on the NIB Name and ViewController I pass in.
What's happening is the ViewController property is not being retained. If I add the actual property name within the function and set it, the viewController is set and retains the ViewController. Here is what I have in the .m file (Only showing what is needed to get help on.) I've kept in the two comment lines that I tried to do determine where the problem was.
#synthesize femaleModelViewController;
#synthesize maleModelViewController;
- (void) loadModelViewControllerWithModelType:(NSString*) model ModelView:(ModelViewController *)modelViewController {
ModelViewController *viewController = [[ModelViewController alloc] initWithNibName:model bundle:nil];
// [self setFemaleModelViewController:viewController]; // I don't want to set the property here, I want to be able to pass it as an argument.
modelViewController = viewController;
// [modelViewController retain]; // I even tried to retain it do see if would but it doesn't.
[viewController release];
}
- (void)viewDidLoad {
[super viewDidLoad];
[self loadModelViewControllerWithModelType:#"FemaleModel" ModelView:femaleModelViewController];
[self loadModelViewControllerWithModelType:#"MaleModel" ModelView:maleModelViewController];
}
In the .h file my Properties are setup like so:
#property (nonatomic, retain) ModelViewController *femaleModelViewController;
#property (nonatomic, retain) ModelViewController *maleModelViewController;
Are you trying to assign a new ModelViewController to maleModelViewController and femaleModelViewController? If so, you're going about it the wrong way.
Frankly, I'd do away with the loadModelViewControllerWithModelType:modelView: method altogether. All you would need to do in viewDidLoad is this:
maleModelViewController = [[ModelViewController alloc] initWithNibName:#"MaleModel"];
femaleModelViewController = [[ModelViewController alloc] initWithNibName:#"FemaleModel"];
(This assumes that maleModelViewController and femaleModelViewController are the instance variables backing the properties of the same name.)
When you pass in maleModelViewController and femaleModelViewController, you're not passing a reference to those variables, you're passing their values. Since they haven't been initialized, all you're doing is passing in nil. To do what you're trying to do, you'd need to pass a pointer to the variables (i.e. declare the parameter as ModelViewController **, pass it in as &maleModelViewController and &femaleModelViewController and assign it using *modelViewController = viewController. If you're used to using pass-by-reference friendly languages like C# or Java, you should read up on how it works in C. (The rules are the same in Objective-C as in C).
HOWEVER, that is still complete overkill for what you're trying to do here.
Also, your code would still not work because you turn around and release viewController. This would cause it to be immediately deallocated, since the only reference you had to it came from when you alloced it. You would be assigning a dead reference that would crash your program as soon as you tried to use it.