What does it mean to return an object in a method? - objective-c

I still cannot understand what does it mean to return an object in a method. What would its value mean?
If I have something like this:
-(ClassName *) methodName: (int) arg {
return arg;
}
I can't understand how an object can be returned through a method as the above. If someone can help me understand.
Thanks.

You would return an object by returning an object. For example, you could ignore the argument:
- (ClassName *)methodName:(int)arg {
return [[[ClassName alloc] init] autorelease];
}
You could turn the int into an object:
- (NSNumber *)methodName:(int)arg {
return [NSNumber numberWithInt:arg];
}
You could use the argument in some calculation to determine some property of the object returned. You could process the argument and return an object indicating the status of the calculation. And so on and so on. There's a practically unlimited range of ways you could return an object from a method. All it requires is that some object be created or accessed and then returned.

The above method returns a pointer to arg which is of type ClassName*.
I assume explaining the question would assume basic knowledge of how functions are called, how passed values are pushed on stack before function call and how return values is returned from a function.
In this specific case your arg variable is part of a class, meaning that it is stored in memory that is part of the object. When you return pointer to it you are pointing to a specific area of memory within the object.
Another option is to return copy of the value. It would mean make a copy and return it.
The difference is that if you return pointer to objects internal variable that object state could be modified from outside.
If you return copy that copy can be modified and the original object will not change.
Not sure if that helps, but you are asking about very basic software development topic which assumes some background knowledge.
Maybe specify what exactly you are looking for?

