iOS NSMutable Array Help

AnonymousInUse

macrumors newbie
Original poster
Oct 9, 2012
5
0
The crash repots telling me EXC_BAD_ACCESS so I know I have a crappy pointer(s) in this code but I have no clue how to fix it.

Cloud is a UIImageView Subclass, a CADisplayLink is a timer that fires a method 60 times per second.

My Header
Code:
@interface NormalGame : NSObject{
NSMutableArray* cloudArray;
NSMutableArray* possibleActions;
Cloud* cloud;
CADisplayLink* displayLink;
NSInteger spawnMore;
}
My Implementation

Code:
typedef void(^ActionBlock)(void);

-(void)spawnCloud{
    NSString* string = @"cloud.png";
    cloud = [[Cloud alloc] initWithName:string];
    [self.view insertSubview:cloud atIndex:0];
    [cloudArray addObject:cloud];
}

-(id)init{
    self = [super init];
    if (self) {
    displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(gameLoop:)];
    [displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode: NSRunLoopCommonModes];

    cloudArray = [[NSMutableArray arrayWithCapacity:10] retain];
    possibleActions = [NSMutableArray arrayWithCapacity:2];
    
    [possibleActions addObject:^{
    [self spawnCloud];
    CGPoint cloudPoint1;
    cloudPoint1.x = 40;
    cloudPoint1.y = 600;
    cloud.center = cloudPoint1;
    }];
    [possibleActions addObject:^{
    [self spawnCloud];
    CGPoint cloudPoint1;
    cloudPoint2.x = 280;
    cloudPoint2.y = 600;
    cloud.center = cloudPoint2;
    }];
    [possibleActions retain];
}

