Assigning the value of a method to a variable - iphone

In Objective-C, how do I assign the return value of a method to a variable of the same type?

Are you having any problem with:
- (NSString *)getString {
return #"hehe";
}
NSString *myString = [self getString];
You need to put the method getString above the assigning or defining the getString in the interface

Say your method prototype looked like this:
- (NSString *) name;
You'd create a variable to hold the return value like this:
NSString *some_name = [obj name];

Suppose you method returns an array
-(NSMutableArray *)getArray;
then NSMutableArray *arr=[self getArray];
or if a function return an object of a class
-(Class *)getObjectOfClass;
then you can hold this object like
Class *objClass=[self getObject];
means by simply assigning the return value to same type of variable.you can access that.

Related

Objective C method with multiple NSStrings as argument

I need to make init method with multiple NSStrings as argument.
Assume it looks like:
'-(id) initWithSomething: (NSString *) things, nil;'
How to recognize number of strings and write them into array ?
Regards
Use a variadic method:
//Interface
-(id) initWithSomething:(NSString*) arg1, ...;
//Implementation
-(id) initWithSomething:(NSString*) arg1, ... {
va_list args;
va_start(args, firstObject);
id obj;
for (obj = firstObject; obj != nil; obj = va_arg(args, id))
//Do stuff with each object.
va_end(args);
}
What you want is a Variadic function.
Basic objective-C syntax is as follows:
-(type)methodNameTakesInput:(type)param1 andMoreInput:(type)param2
So you can do
-(id)initWithString:(NSString *)str andOtherThing:(NSObject *)obj
Alternately, you could just pass the array you want:
-(id)initWithStuff:(NSArray *)arrayOfStuff
and fill the array as you normally would:
NSArray *arrayOfStuff = [NSArray arrayWithObjects:#"Strings!", #"More strings!", nil];

Use return value as argument to method

Is it possible to use the return value of a method as the argument for a different method invocation? I'm using Objective-C.
What I'm going for is something like this:
stringOutput = [object1 method1:[object2 method2:[object3 method3]]];
where method 3 returns a string that goes into method 2, which returns a string that goes into method 1, which returns a string that goes into stringOutput.
Do you mean sending the result from one method as the parameter for another?
NSString *string = [self myMethod:[self myMethod2]];
Where the methods are
- (NSString *)myMethod2 {
return #"A String";
}
- (NSString *)myMethod:(NSString *)string {
// Do something with string
// Return another string
return #"Something else";
}

how do I set the value of an NSNumber variable (without creating a new object) in objective-c

how do I set the value of an NSNumber variable (without creating a new object) in objective-c?
Background
I'm using Core Data and have a managed object that has an NSNumber (dynamic property)
passing (by reference) this to another method which will update it
not sure how to update it? if I allocate it another new NSNumber things don't work, which I guess makes sense it's then got a pointer to a different object not the core data object (I guess)
An NSNumber object isn't mutable. This means that the only way to change a property containing a NSNumber is to give it a new NSNumber. To do what you want, you have three options:
1. Pass the Core Data object to the method and have it directly set the property.
- (void)updateNumberOf:(MyCoreDataObject *)theObject {
NSNumber *newNumber = ...; // create new number
theObject.number = newNumber;
}
Called as [self updateNumberOf:theCoreDataObject];
2. Have the update method return a new NSNumber and update it in the caller.
- (NSNumber *)updateNumber:(NSNumber *)oldNumber {
NSNumber *newNumber = ...; // create new number
return newNumber;
}
Called using:
NSNumber *theNumber = theCoreDataObject.number;
theNumber = [self updateNumber:theNumber];
theCoreDataObject.number = theNumber;
3. Pass a pointer to a number variable and update it in the caller (I would only suggest this over option 2 if you need to return something else).
- (void)updateNumber:(NSNumber **)numberPointer {
if(!numberPointer) return; // or possibly throw an error
NSNumber *oldNumber = *numberPointer;
NSNumber *newNumber = ...; // create new number
*numberPointer = newNumber;
}
Called using:
NSNumber *theNumber = theCoreDataObject.number;
[self updateNumber:&theNumber];
theCoreDataObject.number = theNumber;
I did not bother with memory management in any of these examples. Make sure you release/autorelease objects appropriately.
4. (from Greg's comment) Similar to option 1, but passes the key to the update method to be more portable.
- (void)updateNumberOf:(id)theObject forKey:(NSString *)key {
NSNumber *oldNumber = [theObject valueForKey:key];
NSNumber *newNumber = ...; // create new number
[theObject setValue:newNumber forKey:key];
}
Called as [self updateNumberOf:theCoreDataObject forKey:#"number"];

retain with objective-c (again but with more precision)

I post this question again but with more precision this time,
first, I have this function who return a string, there is some error about memory management or this fonction is ok?
-(NSString *) motAvecCle:(NSString *) cle
{
NSString *motRetour;
motRetour = #"";
cle = [FonctionUtile concatener:[[tableauConfig singletonTableauConfig] langueAffichage] chaine2:#"_" chaine3:[FonctionUtile trim:[cle uppercaseString]] chaine4:#""];
motRetour = [FonctionUtile trim:[dictionnaireLangue objectForKey:cle]];
if (motRetour == nil) {
motRetour = #"Erreur";
}
return motRetour;
}
and when I call this fonction,
NSString *myString = #"";
myString = [self motAvecCle:#"fr"]; // I must do this?
myString = [[self motAvecCle:#"en"]retain]; //or do this?
thx again...
The method motAvecCle: returns an object you do not own. Therefore, at some point it is going to disappear. Whether you care or not depends on where myString is defined. If it's in the same scope:
-(void) foo
{
NSString *myString = [self motAvecCle:#"fr"];
// do some stuff
}
you do not want to retain it (except in one circumstance) because the reference will disappear when foo exits which means if you had retained it you'd need to release it again first.
The one circumstance for retaining is if you modify the object you got the string from i.e. self in this case. That might cause the string to go away (although probably not in your specific example).
If myString is an instance variable of the object, you do want to retain it because otherwise it will disappear (possibly) the next time the auto release pool is drained. However, before assigning the instance variable, you must be sure to release the old value of the instance variable, unless it's actually the same string you are assigning i.e. you need to do something like this:
-(void) foo
{
NSString *tmp = [[self motAvecCle:#"fr"] retain]; // it's a string, technically you should copy, not retain
[myString release];
myString = tmp;
// do some stuff
}
Since you'd have to do that every time you want to assign the ivar, it's normal to create an accessor e.g.
-(void) setMyString: (NSString*) newValue
{
NSString* tmp = [newValue copy];
[myString release];
myString = tmp;
}
-(void) foo
{
[self setMyString: [self motAvecCle:#"fr"]];
// do some stuff
}
If you use properties, you can use #synthesize to create the accessors.

method with 2 return values

I want to call a method which returns two values
basically lets say my method is like the below (want to return 2 values)
NSString* myfunc
{
NSString *myString = #"MYDATA";
NSString *myString2 = #"MYDATA2";
return myString;
return myString2;
}
So when i call it, i would use??
NSString* Value1 = [self myfunc:mystring];
NSString* Value2 = [self myfunc:mystring2];
I guess im doing something wrong with it, can anyone help me out?
Thanks
You can only return 1 value. That value can be a struct or an object or a simple type. If you return a struct or object it can contain multiple values.
The other way to return multiple values is with out parameters. Pass by reference or pointer in C.
Here is a code snippet showing how you could return a struct containing two NSStrings:
typedef struct {
NSString* str1;
NSString* str2;
} TwoStrings;
TwoStrings myfunc(void) {
TwoStrings result;
result.str1 = #"data";
result.str2 = #"more";
return result;
}
And call it like this:
TwoStrings twoStrs = myfunc();
NSLog(#"str1 = %#, str2 = %#", twoStrs.str1, twoStrs.str2);
You need to be careful with memory management when returning pointers even if they are wrapped inside a struct. In Objective-C the convention is that functions return autoreleased objects (unless the method name starts with create/new/alloc/copy).
You have a few options:
NSArray: Just return an array. Pretty simple.
Pointers: Pass in two pointers, and write to them instead of returning anything. Make sure to check for NULL!
Structure: Create a struct that has two fields, one for each thing you want to return, and return one of that struct.
Object: Same a structure, but create a full NSObject subclass.
NSDictionary: Similar to NSArray, but removes the need to use magic ordering of the values.
As you can only return one value/object, maybe wrap them up in an array:
-(NSArray*) arrayFromMyFunc
{
NSString *myString = #"MYDATA";
NSString *myString2 = #"MYDATA2";
return [NSArray arrayWithObjects:myString,myString2,nil];
}
You can then use it like this:
NSArray *arr = [self arrayFromMyFunc];
NSString *value1 = [arr objectAtIndex:0];
NSString *value2 = [arr objectAtIndex:1];
You could pass results back by reference, but this is easy to get wrong (syntactically, semantically, and from memory management point of view).
Edit One more thing: Make sure that you really need two return values. If they are quite independent, two separate function are often the better choice - better reusabilty and mentainable. Just in case you are making this as a matter of premature optimization. :-)
You can only directly return one value from a function. But there is a way of doing it.
-(void) myfuncWithVal1:(NSString**)val1 andVal2:(NSString**)val2
{
*val1 = #"MYDATA";
*val2 = #"MYDATA2";
}
Then to call it outside the method you'd use:
NSString* a;
NSString* b;
[self myfuncWithVal1:&a andVal2:&b];
void myfunc(NSString **string1, NSString **string2)
{
*string1 = #"MYDATA";
*string2 = #"MYDATA2";
}
...
NSString *value1, *value2;
myfunc(&value1, &value2);
Remember that you need to pass a pointer to a pointer when working with strings and other objects.
Wrap the two strings in an NSArray:
- (NSArray*)myFunc
{
NSString *myString = #"MYDATA";
NSString *myString2 = #"MYDATA2";
return [NSArray arrayWithObjects:myString, myString2, nil];
}
NSArray *theArray = [self myFunc]
NSString *value1 = [theArray objectAtIndex:0];
NSString *value2 = [theArray] objectAtIndex:1];
I see everyone has mentioned an NSArray but I'd go with an NSDictionary so the values don't have to be added in order or even at all. This means it is able to handle a situation where you only want to return the second string.
- (NSDictionary*)myFunction {
NSString *myString1 = #"string1";
NSString *myString2 = #"string2";
return [NSDictionary dictionaryWithObjectsAndKeys: myString1, #"key1", myString2, #"key2", nil];
}
NSDictionary *myDictionary = [self myFunction]
NSString *string1 = [myDictionary objectForKey:#"key1"];
NSString *string2 = [myDictionary objectForKey:#"key2"];