UIViewController may not respond to methodName::: - iphone

I'm trying to use methods to pass values from text fields in one view to corresponding text fields in another view. The action valuesChanged is wired to the event "Editing Did End" on the text fields. I tried using "Value Changed" with similar results (it doesn't work.). The only warning I receive is in a method call.
Here's the code for the VolumeViewController:
#implementation VolumeViewController
#synthesize boxWidth;
#synthesize boxHeight;
#synthesize boxLength;
#synthesize sphereRadius;
#synthesize boxResult;
#synthesize sphereResult;
#synthesize areaViewController;
-(IBAction)valuesChanged:(id)sender
{
NSString *length = boxLength.text;
NSString *width = boxWidth.text;
NSString *radius = sphereRadius.text;
NSLog(#"length: %#", length);
NSLog(#"width: %#", width);
NSLog(#"radius: %#", radius);
[areaViewController changeValues:width :length :radius];
}
-(void)changeValues:(NSString*)widthString :(NSString*)lengthString :(NSString*)radiusString
{
boxWidth.text = widthString;
boxLength.text = lengthString;
sphereRadius.text = radiusString;
}
As you can see, the valuesChanged action instantiates three NSString objects, each corresponding to the text properties of a text field. These strings are then passed to the changeValues method of the areaViewController. The areaViewController's changeValues method is identical to the volumeViewController's method, other than the text field names being different. However, the NSLog commands that I have never show anything in the console, so it's obvious that despite my text fields being connected to the action, it is not being called. What do I need to fix?
The warning is given after the method call "[areaViewController changeValues:width :length :radius], and it reads 'UIViewController' may not respond to '-changeValues:::'

Define the method it in your header.

What you can do to "declare" it in .m an not in .h (because it's kind of a private method for you, and it should not visible from outside) is add this before #implementation VolumeViewController :
#interface VolumeViewController()
- (void)changeValues: : : ;
#end
EDIT: It's better to name all the arguments in your method name. The signature should be:
-(void)changeWidth:(NSString*)widthString lenght:(NSString*)lengthString radius:(NSString*)radiusString;
This is more readable when you use it:
[areaViewController changeWidth:#"4" length:#"2" radius:#"6"];

You are calling changeValues on areaViewController, but you have defined that method for the VolumeViewController class
Try changing [areaViewController changeValues:width :length :radius];
to [self changeValues:width :length :radius];

Related

How to use variables created outside of viewDidLoad

Hey I'm very new to Objective C programming and I'm stuck. How come when I create I function, it can't use the variables I created for the labels or textviews, etc. And whenever I call them in the viewDidLoad function, I have to do either self.(variableName) or _(variableName) and it won't let me do that outside of the viewDidLoad function. Is there a way to access them outside of it?
How come when I create I function, it can't use the variables I
created for the labels or textviews, etc.
For one thing, you need to differentiate between a function and an instance method. In Objective-C, classes can have instance variables (variables that are part of an instance of that class) and instance methods (similar to functions that are associated with an instance of that class). Classes can also have properties, which are used rather like instance variables in that they're values associated with an object, but they're accessed through accessor methods. Functions, on the other hand, aren't part of any class. So, a class has an interface where instance variables and methods are declared, like this:
#interface Person : NSObject
{
NSString *firstName;
NSString *lastName;
}
#property (readonly) NSString *fullName;
#property (strong) NSArray *friends;
#property (assign) int age;
- (id)initWithFirstName:(NSString*)first lastName:(NSString*)last;
- (void)addFriend:(Person*)friend;
#end
And also an implementation, like this:
#implementation Person
- (id)initWithFirstName:(NSString*)first lastName:(NSString*)last
{ /* code goes here */ }
- (void)addFriend:(Person*)friend
{ /* code goes here */ }
- (NSString *)fullName
{ return [NSString stringWithFormat:#"%# %#", firstName, lastName; }
#end
Those things in the implementation are instance methods, as denoted by the - at the beginning and the fact that they're defined in an #implementation block. (If they had + instead of -, they'd be class methods instead of instance methods -- I'll let you read about that in the docs.) Properties are accessed by calling an appropriate accessor methods using either normal method calls or dot notation, so if you have:
Person *george = [[Person alloc] initWithFirstName:#"George" lastName:#"Bailey"]
all of these are valid:
NSString *name1 = george.fullName;
NSString *name2 = [george fullName];
george.age = 45;
[george setAge:45];
int years1 = george.age;
int years2 = [george age];
Also, self is a pointer to "the current object". You can use it in instance methods so that objects can call their own methods and access their own properties. For example, the Person class could contain a method like this:
(NSString *)nameAndAge
{
NSString *nameAndAge = [NSString stringWithFormat:#"%#: %d", self.fullName, self.age];
}
Functions, on the other hand, aren't part of any class, use C function syntax rather than Objective-C method syntax, and aren't defined in an #implementation block:
BOOL isMiddleAged(Person* person)
{
return (person.age > 30) && (person.age < 60);
}
You can't use self in function because a function isn't associated with an object, so there's nothing for self to point to. You can, however, use properties of other objects you know about, such as person.age in the example above.
And whenever I call them in the viewDidLoad function, I have to do
either self.(variableName) or _(variableName) and it won't let me do
that outside of the viewDidLoad function.
You must be accessing properties of your view controller. As explained above, self.(variableName) is the way to access properties. _(variableName) refers to a variable (often generated by the compiler) that stores the value of the property. (You shouldn't normally access those variables directly outside initialization methods and -dealloc -- use the property accessors instead.) You can use those properties in any instance method of the class, not just -viewDidLoad. You can also access properties of other objects by replacing self with the name of a pointer to the object, just as I did with person in isMiddleAged().
Seems like your are using autosythesized property. Using Auto Synthesized property you need not to #syhtesize objects.
#sythesize object = _object; will be implicitly implement in this case.
So you can access object using self.object or _object.
You can #synthesize to avoid using objects via self.varName or _varName .You can directly use it using varName.

why do my NSString values get lost in the definition class? is it normal?

I'm defining some simple variables in a class of type NSString
one of them is keeping my sqlite database path for example, and so on...
I am initializing that in the AppDelegate , function didFinishLaunchingWithOptions
and when I'm trying to see it's value outside this function... it's losing it's value durring runtime, (no I'm not overwrting or anything...)
here's my code...
app.h file
#interface AppDelegate : NSObject <UIApplicationDelegate, UITabBarControllerDelegate> {
.....................
NSString *site_domain;
NSString *databaseName;
NSString *databasePath;
..........................
}
app.m file
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
databaseName = #"database.sqlite";
site_domain=#"http://localhost/webservice";
NSLog(#"%#",site_domain);
// inside this function I can use the value, ..if I call whatever function from
//this function, that function can also use the value...
}
-(void) functionTest {
NSLog(#"%#",site_domain);
//here the value is lost, it's like it can't reach it's pointer or something...
//puts on a wierd string
}
What am i Doing wrong?
What am i Doing wrong?
You aren't posting enough information. :)
//here the value is lost, it's like it can't reach it's pointer or something...
//puts on a wierd string
What does that mean? Show the string. Is functionTest defined in the same source file? Where is it called from?
Since you are using constant strings (#""), there is no need for retain/release, so that isn't the problem.
Are those really the string values you are using?
Because you never take ownership of it, your string is getting autoreleased by the auto release pool. In your didFinishLaunchingWithOptions: method, try using:
site_domain = [[NSString alloc] initWithString:#"http://..."];
And don't forget to release it int the dealloc method
-(void)dealloc
{
[site_domain release];
}

Setting a delegate using blocks in iPhone

On a view controller I have multiple textfields, which all use the same delegate. Now in the delegate the code gets really ugly since I have to differentiate between all the textfields (bunch of if/else-if or a switch statement). I came a cross this article:
Blocks in textfield delegates
But from this I still don't understand how this solves the problem? Doesn't this basically call one method and pass it the text and the method has no idea what textfield gave the string? You would still need to differentiate between the textfields, but this time inside the block (with the usual if(textfield == bazTextField)...).
I don't know that it exactly solves the problem so much as shifts it (and into viewDidLoad, which usually gets a bit of mush-mash in it anyway).
However in that example the block itself was being passed in the textfield to run comparisons with and "remembers" the values of all the instance variables as well (if it refers to them), so that's how it knows what text and text field is being dealt with.
I don't see how that code exactly is supposed to help though, since it assigns one block to the single delegate class to be used with all text field delegates - unless perhaps you were supposed to have one per text field, each with a different block. Then you have way more code than you'd have had with the if statements!
The article doesn't make it clear, but I believe the idea is to create one of these blocks (and block delegate objects) for each UITextField that you wish to have respond to textFieldShouldReturn.
hm, maybe I didn't completely understand the article, but I don't see the advantage of using blocks instead of selectors in that concrete example.
you could achieve something similar like this
#interface AlternativeTextFieldDelegate : NSObject <UITextFieldDelegate>
{
SEL selectorToCall;
id objectToCall;
}
- (void) setObjectToCall:(id)obj selector:(SEL)selector;
#end
#implementation AlternativeTextFieldDelegate
- (void) setObjectToCall:(id)obj selector:(SEL)selector
{
objectToCall = obj;
selectorToCall = selector;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[objectToCall performSelector:selectorToCall];
return YES;
}
#end
and the view controller
#interface ViewWithTextFieldsController : UIViewController
{
UITextField *tf1;
AlternativeTextFieldDelegate *delegateForTF1;
UITextField *tf2;
AlternativeTextFieldDelegate *delegateForTF2;
}
// ...IBOutlets and all that...
- (void) tf1ShouldReturn; // handles shouldReturn for tf1
- (void) tf2ShouldReturn; // handles shouldReturn for tf2
#end
#implementation ViewWithTextFieldsController
- (void) viewDidLoad // or wherever
{
delegateForTF1 = [[AlternativeTextFieldDelegate alloc] init];
[delegateForTF1 setObjectToCall:self selector:#selector(tf1ShouldReturn)];
tf1.delegate = delegateForTF1;
delegateForTF2 = [[AlternativeTextFieldDelegate alloc] init];
[delegateForTF2 setObjectToCall:self selector:#selector(tf2ShouldReturn)];
tf2.delegate = delegateForTF2;
}
// ...
#end
don't really know if that's any better than chaining if-elses though.
it seems to me that this complicates things more than the problem it solves.

Does calling a protocol method pass program flow control?

I know this is quite possibly a lame question, but I've pulled three consecutive all-nighters and I'm very blurry. And I'm new to Objective C and Cocoa Touch.
I've created a class that provides a delegate method. I'll use simplified example code since the specifics aren't important. The header file looks like this:
#import <Foundation/Foundation.h>
#protocol UsernameCheckerDelegate <NSObject>
#required
- (void)didTheRequestedThing:(BOOL)wasSuccessful;
#end
#interface TheDelegateClass : NSObject {
id <TheDelegateClassDelegate> tdcDelegate;
}
#property (assign) id <TheDelegateClassDelegate> tdcDelegate;
- (void)methodThatDoesSomething:(int)theValue;
#end
And the source file looks like this:
#import "TheDelegateClass.h"
#implementation TheDelegateClass
#synthesize tdcDelegate;
- (void)methodThatDoesSomething:(int)theValue {
if (theValue > 10) {
[[self tdcDelegate] didTheRequestedThing:NO];
// POINT A
}
// POINT B
int newValue = theValue * 10;
NSString *subject = [NSString stringWithFormat:#"Hey Bob, %i", newValue];
// Some more stuff here, send an email or something, whatever
[[self tdcDelegate] didTheRequestedThing:YES];
// POINT C
}
#end
Here's my question: if theValue is in fact greater than 10 and the line above POINT A runs, does program flow control pass out of this method (and back to the didTheRequestedThing delegate method in the object that called this) or does flow continue on through POINT B to POINT C?
I'm hoping for the former because I can simplify the heck out of my code, currently an unpleasant mess of deeply nested ifs and elses.
When the -didTheRequestedThing: method returns, control flow returns back to your POINT A and continues on to POINT B and POINT C. Delegate method calls are exactly like any other method call. If you want to avoid executing the rest of the method after the delegate call, just stick a call to return where your // POINT A comment is.

Set a variable in a different class

I am trying to create an application were 2 classes share a variable. Just to keep the code looking a little bit cleaner I created a 3rd class. This "third class" sole job is to house this variable.
In class 3 I put a "get" and "set" method.
SharedURL.H (Class 3)
#interface SharedURL : NSObject {
NSString *theURL;
}
-(NSString *)getTheURL;
-(void)setTheURL:(NSString *)blah;
#property (readwrite, copy) NSString *theURL;
#end
Implementation:
#import "SharedURL.h"
#implementation SharedURL
#synthesize theURL;
-(NSString *)getTheURL;
{
return theURL;
}
-(void)setTheURL:(NSString *)blah;
{
theURL=blah;
}
#end
In classes 1 and 2:
I Import the class header
I set up the instance variable like so
SharedURL *XMLURL;
I define the property like so
#property (readwrite, assign) SharedURL *XMLURL;
Then in the implementation I set the set method like this
[XMLURL setTheURL:#"http://localhost:8888/xml/MyXMLFile.xml"];
However whenever I implement the fallowing code the getter method returns nil.
NSLog(#" the url is %#", [XMLURL getTheURL]);
How can I get this to actually save the variable that I imput and then return it. I'm looking at some sample code and i cannot find my error it looks to me like I am doing it perfectly fine I think I am overlooking something stupid.
If I understand this right you are calling class 3 from either class 1 or 2 (lets say 1) and set the URL then your go to class 2 and and only ask for the URL, right?
I think your problem is that you are calling something that is independent for each object. I think you can fix this by instead of saying -(NSString *)getTheURL and -(void)setTheURL you need to change it to +(NSString *)getTheURL and +(void)setTheURL (in both the .h and .m files) making it not variable dependent.