An NSMutableArray was created with 64 capacity. A NSString object was added. However, string value of the object is nil.
static NSString* cake = #"cake";
...
NSMutableArray* food = [NSMutableArray arrayWithCapacity:64];
[food addObject:[NSString stringWithString:cake]];
NSString* dessert = [[food objectAtIndex:0]stringValue];
// dessert is nil
if [NSString stringWithString: cake] is replaced with just cake, it throws an exception
Here is an entire program which is less than 10 lines of code and does not work
#import <Foundation/Foundation.h>
static NSString* cake = #"cake";
int main(int argc, const char * argv[]){
#autoreleasepool {
NSMutableArray* food = [NSMutableArray arrayWithCapacity:64];
[food addObject:cake];
NSString* dessert = [[food objectAtIndex:0]stringValue];
}
}
It throws an exception.
The problem is likely that your array is nil. This code works.
NSMutableArray *foodArray = [NSMutableArray array];
[foodArray addObject:#"cake"];
NSString *dessert = foodArray[0]; //dessert is "cake"
Update
The unrecognized selector exception you are getting is the result of calling stringValue on an NSString. As #Chuck noted, NSString does not have that method.
Related
I'm learning Objective-C runtime, and try to use method_exchangeImplementations to exchange addObject: method and removeObject: method of NSMutableArray.
My code like this:
int main(int argc, const char * argv[]) {
#autoreleasepool {
Method removeMethod = class_getInstanceMethod(NSMutableArray.class, #selector(removeObject:));
Method addMethod = class_getInstanceMethod(NSMutableArray.class, #selector(addObject:));
method_exchangeImplementations(addMethod, removeMethod);
NSMutableArray *array = [[NSMutableArray alloc] init];
NSObject *obj = [[NSObject alloc] init];
[array removeObject:obj];
NSLog(#"%lu", (unsigned long)array.count); // expect print 1, actual print 1
[array addObject:obj];
NSLog(#"%lu", (unsigned long)array.count); // expect print 0, actual print 2
}
return 0;
}
I expect exchange add/remove function, but seems like only removeObject: has been exchange to addObject: , addObject: still is addObject to array, now I have two addObject method of NSMutableArray
I'm not sure the reason. I try to exchange other method like uppercaseString/lowercaseString of NSString, that work correct.
OK, I solved problem. Thanks #Willeke for the tip.
The real class of my array is not NSMutableArray, so use NSMutableArray.class in class_getInstanceMethod can't get correct method. Use [array class] is the answer.
int main(int argc, const char * argv[]) {
#autoreleasepool {
NSMutableArray *array = [[NSMutableArray alloc] init];
Method removeMethod = class_getInstanceMethod([array class], #selector(removeObject:));
Method addMethod = class_getInstanceMethod([array class], #selector(addObject:));
method_exchangeImplementations(addMethod, removeMethod);
NSObject *obj = [[NSObject alloc] init];
[array removeObject:obj];
NSLog(#"%lu", (unsigned long)array.count); // expect print 1, actual print 1
[array addObject:obj];
NSLog(#"%lu", (unsigned long)array.count); // expect print 0, actual print 0
}
return 0;
}
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
#autoreleasepool {
NSMutableArray *groceries;
NSString *a = (#"loaf of bread");
NSString *b = (#"stick of butter");
NSString *c = (#"big ass cookie");
[groceries addObject:a];
[groceries addObject:b];
[groceries addObject:c];
for (NSString *d in groceries){
NSLog(#"%#", d);
}
}
return 0;
}
Why is this not working? What is wrong? Thanks.
I cannot seem to figure it out at this moment, the for loop defiantly seems to be the hangup.
While you didn't initialize NSMutableArray, it's is nil. Adding object to non-initialized mutable array always give nil.
Firstly you need to initialize groceries:
NSMutableArray *groceries = [NSMutableArray new];
or more liked by me way:
NSMutableArray *groceries = #[].mutableCopy;
In your case, for example, you can declare so:
NSMutableArray *groceries = #[#"loaf of bread", #"stick of butter", #"big ass cookie"].mutableCopy;
I have a class which must initialize a group of similar objects the same way.
NSNumber *a = nil;
NSNumber *b = nil;
NSNumber *c = nil;
a, b and c are member variables of an existing object. In my code I use a more complex NSObject subclass, but this example is easier to understand using NSNumbers.
All 3 objects must be initialized in a similar way. Therefore I want to build an array of pointers which I can use within a for-loop like this:
NSPointerArray *objs = [NSPointerArray weakObjectsPointerArray];
[objs addPointer:&a];
[objs addPointer:&b];
[objs addPointer:&c];
Running the above code I get the following error:
error: address doesn't contain a section that points to a section in a object file
How can I build an array which I can explore with a loop like this?
for (id *o in objs) {
*o = #2;
}
just wrap the pointers in 'NSValue' objects and you're good
id v1 = [NSValue valueWithPointer:p1];
id v2 = [NSValue valueWithPointer:p2];
id v3 = [NSValue valueWithPointer:p3];
id array = #[v1,v2,v3];
for(NSValue *value in array) {
void *pointer = value.pointerValue;
NSNumber *n = (__bridge NSNumber*)pointer;
}
demo for what YOU want to do it appears: (NSNumbers are immutable)
#import <Foundation/Foundation.h>
int main(int argc, char *argv[]) {
#autoreleasepool {
NSNumber *a;
NSNumber *b;
NSArray *os = #[ [NSValue valueWithPointer:&a],
[NSValue valueWithPointer:&b] ];
for (NSValue *v in os) {
void *pointer = [v pointerValue];
NSNumber **n_ptr = (__bridge NSNumber**)pointer;
*n_ptr = #2.0;
}
NSLog(#"%# %#", a,b);
}
}
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[])
{
#autoreleasepool {
NSArray *array = [[NSArray alloc] initWithObjects:#"/tmp/1.txt" ,#"/tmp/2.txt", nil];
NSLog(#"%#", array);
NSString *result = [[NSString alloc] init];
NSArray *array2 = [[NSArray alloc]initWithArray:[result stringsByAppendingPaths:array]];
NSLog(#"%#", array2);
}
return 0;
}
The argument we provide to stringsByAppendingPaths: is an array and so is the return type. So what is the use of this NSString method?
Well, you're appending empty string (result), so it doesn't make much sense. But if your receiver contains say /tmp and the array contains 1.txt and 2.txt, getting the array /tmp/1.txt and /tmp/2.txt makes sense.
This program should take 5 NSString's in input and print them.
I put them in an NSMutableArray.
During the loop if I try to print the NSString's they're printed correctly.
But when I try getting the objects from the array, I don't know why it returns null.
So if I try printing them in the second loop, they're all null.
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
NSAutoreleasePool* pool=[[NSAutoreleasePool alloc]init];
NSMutableArray* array;
NSString* str=[[NSString alloc]init];
char* cstr;
cstr=(char*)calloc(100,sizeof(char));
for(int i=0;i<5;i++)
{
fgets(cstr,100,stdin);
str=[NSString stringWithUTF8String:cstr];
[array addObject : str];
}
for(int i=0;i<5;i++)
{
str=[array objectAtIndex:i];
NSLog(#"%#",str);
}
[pool drain];
return 0;
}
In this line:
NSMutableArray* array;
You are declaring array, to be an NSMutableArray, but you're not setting the pointer to anything, so array is just nil.
You want to do this instead to allocate and initialize an actual instance of NSMutableArray and assign it to that pointer:
NSMutableArray* array = [[NSMutableArray alloc] init];
You haven't initialized your array. You should put: NSMutableArray *array = [[NSMutableArray alloc] init];
or better yet: NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:5];