BAD_ACCESS崩溃,除非我用@创建一个字符串 - 使用ARC

时间:2014-08-05 01:39:56

标签: objective-c ios7

如果我将testString2传递给下一个视图控制器(其中字符串被分配给NSManagedObject子类的属性),应用程序很快崩溃并出现BAD_ACCESS错误。我能够确定字符串在将其附加到托管对象并将其分配给接收视图控制器的类成员后一段时间变成僵尸,以尝试消除此问题。然而,在按照所描述的方式分配僵尸之前,它不会变成僵尸。

但是,如果我将testString而不是testString2发送到下一个视图控制器,没有崩溃,一切都很开心。顺便提一下,newKw是文本字段中的文本,但使用从字典中检索的字符串会产生相同的结果。我也尝试使用[NSString stringWithString:newKw]和其他NSString方法来尝试创建一个全新的字符串,我也得到了相同的结果。

如果我发送nil而不是发送任何字符串,则没有错误。

如果我传递testString,托管对象永远不会丢失或损坏。但是,如果我传递testString2,它会在变量变成僵尸时出现,它也会取出托管对象,因为描述中的所有内容都已消失,并且未显示为故障。根据我看到的一些其他建议,我为malloc_error_break设置了断点,在我的日志中我看到了:

Power Passage(3734,0x2dae1a8) malloc: *** error for object 0x9aa67b0: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug

这是从源自字符串的VC传递的位置:

if (proceed) {
            NSString *testString = @"testing123";
            NSString *testString2 = newKw;
            [self.navigationController pushViewController:[[NewKeywordSummary alloc] initWithKeyword:testString2] animated:YES];

以下是指针存储在托管对象中的属性:

@property (nonatomic, retain) NSString * newKeyword;

以下是newKw发送到的方法:

-(instancetype)initWithKeyword:(NSString *)kw
{
    if (self = [self init]) {
        //Create a new request
        kwReq = [ppKeywordRequest keywordRequestInContext:editingContext];
        newKw = kw;
        kwReq.newKeyword = newKw;

    }

    return self;
}

然后将kwReq对象传递给下一个VC:

-(void)viewBtnHandler:(UIButton *)btn
{
    if (btn == addNewTagBtn) {

        [self.navigationController pushViewController:[[TagSummaryVC alloc] initWithKeywordRequest:kwReq tagSubmission:nil] animated:YES];
    }
}

它就在这里:

-(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;
}

它返回到NewKeywordSummary:

  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];
    }
}

我的NSLogs之前和之后都是一个僵尸:

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) 

2 个答案:

答案 0 :(得分:0)

确保使用适当的存储类型(例如,强或保留)将NSString引用分配给类上的@property(在iOS上分配和使用属性的大量示例)。并且,是的,你是正确的iOS应用程序中的任何“标准”字符串通常是NSString的一个实例,因此需要前面的“@”符号。

尝试在例外情况下设置一个断点...这将有助于您识别有问题的陈述。

我建议拿一本关于Objective-C / iOS / iPad开发的介绍...我认为你会发现这些信息非常宝贵而且节省了大量时间。

答案 1 :(得分:0)

我相信我找到了问题的答案。我遇到了这篇文章:

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

来自链接的引用:&#34; Objective-C有一个由编译器强制执行的内存管理命名约定。以new开头的方法(也包括&#34; alloc&#34;,&#34; copy&#34;,&#34; mutableCopy&#34;)需要返回一个将拥有&#34;拥有的对象&#34 ;由来电者。请参阅文档。&#34; (谢谢progrmr!)

并意识到我有一个以&#34; new&#34;开头的属性,虽然它没有被合成,但它使用@dynamic生成setter / getter ...所以每次成员kwReq .newKeyword在我的托管对象上被引用,我猜测编译器试图更改所有权或以其他方式更改保留计数 - 所以几次我没有保留。所以我将成员名称更改为reqKw,我没有更多问题。我没有收到任何警告。(感谢Apple: - )