Link to home
Start Free TrialLog in
Avatar of NOTBOB90
NOTBOB90

asked on

Why can't I just change the value in an array in xcode.

I am so annoyed at this, I can hardly type.  For 20 years I could simple change an array by doing something simple like sArray(20) = "New Array Value"

With all the technology available it baffles me that those designing languages are making it more complex.  In any event, can someone please help me set the value of a mutable array.
Avatar of Hamidreza Vakilian
Hamidreza Vakilian

NSMutableArray* array = [NSMutableArray new];//initialization
[array addObject: someObject];//simply adding an object to the array
[array insertObject: someObject2 atIndex:0];//inserting an object at desired index
[array replaceObjectAtIndex:0 withObject: someObject3];//replacing an object this is what you are looking for

Open in new window


You should notice that you can only add NSObject derived objects to NSMutableArray.... e.g. You cannot add int or bool directly to this kind of array.
Avatar of NOTBOB90

ASKER

Ok so how do you change a value.
Ok so how do you change a value.
For example you want to change the value at index 5 to newObject:

int index = 5;
[array replaceObjectAtIndex: index withObject: newObject];
Ok I tried that and I think the problem I am having is this is a global array.  I want to set this array up in the main file, but be able to use it in multiple viewcontrollers.  

In the Main file I have:

NSMutableArray *gArrBot1;

--------------------------

Then in FrontViewController.m I have:

       

        extern NSArray *gArrBot1;
   
       
        [NSMutableArray *gArrBot1 = [NSMutableArray new];//initialization   RIGHT HERE
       
        [gArrBot1 addObject: @"ACTONE"];
        [gArrBot1: @"37"];
        [gArrBot1 addObject: @"83"];

 [gArrBot1 replaceObjectAtIndex:0 withObject: @"RANDY"];  

I get an error on the line I marked RIGHT HERE

The error is Expected Identifier
       
You cannot declare global variables that way. You should declare it in yourAppDelegate.h file. viewControllers can only access yourAppDelegate properties. So to make a global variable we make a property in yourAppDelegate.h:

In yourAppDelegate.h add this line before @end:
@property (retain, nonatomic) NSMutableArray* array;

Open in new window


Now in yourAppDelegate.m add this after @implementation:
@synthesize array;

Open in new window


Then at the top of your viewController header file include the yourAppDelegate header file:
#import "yourAppDelegate.h"

Open in new window


Now in the body of your viewController:
yourAppDelegate* theAppDelegate = [[UIApplication sharedApplication] delegate];
NSMutableArray* theGlobalArray = [theAppDelegate array];
//now do whatever with theGlobalArray

Open in new window


Notice: in objective c there's no global variable, instead we have properties.
Here is the code that gets triggered when I click a button.  I used the code you sent me and made some modifications as I thought needed done.  Array1Update 1-3 are labels.  When I run this it clears the default label text and makes it blank.  In other words I don't think any array is being loaded. :(  frustrating
-(IBAction)actBuildArray:(id)sender

{
    ArrayTestAppDelegate *theAppDelegate = [[UIApplication sharedApplication] delegate];
    NSMutableArray *theGlobalArray = [theAppDelegate theRGArray];
    
    [theGlobalArray addObject:@"ARRAY 0"];
    [theGlobalArray addObject:@"ARRAY 1"];
    [theGlobalArray addObject:@"ARRAY 2"];
    
    Array1Update.text = [theGlobalArray objectAtIndex:(0)];
    Array2Update.text = [theGlobalArray objectAtIndex:(1)];
    Array3Update.text = [theGlobalArray objectAtIndex:(2)];
    
    
}

Open in new window

Beacause you have not initialized theGlobalArray. Add
theGlobalArray = [NSMutableArray new];

Open in new window

before adding the strings to it.
Well that updated my labels correctly - thanks.  The only problem is the values that are loaded there do not stay when I go to another method or a different viewcontroller.  I have to reload the array and the values are reset.
For initialization use:
if (!theGlobalArray)
theGlobalArray = [NSMutableArray new];

Open in new window

The issue probably was that you initialize it every time you want to access it. You should initialize it once, to retain your data.
I added the code for the 2 buttons that call actions.  The first one works fine, but the second one give me an error about array out of range.

I just want to be able to load array variables in the first action and read/change them in the second action.  I also want to do this across view controllers.
-(IBAction)actBuildArray:(id)sender

{
    ArrayTestAppDelegate *theAppDelegate = [[UIApplication sharedApplication] delegate];
    NSMutableArray *theGlobalArray = [theAppDelegate theRGArray];
    
     theGlobalArray = [NSMutableArray new];

    [theGlobalArray addObject:@"TEXT FOR ARRAY 0"];
    [theGlobalArray addObject:@"TEXT FOR ARRAY 1"];
    [theGlobalArray addObject:@"TEXT FOR ARRAY 2"];
    
    Array1Update.text = [theGlobalArray objectAtIndex:(0)];
    Array2Update.text = [theGlobalArray objectAtIndex:(1)];
    Array3Update.text = [theGlobalArray objectAtIndex:(2)];
       
}

-(IBAction)actShowArray:(id)sender

{
    
    ArrayTestAppDelegate *theAppDelegate = [[UIApplication sharedApplication] delegate];
    NSMutableArray *theGlobalArray = [theAppDelegate theRGArray];
    
    theGlobalArray = [NSMutableArray new];
    
    Array1Update.text = [theGlobalArray objectAtIndex:(1)];
 
}

Open in new window

In actShowArray add
If (!theGlobalArray)

Open in new window

right before
theGlobalArray = [NSMutableArray new];

Open in new window

I corrected the code for you, here:


-(IBAction)actBuildArray:(id)sender

{
    ArrayTestAppDelegate *theAppDelegate = [[UIApplication sharedApplication] delegate];
    NSMutableArray *theGlobalArray = [theAppDelegate theRGArray];
   
     theGlobalArray = [NSMutableArray new];

    [theGlobalArray addObject:@"TEXT FOR ARRAY 0"];
    [theGlobalArray addObject:@"TEXT FOR ARRAY 1"];
    [theGlobalArray addObject:@"TEXT FOR ARRAY 2"];
   
    Array1Update.text = [theGlobalArray objectAtIndex:(0)];
    Array2Update.text = [theGlobalArray objectAtIndex:(1)];
    Array3Update.text = [theGlobalArray objectAtIndex:(2)];
       
}

-(IBAction)actShowArray:(id)sender

{
   
    ArrayTestAppDelegate *theAppDelegate = [[UIApplication sharedApplication] delegate];
    NSMutableArray *theGlobalArray = [theAppDelegate theRGArray];
   
    If (!theGlobalArray)
    theGlobalArray = [NSMutableArray new];
   
    Array1Update.text = [theGlobalArray objectAtIndex:(1)];
 
}
I get an error when I copy your updated code in.

Implicit declaration of function "if" is invalid in c99

on this line:

 If (!theGlobalArray)
    theGlobalArray = [NSMutableArray new];
Oh it is a mistype. if should be in lower case letters... change those 2 lines to:
if (!theGlobalArray)
ThGlobalArray = [NSMutableArray new];

Ok when I run that I get an error in the main file:

int main(int argc, char *argv[])
{
   
   
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([ArrayTestAppDelegate class]));
    }
}

