类变量可在一个函数的末尾访问,并在下一个开始时访问时崩溃

时间:2022-04-26 21:31:49

(programming in iPhone objective-C)

(在iPhone目标-C编程)

I have a class level NSString* that I create, add property(nonatomic,retain) and synthesize code for and I can modify the string endlessly with stringByAppendingString functions and display the string using NSLog just fine. All of this is done in a subclass, overridden viewDidLoad function. When I try to access the same variable from the cellForRowAtIndexPath function when determining what to display in the cell of a tableView, the program crashes. Anyone have any clues?

我有一个类级NSString *我创建,添加属性(非原子,保留)和合成代码,我可以使用stringByAppendingString函数无限地修改字符串,并使用NSLog显示字符串就好了。所有这些都是在子类中完成的,重写了viewDidLoad函数。当我在确定在tableView的单元格中显示什么时尝试从cellForRowAtIndexPath函数访问相同的变量时,程序崩溃。有人有任何线索吗?

Related Code:

@interface InfoViewController : UITableViewController {
    NSString *shipAddr;
}
@property (nonatomic,retain) NSString *shipAddr;

@synthesize shipAddr;

VIEWDIDLOAD:

shipAddr = [[[NSString alloc] initWithString:@""] retain];

**CRASHES HERE:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSLog(shipAddr);

**

4 个解决方案

#1


You're actually double-retaining the original string, which leaks it, but that's not the cause of your crash.

你实际上是双重保留原来的字符串,这会泄漏它,但这不是导致崩溃的原因。

You're crashing because stringByAppendingString: returns an autoreleased string. So it doesn't matter how many times you retain the original; every time you call stringByAppendingString: (or any of the other stringByWhatever methods) you get a new string that has a limited lifetime.

你崩溃是因为stringByAppendingString:返回一个自动释放的字符串。因此保留原件的次数并不重要;每次调用stringByAppendingString :(或任何其他stringByWhatever方法)时,您都会获得一个具有有限生命周期的新字符串。

For your code, I would suggest simply always assigning to self.shipAddr, and just assigning @"" to the string to begin with. The self.shipAddr version will handle memory management for you automatically.

对于你的代码,我建议简单地总是分配给self.shipAddr,并且只是将@“”分配给字符串开头。 self.shipAddr版本将自动为您处理内存管理。

#2


Try putting an NSLog statement at the beginning of your viewDidLoad and tableView:cellForRowAtIndexPath: methods. If the latter is running first, then it'll try to access the variable before it's been created.

尝试在viewDidLoad和tableView:cellForRowAtIndexPath:方法的开头放置一个NSLog语句。如果后者首先运行,那么它将在创建之前尝试访问该变量。

If you know what shipAddr should be early enough, I'd put the initialization in your init method.

如果你知道shipAddr应该足够早,我会在初始化方法中进行初始化。

#3


I assume you do realize that the @synthesize statement goes in the implementation file and not the header.

我假设你确实意识到@synthesize语句进入实现文件而不是标题。

Also in viewDidLoad, if you must do that, I think you can just do:

同样在viewDidLoad中,如果你必须这样做,我认为你可以这样做:

self.shipAddr = @"";

Since the property is already defined to retain the passed argument.

由于已定义属性以保留传递的参数。

One last thing I notice is that, I believe the call to NSLog should be like so:

我注意到的最后一件事是,我相信对NSLog的调用应该是这样的:

NSLog(@"%@", shipAddr);

The function's format is like so: void NSLog(NSString *format, ...);

函数的格式如下:void NSLog(NSString * format,...);

And yes, as Brent mentioned, because stringByAppendingFormat returns an auto-released string, it probably 'disappears' before you can ever see it in your other method. So you should use this:

是的,正如Brent所提到的,因为stringByAppendingFormat返回一个自动释放的字符串,它可能会“消失”,然后才能在其他方法中看到它。所以你应该使用这个:

self.shipAddr = [shipAddr stringByAppendingFormat: blah blah];

Since this uses the property for shipAddr, which, as you defined, retains the passed argument and takes care of the problem.

