How Can I Loop Through All Objects Inside A Compound CCArray - cocos2d-iphone

I'm working on a project which required me to create an CCArray that contains more CCArrays. I'm looking for a way to loop through all objects within the arrays housed inside the root array. I'd like to loop through all 15 objects using CCARRAY_FOREACH. Is this possible?
rootArray [0] - Contains subArrayA full of 5 objects
rootArray [1] - Contains subArrayB full of 5 objects
rootArray [2] - Contains subArrayC full of 5 objects
I've used CCARRAY_FOREACH when using a CCSpriteBatchNode by using CCARRAY_FOREACH([batchnode children], object) but how can I use with an array of arrays? I know CCARRAY_FOREACH(rootArray, object) won't work since it returns the inside arrays and not the objects inside those arrays.
Let me know and sorry if a noob question. :0/

Have you tried this?
CCARRAY_FOREACH(array, innerArray)
{
CCARRAY_FOREACH(innerArray, item)
{
// stuff
}
}

Recursion is your friend.
-(void) recurseIntoArray:(CCArray*)array
{
for (id item in array)
{
if ([item isKindOfClass:[CCArray class]])
{
[self recurseIntoArray:(CCArray*)item];
}
else
{
NSLog(#"item: %#", item);
}
}
}
Just start the iteration anywhere with the root array:
[self recurseIntoArray:rootArray];
Worth mentioning: CCARRAY_FOREACH is no longer necessary, at least in cocos2d 1.1 and 2.0 you can just use regular fast iteration with for. May also work in cocos2d 1.0.1, I think I used fast enumeration there as well.

you can use foreach loop...
for(CCArray *array in yourArray)
{
for(YourObject *obj in array)
{
//access objects here
}
}
Check for the syntax as I don't have x-code right now.. Its just a snippet.. Hope this helps.. :)

Related

Deleting and Reassigning a pointer from QList<Object *> to new Object using Iterator, is this right?

I have a QList and I'm trying to replace the objects in the list with new objects. The context is that I have a list of custom objects (the class name is "Conversation") to represent a list of group chats in a messaging platform. I use std::find_if to iterate through the list of pointers to find one with the right ID, and I want to take the pointer to that found object, deallocate it (delete?), and reassign that pointer to point at an object I generate with the "new" keyword. I think I'm doing this right but I'm not sure how to verify.
I tried a couple different iterations, ran into some issues where I realized I was using a const_iterator rather than just an iterator, so I couldn't modify any data. But I've fixed that and it seems like it's working, but I'm not positive.
Here's what I've got:
GroupChat *gc = new GroupChat(); // extends Conversation
// ...I update the member data here...
auto foundChat = std::find_if(conversations_.Conversations.begin2(),
conversations_.Conversations.end2(),
[this, gc](Conversation* o) { // my code to find the correct one...
}
if (foundChat != conversations_.Conversations.end()) {
auto c = (*foundChat);
delete c; // Is this right? Not positive...
//*foundChat = nullptr; // do I need this?
c = gc;
}
It seems like it's working but I'm worried about dangling pointers and incorrect memory deallocation/allocation. Could someone spot check me on this? Thanks for any help!

Creating and freeing a temporary dummy variable in C++

I'm using the Qt framework to create a ui for my business logic.
The class responsible for building the ui provides several methods which, step by step, initialize the ui elements, layout them, group them and, finally, format (i.e. void MyUi::init3_formatUiElements()) them.
Naturally, some ui elements need numerous layout settings set, so this method might look like
void MyUi::init3_formatUiElements() {
_spinBox_distance->setMinimum(0.0);
_spinBox_distance->setMaximum(10.0);
_spinBox_distance->setSingleStep(0.5);
_spinBox_distance->setSuffix(" meters");
//...
//same for other widgets
return;
}
Objects like QDoubleSpinBox* _spinBox_distance are member fields of the MyUi class.
I would like to have a "temporary alias" for _spinBox_distance, in that the above method body simplifies to
void MyUi::init3_formatUiElements() {
//create alias x for _spinBox_distance here
x->setMinimum(0.0);
x->setMaximum(10.0);
x->setSingleStep(0.5);
x->setSuffix(" meters");
//...
//free alias x here
//same for other widgets: create alias x for next widget
//...
//free alias x here
return;
}
This would speed up the typing process and would make code fragments more copy/paste-able, especially for ui elements of a similar type.
Apart from scoping each block in curly braces
{ QDoubleSpinBox*& x = _spinBox_distance;
x->setMinimum(0.0);
//...
}
{ QLabel*& x = _label_someOtherWidget;
//...
}
is there an elegant way to achieve this?
I tried the above syntax without scoping, but destructing x then of course leads to destruction of the underlying widget.
Maybe
QDoubleSpinBox** x = new QDoubleSpinBox*;
x = &_spinBox_distance;
(*x)->setMinimum(0.0);
//...
delete x;
but that doesn't make things much more type-easy (three extra lines, pointers to pointers, (*x))... :D
EDIT: This one does not work as after delete x, can't be redeclared another type.
What about using a macro ?
#define Set(argument) _spinBox_distance->set##argument
and
Set(Minimum(0.0));
Set(Maximum(10.0));
Set(SingleStep(0.5));
Set(Suffix(" meters"));
Or
#define Set(Argument, Value) _spinBox_distance->set##argument(Value)
Set(Minimum, 0.0);
Set(Maximum, 10.0);
Set(SingleStep, 0.5);
Set(Suffix, " meters");
Collecting the fundamental conceptual thoughts about the problem in question from the comments section, I may post the syntactical/technical answer to the question. This approach, without a doubt, should not be chosen in any kind of "complex" situation (or rather not at all).
bad coding style:
same name for different things
name which doesn't tell you anything about the object
move repeated code to dedicated functions, which...
may specialize on several ui types
are template functions
...
in case of Qt: Use Qt Designer.
...
{ auto x = _spinBox_distance;
x->setMinimum(0.0);
//...
}
{ auto x = _label_someOtherWidget;
//...
}
will do the trick.
I think your code looks fine as it is, I find it much more useful to have the code be easy to read/understand than it is to have the code be easy to write. Remember that you write the code once, then have to read it many times afterwards.
In cases like this I make it easier to write with good old (and oft blamed for mistakes) copy and paste. Grab _spinBox_distance->set and just paste, finish the line, paste, finish the line, etc...
If, however, you find yourself writing those 4 setters in a row over and over again, then put them in 1 function that takes in the 4 parameters.
void SetParameters(QDoubleSpinBox* spinBox_distance, double min, double max, double step, std::string suffix)
{
//the setters
}

In Cocos2d-x, What is the difference between CC_SAFE_DELETE and CC_SAFE_RELEASE_NULL?

I don't know the real difference between this two macros in Cocos2d-x
CC_SAFE_DELETE and CC_SAFE_RELEASE_NULL
Can anyone explain it to me? It probably can solve a few memory leaks I have in my game.
Here is an example of where I want to use it.
CoolLayer * CoolLayer::create()
{
CoolLayer * pRep = new CoolLayer();
if (pRep && pRep->init() )
{
pRep->autorelease();
}
else
{
CC_SAFE_DELETE(pRep);
}
return pRep;
}
Thanks in advance.
CC_SAFE_DELETE is defined as
do { delete (p); (p) = nullptr; } while(0)
basically used for deleting usual c++ declared objects you want to remove.
CC_SAFE_RELEASE is defined as
do { if(p) { (p)->release(); } } while(0)
(edit just realized your question asks about CC_SAFE_RELEASE_NULL, its exactly the same except it also nulls out your pointer)
This will decrement the reference count of your cocos2d-x objects which is used by cocos2d-x's reference counting construct, if an object hits a reference count of 0 it will be de-alloced for you.
Use safe delete for standard c++ things like vectors or arrays or whatever your custom classes may be. Use safe release for anything to inherits from cocos2d::Object, as it has the native reference counting built in, making keeping track of your object references a little easier.
If you are unfamiliar with reference counting, it comes from the fact that cocos2d was originally created in objective-c, where reference counting is the norm, so after the port, they continued to use it for all their native objects.

Filling list inside object and accessing to it later

I'm sorry if the title isn't very explicit, but I'll try to explain it better. I'm not very familiar with c++ and I'm using openFrameworks for the first time. I'm trying to do something that's probably quite easy, at least in other languages it is, but I'm not being able to do it :(
I have a class Video and inside it I have an object list<ofImage> keyFrames; and several methods to interact with it like the following:
void addKeyFrame(ofImage img) {
if(keyFrames.size() == 0) {
keyFrames.push_front(img);
}
else {
keyFrames.push_back(img);
}
}
list<ofImage> * getKeyFrames() {
list<ofImage> *list = &keyFrames;
return list;
}
void clearKeyFrames() {
keyFrames.clear();
}
In other class I have several Video objects and I have a function that uses addKeyFrame(ofImage img) to fill the list for each object. In the end of that function if I print the list size it is greater than zero.
Inside draw() function I iterate each Video object and I try to draw each image inside their keyFrame list, but the list is always empty and I just filled it with images... I'm using getKeyFrames() function to return a pointer to the list. How can it be empty if I just added objects to it in another function and if I verified that the size was greater than zero? And if I try to debug the application I feel even more lost lol.
Please tell me if you need anymore information and if you know what I'm doing wrong. Thanks!
Ok, A few little things:
1- You shouldn't check for empty lists (or any other STL containers) like this:
if(keyFrames.size() == 0)
This is faster and more "stylish":
if(keyFrames.empty())
2- You've created an unnecessary variable here:
list<ofImage> * getKeyFrames() {
list<ofImage> *list = &keyFrames;
return list;
}
You could do just:
list<ofImage> * getKeyFrames() {
return &keyFrames;
}
3- Pointers are not (most times) the best solution in C++. A reference is the most used substitute, but it would be even better in htis case if you returned an iterator:
list<ofImage>::iterator GetBeginIterator() {
return keyFrames.begin();
}
This way you could use the iterator just like a pointer, increasing it to iterate trough the frames and dereferencing it (with * operator)...

NSMutableArray insertObject:(id) atIndex:int inserting a void ptr

In my application, i have a mix of C++ and Objective C++ code, at one place, i need to insert pointer of c++ class object to NSMutableArray , but i am getting NSINvalidArgument exception,
Can anyone guide me, how can i insert void pointer to NSMuatableArray
This is what i have tried ,
pArray = [[NSMutableArray alloc]initWithCapacity:myList.size()];
Node *node = myList.getHead();
int idx =0;
void *ptr = nil;
while ( node ) {
[pCTArray insertObject:(NSObject *)node atIndex:idx];
node = node->getNext();
idx++;
}
Is there any otherway to insert it into the MutableArray,
the possible workaround i made is : having store index link this
[myArray insertObject:[NSNumber numberWithInt:idx] atIndex:idx];
and this array i would be using in all NSTable/NSOutliveVIew delegate method , i need to pick the index and get the element from the linklist, but worried because of performance, as too many function call would be needed,
Is this any bug in Cocoa or i am making anything wrong ?
NSArrays expect to hold objective-C objects conforming to the NSObject protocol. If you wish to wrap a pointer, use NSValue:
[myArray insertObject:[NSValue valueWithPointer:node] atIndex:idx];
You are manually responsible for all memory management of that pointer, as objective-C can't reference count it in the usual way.
NSMurableArray only accepts Objective-C objects (hence the argument type of addObject: being id).
Are you on the Mac or iOS? If you're on the Mac, You might want to look at NSPointerArray.
You might also be able to be CFMutableArray with custom callback functions, but I haven't tried this myself.
A third option is NSPointerArray.