-2

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) 
Craig1481
  • 39
  • 4
  • Obviously, the problem, in part, has to do with how the pointer is stored in NewKeywordSummary, yet you do not show us any of that class, so we do not have the foggiest idea what you're doing with the pointer. – Hot Licks Aug 05 '14 at 01:58
  • (String literals in Objective-C -- something like `@"some string"` -- are not dynamically allocated but persist "forever", and hence do not "go poof" when you make an error with reference counting. Strings that come from other sources, however, must be appropriately reference counted (like most other objects) or they can cause errors.) – Hot Licks Aug 05 '14 at 02:01
  • Please see my comments to Bonanza driver... and I am using ARC – Craig1481 Aug 05 '14 at 02:03
  • I didn't ask if you were using ARC. ARC only works if you use it correctly, and you clearly are not. Yet you refuse to show us what you're actually doing. Why? – Hot Licks Aug 05 '14 at 02:06
  • Q#1, what is `newKw` - I suspect something is happening when the `newKeyword` in the view controller you are trying to push on does something with whatever object/memory `newKw` is. Please update your post to include some more information because the code you did post is almost irrelevant – cream-corn Aug 05 '14 at 02:13
  • Code has been added - let me know if you'd like anything else. – Craig1481 Aug 05 '14 at 02:57

2 Answers2

0

Make sure your NSString references are assigned to a @property on your classes (plenty of examples of assigning and using properties on iOS) using an appropriate storage type (strong or retain, for example). And, yes you are correct any "standard" string in an iOS app is usually an instance of NSString, and thus required the "@" symbol in front.

Try setting a break point on Exceptions ... this will help you identify the offending statement.

I would suggest picking up a book on an intro to Objective-C / iOS / iPad development ... I think you'll find the information invaluable and a HUGE time saver.

BonanzaDriver
  • 6,411
  • 5
  • 32
  • 35
  • Here is the generated property... @property (nonatomic, retain) NSString * newKeyword; – Craig1481 Aug 05 '14 at 01:59
  • Here is the log file showing what the variable turns into using NSLog: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) – Craig1481 Aug 05 '14 at 02:03
  • Setting a breakpoint on All Exceptions didn't show anything different for me – Craig1481 Aug 05 '14 at 12:42
0

I believe I have found the answer to my question. I ran into this post:

why can't I declare a variable like "newVariable" in Obj-C?

Quote from the link:"Objective-C has a naming convention for memory management that is enforced by the compiler. Methods that start with new (also "alloc", "copy", "mutableCopy") are required to return an object that will be "owned" by the caller. See the documentation." (thanks progrmr!)

and realized that I had a property that started with "new", and while it wasn't being synthesized it WAS generating setters/getters with @dynamic... so every time the member kwReq.newKeyword was referenced on my managed object, I am guessing that the compiler was trying to change ownership or otherwise alter the retain count - so after a couple times I was out of retains. So I changed the member name to reqKw, and I have no more problem. I was NOT getting any kind of warning on this.(thanks Apple:-)

Community
  • 1
  • 1
Craig1481
  • 39
  • 4