Reputation: 29
The following is the entity Player
header file.
@interface Player : NSManagedObject
@property (nonatomic, retain) NSNumber * experience;
@property (nonatomic, retain) id items;
@property (nonatomic, retain) NSNumber * level;
@end
@interface items : NSValueTransformer
@end
items
is essentially an NSMutableArray
with NSNumber
elements. And inside one function, I'm updating this array:
- (void)itemWasDropped:(ItemIndex)item
{ // _player has been correctly retrieved from the database
// the current number of this item
int nNum = [[_player.items objectAtIndex:item] intValue];
// to increment the number
[_player.items replaceObjectAtIndex:item withObject:[NSNumber numberWithInt:nNum + 1]];
}
This function gets called perfectly. I save the context in the viewWillDisappear
function.
- (void)viewWillDisappear:(BOOL)animated
{ // _moc is an NSManagedObjectContext instance that has been correctly initialised.
// to update the database
NSError* err = nil;
BOOL bSucc = [_moc save:&err];
if (err || !bSucc)
{
...
}
}
The problem is that the updates are visible in other views as long as I do not shut down the app in the task bar. What's the problem? Anyone can help?
Upvotes: 0
Views: 2971
Reputation: 80265
Core data can store arrays, but you will have to use a "transformable" attribute. In general it is not very good design. One easy solution is to transform your numbers array into something that can be stored. For example, in many cases it is sufficient to just use a string.
Encode:
player.items = [numbers componentsJoinedByString:@","];
// Swift
player.items = numbers.joinWithSeparator(",")
Decode:
NSMutableArray* numbers = [NSMutableArray array];
for (NSString *s in [player.items componentsSeparatedByString:@","]) {
[numbers addObject:@([s integerValue])];
}
// Swift
let numbers = player.items.characters.split { $0 == "," } .map { Int($0!) }
Upvotes: 2
Reputation: 29
Just solved it. In order to update an array attribute inside a Core Data entity, that array has to be assigned to another @property
array in the view controller class or, and update the @property
array. Before database updating, the @property
array has to be assigned back to the entity attribute.
// to hold the player items
// _player.items cannot be directly updated
@property (strong, nonatomic) NSMutableArray* items;
- (void)viewDidLoad
{
[super viewDidLoad];
...
NSError* err = nil;
NSMutableArray* results = [[_moc executeFetchRequest:fr error:&err] mutableCopy];
if (err || results.count == 0)
{
...
} else
{
_player = [results objectAtIndex:0];
_items = _player.items;
}
}
// events
- (void)itemWasDropped:(ItemIndex)item
{
// the current number of this item
int nNum = [[_items objectAtIndex:item] intValue];
// to increment the number
[_items replaceObjectAtIndex:item withObject:[NSNumber numberWithInt:nNum + 1]];
}
- (void)viewWillDisappear:(BOOL)animated
{
// to update the database
_player.items = _items;
NSError* err = nil;
BOOL bSucc = [_moc save:&err];
if (err || !bSucc)
{
...
}
}
Upvotes: 0