-(void)gameLoop:(CADisplayLink *)sender{
    spawnMore++;
    if (spawnMore >= 280) {
        spawnMore -= 280;

      ActionBlock block = [possibleActions objectAtIndex:arc4random_uniform(possibleActions.count)];
        block();
    }
    for (cloud in cloudArray){
        if (cloud.center.y >= -100) {
            cloud.center = CGPointMake(cloud.center.x, cloud.center.y - 3;
    }
    else if (cloud.center.y >= -100) {
            [cloud removeFromSuperview];
            [cloudArray removeObject:cloud];
    }
}
if I just call [self spawnCloud] and then give it a position where the [possibleActions objectAtIndex:arc4random_uniform(possibleActions.count)] is it will work, so I know something is wrong with what I'm doing in the NSMutable Array. I did get EXC_BAD_ACCESS so I do have a bad pointer somewhere in the code
 
Last edited:

chown33

Moderator
Staff member
Aug 9, 2009
8,717
5,033
vertical
1. Which version of Xcode?

2. Using ARC or not? I'm guessing not, because you have at least one overt retain in your code. But guessing about code is always bad.

3. I see no possibleActions here. It's undefined in any posted code. Maybe it's a global or a static variable. No one but you knows.

4. Have you run your code with zombies enabled? If the cause of the bug is an over-release or under-retain, zombies should eventually show it.
 
Comment

AnonymousInUse

macrumors newbie
Original poster
Oct 9, 2012
5
0
1. Which version of Xcode?

2. Using ARC or not? I'm guessing not, because you have at least one overt retain in your code. But guessing about code is always bad.

3. I see no possibleActions here. It's undefined in any posted code. Maybe it's a global or a static variable. No one but you knows.

4. Have you run your code with zombies enabled? If the cause of the bug is an over-release or under-retain, zombies should eventually show it.
1. 4.5
2. no
3. whoops I forgot to write it in the post but it is in my header, its a NSMutable array.
4. No I have not, actually I don't even know what zombies is
 
Comment

chown33

Moderator
Staff member
Aug 9, 2009
8,717
5,033
vertical
3. whoops I forgot to write it in the post but it is in my header, its a NSMutable array.
You're "correction" to the original post is missing a semicolon.
Please post real code that's actually been compiled.


4. No I have not, actually I don't even know what zombies is
Google search terms: ios zombies xcode 4


The blocks you're adding to possibleActions are C blocks, which are not Objective-C objects. Furthermore, those C blocks have a limited scope, unless they are copied.

You should start here:
https://developer.apple.com/library...eral/Conceptual/DevPedia-CocoaCore/Block.html

And you should probably read the entire Blocks Programming Topics. In the Using Blocks section, pay particular attention to the headings "Copying Blocks", and "Patterns to Avoid".

Also see:
http://developer.apple.com/library/...iveC/WorkingwithBlocks/WorkingwithBlocks.html

You might be better off using NSInvocation, or make a suitable wrapper class for holding and invoking the C block.

Google search terms: block objective-C site:developer.apple.com
 
Comment

Duncan C

macrumors 6502a
Jan 21, 2008
853
0
Northern Virginia
You're "correction" to the original post is missing a semicolon.
Please post real code that's actually been compiled.



Google search terms: ios zombies xcode 4


The blocks you're adding to possibleActions are C blocks, which are not Objective-C objects. Furthermore, those C blocks have a limited scope, unless they are copied.

You should start here:
https://developer.apple.com/library...eral/Conceptual/DevPedia-CocoaCore/Block.html

And you should probably read the entire Blocks Programming Topics. In the Using Blocks section, pay particular attention to the headings "Copying Blocks", and "Patterns to Avoid".

Also see:
http://developer.apple.com/library/...iveC/WorkingwithBlocks/WorkingwithBlocks.html

You might be better off using NSInvocation, or make a suitable wrapper class for holding and invoking the C block.

Google search terms: block objective-C site:developer.apple.com
Actually, blocks ARE objects. A block is interchangeable with id type. You can add block objects to arrays as the OP is doing, and the array will take ownership of them (which copies them from the stack to the heap)

To quote the llvm.org article about blocks:

(From http://clang.llvm.org/docs/BlockLanguageSpec.txt)

Objective-C extends the definition of a Block reference type to be that also of id. A variable or expression of Block type may be messaged or used as a parameter wherever an id may be. The converse is also true. Block references may thus appear as properties and are subject to the assign, retain, and copy attribute logic that is reserved for objects.

All Blocks are constructed to be Objective-C objects regardless of whether the Objective-C runtime is operational in the program or not. Blocks using automatic (stack) memory are objects and may be messaged, although they may not be assigned into __weak locations if garbage collection is enabled.
 
Comment

AnonymousInUse

macrumors newbie
Original poster
Oct 9, 2012
5
0
I'll look over the docs but maybe I'm approaching this wrong and using blocks isn't a good idea. I've been homeschooling myself programming and I'm not so good at it. How would you approach call one of these objects of these two objects randomly?
 
Comment

Duncan C

macrumors 6502a
Jan 21, 2008
853
0
Northern Virginia
The crash repots telling me EXC_BAD_ACCESS so I know I have a crappy pointer(s) in this code but I have no clue how to fix it.

Cloud is a UIImageView Subclass, a CADisplayLink is a timer that fires a method 60 times per second.

--snip--

if I just call [self spawnCloud] and then give it a position where the [possibleActions objectAtIndex:arc4random_uniform(possibleActions.count)] is it will work, so I know something is wrong with what I'm doing in the NSMutable Array. I did get EXC_BAD_ACCESS so I do have a bad pointer somewhere in the code

I'm still getting used to the syntax of blocks, but I don't think these 2 lines are correct:


Code:
        [possibleActions objectAtIndex:arc4random_uniform(possibleActions.count)];
        block();
The way I read it, the first line will simply return the block as the result of the method, but won't do anything with it. I have no idea what the function call block() is supposed to do. I guess you defined a block variable somewhere named block, but you did not show that code.

This code should invoke one of the blocks from your array:

Code:
        ActionBlock theBlock = [possibleActions objectAtIndex:arc4random_uniform(possibleActions.count)];
        theBlock();
 
Comment

AnonymousInUse

macrumors newbie
Original poster
Oct 9, 2012
5
0
Oh my god, this is embarrassing but I cut a lot of code out when writing this so it would've been less confusing an when writing this I forgot to write actionBlock block in it... Im sorry, it is in the actual code
 
Comment

Duncan C

macrumors 6502a
Jan 21, 2008
853
0
Northern Virginia
Oh my god, this is embarrassing but I cut a lot of code out when writing this so it would've been less confusing an when writing this I forgot to write actionBlock block in it... Im sorry, it is in the actual code
The code as posted is incomplete. Post the complete section that's relevant, or we can't help you fix it.
 
Comment

chown33

Moderator
Staff member
Aug 9, 2009
8,717
5,033
vertical
I believe the post is now correct, sorry again for the issue
This seems wrong, or unexplained:
Code:
    [possibleActions addObject:^{
    [self spawnCloud];
    CGPoint [COLOR="Red"]cloudPoint1[/COLOR];
    [COLOR="Blue"]cloudPoint2[/COLOR].x = 280;
    [COLOR="blue"]cloudPoint2[/COLOR].y = 600;
    cloud.center = [COLOR="Blue"]cloudPoint2[/COLOR];
    }];
Should cloudPoint1 really be cloudPoint2? Or is there a cloudPoint2 variable outside the block's scope that hasn't been posted?


The use of the ivar 'cloud' to couple the blocks to the factory method spawnCloud is a dubious design choice, at best.


The summary of what the whole complex structure (array of blocks, coupling via 'cloud', etc.) is doing seems to be, "Randomly pick one of two distinct coordinates, and make a Cloud instance whose center is at that coordinate". I'd probably do that using a simple if/else. If the number of outcomes was more than two, I'd probably use a switch statement. It's what we did in the old days, before blocks. Or we used an initialized C array of values, and did a table lookup.

If the coordinates needed to be read from a file, I'd use a plist containing an array of coord-pairs (an array of arrays, where each sub-array holds two numbers). Read the plist once, keep it around. Randomly pick one coord-pair from the array. Make the Cloud instance, set its center. Done.
 
Comment

dejo

Moderator
Staff member
Sep 2, 2004
15,981
450
The Centennial State
...but I cut a lot of code out when writing this so it would've been less confusing
It is recommended that you don't cut out code. Either cut-and-paste entire code or, if you're trying to simplify it or are dealing with non-disclosure, provide code from a stand-alone test project made specifically to replicate the issue.
 
Comment

Similar threads

Register on MacRumors! This sidebar will go away, and you'll see fewer ads.