the code is:
typedef struct _Package
{
char* data;
int dataLen;
}Package;
Package *pack=(Package *)malloc(sizeof(pack));
pack->dataLen = 10;
pack->data = (char *)malloc(10);
strcpy(pack->data,"hellohello");
NSMutableArray *lstPack = [[NSMutableArray alloc] init];
[lstPack addobjec:pack];
when the program goto [lstPack addobject:pack],it cann't go on.
If you know the reason,please tell me。
Thank you!
You can add to obj-c containters (including NSMutableArray) only obj-c objects. To add a c-structure to array you can wrap it to NSValue object:
[lstPack addObject:[NSValue valueWithPointer:pack]];
Later you access stored value:
Package* pack = (Package*)[[lstPack objectAtIndex:i] pointerValue];
Note also that you possibly have a typo in that line - method name is incorrect.
“… the result is that the p->data is nil …” — perhaps because of pack->dataLen = (char *)malloc(10);
I think, you wanted to do pack->data = (char *)malloc(10); instead?
Greetings
You can create a CFMutableArray instead which can handle arrays of arbitrary objects, and you can use it as you would an NSMutableArray (for the most part).
// create the array
NSMutableArray *lstPack = (NSMutableArray *) CFArrayCreateMutable(NULL, 0, NULL);
// add an item
[lstPack addObject:pack];
// get an item
Pack *anObject = (Pack *) [lstPack objectAtIndex:0];
// don't forget to release
// (because we obtained it from a function with "Create" in its name)
[lstPack release];
The parameters to CFArrayCreateMutable are:
The allocator to use for the array. Providing NULL here means to use the default allocator.
The limit on the size of the array. 0 means that there is no limit, any other integer means that the array is only created to hold exactly that many items or less.
The last parameter is a pointer to a structure containing function pointers. More info can be found here. By providing NULL here, it means that you don't want the array to do anything with the values that you give it. Ordinarily for an NSMutableArray, it would retain objects that are added to it and release objects that are removed from it¹, but a CFMutableArray created with no callbacks will not do this.
¹ The reason that your code is failing is because the NSMutableArray is trying to send retain to your Pack struct, but of course, it is not an Objective-C object, so it bombs out.
Related
Hey there I'm new to objective c is there any way to grab and objects properties once it's in an NSMutable array.
like this:
so in c++ it would look like this
for (int i = 0; i < length; i++)
{
someArray[i].someClass.somePropertyInTheClass;
}
is there any possible way to do that with an NSMutableArray in OBJECTIVE -C
Thanks in advance all you pro objective c-ers!
There are two main ways to loop through an array in Objective-C. First, using an index:
NSInteger count = [array count];
for (int i; i < count; i++)
{
id object = [array objectAtIndex:i];
NSLog(#"%#", [object somePropertyInTheClass]);
}
Note that the the count is stored in a variable rather than in the for loop. This avoids having to recalculate the count each time through the loop.
A more concise method is with fast enumeration:
for (id object in array)
{
NSLog(#"%#", [object somePropertyInTheClass]);
}
Both versions are semantically equivalient, they both log each object's somePropertyInTheClass property in the array (assuming each object has a somePropertyInTheClass property). In both versions, id can, and should, be replaced with a specific class, eg NSDictionary * based on what you store in the array.
While fast enumeration is more concise, the approach with the counter is useful if you need to use the index for something other than accessing one array. Also, fast enumeration does not allow you to modify the array, even in another method, while looping. In most cases though, when iterating through an array, fast enumeration can be used.
Hey there I'm new to objective c is there any way to grab and objects
properties once it's in an NSMutable array.
The mere fact of being included in an array or other container doesn't prevent you from accessing the properties of an object. If the object you want is at index i, you can get the object simply:
Person *person = [arrayOfPeople objectAtIndex:i];
or even simpler:
Person *person = arrayOfPeople[i];
You can then of course get the property like this:
NSString *name = [person valueForKey:#"name"];
or just:
NSString *name = person.name;
However, your example shows a loop, suggesting that you might want to get the same property of all the objects in an array. Objective-C containers have the very nice property that they respond to -valueForKey: by getting the value for the given key from each contained object and returning a container with just those values. So, you can say:
NSArray *names = [arrayOfPeople valueForKey:#"name"];
and you get an array of names in names, with one name for each object in the array arrayOfPeople.
You can, of course, also iterate over the array:
for (Person *person in arrayOfPeople) {
NSString *name = person.name;
NSLog(#"The name is %#", name);
}
Finally, you should know that mutable arrays work just the same way as non-mutable arrays when it comes to accessing objects. The only difference between a mutable array and a non-mutable array is that you can add or remove objects from a mutable array after you create it. The mutability of the objects contained in the array isn't affected by the array's own mutability. That is, if you have an array arrayOfPeople, and if the Person objects stored in it can be modified, then you're free to change the name, age, etc. of any object stored in the array regardless of whether arrayOfPeople is mutable or non-mutable.
I need a array of strings in a constant. is a good idea to use #define?
For example:
#define rows [NSArray arrayWithObjects: #"NameRowA",#"NameRowB",#"NameRowC", nil]
#define KEY_ROWA [columnas objectAtIndex:0]
#define KEY_ROWB [columnas objectAtIndex:1]
#define KEY_ROWC [columnas objectAtIndex:2]
I need to access to the array of strings and the elements of that array.
I have read, (i don´t know if is true) with this way it is created a new NSArray when it is used, I suppose then the array is released, so I think this is good because you only use that part of memory when you need it.
Use a singleton, it's just a couple of lines of code.
All you need is a static singleton, and a static method for retrieving it (and settings it once).
Your .m file should contain this:
#implementation MyClass
static NSArray *mySingletonArray; // this will be your array
+ (NSArray *)mySingletonArray // this is the static method for accessing your array
{
if (nil == mySingletonArray) {
mySingletonArray = [NSArray arrayWithObjects:#"firstString", #"secondString", nil];
}
return mySingletonArray;
}
Acquire what you need from you array using the static access method [MyClass mySingletonArray], e.g.
NSLog("%#", [[MyClass mySingletonArray] objectAtIndex:0]);
I don't think you want to use #define for this.
In your example, there is no constant array of strings made with this code. Every single time rows is used in your code, a new NSArray is going to be allocated. Also, KEY_ROWA refers to columnas, but that isn't in the rows define. I assume you have something like this
NSArray *columnas = rows;
There is really no difference between that and
NSArray *columnas = [NSArray arrayWithObjects: #"NameRowA",#"NameRowB",#"NameRowC", nil];
But the second line is a lot more obvious. The same is true with KEY_ROWA -- the objectAtIndex call would be more obvious and the macro doesn't get you anything.
I'm not sure what you need exactly, but if you need a shared constant array of strings inside of one class, you could declare it as + instead of - at the beginning, and allocate it once (this is a class variable as opposed to an instance variable). More info here:
How do I declare class-level properties in Objective-C?
I thought that NSArray/NSDictionary/NSSet and their mutable subclasses just added the pointer to the object, and not the object it self.
So if set my "simple" object to nil after I added it to the container, why isn't the reference nil also in the Array (container)?
Here is the code:
NSMutableArray *array = [[NSMutableArray alloc] init];
Simple *simple = [[Simple alloc] init];
[array addObject:simple];
//Array sends retain, lets release
[simple release], simple = nil;
NSLog(#"Simple = \"<Simple: %p>", simple);
NSLog(#"Array: %#", array);
[array release], array = nil;
Here is the output:
2011-02-16 20:00:03.149 Allocations[5433:207] Simple = <Simple: 0x0>
2011-02-16 20:00:03.150 Allocations[5433:207] Array: (
<Simple: 0x4d3d4e0>
)
NSArray adds a pointer to the object. In order to track changes to variable, the array would have to add a pointer to the variable itself (remember, you're just setting the variable to nil, not the object). There can be many variables all pointing to the same object, and reassigning them won't change any others.
Remember: Pointers aren't magic. They're just ordinary variables whose value is a memory address — in this case, the memory address of an object. Two pointers to the same object aren't "linked" any more than two ints with the value 5. Changing the pointer doesn't affect the object; in order to affect the object, you have to either send it a message that causes it to change (e.g. [object setValue:6]) or dereference the pointer to access the object's members directly (e.g. object->value = 6).
PS: Don't access an object's members directly. It's bad and fragile and very prone to bugs. I just mentioned it here to explain how pointers work.
Setting simple = nil just makes that pointer point to nothing. It doesn't delete the object that the array still has a pointer to. At the point of your NSLog statements, the retainCount of the Simple instance that simple pointed to would be one.
Create simple
simple => (Simple instance: retain count 1)
Add to array
simple => (Simple instance: retain count 2)
[array objectAtIndex:0] => (Simple instance: retain count 2)
Release simple
simple => (Simple instance: retain count 1)
[array objectAtIndex:0] => (Simple instance: retain count 1)
Set simple = nil
simple => nil
[array objectAtIndex:0] => (Simple instance: retain count 1)
Release array
(Simple instance: retain count 0, subsequently destroyed)
NSArray does contain only a pointer to the object that is added, but that's ok -- it's not pointing to the simple pointer itself, but rather to the Simple object that simple pointed to. Thus in your example, after you change what simple points to, the array is still pointing at the original Simple object.
sorry for my stupid question (beginner)
I got the demo program Accelerometergraph the apple site and would like to use
NSMutableArray in the values of acceleration x.
but my NSMutableArray contains only one object, there being several passage
NSMutableArray routine and should contain the same number of objects that the counter
show, how code below
if(!isPaused)
{
array = [[NSMutableArray alloc] init];
[filter addAcceleration:acceleration];
[unfiltered addX:acceleration.x y:acceleration.y z:acceleration.z];
NSNumber *number = [[NSNumber alloc] initWithDouble:acceleration.x];
[array addObject:number];
++a;
if (a == 30) // only check the # objs of mutablearray
{
sleep(2);
}
[filtered addX:filter.x y:filter.y z:filter.z];
}
It looks like you're missing a loop of some kind. The code you list above:
Makes sure something isn't paused.
Creates a new (empty) mutable array.
Adds a value to the new array.
And does some other work.
My guess is that this whole if{} block sits inside some kind of loop. You need to alloc and init the mutable array outside of the loop instead.
You create a new array each time the if block is entered, so the addObject: will only add the object to the most recently created array.
Furthermore, you are leaking the array and number objects. Each time you allocate an object, you are responsible for releasing it. Make sure you're familiar with the guidelines set out in the memory management programming guide.
I've come across a problem related to pointers within arrays in objective-c.
What I'm trying to do is take the pointers within an NSArray, pass them to a method, and then assign the returned value back to the original pointer(the pointer which belongs to the array).
Based on what I know from C and C++, by dereferencing the pointers within the array, I should be able to change the values they point to... Here is the code I'm using, but it is not working (the value phone points to never changes based on the NSLog output).
NSArray *phoneNumbers = [phoneEmailDict objectForKey:#"phone"];
for (NSString* phone in phoneNumbers) {
(*phone) = (*[self removeNonNumbers:phone]);
NSLog(#"phone:%#", phone);
}
And here is the method signature I am passing the NSString* to:
- (NSString*) removeNonNumbers: (NSString*) string;
As you can see, I am iterating through each NSString* within phoneNumbers with the variable phone. I pass the phone to removeNonNumbers:, which returns the modified NSString*. I Then dereference the pointer returned from removeNonNumber and assign the value to phone.
As you can tell, I probably do not understand Objective-C objects that well. I'm pretty sure this would work in C++ or C, but I can't see why it doesn't work here! Thanks in advance for your help!
Yeah, that's not going to work. You'll need an NSMutableArray:
NSMutableArray * phoneNumbers = [[phoneEmailDict objectForKey:#"phone"] mutableCopy];
for (NSUInteger i = 0; i < [phoneNumber count]; ++i) {
NSString * phone = [phoneNumbers objectAtIndex:i];
phone = [self removeNonNumbers:phone];
[phoneNumbers replaceObjectAtIndex:i withObject:phone];
}
[phoneEmailDict setObject:phoneNumbers forKey:#"phone"];
[phoneNumbers release];
You can't dereference Objective-C object variables. They are always pointers, but you should treat them as though they're atomic values. You need to mutate the array itself to contain the new objects you're generating.
NSArray is not a C/C++ style array. It's an Objective-C object. You need to use the instance methods of the NSArray class to perform operations on it.
In Objective-C you never "dereference" an object pointer to set its value.
Also, you're using what is called Fast Enumeration, which does not allow mutation.
You can also use enumerateObjectsUsingBlock:.
NSArray *array = [NSArray array];
__block NSMutableArray *mutableCopyArray = [array mutableCopy];
[mutableCopyArray enumerateObjectsUsingBlock:^(id object, NSUInteger idx, BOOL *stop) {
[mutableCopyArray replaceObjectAtIndex:idx withObject:[object modifiedObject]];
}];
Checkout How do I iterate over an NSArray?
While this may work to some degree, I haven't tested it, I'd file this under 'bad idea' and not touch. NSArray, and many other cocoa objects, a fairly complex and can have a variety of implementations under the hood as part of the class cluster design pattern.
So when it comes down to it you really won't know what you're dealing internally. NSArray is actually designed to be immutable so in place editing is even doubly a bad idea.
Objects that are designed to let you mess around with the internals expose those through api methods like NSMutableData's mutableBytes.
You're better off constructing a new NS(Mutable)Array with the processed values.