If I pass testString2 to the next view controller (where the string is assigned to a property of a NSManagedObject subclass), the app crashes soon after with a BAD_ACCESS error. I was able to determine the string was turning into a zombie a while after attaching it to the managed object and also assigning it to a class member of the receiving view controller, to try and eliminate this problem. However, it doesn't turn into a zombie until well after it has been assigned as described.
IF, however, I send testString instead of testString2 to the next view controller, no crashes and everything is happy. Incidentally, newKw is text from a text field, but using strings retrieved from a dictionary gives the same result. I have also tried using [NSString stringWithString:newKw] and other NSString methods in an attempt to create a brand new string, and I get the same result then too.
If I send nil instead of sending any string, there are no errors.
The managed object is never lost or corrupted if I pass testString. But if I pass testString2, it appears when the variable turns into a zombie, it takes out the managed object too because everything in the description is gone and is not shown as a fault. Following some other advice I have seen, I set a breakpoint for malloc_error_break, and in my log I see this:
Power Passage(3734,0x2dae1a8) malloc: *** error for object 0x9aa67b0: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Here is where it is passed from the VC where the string originated:
if (proceed) {
NSString *testString = @"testing123";
NSString *testString2 = newKw;
[self.navigationController pushViewController:[[NewKeywordSummary alloc] initWithKeyword:testString2] animated:YES];
Here is the property where the pointer is getting stored in the managed object:
@property (nonatomic, retain) NSString * newKeyword;
Here is the method newKw is being sent to:
-(instancetype)initWithKeyword:(NSString *)kw
{
if (self = [self init]) {
//Create a new request
kwReq = [ppKeywordRequest keywordRequestInContext:editingContext];
newKw = kw;
kwReq.newKeyword = newKw;
}
return self;
}
Then the kwReq object is passed to the next VC:
-(void)viewBtnHandler:(UIButton *)btn
{
if (btn == addNewTagBtn) {
[self.navigationController pushViewController:[[TagSummaryVC alloc] initWithKeywordRequest:kwReq tagSubmission:nil] animated:YES];
}
}
and it goes here:
-(instancetype)initWithKeywordRequest:(ppKeywordRequest *)req tagSubmission:(ppTagSubmission *)t
{
if (self = [super init]) {
delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
user = delegate.user;
phrases = [delegate.languagePhrases objectForKey:@"TagSummaryVC"];
if (req) {
editingContext = req.managedObjectContext;
kwReq = req;
}
else {
editingContext = [[NSManagedObjectContext alloc] init];
[editingContext setPersistentStoreCoordinator:[delegate.localDataContext persistentStoreCoordinator]];
delegate.editingContext = editingContext;
}
if (!t) {
ts = [ppTagSubmission tagSubmissionInContext:editingContext];
newTS = YES;
}
else
ts = (id)[editingContext objectWithID:[t objectID]];
self.navigationItem.backBarButtonItem =
[[UIBarButtonItem alloc] initWithTitle:@""
style:UIBarButtonItemStyleBordered
target:nil
action:nil];
}
return self;
}
And it returns to NewKeywordSummary here:
if (alertView.tag == AttachAlert) {
if (index == 0)
return;
NSString *testString = kwReq.newKeyword;
NSLog([NSString stringWithFormat:@"Test variable is %@", kwReq.newKeyword]);
[kwReq addTagSubmissionsObject:ts];
[self.navigationController popViewControllerAnimated:YES];
}
}
My NSLogs before and after it is a zombie:
2014-08-04 21:00:52.306 Power Passage[3838:60b] Test variable is vcxvzcx
2014-08-04 21:00:53.378 Power Passage[3838:60b] Test variable is vcxvzcx
2014-08-04 21:00:55.908 Power Passage[3838:60b] Test variable is <__NSMallocBlock__: 0x8ea4b00>
(lldb)