The error in on the return line and says Thread 1 Program receives signal sigbrt
2012-01-08 10:36:00.708 ArrayTest[812:f803] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array'
*** First throw call stack:
(0x13bc052 0x154dd0a 0x13a8db8 0x2d0f 0x13bdec9 0x165c2 0x1655a 0xbbb76 0xbc03f 0xbb2fe 0x3ba30 0x3bc56 0x22384 0x15aa9 0x12a6fa9 0x13901c5 0x12f5022 0x12f390a 0x12f2db4 0x12f2ccb 0x12a5879 0x12a593e 0x13a9b 0x22b8 0x2215 0x1)
terminate called throwing an exceptionCurrent language:  auto; currently objective-c
The error means you are requesting object with index 0 but it does not exist in the array. It's because actShowArray gets executed before actBuildArray.
actBuildArray should be called before actShowArray. Correct your code due to this...
But I am running the code in the first method first which adds three objects to the array
You see this is my whole frustration.  I am able to add and edit things in the same method, but as soon as I go somewhere else (another method) the array disappears.  I populate with one method and want to edit in another, but nothing is there.
Change actShowArray to:

-(IBAction)actShowArray:(id)sender

{
   
    ArrayTestAppDelegate *theAppDelegate = [[UIApplication sharedApplication] delegate];
    NSMutableArray *theGlobalArray = [theAppDelegate theRGArray];
   
    Array1Update.text = [theGlobalArray objectAtIndex:(1)];
 
}

If it does not work again, please send your complete source file of the viewcontroller.
Did not work again.  I clicked first button it load the array and updated the labels.  When I then click on second button it made the first label blank.  Sending code
#import "ArrayTestViewController.h"
#import "ArrayTestAppDelegate.h"
#import "PageTwo.h"

@implementation ArrayTestViewController

@synthesize Array1Update;
@synthesize Array2Update;
@synthesize Array3Update;
@synthesize theArray;

-(IBAction)actBuildArray:(id)sender

{
    ArrayTestAppDelegate *theAppDelegate = [[UIApplication sharedApplication] delegate];
    NSMutableArray *theGlobalArray = [theAppDelegate theRGArray];
    
    theGlobalArray = [NSMutableArray new];
    
    [theGlobalArray addObject:@"TEXT FOR ARRAY 0"];
    [theGlobalArray addObject:@"TEXT FOR ARRAY 1"];
    [theGlobalArray addObject:@"TEXT FOR ARRAY 2"];
    
    Array1Update.text = [theGlobalArray objectAtIndex:(0)];
    Array2Update.text = [theGlobalArray objectAtIndex:(1)];
    Array3Update.text = [theGlobalArray objectAtIndex:(2)];
    
}

-(IBAction)actShowArray:(id)sender

