Pointers in method params - objective-c - objective-c

How to pass pointer as param in method?
for example:
-(void) dosomething:(NSString *) simpleString :(NSMutableArray *) pointerToArray;
where simpleString is simple param, and pointerToArray is pointer to an array;

In Objective-C, strings and arrays are both classes. As you can see, they are already accessed through pointers. So you simply use them as the declaration says:
-(void) dosomething:(NSString *) simpleString :(NSMutableArray *) pointerToArray;
And you invoke like:
NSString *s = #"Hello, world";
NSMutableArray *a = [NSMutableArray arrayWithObjects: #"Hello", #"silly", #"example", nil];
[yourClass dosomething:s :a];
FWIW, the name of your method is dosomething::. It is customary to denote each parameter, so I would call it:
-(void) doSomethingWithString:(NSString *)greeting array:(NSMutableArray *)strings;
then the name is doSomethingWithString:array: which is much more readable, IMO. You
invoke it with:
[yourClass doSomethingWithString:s array:a];

Like this:
-(void) dosomething:(NSString *) simpleString :(NSMutableArray **) pointerToArray;
(Add a second '*' to the parameter type
In your method, you then do something like:
*pointerToArray = [NSMutableArray array];

For example:
NSString *localSimpleString;
NSMutableArray *localArray;
[self dosomething:localSimpleString :pointerToArray];

Related

how to pass enum as parameter to function in objectivec

The header file looks like:
enum RatingsEnum
{
userRating,
criticRating,
};
#interface SFMovie : NSObject
- (NSNumber *)getRating:(NSDictionary *)movieDic :(enum RatingsEnum) rating;
#end
How can I use this method getRating? I am not sure how to pass the enum. My calling code:
- (void) testGetCriticRatingMethod{
NSMutableDictionary *ratingDictionary = [[NSMutableDictionary alloc]init];
[ratingDictionary setObject:#"Certified Fresh" forKey:#"critics_rating"];
[ratingDictionary setObject:#"70" forKey:#"critics_score"];
[ratingDictionary setObject:#"Certified Fresh" forKey:#"audience_rating"];
[ratingDictionary setObject:#"87" forKey:#"audience_score"];
SFMovie *movie = [[SFMovie alloc]init];
enum RatingsEnum ratings;
NSInteger userRating = [movie getRating:ratingDictionary rating:userRating];
}
This produces the following warning:
No visible #interface for 'SFMovie' declares the selector 'getRating:rating:'
Can somebody guide me to a good enum tutorial? Thank you all.
Change
- (NSNumber *)getRating:(NSDictionary *)movieDic :(enum RatingsEnum) rating;
to
- (NSNumber *)getRatingWithDictionary:(NSDictionary *)movieDic ratingEnum:(enum RatingsEnum) ratingEnum;
Change
enum RatingsEnum ratings;
NSInteger userRating = [movie getRating:ratingDictionary rating:userRating];
to
enum RatingsEnum ratings = userRating;
NSNumber *ratingFromUser = [movie getRatingWithDictionary:ratingDictionary ratingEnum:ratings];
This has nothing to do with the enum, or the type of the parameter at all. Your syntax is simply wrong. The name of the method as declared is getRating::. A correct call looks like
[movie getRating:ratingDictionary :userRating];
Add a label to the second parameter
- (NSNumber *)getRating:(NSDictionary *)movieDic ofType:(enum RatingsEnum)rating;

Iterating a va_list when passed as a parameter to a method in Objective-C

I would like to pass a variable argument list from one method (functionOne) to another (functionTwo). Everything works fine, except that I have not been able to figure out how to setup the va_list in functionTwo in a way where I can access the first parameter in the va_list. Using va_arg advances to the second parameter in the va_list. Thx.
- (void)functionOne:(NSString *)configFiles, ... {
va_list args;
va_start(args, configFiles);
[self functionTwo:args];
va_end(args);
}
- (void)functionTwo:(va_list)files {
NSString *file;
while ((file = va_arg(configFiles, NSString *))) {
...
}
}
The first variadic argument is not the argument passed to va_start – it's the one immediately following it. If you want functionTwo: to have access to the configFiles string, you'll need to pass it in explicitly.
See Technical Q&A QA1405: Variable arguments in Objective-C methods.
Methods that take variable arguments are known as variadic methods.
Keep in mind that the implementation of an Objective-C method is just
a block of code, like a C function. The variadic argument macros
described in the stdarg(3) manual page work the same way in a method
as they do in an ordinary function.
Here's an example of an Objective-C category, containing a variadic
method that appends all the objects in a nil-terminated list of
arguments to an NSMutableArray instance:
#import <Cocoa/Cocoa.h>
#interface NSMutableArray (variadicMethodExample)
// This method takes a nil-terminated list of objects.
- (void)appendObjects:(id)firstObject, ...;
#end
#implementation NSMutableArray (variadicMethodExample)
- (void)appendObjects:(id)firstObject, ... {
id eachObject;
va_list argumentList;
if (firstObject) // The first argument isn't part of the varargs list,
{ // so we'll handle it separately.
[self addObject: firstObject];
// Start scanning for arguments after firstObject.
va_start(argumentList, firstObject);
while (eachObject = va_arg(argumentList, id)) // As many times as we can get an argument of type "id"
[self addObject: eachObject]; // that isn't nil, add it to self's contents.
va_end(argumentList);
}
}
#end
A solution that I use for debugging purposes is like
-(void) debug:(NSString*)format, ... {
if (level < MXMLogLevelDebug) return;
if(format == nil) return;
va_list args, args_copy;
va_start(args, format);
va_copy(args_copy, args);
va_end(args);
NSString *logString = [[NSString alloc] initWithFormat:format
arguments:args_copy];
NSString *funcCaller = #"";
NSArray *syms = [NSThread callStackSymbols];
if ([syms count] > 1) {
funcCaller = [syms objectAtIndex:1];
}
NSString *logMessage = [NSString stringWithFormat:#"%# DEBUG: %#", funcCaller, logString];
NSLog(#"%#",logMessage);
}
The side-effect that this can have is that you have to add a guard on the args to be sure is not NULL.

Self assignment for NSString category

I want to self assign an adjusted nsstring via category.
The example is a trim function:
I do not want that way:
NSString *theTempString = [theExampleString xTrim];
// ... go on doing stuff with theTempString
I want it this way:
[theExampleString xTrim];
// ... go on doing stuff with theExmapleString
The category looks like this:
- (void)xTrim
{
self = [self stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet]];
}
The error that an assignment outside init is not possible - I understand that.
But now I'm interested in it, of course I can write an custom init methode, but is there no way around it like the one above???
Greetings and thanks,
matthias
You don't need to create a new NSString, the method already does that for you:
- (NSString *)xTrim
{
return [self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
}
NSString is immutable so you need to assign it:
yourString = [yourString xTrim];
You cannot do that in a category on NSString, because NSString manages immutable strings, which means that the string can not be changed after it has been created.
You could implement it as category on NSMutableString:
- (void)xTrim
{
NSString *trimmed = [self stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet]];
[self setString:trimmed]; // replaces the characters of "self" with those of "trimmed".
}
And if your question is: Can I write a method xTrim such that
[theExampleString xTrim]
replaces the receiver theExampleString with a new instance: No, that is not possible.

Why isn't NSString answering to call by reference?

I'm trying to change a variable of NSString type by calling a method. But it doesn't work. I tried this very same method with othe types and it worked perfectly fine. Can you help me out there?
Interface:
- (void) changeNSString: (NSString *) stringToChange;
Implementation:
- (void) changeNSString: (NSString *) stringToChange{
stringToChange = #"Test";
}
- (IBAction)actionBla:(id)sender {
NSString *myString = [NSString string];
[self changeNSString:myString];
NSLog(myString); //Returns nothing or empty string
}
======================
Edit: thanks to the help of CrimsonDiego, here is a working solution. Though I still have a little understanding issue: why is there no type-error when assigning a NSMutableString to a NSString var?
Interface:
- (void) changeNSMutableString: (NSMutableString *) stringToChange;
Implementation:
- (void) changeNSMutableString: (NSMutableString *) stringToChange{
[stringToChange setString:#"Test"]
}
- (IBAction)actionBla:(id)sender {
NSMutableString *myString = [NSMutableString string];
[self changeNSMutableString:myString];
self.myLabel.text = myString; //Why is there no type error???
}
You are assigning a new variable to a local variable within the function.
The local variable stringToChange references the same variable as myString at first, but when you assign #"Test" to stringToChange, it no longer references the original string.
The solution here would be to use NSMutableString, or have a class variable (or property) and use that instead of passing it to the function.
Your setting stringToChange as local in your function. Try the following:
- (NSString*) changeNSString: (NSString *) stringToChange{
stringToChange = #"Test";
return stringToChange;
}
- (IBAction)actionBla:(id)sender {
NSString *myString = [NSString string];
myString = [self changeNSString:myString];
NSLog(myString); //Returns nothing or empty string
}
I am no expert on Objective-C but it seems to me that stringToChange, as in "normal" C, is a parameter that can contain a pointer to a string. The parameter is pass-by-value and thus, when you assign #"Test" to stringToChange you are actually only changing the local parameter stringToChange and not myString. If you want to change myString you have to change the parameter type to NSString ** and pass &myString as a parameter instead.

NSArray of structures?

Trying to implement the following structure from "c" to use NSArray in objective-c:
In standard-c:
struct structDog{
char *name;
int age;
};
struct structLitter{
struct structDog puppy[10];
};
Then I use malloc to allocate space.
But since I am using NSArray.
But in Objective-c I am using NSArray... so ???
NSArray struct structDog *puppy; // <<---this doesn't work
thanks
Assuming that you are trying to do is get your struct into your NSArray you need to use NSValue. For instance you can do something like:
NSArray* myArray = [NSArray arrayWithObjects:[NSValue valueWithPointer: myDog],
[NSValue valueWithPointer: myPuppy],
nil];
structDog* dog = (structDog*)[[myArray objectAtIndex:0] pointerValue];