Get property from object in array - ios

I am having trouble getting an NSString property from an array. I have an NSArray composed of an object called JSMessage. Inside of this object is a string called sender I am trying to retrieve. At the moment, I am only trying to print it to the log. Here is the code I am trying:
NSLog(#"%#",[[self.messages [objectAtIndex:indexPath.row]].sender ]);
I get an error about my brackets and another one telling me objectAtIndex is an undeclared identifier.
What am I doing wrong?

It should be [self.messages objectAtIndex:indexPath.row]
From here you can see the object in a certain index.
To get the JSMessage object:
JSMessage *jSMessageObj = [self.messages objectAtIndex:indexPath.row];

Well, think about it. Your code contains the phrase [objectAtIndex. But a method name can never be the first thing in square brackets. The first thing in square brackets must be the receiver to which the message is being sent.
For example, you say [myString lowercaseString]. You don't say [lowercaseString]. But that is what you are saying.

Besides removing all of the extra brackets, you can also do the following:
NSLog(#"%#", [self.messages[indexPath.row] sender]);
This uses the modern syntax for accessing elements from an NSArray. And since the array access returns an object of type id, you can't directly access the object's property using property syntax. You need to call the getter method as I show above.

Related

Trying to understand NSLog for printing to the console in Xcode

I'm trying to understand NSLog and how to print to the console in Xcode. I understand that NSLog uses what are called "tokens" to setup the type of variable being referenced to print (I think that's right?). What I need to know is the difference in which tokens to use and what they mean?
For example, after declaring an NSArray like below, I'd want to print the drink names to the console. I could do that like:
NSArray *drinks = #[#"juice", #"water", #"coffee"];
for (NSString *drinkName in drinks) {
NSLog(#"%#", drinkName);
}
So...am I using the #"%#" token because it's an NSString?
I would use #"%i" for an integer, and a #"%f" for a float? What about doubles? If anyone could shed some easy-to-understand beginner's knowledge on NSLog, that would be great! =)
As I understand it, NSLog isn't an Objective C function but a C function built into the foundation of Cocoa. Therefore it conforms to basic C functions with variadic arguments. You can use %# for all objects including NSString. This will in turn call the objects description method and print the appropriate string. Most objects have a rather useful representation already there (e.g. NSArray objects return the descriptions of all their contents)

How to call a method from an object in an array?

I'm new to Objective-c and I think this should be really easy but somehow I can't figure it out.
I need to call a method from an object which is stored in an NSArray.
The Java code would be: myArray[0].getMyValue();
So I read on the internet that in Objective-c it should look like this: [[myArray objectAtIndex: 0] getMyValue]. Unfortunately this didn't work.
I found other solutions on the internet but none of them worked.
So I hope you guys could help me out?
Update
I'm getting these two error messages:
No known instance method for selector 'getMyValue'
Sending 'id' to parameter of incompatible type 'CGFloat' (aka 'double')
This doesn't work because Objective-C doesn't know what is the type of the object in the array.
Luckily, Apple has added lightweight generics in Xcode 7, which allow you to create typed arrays. This will of course work only if you intend to have one type of object in the array. The syntax looks like this:
NSArray<NSString *> *stringArray;
If you plan to have objects with different types in the array, then you need to cast the object to your type, to be able to call your method. That would look like this:
[((YourObject *)[myArray objectAtIndex: 0]) getMyValue];
And as #Michael pointed out in the comment, another and nicer way to do this would be:
[((YourObject *)myArray[0]) getMyValue];
Objects are stored with id type in NSArray, so you can cast this object to the object type you want. For instance :
NSNumber *myNumber = (NSNumber *)[NSArray objectAtIndex:0];
[myNumber myMethod];

Using makeObjectsPerformSelector with an object

I have an NSArray of objects and I want to perform the selector pinInBackgroundWithName:(NSString *) on each object. I know that I can use [arr makeObjectsPerformSelector:#selector(selector_name) withObject:obj]; but how does passing in the string to the withObject: argument work? For example, what if the selector I wanted to perform on the objects in the array had multiple arguments? Then would the withObject: argument we an NSArray of objects?
From the docs:
A selector that identifies the message to send to the objects in the array. The method must take a single argument of type id
So you can't use this for a selector with multiple arguments.
If you want to send a message with multiple arguments to each object in the array, you could roll your own version that takes an array, and then fills out an NSInvocation object that it then invokes on each object, or, if you wanted to be really fancy, use higher order messaging.
I would suggest ditching the selector-based calls and using enumerateObjectsUsingBlock or one of it's variants.
Blocks inherit their enclosing scope, so you can invoke a block of code that uses as many variables as you want from the scope of the call.

NSMutableArray and indexAtObject

I am a newbie to Objective-C and I am working on getting a good handle in working with arrays.
According to Apples own documentation NSMutableArray inherits from NSArray. I am seeking to use the method objectAtIndex:i within a for loop. Yet Xcode is claiming that
"Property 'objectAtIndex' not found on object of type
'NSMutableArray'".
Within a for loop I am performing (or seeking to) the following test:
if([self.cards objectAtIndex:i].isChosen){
do something here }
I am certain I not doing this right. It can be frustrating learning the idiosyncrasies of a new programming language. For me Objective C has, so far, borne little resemblance to C++ or C.
Any pointer or assistance would be greatly appreciated.
Thanks in advance
Walt Williams
From your error message, you could not be using the method and parameter correctly. Possibly you're trying to use a dot notation?
Your code should be like:
id object = [array objectAtIndex:index];
where the index comes from your loop and you then use the object.
In addition to Wain's answer, which is correct, but for the sake of completeness, you are using the array and trying to call the method this way:
Ex:
array.objectAtIndex.i = 5; //Java.....?
which is the cause of this error:
"Property 'objectAtIndex' not found on object of type
'NSMutableArray'".
It is complaining that you are trying to access a property named "objectAtIndex", which of course, doesn't exist.
You mean to call the method:
[array objectAtIndex:i];
In Objective-C, it is called "you are sending a message (objectAtIndex:i) to the array".
I am guessing, but hard to tell without your header file declarations, that your problem is you need to #import the file where your class is declared. This is the most common problem when having issues like this. It somehow does not know that it is an NSMutableArray. Also as I noted above you need to assign the value you get back from the array into a typed variable of that class so that you can then access the isChosen property.

function parameters not retained using Arc?

EDIT: This is for a static NSMutableDictionary, not a class member. I see a lot of answers thinking it's a class member, sorry about that. Thanks for the quick responses.
I had a working piece of code, but it was used 2x, so I wrote a convenience function:
- (void) initializeDictionary:(NSMutableDictionary*)mutableDict fromPathName:(NSString*)path
{
mutableDict = // get from file, init if not there.
}
Then I noticed nothing was saving. Stepping through the code, the function creates a dictionary, but the "passed in" value is still nil upon returning. This completely blows away my understanding of pointers (don't take this the wrong way, I'm very comfortable). But their purpose, I thought, was to let you "pass the address" so I could hydrate the thing it points to.
since mutableDict is the "value copy", ARC appears to be wiping it out. I'm asking here because
the other questions have the opposite question "Why is this being retained?" and
It doesn't seem right. Your very first tutorial in any pointer language is "so you can mess with the original value". Does Arc really do this? Is there a concept I'm not getting?
And of course, I may be overlooking something simple.
I seem to have solved it by doing the writeback trick I found elsewhere:
- (void) initializeDictionary:(NSMutableDictionary* __strong *)mutableDictionary fromPath:(NSString*)path;
and using the & to call and * deref to change the value. It just seems far less than elegant.
You pass a pointer of NSDictionary. If you change the pointer value of mutableDict (by allocation or assignment) this will NOT be reflected on the variable passed as this function's argument and since mutableDict is locally defined in the function it will be released by ARC automatically. (Do not forget that even for pointers the address is copied when passed to a function).
The reason that your second solution works is because you pass a pointer to a pointer (not sure if strong is needed there). The value of *mutableDict will be reflected outside since you update a value in the address pointed to by mutableDict. This value is the address of your allocated dictionary and since you change it via a pointer it will be reflected outside the function.
To do what you want you use multiple indirection
- (void) initializeDictionary:(NSMutableDictionary**)mutableDict fromPathName:(NSString*)path
{
mutableDict = // get from file, init if not there.
}
Notice the parameter is (NSMutableDictionary **), a pointer to a pointer to an NSMutableDictionary.
To call the method you need to create a pointer and pass it in like this:
NSMutableDictionary *mutableDictionary;
[self initializeDictionary: &mutableDictionary fromPathName:...];
And on return, the mutableDictionary variable will have been initialised by the method.
However, It's probably easier to just return the dictionary from the method rather than doing it this way.
In Objective-C if you define a variable in a method, the variable is visible only in that method.
If you need to save the variable to use it outside, you need to "return" it from your function. What you did wasn't a trick, is another way of returning a variable.
Try with:
- (void)initializeDictionaryFromPath:(NSString*)path {
NSMutableDictionary *mutableDict = // your initialization
return mutableDict;
}
Then you can define your dictionary with this code:
NSMutableDictionary *mutableDict = [self initializeDictionaryFromPath:path];

Resources