{
    
//    ArrayTestAppDelegate *theAppDelegate = [[UIApplication sharedApplication] delegate];
 //   NSMutableArray *theGlobalArray = [theAppDelegate theRGArray];
    
 //   if (!theGlobalArray)
        
  //  theGlobalArray = [NSMutableArray new];
    
   // Array1Update.text = [theGlobalArray objectAtIndex:(0)];
    
    
    ArrayTestAppDelegate *theAppDelegate = [[UIApplication sharedApplication] delegate];
    NSMutableArray *theGlobalArray = [theAppDelegate theRGArray];
    
    Array1Update.text = [theGlobalArray objectAtIndex:(1)];
    
    
}


-(IBAction)actSwitchView:(id)sender
{
    
    PageTwo *second =[[PageTwo alloc]initWithNibName:nil bundle:nil];
    
    [self presentModalViewController:second animated:NO];    
}



-(IBAction)actChangeArray:(id)sender

{
    
    
     Array1Update.text = [theArray objectAtIndex:(2)];  
    
    [theArray replaceObjectAtIndex:(2) withObject:@"IT WORKED"];
    

    Array2Update.text = [theArray objectAtIndex:(2)];
    Array3Update.text = [theArray objectAtIndex:(5)];
   
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Release any cached data, images, etc that aren't in use.
}

#pragma mark - View lifecycle

- (void)viewDidLoad
{
    [super viewDidLoad];
	// Do any additional setup after loading the view, typically from a nib.
}

- (void)viewDidUnload
{
    [self setArray1Update:nil];
    [self setArray2Update:nil];
    [self setArray3Update:nil];
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
}

- (void)viewWillDisappear:(BOOL)animated
{
	[super viewWillDisappear:animated];
}

- (void)viewDidDisappear:(BOOL)animated
{
	[super viewDidDisappear:animated];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}

@end

Open in new window

I know the code for actChangeArray is wrong, that is my next step is to change the array in that method and post it to the label.  My final step is to switch to the page 2 controller and make modification there and post them back to the first controller.
Wowww I got it. Are you programming in ARC mode (automatic reference counting) or not? Arc is only available in xcode 4.2

If you are not, I guess so, we should retain our objects... Tell me if you are not coding in ARC mode so I will repeair the code for you...
If you are not sure about the answer add this line after array initialization:
[theGlobalArray retain];

If you got error, then you may be in ARC...
It is version 4.2.1
It puts and error and says ARC FORBIDS EXPLICIT MESSAGE SEND of 'RETAIN'
So here is your new actBuildArray:

-(IBAction)actBuildArray:(id)sender
{
    ArrayTestAppDelegate *theAppDelegate = [[UIApplication sharedApplication] delegate];
    NSMutableArray *theGlobalArray = [theAppDelegate theRGArray];
   
    theGlobalArray = [NSMutableArray new];
    [theGlobalArray retain];

   
    [theGlobalArray addObject:@"TEXT FOR ARRAY 0"];
    [theGlobalArray addObject:@"TEXT FOR ARRAY 1"];
    [theGlobalArray addObject:@"TEXT FOR ARRAY 2"];
   
    Array1Update.text = [theGlobalArray objectAtIndex:(0)];
    Array2Update.text = [theGlobalArray objectAtIndex:(1)];
    Array3Update.text = [theGlobalArray objectAtIndex:(2)];
Ignore my last comment. Can you provide the header and source of appdelegate class?

#import <UIKit/UIKit.h>

@class ArrayTestViewController;

@interface ArrayTestAppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;

@property (strong, nonatomic) ArrayTestViewController *viewController;



@property (retain, nonatomic) NSMutableArray *theRGArray;

@end

Open in new window


//
//  ArrayTestAppDelegate.m
//  ArrayTest
//
//  Created by Randy Gardner on 1/6/12.
//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//

#import "ArrayTestAppDelegate.h"

#import "ArrayTestViewController.h"

@implementation ArrayTestAppDelegate

@synthesize theRGArray;

@synthesize window = _window;
@synthesize viewController = _viewController;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.
    self.viewController = [[ArrayTestViewController alloc] initWithNibName:@"ArrayTestViewController" bundle:nil];
    self.window.rootViewController = self.viewController;
    [self.window makeKeyAndVisible];
    return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application
{
    /*
     Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
     Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
     */
}

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    /*
     Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 
     If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
     */
}

- (void)applicationWillEnterForeground:(UIApplication *)application
{
    /*
     Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
     */
}

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    /*
     Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
     */
}

- (void)applicationWillTerminate:(UIApplication *)application
{
    /*
     Called when the application is about to terminate.
     Save data if appropriate.
     See also applicationDidEnterBackground:.
     */
}

@end

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of Hamidreza Vakilian
Hamidreza Vakilian

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
WHEW WHOOOOOOOOOOOOOOOO!
THANK YOU SO MUCH !  I put that code in and it worked perfect!.  I added it to the other controller and it updates the array perfect.  Thank you so much for your time and work.  
Thanks so much again for the help.
You're welcome :-)