0

I have a sharedInstance which consists of many NSMutableArrays which holds all my form data that is spread across many views in my App.

An example of their declaration in .h looks like

@property (atomic, retain) NSMutableArray *i_date;
@property (atomic, retain) NSMutableArray *i_tailNumber;
@property (atomic, retain) NSMutableArray *i_pic;
@property (atomic, retain) NSMutableArray *i_sic;

and in .m (- init)

self = [super init];

_i_date = [NSMutableArray array];
_i_tailNumber = [NSMutableArray array];
_i_pic = [NSMutableArray array];
_i_sic = [NSMutableArray array];

The shared instance function is

+(id) sharedInstance
{    
    static id sharedInstance = nil;
    if (sharedInstance == nil) {
        sharedInstance = [[self alloc] init];        
    }
    return sharedInstance;
}

EDIT:

I instantiate all the arrays with an empty string on the first view as seen below

[_fd.i_date addObject:@""];
[_fd.i_tailNumber addObject:@""];

Finally I interact with my data this way in the prepare for segue function

[_fd.i_date replaceObjectAtIndex:leg withObject:transferDate];
rinse and repeate

My problem, which I've spent many hours investigating today by reading various blogs, the documentation, and all the wonderful resources here at SO, is that my arrays lose any objects I place in them when I segue to another view.

When I hit the code line above, I get the classic

signal SIGABRT

error, which complains that my arrays are empty (0 objects), so it cannot replace anything.

I suspect I'm not handling my shared instance properly and that ... maybe, perhaps, multiple instances of my arrays are being allocated, but I'm certain that I'm turned around in my understanding.

Any ideas what is occurring? I think I provided all the necessary code snippets but if I forgotten something just ask. Thanks again!

Jesse


EDIT: You guys are FAST! :D I created my OBJ-C file with ARC enabled, so I think I am using it. I'm a C++ guy, mostly so this optional hand holding mem stuff is natively ambiguous to me.


EDIT: The complete error is

2013-04-10 20:25:03.239 ProjectName[4230:c07] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM replaceObjectAtIndex:withObject:]: index 0 beyond bounds for empty array'
*** First throw call stack:
(0x1caf012 0x10ece7e 0x1c65ba9 0x7c7e 0x478b87 0x478c14 0x1100705 0x342c0 0x270a64 0x1100705 0x342c0 0x34258 0xf5021 0xf557f 0xf46e8 0x63cef 0x63f02 0x41d4a 0x33698 0x1c0adf9 0x1c0aad0 0x1c24bf5 0x1c24962 0x1c55bb6 0x1c54f44 0x1c54e1b 0x1c097e3 0x1c09668 0x30ffc 0x222d 0x2155)
libc++abi.dylib: terminate called throwing an exception
Wojciech Rutkowski
  • 11,299
  • 2
  • 18
  • 22
Jesse Meyer
  • 315
  • 1
  • 3
  • 12
  • Post the complete error message. Also try turning on zombie checking. That should give you a better error message if it's a memory management issue. Also run the Analyzer on your code and see what comes up. – rmaddy Apr 10 '13 at 23:50
  • I've added the error message w/ zombie checking enabled (it didn't seem the alter the error message). – Jesse Meyer Apr 11 '13 at 00:48

4 Answers4

1

Assuming you are not using ARC, your init method is using poor memory management. Since you are directly accessing the ivars (and not the properties) you need to retain the arrays:

