Objective C help <SOLVED>

I have written some functions in Objective-C which I have residing in a XCODE library project. I wrote an Objective C test application to call the main library functions and display the resulting output in a view. All good so far.

Now I am integrating that library with my Unity project and while I am able to call one of the functions, so far one specific bit of code gets an SIGABRT exception.

The shuffle is implemented as a category. I am not sure why this is having a problem when compiled together with Unity but works okay standalone?

2010-07-23 21:41:57.102 matchPoint[4175:307] -[__NSArrayM shuffle]: unrecognized selector sent to instance 0x8b5eda0
2010-07-23 21:41:57.115 matchPoint[4175:307] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayM shuffle]: unrecognized selector sent to instance 0x8b5eda0'
*** Call stack at first throw:
(
	0   CoreFoundation                      0x3513cfd3 __exceptionPreprocess + 114
	1   libobjc.A.dylib                     0x303928a5 objc_exception_throw + 24
	2   CoreFoundation                      0x35140a77 -[NSObject(NSObject) doesNotRecognizeSelector:] + 102
	3   CoreFoundation                      0x3513ff15 ___forwarding___ + 508
	4   CoreFoundation                      0x350d2680 _CF_forwarding_prep_0 + 48
	5   matchPoint                          0x00dfd53c start + 14604160
	6   matchPoint                          0x00dfa118 start + 14590812
	7   matchPoint                          0x000a6070 start + 615092
	8   matchPoint                          0x000a26ec start + 600368
	9   matchPoint                          0x00cc2ebc start + 13316352
	10  matchPoint                          0x01149e78 _ZN4FMOD7SystemI26createChannelGroupInternalEPKcPPNS_13ChannelGroupIEbb + 1411308
	11  matchPoint                          0x011da814 _ZN4FMOD7SystemI26createChannelGroupInternalEPKcPPNS_13ChannelGroupIEbb + 2003592
	12  matchPoint                          0x00ec4304 start + 15418696
	13  matchPoint                          0x00ec4348 start + 15418764
	14  matchPoint                          0x00ed1a10 start + 15473748
	15  matchPoint                          0x00e38568 start + 14845868
	16  matchPoint                          0x00ef6e64 start + 15626408
	17  matchPoint                          0x00f50600 start + 15992900
	18  matchPoint                          0x00010044 start + 648
	19  CoreFoundation                      0x350c87ff -[NSObject(NSObject) performSelector:withObject:] + 22
	20  Foundation                          0x339cbbbd __NSThreadPerformPerform + 268
	21  CoreFoundation                      0x35112a8d __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 12
	22  CoreFoundation                      0x3511476f __CFRunLoopDoSources0 + 382
	23  CoreFoundation                      0x3511550b __CFRunLoopRun + 230
	24  CoreFoundation                      0x350be8eb CFRunLoopRunSpecific + 230
	25  CoreFoundation                      0x350be7f3 CFRunLoopRunInMode + 58
	26  GraphicsServices                    0x309776ef GSEventRunModal + 114
	27  GraphicsServices                    0x3097779b GSEventRun + 62
	28  UIKit                               0x321c12a7 -[UIApplication _run] + 402
	29  UIKit                               0x321bfe17 UIApplicationMain + 670
	30  matchPoint                          0x00010ed8 start + 4380
	31  matchPoint                          0x0000fde4 start + 40
)
terminate called after throwing an instance of 'NSException'
	NSMutableArray *iconIndex;
	// Make array and fill it with 0 to 99
	iconIndex = [[NSMutableArray alloc] initWithCapacity:100];
	for (int i = 0 ; i < 100 ; i++) {
		[iconIndex addObject:[NSNumber numberWithInt:i]];
	}
	
	// Random shuffle
	[iconIndex shuffle];

The shuffling code came from this web page ( objective c - What's the Best Way to Shuffle an NSMutableArray? - Stack Overflow )

Header


#import <UIKit/UIKit.h>


@interface NSMutableArray (Shuffling)
- (void)shuffle;
@end
Function

#import "NSMutableArray_Shuffling.h"

@implementation NSMutableArray (Shuffling)

- (void)shuffle
{
    NSUInteger count = [self count];
    for (NSUInteger i = 0; i < count; ++i) {
        // Select a random element between i and end of array to swap with.
        int nElements = count - i;
        int n = (arc4random() % nElements) + i;
        [self exchangeObjectAtIndex:i withObjectAtIndex:n];
    }
}

@end

Any suggestions appreciated.

iByte

Well so far I have back-tracked it to the fact I had to use the linker flag “-all_load” in order to get categories recognized in my test application (and of course I forgotten I had to do that :x ). Problem is that -all_load doesn’t seem to work for me with UnityB4 (causes other errors) and I understand it is not preferable anyway as it would add unneeded code to the final application.

A previous post on the Unity forums was never answered - http://forum.unity3d.com/viewtopic.php?p=292628 but I did find some possible help with a work around. I will give this try and from what I understand from the stackoverflow post this problem is fixed with Xcode4 (but I am sure that will present it’s own set of challenges once we upgrade to that SDK).

Additional info

http://stackoverflow.com/questions/932856/calling-method-on-category-included-from-iphone-static-library-causes-nsinvalidar

bilprob (or anyone else) if you read this and you are successfully using categories would you share how you managed it?

Life is a moving target …

Okay - that did it - making a dummy class def in the same file as my category definition resolved the error of the linker not including the category code.

I hope this info helps anyone else out who runs into this problem.

Header
//  NSMutableArray_Shuffling.h
#import <UIKit/UIKit.h>


@interface NSMutableArray (Shuffling)
- (void)shuffle;
@end

@interface CategoryDummy : NSObject {
	
}

@end
Code
//  NSMutableArray_Shuffling.m

#import "NSMutableArray_Shuffling.h"


@implementation CategoryDummy
@end


@implementation NSMutableArray (Shuffling)

- (void)shuffle
{
    NSUInteger count = [self count];
    for (NSUInteger i = 0; i < count; ++i) {
        // Select a random element between i and end of array to swap with.
        int nElements = count - i;
        int n = (arc4random() % nElements) + i;
        [self exchangeObjectAtIndex:i withObjectAtIndex:n];
    }
}

@end