0

このサイトを使用するのはこれが初めてで、Objective-cはまったく初めてです。これは簡単な質問だと思いますが、どういうわけか私は多くの問題を抱えています。このアプリは、ユーザーがテキストフィールドから文字列を入力できるように設計されており、文の残りの部分を選択して表示します。問題は、私の* nameがkeyboardメソッドの後に保持され、changelabelメソッドで1回機能することです。次に、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

NSStringの自動リリースされたインスタンスに名前を設定しています。これが、アプリのクラッシュの原因である可能性があります。

使用する

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

合成されたミューテーターはNSStringを保持し、解放されないようにします。

于 2012-06-25T18:39:58.977 に答える
1

microcosmで1つのことを取り上げると、投稿したコードはname、インスタンス変数とプロパティという2つの名前の付いたものを作成します。

インスタンス変数は、ストレージに直接アクセスされます。彼らには行動がありません。

プロパティは、ゲッターとセッターを介してアクセスされる名前付き属性です。したがって、彼らは恣意的な振る舞いをするかもしれません。それらは、インスタンス変数の値、インスタンス変数から計算された値、または他の手段によって計算または取得された値を報告する場合があります。関連して、セッターは他の方法で行動するretain可能性があります。assign

インスタンス変数には、それらが属するクラスのインスタンスからのみアクセスできます。プロパティは通常、誰でもアクセスできるようになっています。

保持は動作であり、あなたはそれをあなたのname財産に帰したので、それに何かを設定すると、結果になりretainます。インスタンス変数は動作を持たないため、値を設定しても、retainまたは他の結果にはなりません。

結果として、この行は次のようになります。

name = [NSString stringWithString:name];

新しい文字列を作成し、所有していない参照を返します。つまり、この自動解放プールの期間中は間違いなく持続します(つまり、自動解放プールを手動で制御していない場合は、明示的に引数として渡すか、安全に返すことができます)。

その参照をインスタンス変数に格納します。インスタンス変数には動作がないため、参照は保存されますが、そのオブジェクトを所有していません。それでも、その自動解放プールの期間中のみ使用するのが安全です。

したがって、その方法でアクセスする場合は安全です。後でアクセスするときは安全ではありません。

代わりにあなたが行った場合:

self.name = [NSString stringWithString:name];

次に、その文字列をプロパティの新しい値に設定します。プロパティにはretain動作があるため、特に指定しない限り、その後は文字列オブジェクトに完全に安全にアクセスできます。

nameインスタンス変数とまったく同じ名前のプロパティがあるため、後で同じように、またはとしてアクセスできますself.name。同様に、所有する参照が手動であることを確認した場合は、プロパティを介してではなく、インスタンス変数に直接格納することもできます。

上で示唆したように、ARCの使用は、コンパイラーにこれらすべてのものを理解させる方法です。

その問題がコードのクラッシュの原因になります—有効でなくなった参照にアクセスしようとすることになります。あなたがそれの所有権を取得した場合、少なくともあなたが所有権を保持している限り、それは存在し続けたでしょう。

于 2012-06-25T18:49:47.340 に答える
0

self.nameを使用してみてください。このようなもので混乱することもあります。そのため、arcの使用を検討することをお勧めします。その場合、このようなもののほとんどを回避できます。

プロパティを使用するときは、常にself.propertyNameとpropertyName(のみ)を使用する必要があります。ポインターの値に直接アクセスするのではなく、アクセサー(get propertyName、set propertyName)を使用します。

ルールには、selfを使用してはならないinitとdeallocの2つの例外があることに注意してください。

self.name = [NSString stringWithString:name];

技術的には、変数を初期化するためのinitメソッドも必要です。また、deallocメソッドの最初ではなく、最後に[superdealloc]を呼び出す必要があると思いますが、それは問題ではなく、問題ではない可能性があります(arcを使用しない場合はどうすればよいですか)。 )。

于 2012-06-25T18:37:43.347 に答える
0

でインスタンス変数を変更するときはchangeLabel、前の値を解放して新しい値を保持する必要があります。アクセサを使用して、メモリ管理を実行できます。また、の実装でインスタンス変数を解放した[super dealloc] に呼び出す必要があると思いますdealloc

Cocoaのメモリ管理に慣れていない場合(そして慣れている場合でも)、ARC(自動参照カウント)を有効にして、コンパイラに処理させるのが最善です。

于 2012-06-25T18:41:43.203 に答える