Objective-c noob here. I'm experiencing a EXC_BAD_ACCESS
error in my tests and can't figure out why. I've written a Cart
class for my application representing a user's cart. A Cart
can have multiple Order
s, stored in an array. I'm attempting to implement KVO compliance for the Order
s array with the given code (Apologies for the long code snippet, want to make sure everything is present to resolve the problem). The .h
file:
#import "Model.h"
@class Item;
@class Organization;
@class Order;
@interface Cart : NSObject
@property (copy, readonly, nonatomic) NSArray *orders;
- (instancetype) init __attribute__((unavailable("init not available. Use `sharedCart`.")));
+ (instancetype)sharedCart;
- (void)setItem:(Item *)item withQuantity:(NSNumber *)quantity;
- (void)removeItem:(Item *)item;
- (NSNumber *)itemCount;
- (Order *)orderForSeller:(Organization *)seller;
@end
And the .m
:
@interface Cart()
- (void)addOrder:(Order *)order;
- (void)removeOrder:(Order *)order;
@property (copy, readwrite, nonatomic) NSArray *orders;
@end
NSString * const ordersKey = @"orders";
@implementation Cart
{
NSMutableArray *_orders;
}
@synthesize orders = _orders;
+ (instancetype)sharedCart {
static dispatch_once_t onceToken;
static Cart *cart;
dispatch_once(&onceToken, ^{
cart = [[Cart alloc] initPrivate];
});
return cart;
}
- (void)insertObject:(Order *)order inOrdersAtIndex:(NSUInteger)index {
[_orders insertObject:order atIndex:index];
}
- (void)removeObjectFromOrdersAtIndex:(NSUInteger)index {
[_orders removeObjectAtIndex:index];
}
- (void)setOrders:(NSArray *)array {
if (array != _orders) {
_orders = [array mutableCopy];
}
}
- (instancetype)initPrivate {
self = [super init];
if (self) {
self = [super init];
_orders = [[NSMutableArray alloc] init];
}
return self;
}
+ (instancetype)object {
@throw [NSException exceptionWithName:NSInternalInconsistencyException reason:@"Can not create new Cart instance. Used [Cart sharedCart]" userInfo:nil];
}
-(Order *)orderForSeller:(Organization *)seller {
for (Order *order in self.orders) {
if ([order.seller is:seller]) {
return order;
}
}
return nil;
}
- (void)setItem:(Item *)item withQuantity:(NSNumber *)quantity {
Order *order = [self orderForSeller:item.seller];
if (!order) {
order = [Order object];
order.seller = item.seller;
order.user = [User currentUser];
[self addOrder:order];
}
[order setItem:item withQuantity:quantity];
}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
// If an order is ever empty, remove it from cart.
if ([object isKindOfClass:[Order class]] && [keyPath isEqualToString:@"orderItems"]) {
Order *order = (Order *)object;
if ([[order itemCount] integerValue] == 0) {
[self removeOrder:order];
}
}
// When orders are saved, remove them from cart.
if ([object isKindOfClass:[Order class]] && [keyPath isEqualToString:@"isNew"]) {
Order *order = (Order *)object;
BOOL orderHasBeenPlaced = ![order isNew];
if (orderHasBeenPlaced) {
[self removeOrder:order];
}
}
}
- (void)addOrder:(Order *)order {
[order addObserver:self forKeyPath:@"orderItems" options:NSKeyValueObservingOptionNew context:nil];
[order addObserver:self forKeyPath:@"isNew" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
[self insertObject:order inOrdersAtIndex:[_orders count]];
}
-(void)removeOrder:(Order *)order {
[order removeObserver:self forKeyPath:@"orderItems"];
[order removeObserver:self forKeyPath:@"isNew"];
NSUInteger index = [_orders indexOfObject:order];
[self removeObjectFromOrdersAtIndex:index];
}
-(void)removeItem:(Item *)item {
Order *order = [self orderForSeller:item.seller];
if (order) {
[order removeItem:item];
}
}
-(NSNumber *)itemCount {
return [self.orders valueForKeyPath:@"@sum.itemCount"];
}
- (void)dealloc {
for (Order *order in self.orders) {
[order removeObserver:self forKeyPath:@"isNew"];
[order removeObserver:self forKeyPath:@"orderItems"];
}
}
@end
The addOrder:
method is producing the EXC_BAD_ACCESS
exception on this line:
[self insertObject:order inOrdersAtIndex:[_orders count]];
Debugging, the _orders
array is a valid NSMutableArray
. Anyone have any idea what's going on? Much appreciated.
`