_i_date = [[NSMutableArray alloc] init];
_i_tailNumber = [[NSMutableArray alloc] init];
_i_pic = [[NSMutableArray alloc] init];
_i_sic = [[NSMutableArray alloc] init];
rmaddy
  • 314,917
  • 42
  • 532
  • 579
  • If you are using ARC, setting autoreleased variables to the ivars of a strong property will work correctly. However, since it says "retain", I'm guessing he's not using ARC. – sudo rm -rf Apr 10 '13 at 23:44
  • @sudorm-rf The use of `retain` leads me to believe the code is using MRC, not ARC. – rmaddy Apr 10 '13 at 23:45
  • Thanks for the help! I am using ARC or so I think... (I updated my post to reflect that for new readers). Does that fact alter your advice? – Jesse Meyer Apr 10 '13 at 23:47
  • @JesseMeyer If you really are using ARC then this shouldn't be an issue. Post the complete error message. Also try turning on zombie checking. That should give you a better error message if it's a memory management issue. Also run the Analyzer on your code and see what comes up. – rmaddy Apr 10 '13 at 23:49
  • 2013-04-10 20:25:03.239 ProjectName[4230:c07] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM replaceObjectAtIndex:withObject:]: index 0 beyond bounds for empty array' *** First throw call stack: (0x1caf012 0x10ece7e 0x1c65ba9 0x7c7e 0x478b87 0x478c14 0x1100705 0x342c0 0x270a64 0x1100705 0x342c0 0x34258 0xf5021 0xf557f 0xf46e8 0x63cef 0x63f02 0x41d4a 0x33698 0x1c0adf9 0x1c0aad0 0x1c24bf5 0x1c24962 0x1c55bb6 0x1c54f44 0x1c54e1b 0x1c097e3 0x1c09668 0x30ffc 0x222d 0x2155) libc++abi.dylib: terminate called throwing an exception – Jesse Meyer Apr 11 '13 at 00:39
  • Which BTW, I've attempted this method of allocating the arrays and it didn't work. – Jesse Meyer Apr 11 '13 at 00:40
1

You are not using the properties but you create autoreleased objects.

Either use the properties like

+(id) sharedInstance
{    
    static id sharedInstance = nil;
    if (sharedInstance == nil) {
        sharedInstance = [[self alloc] init];   

         sharedInstance.i_date = [NSMutableArray array];
         sharedInstance.i_tailNumber = [NSMutableArray array];
         sharedInstance.i_pic = [NSMutableArray array];
         sharedInstance.i_sic = [NSMutableArray array];     
    }
    return sharedInstance;
}

or do as rmaddy suggested.


[_fd.i_date replaceObjectAtIndex:leg withObject:transferDate];

this lines crash, as the array yet doent have an object at index leg

try

[_fd.i_date addObject:transferDate];
vikingosegundo
  • 52,040
  • 14
  • 137
  • 178
  • I edited the primary post. During the first view, I add an empty string to all the arrays. Now that I think of it it's probably a wasted step. I'll make the change and see what happens. Thanks! – Jesse Meyer Apr 11 '13 at 00:31
  • honestly: you should not maintain all these arrays but create a class that holds these information and just put instances of that in one array. – vikingosegundo Apr 11 '13 at 00:33
  • It's vitally important that I know and track which "leg" any input is assigned to. For this reason I decided to split it all up. Input isn't 100% required, so "addObject" could invade the incorrect "leg" space. Maybe I'm not understanding you properly. – Jesse Meyer Apr 11 '13 at 00:38
  • you would have one array where you can use `leg`. – vikingosegundo Apr 11 '13 at 00:46
  • I need to differentiate between many of the different inputs. I don't see how a single array would suffice. – Jesse Meyer Apr 11 '13 at 00:49
  • I attempted this change, with sharedInstance.x = [object array]; and it's barking that none of the properties are found on object type "strong id". Investigating. – Jesse Meyer Apr 11 '13 at 00:51
0

You should alloc and init your NSMutableArrays:

_i_date = [[NSMutableArray alloc] init];

And then use your singleton class i.e.:

[[_fd sharedInstance] i_date] addObject...]
Wojciech Rutkowski
  • 11,299
  • 2
  • 18
  • 22
0

Unbeknownst, I used the function "didMoveToParentViewController", which is called after a new view is displayed if it's overloaded and used by the view. In it, I was clearing all the arrays, thinking that it would only be called WHEN moving BACK to the parent view, since the word "did" which is a past tense word. Since that isn't the case, I was clearing my arrays right after page load, which resulted in empty arrays during the segues.

Jesse Meyer
  • 315
  • 1
  • 3
  • 12