Printing a string object from an NSMutableArray - objective-c

I stored some strings in objects and added the objects to an NSMutableArray. Now I want to print the strings in each element of the array. Clearly, I'm doing something wrong. I'm going to back and review these basics, but I was hoping someone could explain how I can print the string instead of the what looks to be the element address.
/** interface **/
#property (nonatomic, copy) NSString*myNumber;
-(void)setNumber: (NSString*) randomNumber;
/** implementation **/
#synthesize myNumber;
-(void) setNumber:(NSString *)randomNumber
{
myNumber = randomNumber;
}
/**main**/
Fraction * aFrac = [[Fraction alloc] init];
[aFrac setNumber:#"5/6"];
Fraction * bFrac = [[Fraction alloc] init];
[bFrac setNumber:#"2/3"];
NSMutableArray * myArray = [[NSMutableArray alloc] init];
[myArray addObject:aFrac];
[myArray addObject:bFrac];
int i;
for(i = 0; i<2; ++i)
{
id myArrayElement = [myArray objectAtIndex:i];
NSLog(#"%#", myArrayElement);
}
for(i = 0; i<2; ++i)
{
NSLog(#"%#", myArray[i]);
}
Both for loops print the same thing.

When you pass a custom object to NSLog you have to override the -(NSString)description method in that object.
So in your Fraction class if you simply override this function like so
- (NSString*)description
{
return self.myNumber;
}
that should log out what you want.
I would probably think about renaming that property from number as you are storing a string.
Hope that helps

I'm guessing the Fraction type you created has a NSString property or method named number (to match the -setNumber: method), in which case you would use the following code to print it:
NSLog("%#", [myArrayElement number]);
Or, for the second loop:
NSLog("%#", [myArray[i] number]);

In your code both for loop meaning has same only, try below
for(i = 0; i<2; ++i)
{
id myArrayElement = [myArray objectAtIndex:i];
NSLog(#"%#", myArrayElement.number);
}
for(i = 0; i<2; ++i)
{
NSLog(#"%#", myArray[i].number);
}
Now here two array value you are extracting
[myArray objectAtIndex:i] which is equivalent to myArray[i]

Related

Adding objects to an NSmutableArray from a C Array

I have an NSmutable array and I am adding some strings present in the C array to it. By using this method
if (!self.arrayOfVariableNames) {
self.arrayOfVariableNames = [[NSMutableArray alloc] init];
for (int i = 0; i< cols; i++) {
[self.arrayOfVariableNames addObject:[NSString stringWithCString:cArrayOfVariableNames[i] encoding:NSUTF8StringEncoding ]];
}
}
else{
[self.arrayOfVariableNames removeAllObjects];
for (int i = 0; i< cols; i++) {
[self.arrayOfVariableNames addObject:[NSString stringWithCString:cArrayOfVariableNames[i] encoding:NSUTF8StringEncoding ]];
}
}
Does this method ensure that the objects in the NSmutableArray won't be deallocated when the C array is taken out of memory?
if this array arrayOfVariableNames is becoming Null, then the problem is with the initialisation of the array. Please try to use Lazy loading by doing this:
- (NSArray*)arrayOfVariableNames {
if (!_arrayOfVariableNames) {
_arrayOfVariableNames = [[NSMutableArray alloc] init]; //initialise the array if needed
}
return _arrayOfVariableNames; //else return the already initialized array
}
and please comment out this line in your code: self.arrayOfVariableNames = [[NSMutableArray alloc] init];
****EDIT****
Please find the update code in https://docs.google.com/file/d/0BybTW7Dwp2_vdHhQN1p1UzExdTA/edit?pli=1. Have a look at it.
Yes. NSArray retains anything in it.
But you should stop chaining your NSString creation and instead creat a string a line before adding it to the array. Then check for nil.
Only add it to the array if it is not nil.
Do code defensively.
arrayOfVariableNames will not change when the C array get deallocated.
Make sure that your arrayOfVariableNames variable is strong.
#property (nonatomic, strong) NSMutableArray *arrayOfVariableNames;
if (!self.arrayOfVariableNames)
{
self.arrayOfVariableNames = [[NSMutableArray alloc] init];
}
else
{
[self.arrayOfVariableNames removeAllObjects];
}
for (int i = 0; i< cols; i++)
{
NSString *tempString = [NSString stringWithCString:cArrayOfVariableNames[i] encoding:NSUTF8StringEncoding];
if([tempString length] > 0)
{
[self.arrayOfVariableNames addObject:tempString];
}
else
{
NSLog(#"string is empty");
}
}

How can I create array of numbers in Objective-C?

i trying to create my firsy iphone program and i realize that making an array or matrix of 2 dims is difficult for me... :-(
*how and where i declarer somthing like this (take from java) so all the function can see it:
int[] myArray = new int[6];
*how can i trnslete this function:
public int[] sortArray (int[] myArray){
int tmp;
for (int x = 0; x < myArray.length; x++) {
for (int y = x+1; y < 6; y++) {
if (myArray[y] < myArray[x]) {
tmp = myArray[x];
myArray[x] = myArray[y];
myArray[y] = tmp;
}
}
}
return myArray;
}
*and how i call this function?
sortArray(myArray);
thanks for everyone!!!
sharon
You can do it with one line of code:
NSArray *array = #[#[#1, #2, #3],
#[#4, #5, #6],
#[#7, #8, #9]];
Learn about Objective-C literals here.
As in C,
int twoDArray[3][3];
In objective-C
NSArray *a=#[#"apple",#"axe",#"ant"];
NSArray *b=#[#"ball",#"book",#"baby"];
NSArray *c=#[#"cup",#"cat",#"cow"];
NSArray *twoDArray=#[a,b,c];
or in one statement:
NSArray *twoDArray=#[#[#"apple",#"axe",#"ant"],
#[#"ball",#"book",#"baby"],
#[#"cup",#"cat",#"cow"]];
EDIT:
NO need to convert that java function to obj-c method.
To sort the array :
NSArray *sortedArray = [array sortedArrayUsingComparator:^(id str1, id str2) {
return [((NSString *)str1) compare:((NSString *)str2) options:NSNumericSearch];
}];
EDIT 2: (Removed unwanted typecast of nsstring to id and back to string)
NSArray *sortedArray = [array sortedArrayUsingComparator:^(NSString *str1, NSString *str2) {
return [str1 compare:str2 options:NSNumericSearch];
}];
Declare in your respective .h file
NSMutableArray *numbers;
Then in your .m file
numbers = [[NSMutableArray alloc] init];
for (NSInteger i = 0; i < 6; i++)
[numbers addObject:[NSNumber numberWithInteger:i]];
and declare it in your .h as
-(NSMutableArray *)sortArray:(NSMutableArray *)numbers;
This is the translated method above in Objective-C:
-(NSMutableArray *)sortArray:(NSMutableArray *)numbers
{
NSInteger tmp = 0;
for(int x = 0; x < [numbers count]; x++)
for(int y = x + 1; y < 6; y++)
if([numbers objectAtIndex:y] < [numbers objectAtIndex:x])
{
tmp = [numbers objectAtIndex:x];
[numbers replaceObjectAtIndex:x withObject:[numbers objectAtIndex:y]];
[numbers replaceObjectAtIndex:y withObject:tmp];
}
return numbers;
}
Also you can call a method in objective-c as follows:
[self sortArray:numbers];
You seem to have (at least) two related-but separate questions here.
1/ how to create an array of numbers
Objective-C arrays come as immutable NSArrays (fixed contents) or mutable NSMutableArrays (you can add delete and shuffle contents around). You sort function as written is asking for a mutable array.
To create and populate an immutable array with NSNumber objects:
NSArray* array = #[#3,#5,#8,#2,#9,#1]; //"#1" is an NSNumber object literal
//access: array[3] etc
Multidimensional:
NSArray* arrayOfArrays #[#[#3,#5,#8],#[#2,#9,#1]];
//access: arrayOfArrays[1][2] etc
To create an empty variable-length mutable array
NSMutableArray* mutableArray = [[NSMutableArray alloc] init];
Create and populate a variable-length mutable array
myArray = [NSMutableArray arrayWithObjects:#3,#5,#8,#2,#9,#1, nil]; //note nil termination
To turn your immutable NSArray into a mutable NSMutableArray
NSMutableArray* mutableArray = [array mutableCopy];
(but take care, this will only render the top level as mutable, if it contains immutable subarrays they will remain immutable)
Objective-C collections (NSArray, NSDictionary, NSSet) can only hold objective-C objects. Therefore if you want to store ints or floats you need to box them into objective-C NSNumber objects before adding to a collection, and unbox them again to access the value.
int x;
float y;
NSNumber xNum = [NSNumber numberWithInt:x]; //box
NSNumber yNum = [NSNumber numberWithFloat:y]; //box
x = [xNum intValue]; //unbox
y = [yNum floatValue]; //unbox
2/ how to translate code
Here is a like-for-like translation:
To create the (mutable) myArray object:
NSMutableArray* myArray = [[NSMutableArray alloc] init];
Populate it:
[myArray addObjects:#3,#6,#8,#1,#9,nil]; //last value is nil to indicate termination
The method:
- sortArray:(NSMutableArray*)myArray
{
id tmp;
for (int x = 0; x < [myArray count]; x++) {
for (int y = x+1; y < 6; y++) {
if ([myArray[y] floatValue] < [myArray[x] floatValue]) {
tmp = myArray[x];
myArray[x] = myArray[y];
myArray[y] = tmp;
}
}
}
}
To call:
[self sortArray:myArray];
To declare with object scope, make a property in your #interface section
#interface myObject:NSObject
#property (nonatomic, strong) NSMutableArray* myArray;
#end
You will still need to create myArray before you can use it:
self.myArray = [[NSMutableArray alloc] init];
but you will be able to set and access it's values from anywhere inside the object thus:
self.myArray
And - if it is in the public header file #interface section - from outside the object thus:
myObject.myArray

Objective-C Why is this not working?

#import <Foundation/Foundation.h>
int main(int argc, const char * argv[])
{
#autoreleasepool {
NSMutableString *outputStringSet = [[NSMutableString alloc] init];
NSMutableString *outputStringArray = [[NSMutableString alloc] init];
NSMutableSet *mySet = [[NSMutableSet alloc] init];
NSMutableArray *myArray = [[NSMutableArray alloc] initWithCapacity: 10];
int userInput;
NSLog(#"Enter 10 numbers");
for( int i = 0; i < 10; i++) {
scanf("%i", &userInput);
NSNumber *input = [[NSNumber alloc] initWithInt: userInput];
[myArray addObject:input];
if([mySet member: input]) {
[mySet addObject: input];
}
}
for (int k = 0; k < [myArray count]; k++) {
[outputStringArray appendFormat:#"%#, ", [myArray objectAtIndex:k]];
}
NSLog(#"%#", [outputStringArray substringToIndex:[outputStringArray length] - 2]);
for (int j = 0; j < [myArray count]; j++) {
if([mySet containsObject: [myArray objectAtIndex:j]]) {
[outputStringSet appendFormat:#"%#, ", [myArray objectAtIndex:j]];
}
NSLog(#"%#", outputStringSet);
}
}
return 0;
}
Code above prints the array but not the appropriate object in the set
Why?
Please explain clearly. I am a bit of a noob, and couldnt find the answer anywhere else.
thanks
if([mySet member: input]) {
[mySet addObject: input];
}
You're adding the object to the set if it’s already in it. You want the reverse: add the object if it's not in it.
Thus:
if ( ! [mySet member:input] )
[mySet addObject:input];
By the way, you should use containsObject: instead of member: in your test:
containsObject:
Returns a Boolean value that indicates whether a given
object is present in the set.
- (BOOL)containsObject:(id)anObject
Edit: you don't even need to test if the object is already in the set before adding it. After all, that's the main purpose of a NSSet: to ensure uniqueness of its objects. So if you add an object twice, the second call will silently be ignored, as the object is alreay in it.
Your set is empty because of
if([mySet member: input]) {
[mySet addObject: input];
}
member:
Determines whether the set contains an object equal to a given object,
and returns that object if it is present.

Add objects to NSMutableArray

I'm trying to add objects to NSMutableArray (categoriasArray), but its not done by the iterator:
#synthesize categoriasArray;
for (int i = 0; i < [categories count]; i++) {
categoria *cat = [[categoria alloc] initWithDictionary:[categories objectAtIndex:i]];
[self.categoriasArray addObject:cat];
cat=nil;
}
After the for iterator, categoriasArray has 0 objects.
Many thanks
Check that the array is not nil before the loop starts:
NSLog(#"%#", self.categoriasArray); // This will output null
for (int i = 0; i < [categories count]; i++) {
// ...
}
What you should understand is that synthesizing the property categoriasArray doesn't initialize it, it just generates the setter and the getter methods. So, to solve your problem, initialize the array before the loop, (or in the init method of your class):
self.categoriasArray = [[NSMutableArray alloc] init];
The other possibility is that categories is itself nil or doesn't contain any items. To check that, add NSLogs before the loop:
NSLog(#"%#", self.categoriasArray);
NSLog(#"%#", categories);
NSLog(#"%d", [categories count]);
for (int i = 0; i < [categories count]; i++) {
// ...
}
try this
for(categoria *cat in categoria){
[self.categoriasArray addObject:cat];
// check you go here or not
}
I would advise getting in the habit of initializing your arrays with autorelease formatting such as the following.This is not only less to type but also good practice for mem management purposes. Of course if you are using ARC then both will work. This goes the same for NSString and many others (i.e. self.categoriasString = [NSMutableString string];)
self.categoriasArray = [NSMutableArray array];
Afterword you can add objects to that array by calling [self.categoriasArray addObject:cat];

Can I assign array size using NSMutableArray?

I used to be a Java Programmer, which the array need to declare the very first time, like this:
int[] anArray; // declares an array of integers
anArray = new int[10]; // allocates memory for 10 integers
I don't know whether the Objective C , NSMutableArray also give me this ability or not. Actually, I want to make a 10*10 array. thz in advance.
I try to do this:
myArray = [[NSMutableArray alloc] initWithCapacity:10];
for (int i=0; i<10; i++) {
myArray[i] = [[NSMutableArray alloc] initWithCapacity:10];
}
But it occurs errors, telling my incompatible type assignment.
The capacity field is seldom useful. The array will be expanded on demand anyway.
And the capacity field just tells the array how much memory you may use. The array's length is still 0.
But you can grow the array from empty:
for (int i = 0; i < 10; ++ i)
[myArray addObject:…];
To read and write to an element in an NSMutableArray, you need:
id x = [array objectAtIndex:i]; // x = array[i];
[array replaceObjectAtIndex:i withObject:y]; // array[i] = y;
You cannot subscript an NSArray directly.
Your code has memory leak. Unlike Java, ObjC doesn't use a GC unless you explicitly enable it (and ObjC on iPhoneOS doesn't have GC). ObjC manages memory by manual reference counting. Basically you need to ensure the ref count of stuff you don't own doesn't change in the process. See http://developer.apple.com/mac/library/documentation/cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html for detail.
In your case, [[NSMutableArray alloc] …]; creates an object of ref count +1, then the assignment will take over the array, that means you don't own it any more, but the ref count is not balanced to 0, so this memory will not be properly deallocated. You need to use convenient methods such as [NSMutableArray array…] to create an object with ref count 0.
NSArray's can only store ObjC objects. int in C (ObjC) is a primitive, and cannot be stored into an NSArray. You have to box it into an NSNumber by [NSNumber numberWithInt:0]. You can get back the integer with -intValue.
To conclude, your code needs to be modified as:
-(NSMutableArray*)get10x10Array {
NSMutableArray* arr = [NSMutableArray array];
for (int i = 0; i < 10; ++ i) {
NSMutableArray* subarr = [NSMutableArray array];
for (int j = 0; j < 10; ++ j)
[subarr addObject:[NSNumber numberWithInt:0]];
[arr addObject:subarr];
}
return arr;
}
But ObjC is a superset of C. You can just use a plain 10x10 C array.
int arr[10][10];
You want a 10x10 array -- of what?
myArray = [[NSMutableArray alloc] initWithCapacity:10];
for (int i=0; i<10; i++) {
myArray[i] = [[NSMutableArray alloc] initWithCapacity:10];
}
But it occurs errors, telling my
incompatible type assignment.
Because you can't assign to myArray like that. myArray is an object that represents an array data structure. It is not a C array.
If you want a 10x10 array of a primitive data type, you can declare one like you would in C:
int myArray[10][10];
initWithCapacity: is what you want. It may look like
NSMutableArrat *array = [[NSMutableArray alloc] initWithCapacity:10];
You can't access Cocoa array objects with the bracket notation. Your second bit of code should be:
NSMutableArray *myArray = [[NSmutableArray alloc] initWithCapacity:10];
for (int i = 0; i < 10; i++) {
[myArray insertObject:[NSMutableArray arrayWithCapacity:10] atIndex:i]; // Note: not using myArray[i]!
}
There are two ways to do this.
Plain old C
If you want to store objects, you should use the id type instead of int.
int myarray[10][10];
myarray[5][2] = 412;
Objective-C
NSArray's are not meant to have spaces without objects, if you need them you could use [NSNull null], but if that's the case a C array would be better anyway.
NSMutableArray *myArray = [[NSMutableArray alloc] initWithCapacity:10];
for (int i=0; i < 10; i++) {
NSMutableArray *innerArray = [[NSMutableArray alloc] initWithCapacity:10];
for (int j=0; j < 10; j++) {
[innerArray addObject:[NSNull null]];
}
[myArray addObject:innerArray];
[innerArray release];
}
[[myArray objectAtIndex:5]
replaceObjectAtIndex:2 withObject:[NSNumber numberWithInteger:123]];
NSArray objects have a fixed size that cannot be changed once they have been initialised. NSMutableArray objects can change size. A 10×10 array is sometimes implemented as an NSArray containing 10 individual NSArray objects, each of these containing ten items. This quickly gets cumbersome, sometimes it is easier to resort back to plain C for such a task:
int tenByTen[10][10];
Or, you can use this:
typedef struct
{
int y[10];
} TenInts;
typedef struct
{
TenInts x[10];
} TenByTen;
Then you could do:
- (void) doSomethingWithTenByTen:(const TenByTen) myMatrix
{
NSLog ("%d", myMatrix.x[1].y[5]);
}
And you can also return them from methods:
- (TenByTen) mangleTenByTen:(const TenByTen) input
{
TenByTen result = input;
result.x[1].y[4] = 10000;
return result;
}
You want NSMutableArray +arrayWithCapacity:
Note that setting the initial capacity is merely an optimization - Mutable arrays expand as needed.
EDIT:
To do the 10x10 case,
myArray = [[NSMutableArray alloc] initWithCapacity:10];
for (int i=0; i<10; i++) {
NSMutableArray *subArray = [NSMutableArray arrayWithCapacity:10];
[myArray addObject:subArray];
for (int j = 0; j<10; j++) {
[subArray addObject:[NSNumber numberWithInt:0]];
}
}
Notes:
an array retains the objects added to it, so its not necessary to retain subArray
only objects (not primitive types like "int") can be added to an NSArray, hence the need for NSNumber numberWithInt:
you use methods like objectAtIndex: and replaceObjectAtIndex:withObject: to get/set a value from an NSArray, not array subscript ([]) syntax
See Apple refs for NSArray and NSMutableArray
You can use the following code to resize the NSMutableArray once it was created:
#interface NSMutableArray (Resizing)
- (NSMutableArray *)resize:(NSInteger)newSize;
#end
#implementation NSMutableArray (Resizing)
- (NSMutableArray *)resize:(NSInteger)newSize
{
int size = (newSize > [self count]) ? self.count : newSize;
NSMutableArray *array = [NSMutableArray arrayWithCapacity:size];
for (int i = 0; i < size; i++){
[array addObject:[self objectAtIndex:i]];
}
return array;
}
#end