Calling a method in another method? - iphone

I've got a delegate method which just has a bit of code in there that puts a % sign on the end of the number entered.
- (void)textFieldDidEndEditing:(UITextField *)UItextfield {
NSString *oldTextFieldValue = UItextfield.text;
UItextfield.text = [NSString stringWithFormat:#"%# %%",oldTextFieldValue];
}
Could I instead of having that, have the following action
-(IBAction)Calculate:(UITextField *)UITextfield;
{
NSString *oldTextFieldValue = UItextfield.text;
UItextfield.text = [NSString stringWithFormat:#"%# %%",oldTextFieldValue];
}
And then in the Delegate function, call that action? Something like
-(void)textFieldDidEndEditing:(UITextField *)UItextfield {
[self Calculate:self]
}
I tried that, it doesn't work. I know it'll get me to the same result but I just want to know if it can be done. I think i'm asking can a method (Calculate) be called in another method (textFieldDidEndEditing) and how.

You are providing self as the method argument which is the instance of the class you are in. Which in this case is wrong since the method argument should be an instance of UITextField. Try instead [self Calculate:UItextfield] in your method.

Calling other methods from methods happen all the time in most programming languages.
It's a great way to split code up and reuse code in different places without having to copy/paste.
(This might be too basic for you. Sorry in that case)
Things may be easier to understand if you use standard naming conventions too. ('likeThis' for variables and method names; 'LikeThis' for class names)
- (void)textFieldDidEndEditing:(UITextField *)textField {
NSString *oldTextFieldValue = textField.text;
textField.text = [NSString stringWithFormat:#"%# %%",oldTextFieldValue];
}
textField here, is the pointer to the UITextField object which just finished editing.
You want to pass this object to your new 'other' method.
[self calculate:textField];
self is a pointer to an instance of the current class. For example, in a UIViewController subclass called 'MyViewController', self refers to the current instance of this class.
Since the -calculate method is an instance method (beginning with a '-') it requires you to use self. The variable textField is passed after the colon.
- (void)calculate: (UITextField*)textField {
NSString *oldTextFieldValue = textField.text;
textField.text = [NSString stringWithFormat:#"%# %%",oldTextFieldValue];
}
Use only the IBAction keyword when you want the method to be called from a UIComponent in an xib or storyboard.

Related

How to call a non-void function? Xcode

How do I call a non-void function? Normal [self methodName]; works. But how do I do this for a method that returns an NSString. I keep getting an error. For example:
+ (NSString *)formulateYQLRequestFor:(NSArray *)tickers
How do I call this? [self formulateYQLRequestFor]; gives me an error.
Sorry about the formatting, for some reason safari won't let me indent.
Thanks!
+ designates a class function. You call it with the class name, not an instance.
Instead of:
[self formulateYQLRequestFor:myArray];
Do this:
[MyClassName formulateYQLRequestFor:myArray];
Alternatively, you can do this:
[[self class] formulateYQLRequestFor:myArray];
You don't have to do anything with the return value if you don't want to. At least with ARC, the return value will be automatically released. However, since it's unlikely that the function does anything on its own, you probably should do something with the return value:
NSString *returnValue = [[self class] formulateYQLRequestFor:myArray];
// Do something with returnValue
Finally, if you want to call the function without passing in an array, you still need the array parameter, but perhaps the function will accept nil for the array:
NSString *returnValue = [[self class] formulateYQLRequestFor:nil];
There are two problems with your call to [self formulateYQLRequestFor];
Firstly, the method takes a parameter, which you haven't provided. Because of this, the compiler is looking for the method called formulateYQLRequestFor instead of formulateYQLRequestFor: This is significant, because the : is part of the method name in Objective-C. So you are trying to call a method that doesn't exist.
Secondly, self is sending a message to an instance of your class. The + in the method signature indicates that you have a class method, and so self does not respond to the method you are trying to call.
The correct way to do this is:
NSString *resultString = [[self class] formulateYQLRequestFor:someArray];
where someArray is a valid NSArray parameter.
I don't know what - (NSString *)formulateYQLRequestFor: does with the NSArray, but if it isn't necessary you can just call [self formulateYQLRequestFor:nil];. Alternatively you can call it with an empty array [self formulateYQLRequestFor:[NSArray array]];.

custom setter for NSString

I have a NSString called fontType
and I am trying to have a custom setter for it:
- (void) setFontType:(NSString *) fType
{
if (self.fontType != fType){
[fontType release];
self.fontType = [fType retain];
//some more custom code
}
}
Is there any issue with this?
A few things that stand out for me:
do not use self. inside of custom accessors. access the variable directly
it's better use copy semantics for properties of a type that has a
mutable subtype
be careful with whatever is // some more custom code
My personal style preferences are like so:
-(void)setFontType:(NSString *)fontType_ {
if (fontType == fontType_) return; // get out quick, flatten the code
[fontType release];
fontType = [fontType_ copy];
// some more code
}
Cocoa with Love has a good article on this topic. It's worth a read.
When you do self.fontType = newFontType, you are doing [self setFontType:newFontType] (just with a different syntax), this means you are calling the method inside itself.
This is called recursion, but in this case, you don't have a base case in which the method will stop calling itself, so my guess is that this method will call itself until the app crashes. In short, recursion is not something you want here.
Just replace self.fontType = [fType retain] with fontType = [fType retain] (Assuming the var linked to the fontType property is called fontType as well).
PS. At the end of the question you asked
Is there any issue with this?
If you didn't try this, then you shouldn't even be asking that here on StackOverflow, and if you did try it, then you should have realized that this method didn't work, so that last line is pretty meaningless. Just saying.

pass a variable between two methods

I was trying to pass a variable of type NSString from a method to another. what I have done is:
-(void)some{
NSString *lat = something
NSString *longt = somethingElse
[self test:lat:longt];
}
and then
- (IBAction)test:(NSString *)lat:(NSString *)longt{
doSomeThing
}
But my problem is that now the IBAction button is activated without my press.
how do I run the method IBAction under my control
you cannot pass arbitrary parameters through an IBAction, you can either pass the control sending the action or nothing:
-(IBAction)action:(id)sender;
or
-(IBAction)action;
The test method should not be an IBAction. Instead do this:
- (void)test:(NSString *)lat:(NSString *)longt{
//doSomeThing
}
-(IBAction)myAction:(id)sender
{
//call test from here
[self some];
}
You should use void as returm type of method not ibaction. If u need it for some action thn call it from there.
use
- (void) test:(NSString *)lat:(NSString *)longt
instead of
- (IBAction)test:(NSString *)lat:(NSString *)longt

NSString self modifying category dilemma

Both work, but which one would you use and why?
#implementation NSString (Extender)
-(NSString *) stringByTrimmingPrefix:(NSString *)strPrefix
{
while ([self hasPrefix:strPrefix])
{
self = [self substringFromIndex:strPrefix.length];
}
return self;
}
#end
or
#implementation NSString (Extender)
-(NSString *) stringByTrimmingPrefix:(NSString *)strPrefix
{
NSString *returnValue = [NSString stringWithString:self];
while ([returnValue hasPrefix:strPrefix])
{
returnValue = [returnValue substringFromIndex:strPrefix.length];
}
return returnValue;
}
#end
Option #2.
NSString is intended to be an immutable object. All of the standard "stringBy" methods on NSString return new autoreleased NSStrings.
While #1 also ends up returning a new NSString, it is at best semantically incorrect and at worst altering the referenced object of what was supposed to be an immutable object.
Firstly, your Objective-C method definition is exactly equivalent to this C function:
NSString* stringByTrimmingPrefix(NSString* self, SEL _cmd, NSString* strPrefix)
{
...
}
As you can see, self is just another function parameter; you can re-assign it to anything you want and it won't affect the state of the original NSString* instance it was originally pointing to.
So there's nothing wrong with what you're doing in your first implementation, in that respect.
However, neither of your implementations are very efficient, and both have bugs (what happens if you pass a prefix with more than one character?)
I would use rangeOfString:options:range: to find your prefixes, so that you're only creating at most one extra NSString instance.
See Searching, Comparing, and Sorting Strings
so this just chops off a single letter from the front of a string (if that letter is there more than once, it will cut off as many as there are)?
Since NSString is immutable, I don't there is a difference either way, performance wise. In the first case you are replacing self with a new string object each time, and in the second case, you are replacing returnValue with a new string object each time. I guess since the first option saves a line of code i would use that one.

Can't include "self" in Objective-C description method?

I have a very straight forward class with mostly NSString type properties. In it, I wrote a trivial implementation of the description method. I found that whenever I try to include "self" in the description, it crashes my iPhone app. An example is something such as the following:
- (NSString *)description
{
NSString *result;
result = [NSString stringWithFormat:#"me: %#\nsomeVar: %#", self, self.someVar];
return result;
}
As soon as I remove the first parameter to the format string, self, it works as expected.
Use %p for self, then it will display the address of self. If you use %#, then it will call description on self, which will set up an infinite recursion.
You can use [super description] instead of self to avoid the infinite recursion, like so:
- (NSString *)description
{
return [NSString stringWithFormat:#"%#: %#", [super description], [self someVar]];
}
You do realise that sets up an infinite recursion.
Your description implementation is implicitly calling itself when you pass in self, which then calls itself, and so on.
Your crash is mostly likely due to stack space running out... a "stackoverflow" if you will. Fitting considering the site :-)