因为它使用了shipAddr的属性,正如您所定义的那样,它保留传递的参数并处理问题。

#4


Are you sure that viewDidLoad is called before tableView:cellForRowAtIndexPath:? It sounds like the string is either uninitialized or released when you reference it within that function. Given that you're allocing and retaining the string in viewDidLoad (you actually don't need a retain there), I'd say it hasn't been initialized yet!

你确定在tableView之前调用了viewDidLoad:cellForRowAtIndexPath :?听起来这个字符串要么未初始化,要么在该函数中引用时释放。鉴于你在viewDidLoad中分配和保留字符串(你实际上不需要保留),我会说它还没有被初始化!

#1


You're actually double-retaining the original string, which leaks it, but that's not the cause of your crash.

你实际上是双重保留原来的字符串,这会泄漏它,但这不是导致崩溃的原因。

You're crashing because stringByAppendingString: returns an autoreleased string. So it doesn't matter how many times you retain the original; every time you call stringByAppendingString: (or any of the other stringByWhatever methods) you get a new string that has a limited lifetime.

你崩溃是因为stringByAppendingString:返回一个自动释放的字符串。因此保留原件的次数并不重要;每次调用stringByAppendingString :(或任何其他stringByWhatever方法)时,您都会获得一个具有有限生命周期的新字符串。

For your code, I would suggest simply always assigning to self.shipAddr, and just assigning @"" to the string to begin with. The self.shipAddr version will handle memory management for you automatically.

对于你的代码,我建议简单地总是分配给self.shipAddr,并且只是将@“”分配给字符串开头。 self.shipAddr版本将自动为您处理内存管理。

#2


Try putting an NSLog statement at the beginning of your viewDidLoad and tableView:cellForRowAtIndexPath: methods. If the latter is running first, then it'll try to access the variable before it's been created.

尝试在viewDidLoad和tableView:cellForRowAtIndexPath:方法的开头放置一个NSLog语句。如果后者首先运行,那么它将在创建之前尝试访问该变量。

If you know what shipAddr should be early enough, I'd put the initialization in your init method.

如果你知道shipAddr应该足够早,我会在初始化方法中进行初始化。

#3


I assume you do realize that the @synthesize statement goes in the implementation file and not the header.

我假设你确实意识到@synthesize语句进入实现文件而不是标题。

Also in viewDidLoad, if you must do that, I think you can just do:

同样在viewDidLoad中,如果你必须这样做,我认为你可以这样做:

self.shipAddr = @"";

Since the property is already defined to retain the passed argument.

由于已定义属性以保留传递的参数。

One last thing I notice is that, I believe the call to NSLog should be like so:

我注意到的最后一件事是,我相信对NSLog的调用应该是这样的:

NSLog(@"%@", shipAddr);

The function's format is like so: void NSLog(NSString *format, ...);

函数的格式如下:void NSLog(NSString * format,...);

And yes, as Brent mentioned, because stringByAppendingFormat returns an auto-released string, it probably 'disappears' before you can ever see it in your other method. So you should use this:

是的,正如Brent所提到的,因为stringByAppendingFormat返回一个自动释放的字符串,它可能会“消失”,然后才能在其他方法中看到它。所以你应该使用这个:

self.shipAddr = [shipAddr stringByAppendingFormat: blah blah];

Since this uses the property for shipAddr, which, as you defined, retains the passed argument and takes care of the problem.

因为它使用了shipAddr的属性,正如您所定义的那样,它保留传递的参数并处理问题。

#4


Are you sure that viewDidLoad is called before tableView:cellForRowAtIndexPath:? It sounds like the string is either uninitialized or released when you reference it within that function. Given that you're allocing and retaining the string in viewDidLoad (you actually don't need a retain there), I'd say it hasn't been initialized yet!

你确定在tableView之前调用了viewDidLoad:cellForRowAtIndexPath :?听起来这个字符串要么未初始化,要么在该函数中引用时释放。鉴于你在viewDidLoad中分配和保留字符串(你实际上不需要保留),我会说它还没有被初始化!