-2

@property (strong, nonatomic)NSMutableArray *billsArray;

- (void)viewDidLoad {
    [super viewDidLoad];

    self.billsUserDefault = [NSUserDefaults standardUserDefaults];
    self.billsArray = [[NSMutableArray alloc] init];
    self.billsArray = [self getBillsArray];

}


- (NSMutableArray *)getBillsArray {
    NSMutableArray *billsArr = [self.billsUserDefault objectForKey:@"billArray"];
    return billsArr;
}


- (void)AddOneBill:(Bill *)bill {
    // add bill to array
    [self.billsArray addObject:bill];

    // store the new bill
    [self.billsUserDefault setObject:self.billsArray forKey:@"billArray"];
    [self.billsUserDefault synchronize];

    // reload the table view
    [self.billTableView reloadData];

}

The addObject method in addOneBill: method does not work.

I have googled the same problem, others also met this problem. The answers suggested to add [[NSMutableArray alloc] init] for mutable array. I did but not works.

Cokile Ceoi
  • 1,326
  • 2
  • 15
  • 26

5 Answers5

1

In your getBillsArray method, add mutableCopy call to get mutable array for objectForKey. Because objects got from NSUserDefaults are not mutable. Modified code would look like this:

- (NSMutableArray *)getBillsArray {
    NSMutableArray *billsArr = [[self.billsUserDefault objectForKey:@"billArray"] mutableCopy];
    return billsArr;
}

EDIT: You are adding custom objects in array and trying to save in NSUserDefaults which is not possible. You need to convert your object into NSDictionary object in which each key value pair will represent one variable of that object. You will have to recursively do this conversion step if your custom object also contain custom objects.

Salman Zaidi
  • 9,342
  • 12
  • 44
  • 61
  • add a breakpoint where you are adding objects in your array. See the type of `billsArray` in debug area. Check whether type is `NSMutableArray` or `NSArray`?? – Salman Zaidi Mar 16 '15 at 12:27
  • The type is __NSArrayM, maybe the key point of the problem is NSUserDefault can not store array of custom objects. – Cokile Ceoi Mar 16 '15 at 13:03
  • yes.. you can't store custom objects in NSUserDefaults. You need to convert all your objects (recursively if custom objects contain other custom objects) into primitive objects i.e., into NSString, NSNumber to store into NSUserDefaults. – Salman Zaidi Mar 16 '15 at 13:28
0

Try NSMutableArray *billsArr = [[self.billsUserDefault objectForKey:@"billArray"] mutableCopy]; in getBillsArray

ryancrunchi
  • 465
  • 2
  • 16
0

NSUserDefaults objects are not not mutable. You have to make them mutable.

try following code.

NSMutableArray *billsArr = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:@"billArray"]];
Nirav Gadhiya
  • 6,342
  • 2
  • 37
  • 76
  • `addObject` method worked, but the app terminated : Property list invalid for format: 200 (property lists cannot contain objects of type 'CFType') Attempt to set a non-property-list object ( "" ) as an NSUserDefaults/CFPreferences value for key billArray *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attempt to insert non-property list object ( "" ) for key billArray' – Cokile Ceoi Mar 16 '15 at 12:45
  • maybe the key point of the problem is NSUserDefault can not store an array of custom objects. – Cokile Ceoi Mar 16 '15 at 13:05
  • You can store only properties in the userDefaults, you are storing an object of class Bill. Thats the error. If you want to store objects in plist or userDefaults you need to archive them using `NSKeyedArchiver` – Nirav Gadhiya Mar 17 '15 at 04:56
0
- (void)viewDidLoad {
    [super viewDidLoad];

    self.billsUserDefault = [NSUserDefaults standardUserDefaults];
    self.billsArray = [[NSMutableArray alloc] init];
    self.billsArray = [self getBillsArray];

}

In viewDidLoad you call getBillsArray. But what value in userDefauls for key - billArray you what to get at viewController start?

You set array for this key in addOneBill method. So in viewDidLoad you creates mutableArray: self.billsArray = [[NSMutableArray alloc] init];

and then set it to nil here: self.billsArray = [self getBillsArray];

Pavel Gatilov
  • 2,570
  • 2
  • 18
  • 31
0

Another solution : For the explication why it does not work, see Salman's answer (Returned values from NSUserDefaults are not mutable)

- (void)viewDidLoad {
    [super viewDidLoad];

    self.billsUserDefault = [NSUserDefaults standardUserDefaults];
    self.billsArray = [[NSMutableArray alloc] init];
    [self.billsArray addObjectsFromArray: [self getBillsArray]];
}


- (NSArray *)getBillsArray {
    NSArray *billsArr = [self.billsUserDefault objectForKey:@"billArray"];
    return billsArr;
}

In order to save your 'Bill' objects into NSUserDefaults, if it's derived from NSObject, you can use NSKeyedArchiver & NSKeyedUnarchvier:

//encode
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:your_bill_array];
//then save to NSUserDefaults 

//decode:   
id result = [NSKeyedUnarchiver unarchiveObjectWithData:data_returned_from_NSUSerDefaults];
Duyen-Hoa
  • 15,384
  • 5
  • 35
  • 44
  • I tried your solution, but the app terminated: Property list invalid for format: 200 (property lists cannot contain objects of type 'CFType') Attempt to set a non-property-list object ( "" ) as an NSUserDefaults/CFPreferences value for key billArray *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attempt to insert non-property list object ( "" ) for key billArray' – Cokile Ceoi Mar 16 '15 at 12:41
  • There's another problem for your code. NSUserDefaults accepts only primitive data types (NSData, NSArray, NSString,...). Your 'Bill' is a custom object so it cannot be inserted directly into the NSUSerDefaults. If Bill is derived from NSObject, you can use NSKeyedArchiver & NSKeyedUnarchiver. (See my updated answer) – Duyen-Hoa Mar 16 '15 at 13:08
  • This time, the app terminated by:-[Bill encodeWithCoder:]: unrecognized selector sent to instance 0x7f990c00cc20 – Cokile Ceoi Mar 16 '15 at 13:40
  • take a look at this: http://stackoverflow.com/questions/5768495/how-to-encode-and-decode-a-custom-class-with-nskeyedarchiver – Duyen-Hoa Mar 16 '15 at 13:45