Think of methods like they are functions in math. In math, sin(180) is equal to 0. sin is the method, 180 is the argument and 0 is the return value of the method. An example of sin in objective-c might go like this:
-(double) sin:(double)angleInDegrees;
{
double sinValue;
//calculate the return value here and store it in sinValue.
//for example, if angleInDegrees is 180, then set sinValue to 0
return sinValue;
}
Returning objects is exactly the same. Look at this example:
-(NSString*) sayHelloTo:(NSString*)name;
{
return [NSString stringWithFormat:#"Hello %#!", name];
}
If I were to write it like a math function, then sayHelloTo(#"Tom") is equal to #"Hello Tom!". The only difference is that #"Hello Tom!" is an NSString object, not a double.

Related

Obj C - Is there a way to make a method return the method in which it is called?

I want to know whether there is the way to achieve the following requirement:
First, there is a methodA, which takes an input objA and check whether objA is valid for the method. If it's valid, then it returns an object objB. However, if objA is not valid, it just returns objA itself. Note that even if objA is valid, the returned objB may still be the same with objB.
Then, there is a methodB and in the method, methodA is called. If the input of methodA is valid, the program go on without error. However, if methodA is called with invalid input, then methodB should terminate (a.k.a return with a certain string signaling an error) to prevent future crash.
The current solution that I could think of is to create a (BOOL)methodAInputIsValid:(obj)input and in methodB there is:
if(methodAInputIsValid:input) {
obj objReturn = methodA:input;
}else{
//show error warning
return;
}
//continue doing something with objReturn and finally return some valid thing
A problem of the code is that (BOOL)methodAInputIsValid:(obj)input and methodA:(obj)input share a lot of code in common because there is a validity-test in methodA. So I want to use the validity-test more efficiently so that it will work for methodB and drop the (BOOL)methodAInputIsValid.
Here is one possible application that I could think of:
In a program the user is asked to enter a string that will direct the action of the program. However, the input string may need to be standardized such as converting all letters to lower-case and converting all single quotation to double quotation and auto-complete any missing right parenthesis or quotation marks. However, if the user is just entering nonsense that cannot be standardized, then the program should terminate and warn the user of the problem. The two methods are (BOOL)isStandardizeable:(NSString *)input and (NSString *)standardize:(NSString *)input. Because (NSString *)standardize already returns an NSString *, I can't make it to return another BOOL, right? So the following code is not achievable:
if(standardize:input){
NSString *result = standardize:input;
} else {
NSLog(#"unrecognizable input!");
return;
}
//continue...
Can anyone think of a way to do this?
Realistically, I'd just have methodA return nil if the input is not valid. This is a fairly common method to signal failure to a caller. If you really need the "identity" part of the method, just have callers do
id res = [... methodA:input];
if(res == nil)
res = input;

objective-c: return value

I'm reading Stephen Kochan's "Programming in Objective-C" (I'm n0000b). Everything has been obvious to me until exercise 4-8.
It asks me to modify methods, in an "Accumulator" class created earlier in the chapter, to "return" the value of the accumulator when one of the math methods is used (basically it's a calculator). I took this originally to mean that I want the program to display the result whenever one of the methods is used (+, -, *, /), so I set it up to do so, so each line displays the cumulative result rather than just the final result:
[deskCalc setAccumulator: 0.0];
[deskCalc add: 200.]; //the result is displayed
[deskCalc divide: 100.0]; //the result is displayed
[deskCalc subtract: 1.0]; //the result is displayed
[deskCalc multiply: 5]; //the result is displayed
NSLog (#"The result is %g", [deskCalc accumulator]);
But after looking up other people's solutions, it appears that "returning the value of the Accumulator" means something different.
Can someone describe to me what returning a value means, and what purpose it serves? I have looked through the previous chapter a few times but it is still unclear to me how this will make the program behave differently.
Thanks!
-Andrew
The calculation methods you have in your accumulator class probably look something like this at the moment:
- (void)add:(float)aFloat {
result += aFloat;
NSLog(#"%f", result);
}
This method, in its current state, returns nothing (void). It outputs the current total on screen only. That's nice for an exercise, but in real-world programs, a calculation result will probably not be very useful if it's displayed on screen. Instead, you probably will want to do something else with the result, so you want the method to return it. For example, the NSString class has a method length. This method would not be very useful if it were to print the length of the string on screen. Instead, it returns the length, so the program can do something useful with this value (like checking that the string has the correct length):
int length = [tweet length];
if (length > 140) {
// display a useful error message
...
} else {
// tweet it :)
...
}
To modify your calculator methods to return something, you will (a) have to change the method signature to have a return value, and (b) to actually return this value.
In the method signature, simply change the return type to something other than void. In your example, the correct type would probably be float (or whatever type the calculator is using internally for its current result).
- (float)add:(float)aFloat {
...
}
To actually return the current value, you would add a return statement add the end of your method (before the closing })
return result;
(this assumes that result is the instance variable containing the current calculation result).
They are asking you to modify your add, divide, substract methods to return the value of the accumulator upon completion of the performed operation. My guess is that your original add/divide/etc methods defined a (void) return value, meaning they don't return any value from the function call. As a result you could not perform a execution similar to the following:
NSLog(#"Updated value: %g", [deskCalc substract: 1.0]);
Returning a value from a function means that not only could the function perform some type of operation, but it also returns some sort of value to the calling code. The purpose of returning a value is that it allows you to separate your code into logical components, allows for code reuse and increases maintainability of your code.
Here's an example of how it would be useful: let's say you need to calculate the square root of a number. Your code don't care how the square root is calculated, you just want the number. By using a function which takes in a value, calculates its square root and then returns the calculated value to the calling code, your code can worry about what it needs to do with the returned value of the function without having to worry about the logic itself.
Here is an example of a function which returns a NSString:
- (NSString *) getAString {
return #"String being returned";
}
Here is how you would use that function:
NSString *myString = [someObject getAString];
I hope this helps you along in your learning process.

How to determine whether a #selector wants a parameter?

The scenario presents itself where I have an object that stores an outside #selector for later use. By design, I would like to be able to add two kinds of selectors. The simple one, without parameters, like [object add:#selector(doSomething)], and the more complex one, with one parameter, like [object add:#selector(doSomething:)] (mind the colon). Let's say the selector is stored in a variable SEL mySelector.
In the execution, I need to decide between [anotherObject performSelector:mySelector] or [anotherObject performSelector:mySelector withObject:userInfo]].
The way I implemented this decision, is by providing a BOOL flag that redundantly stores whether the performance should be with or without the extra parameter. Yet although I can't find this in the docs, I have the feeling that I should also be able to ask the selector something like -(BOOL)needsParameter. I know, for example, that UIGestureRecognizer's addTarget:action: somehow makes this distinction automatically.
Could someone point me in the right direction?
You can use the NSMethodSignature class for that. For instance,
SEL mySelector = …;
NSMethodSignature *msig = [anotherObject methodSignatureForSelector:mySelector];
if (msig != nil) {
NSUInteger nargs = [msig numberOfArguments];
if (nargs == 2) { // 0 non-hidden arguments
}
else if (nargs == 3) { // 1 non-hidden argument
}
else {
}
}
Alternatively, you could use NSStringFromSelector() to get the string representation of mySelector and count the number of occurrences of the colon character.

Passing arguments by value or by reference in objective C

I'm kind of new with objective c and I'm trying to pass an argument by reference but is behaving like it were a value. Do you know why this doesn't work?
This is the function:
- (void) checkRedColorText:(UILabel *)labelToChange {
NSComparisonResult startLaterThanEnd = [startDate compare:endDate];
if (startLaterThanEnd == NSOrderedDescending){
labelToChange.textColor = [UIColor redColor];
}
else{
labelToChange.textColor = [UIColor blackColor];
}
}
And this is the call:
UILabel *startHourLabel; // This is properly initialized in other part of the code
[self checkRedColorText:startHourLabel];
Thanks for your help
Objective-C only support passing parameters by value. The problem here has probably been fixed already (Since this question is more than a year old) but I need to clarify some things regarding arguments and Objective-C.
Objective-C is a strict superset of C which means that everything C does, Obj-C does it too.
By having a quick look at Wikipedia, you can see that Function parameters are always passed by value
Objective-C is no different. What's happening here is that whenever we are passing an object to a function (In this case a UILabel *), we pass the value contained at the pointer's address.
Whatever you do, it will always be the value of what you are passing. If you want to pass the value of the reference you would have to pass it a **object (Like often seen when passing NSError).
This is the same thing with scalars, they are passed by value, hence you can modify the value of the variable you received in your method and that won't change the value of the original variable that you passed to the function.
Here's an example to ease the understanding:
- (void)parentFunction {
int i = 0;
[self modifyValueOfPassedArgument:i];
//i == 0 still!
}
- (void)modifyValueOfPassedArgument:(NSInteger)j {
//j == 0! but j is a copied variable. It is _NOT_ i
j = 23;
//j now == 23, but this hasn't changed the value of i.
}
If you wanted to be able to modify i, you would have to pass the value of the reference by doing the following:
- (void)parentFunction {
int i = 0; //Stack allocated. Kept it that way for sake of simplicity
[self modifyValueOfPassedReference:&i];
//i == 23!
}
- (void)modifyValueOfPassedReference:(NSInteger *)j {
//j == 0, and this points to i! We can modify i from here.
*j = 23;
//j now == 23, and i also == 23!
}
Objective-C, like Java, only has pass-by-value. Like Java, objects are always accessed through pointers. "objects" are never values directly, hence you never assign or pass an object. You are passing an object pointer by value. But that does not seem to be the issue -- you are trying to modify the object pointed to by the pointer, which is perfectly allowed and has nothing to do with pass-by-value vs. pass-by-reference. I don't see any problem with your code.
In objective-c, there is no way to pass objects by value (unless you explicitly copy it, but that's another story). Poke around your code -- are you sure checkRedColorText: is called? What about [startDate compare:endDate], does it ever not equal NSOrderedDescending? Is labelToChange nil?
Did you edit out code between this line
UILabel *startHourLabel;
and this line?
[self checkRedColorText:startHourLabel];
If not, the problem is that you're re-declaring your startHourLabel variable, so you're losing any sort of initialization that was there previously. You should be getting a compiler error here.
Here are the possibilities for why this doesn't work:
the label you pass in to checkRedColorText is not the one you think it is.
the comparison result is always coming out the same way.
... actually, there is no 3.
You claim you initialised startHourLabel elsewhere, but, if it is a label from a nib file, you should not be initialising it at all. It should be declared as an IBOutlet and connected to the label in the nib with interface builder.
If it is not a label in the nib i.e. you are deliberately creating it programmatically, you need to check the address of the label you initialise and check the address of the label passed in to checkRedColorText. Either NSLog its address at initialisation and in checkRedColorText or inspect it with the debugger.

What does "-(void)" mean in this function declaration? `-(void)awakeFromNib`

How come whenever I have to use awakeFromNib protocol I have to put it in this format?
-(void)awakeFromNib
What is the need for -(void)?
The -(void) is used in the declaration of the method. Presumably, you are defining it for someone else to call, rather than calling it yourself.
The - sign indicates that the method is an instance method, as opposed to a class method. It requires an object to call it, and instance variables of the object are available to it inside its definition.
The (void) indicates the return type. This method doesn't return anything, so its result can't be assigned to anything.
think of it this way
say you have a Class you created that is called "Math"
and this class has a method called "calculate". It's type as
-(int)calculate {
2+2;
return 2+2;
}
When you alloc the class and initialize the object and perform the "calculate method on that object, it's going to do the calculation 2+2 and it will return the result, 4.
If you tried
-(void)calculate {
2+2;
}
it wouldn't do anything, it would just have that 2+2 information stored in the method but the calculation would never occur.
Because the method does not return anything, and giving a void return type is how you declare that in C and Objective-C.
(void) marks the return type - in this case, void means it's returning nothing.
If it was instead -(int)awakeFromNib, you'd be expected to return an integer.
The meaning of the return value (if any) should be explained in the documentation.