I found the reason for the unusual crash. My message object as using a property type of assign for NSString properties. It needed to be copy. Spent way to long tracking that one down.
NSObject(RACKVOWrapper) rac_observeKeyPath:options:observer:block: EXC_BAD_ACCESS Crash
-
18-10-2022 - |
Question
I am using ReactiveCocoa to keep a UICollectionView up to date with a list of messages. I am having a crash when trying to update my collection view after my model receives new messages.
Here is my view model, that gets updates via a delegate call from a socket client.
@interface ConversationViewModel : NSObject
@property (nonatomic, strong) NSMutableArray *messages;
- (RACSignal *)rac_signalForMessageReceived;
@end
@implementation ConversationViewModel
....
- (void)client:(PSClient *)theClient didReceiveMessage:(PSMessage *)aMessage {
[self.messages addObject:aMessage];
[_messageReceivedSubscriber sendNext:nil];
}
....
- (RACSignal *)rac_signalForMessageReceived {
RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
self.messageReceivedSubscriber = subscriber;
return [RACDisposable disposableWithBlock:^{
self.messageReceivedSubscriber = nil;
// Do Nothing
}];
}];
[signal setName:@"rac_signalForMessageReceived"];
return signal;
}
And the message object is
@interface Message : NSObject
@property (nonatomic, assign) NSString *message;
@property (nonatomic, assign) NSString *name;
@end
And here is how the controller uses it.
- (void)viewDidLoad
[super viewDidLoad];
[self.conversationViewModel.rac_signalForMessageReceived subscribeNext:^(PSMessage *message) {
[self.collectionView reloadData];
}];
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return [self.conversationViewModel.messages count];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
PSConversationMessageCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"conversationCell" forIndexPath:indexPath];
[cell setMessage:self.conversationViewModel.messages[indexPath.row]];
return cell;
}
And finally, here is how I am doing the binding inside the cell.
- (void)awakeFromNib {
RAC(self.messageLabel, text) = RACObserve(self, message.message);
RAC(self.nameLabel, text) = RACObserve(self, message.name);
}
As soon as the collection view reloads, I get an exception in rac_observeKeyPath:options:observer:block:. The stack is seen below in the screen shot.
Does anyone know why this is causing an exception? Or a better way to handle receiving the message in the ConversationViewModel?
Solution
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow