0

这是我第一次使用这个网站,而且我对 Objective-c 还是很陌生。我确信这是一个简单的问题,但由于某种原因,我遇到了很多问题。该应用程序旨在让用户通过文本字段输入一个字符串,然后它将选择句子的其余部分并显示它。问题似乎是我的 *name 将在键盘方法之后保留并在 changelabel 方法中工作一次。然后,如果我再次按下按钮,调用 changelabel 方法,名称似乎已被释放并使应用程序崩溃。#import #import "Array.h"

@interface RandomBoredViewController : UIViewController {
UILabel *label;
UIButton *button;
UITextField *textField;
Array *array;
NSString *name;
NSString *description;
NSMutableString *whole;
}
@property (nonatomic, retain) IBOutlet UILabel *label;
@property (nonatomic, retain) IBOutlet UIButton *button;
@property (nonatomic, retain) IBOutlet UITextField *textField;
@property (nonatomic, retain) Array *array;
@property (nonatomic, retain) NSString *name;
@property (nonatomic, retain) NSString *description;
@property (nonatomic, retain) NSMutableString *whole;

-(IBAction) keyBoard;
-(IBAction) changeLabel;

@end

和我的.m

#import "RandomBoredViewController.h"

@implementation RandomBoredViewController

@synthesize label;
@synthesize checker;
@synthesize button;
@synthesize textField;
@synthesize array;
@synthesize name;
@synthesize description;
@synthesize whole;


-(IBAction) changeLabel {
NSLog(@"Button being pushed");
description = [array getString];
NSLog(@"%@",description);
NSLog(@"%@",name);
name = [NSString stringWithString:name];
whole = [NSMutableString stringWithString:name];
NSLog(@"%@",name);
NSLog(@"%@",whole);
[whole appendString:description];
NSLog(@"%@",name);
NSLog(@"%@",whole);
label.text = whole;
NSLog(@"%@",name);
}

-(IBAction) keyBoard {
name = [NSString stringWithString:textField.text];
NSLog(@"%@",name);
label.text = [NSString stringWithString: name];
[textField resignFirstResponder];
}

- (void)viewDidLoad {
[super viewDidLoad];
array = [[Array alloc]init];
[array createArray];
NSLog(@"%i",[array arrayCount]);
whole = [[NSMutableString alloc]init];
name = [[NSString alloc]init];
}

- (void)dealloc {
[super dealloc];
[label release];
[button release];
[textField release];
[array release];
//[name release];
[description release];
}

@end
4

4 回答 4

3

您将 name 设置为 NSString 的自动发布实例,这可能是导致您的应用程序崩溃的原因。

利用

self.name = [NSString stringWithString:textField.text];

您合成的 mutator 将保留 NSString 并阻止它被释放。

于 2012-06-25T18:39:58.977 回答
1

以一个缩影为例,您发布的代码创建了两个命名的东西name——一个实例变量和一个属性。

实例变量是直接访问的存储。他们没有行为。

属性是通过 getter 和 setter 访问的命名属性。所以他们可能有任意行为。它们可以报告实例变量的值或从实例变量计算的值或通过任何其他方式计算或获得的值。相关地,设置者可以retainassign以任何其他方式行事。

实例变量只能被它们所属的类的实例访问。属性通常旨在供任何人访问。

由于保留是一种行为,并且您已将其归因于您的name属性,因此对其进行设置将导致retain. 实例变量不能有行为,因此为其设置值不会导致 aretain或其他任何结果。

结果,这一行:

name = [NSString stringWithString:name];

创建一个新字符串并返回一个非拥有引用。这意味着它肯定会在此自动释放池的持续时间内持续存在(即,假设您没有手动控制自动释放池,您可以明确地将其作为参数传递或安全返回)。

您将该引用存储到您的实例变量。实例变量没有行为,因此存储了引用,但您仍然不拥有该对象。它仍然只在该自动释放池期间使用是安全的。

因此,当您以该方法访问它时,它是安全的。当您稍后访问它时,它是不安全的。

相反,如果您选择了:

self.name = [NSString stringWithString:name];

然后您将该字符串设置为该属性的新值。因为您的属性具有该retain行为,所以您随后可以完全安全地访问字符串对象,除非您另有说明。

因为您有一个与实例变量同名的属性,所以您随后可以将其作为 justname或 as访问self.name。同样,如果您确保手动拥有拥有引用,您可以直接存储到实例变量而不是通过属性。

如上所述,使用 ARC 是一种让编译器为您解决所有这些问题的方法。

这个问题是导致你的代码崩溃的原因——你最终试图访问一个不再有效的引用。如果您拥有它,那么至少只要您保留所有权,它就会继续存在。

于 2012-06-25T18:49:47.340 回答
0

尝试使用 self.name 有时这些东西也会让我感到困惑,因此您可能需要考虑使用 arc,在这种情况下,大多数这些东西都可以避免。

使用属性时,您应该始终使用 self.propertyName vs propertyName(仅),它使用访问器(get propertyName,set propertyName)而不是直接访问该指针值。

请记住,该规则有 2 个例外,init 和 dealloc 不应使用 self。

self.name = [NSString stringWithString:name];

从技术上讲,你还应该有一个 init 方法来初始化你的变量,我相信你应该在你的 dealloc 方法中最后调用 [super dealloc] 而不是第一个,但这不是你的问题,可能并不重要(当我不使用 arc 时我会做什么)

于 2012-06-25T18:37:43.347 回答
0

当您在 中更改您的实例变量时changeLabel,您应该释放以前的值并保留新的值。您可以使用访问器为您执行内存管理工作。另外,我认为您应该[super dealloc] dealloc.

如果您不熟悉 Cocoa 内存管理(即使您熟悉),最好启用 ARC(自动引用计数)并让编译器处理它。

于 2012-06-25T18:41:43.203 回答