0

私の最初のViewControllerには、3つの入力フィールドがあり、それぞれがユーザー入力を受け取り、アドレス、ユーザー名、パスワードなどの文字列に保存しますNSUserDefaults。この部分は正常に機能します。2番目のビューコントローラーでは、最初のコントローラーから3つの文字列(アドレス、ユーザー名、パスワード)を取得して、3つの文字列に基づいてhtmlリンクを作成しようとしています。運が悪かったので、3つの文字列にアクセスする方法をたくさん試しましたが、結果はですNULL。これが私のコードです:

//.hファイル-3つの入力フィールドを持つ最初のビューコントローラCamSetup.h

 #import <UIKit/UIKit.h>
 @interface CamSetup : UIViewController <UITextFieldDelegate> 
 {
    NSString * address;
    NSString * username;
    NSString * password;

    IBOutlet UITextField * addressField;
    IBOutlet UITextField * usernameField;
    IBOutlet UITextField * passwordField; 
 }

 -(IBAction) saveAddress: (id) sender;
 -(IBAction) saveUsername: (id) sender;
 -(IBAction) savePassword: (id) sender;

 @property(nonatomic, retain) UITextField *addressField;
 @property(nonatomic, retain) UITextField *usernameField;
 @property(nonatomic, retain) UITextField *passwordField; 
 @property(nonatomic, retain) NSString *address; 
 @property(nonatomic, retain) NSString *username; 
 @property(nonatomic, retain) NSString *password;

 @end

//.mファイル-最初のビューコントローラCamSetup.m

#import "CamSetup.h"

@interface CamSetup ()
@end

@implementation CamSetup
@synthesize addressField, usernameField, passwordField, address, username, password;

-(IBAction) saveAddress: (id) sender
{
address = [[NSString alloc] initWithFormat:addressField.text];
[addressField setText:address];
NSUserDefaults *stringDefaultAddress = [NSUserDefaults standardUserDefaults];
[stringDefaultAddress setObject:address forKey:@"stringKey1"];
NSLog(@"String [%@]", address);
}

-(IBAction) saveUsername: (id) sender
{
  username = [[NSString alloc] initWithFormat:usernameField.text];
  [usernameField setText:username];
  NSUserDefaults *stringDefaultUsername = [NSUserDefaults standardUserDefaults];
  [stringDefaultUsername setObject:username forKey:@"stringKey2"];
  NSLog(@"String [%@]", username);
}

-(IBAction) savePassword: (id) sender
{
  password = [[NSString alloc] initWithFormat:passwordField.text];
  [passwordField setText:password];
  NSUserDefaults *stringDefaultPassword = [NSUserDefaults standardUserDefaults];
  [stringDefaultPassword setObject:password forKey:@"stringKey3"];
  NSLog(@"String [%@]", password);
}

- (void)viewDidLoad
{   
[addressField setText:[[NSUserDefaults standardUserDefaults] objectForKey:@"stringKey1"]];
[usernameField setText:[[NSUserDefaults standardUserDefaults] objectForKey:@"stringKey2"]];
[passwordField setText:[[NSUserDefaults standardUserDefaults] objectForKey:@"stringKey3"]];

[super viewDidLoad];
}

@end

//.h2番目のビューコントローラーLiveView.h

 #import <UIKit/UIKit.h>
 #import "CamSetup.h"
 @interface LiveView : UIViewController
 {
  NSString *theAddress;
  NSString *theUsername;
  NSString *thePassword;
  CamSetup *camsetup; //here is an instance of the first class
}
@property (nonatomic, retain) NSString *theAddress;
@property (nonatomic, retain) NSString *theUsername;
@property (nonatomic, retain) NSString *thePassword;

@end

//.mセカンドビューLiveView.mファイル

#import "LiveView.h"
@interface LiveView ()
@end

@implementation LiveView
@synthesize theAddress, theUsername, thePassword;

- (void)viewDidLoad
{
  [super viewDidLoad]; 
  theUsername = camsetup.username; //this is probably not right?
  NSLog(@"String [%@]", theUsername); //resut here is NULL
  NSLog(@"String [%@]", camsetup.username); //and here NULL as well
}
@end
4

5 に答える 5

2

このコードには5つの問題があります。

  1. ARCを使用している場合は、@propertiesのすべての「保持」を「strong」に変更する必要があります
  2. iVarとプロパティに同じ名前を付けます。(一般的な悪い習慣)
  3. コード内のプロパティではなく、常にiVarに直接アクセスしています。
  4. CamSetupのインスタンスを2番目のオブジェクトに保持しません。
  5. 問題の直接の原因:2番目のオブジェクトでは、CamSetupインスタンスのプレースホルダーのみを作成しましたが、プレースホルダーを作成したり、渡したりしていません。2番目のオブジェクトのself.camSetupは現在空です。

ステップバイステップで行きましょう:

まず、iVarsにプロパティとは異なる名前を付けます。これは、特に初心者にとってはベストプラクティスです。:)

@interface CamSetup : UIViewController <UITextFieldDelegate> 
{
    NSString *_address;
}
@property(nonatomic, strong) NSString *address;
@end

@implementation CamSetup
@synthesize address=_address;
...
@end

プロパティを設定したので、これは重要ですが、コードでは、プロパティを使用しておらず、iVarに直接アクセスしています。同じ名前を付けているので、これが表示されない場合があります。

最初のオブジェクトを見てみましょう。コード内のすべての「アドレス」は、プロパティではなくiVarに送信されます。通常、特に断りのない限り、プロパティを介してiVarにアクセスする必要があります。@synthesizeは、@ propertyステートメントで指示したため、変数を保持するiVarのgetterメソッドとsetterメソッドを作成します。ただし、iVarに直接アクセスする場合は、これらのアクセサーを経由しないため、@propertiesに書き込んだ内容は重要ではありません。これについて明確にしないと、多くのエラーやバグを誤解してしまう可能性があります。最初のオブジェクトでは、alloc / initがオブジェクトに保持を設定するため、これはとにかく機能しましたが、常にこれを行うことに気づきました。これにより、問題が発生します。

プロパティを使用すると、saveAddress:メソッドは次のようになります。

-(IBAction) saveAddress: (id) sender
{
   self.address = [[NSString alloc] initWithFormat:self.addressField.text];
   [self.addressField setText:self.address];
   NSUserDefaults *stringDefaultAddress = [NSUserDefaults standardUserDefaults];
   [stringDefaultAddress setObject:self.address forKey:@"stringKey1"];
   NSLog(@"String [%@]", self.address);
}

次に、2番目のオブジェクトで、CamSetupインスタンスのプロパティを設定する必要があります。今、あなたはただiVarを持っています。

 #import <UIKit/UIKit.h>
 #import "CamSetup.h"
 @interface LiveView : UIViewController
 {
  NSString *_theAddress;
  NSString *_theUsername;
  NSString *_thePassword;
  CamSetup *_camSetup; //here is an instance of the first class
}
@property (nonatomic, retain) CamSetup *camSetup; // in synthesize we'll specify that this property uses the _camSetup iVar
@property (nonatomic, strong) NSString *theAddress;
@property (nonatomic, strong) NSString *theUsername;
@property (nonatomic, strong) NSString *thePassword;

@end

実装:

#import "LiveView.h"
@interface LiveView ()
@end

@implementation LiveView
@synthesize camSetup = _camSetup;
@synthesize theAddress = _theAddress;
@synthesize theUsername = _theUsername;
@synthesize thePassword = _thePassword;

- (void)viewDidLoad
{
  [super viewDidLoad]; 
  self.theUsername = self.camSetup.username; //this is probably not right?
  // well, it's better now, but where is camSetup coming from??? it's undefined now
  NSLog(@"String [%@]", self.theUsername); //resut here is NULL
  NSLog(@"String [%@]", self.camSetup.username); //and here NULL as well
}
@end

CamSetupインスタンスへのポインターを保持し、そのポインターを保持するiVarとプロパティのペアを作成しました(プロパティを使用して設定した場合)。ただし、そのCamSetupインスタンスはどこで作成されていますか?どこに割り当て/初期化しますか?

この質問には多くの可能な答えがあります。CamSetupにアドレス、ユーザー名、パスワードのゲッターがあり、ユーザーのデフォルトからそれらを読み戻す場合は、CamSetupを割り当て/初期化してcamSetupに設定するだけです。ただし、現時点では、最初のオブジェクトには保存されたデータを取得する機能がないため、それを行うことはできません。(それでも、これはあなたが実装したいと思う解決策です)。

アプリデリゲートでこれらの両方を初期化している可能性がありますか?ただし、ストーリーボードを使用している場合は、インターフェイスを初期化するときにこれらのオブジェクトを初期化している可能性があります。この場合、appDelegateアプリの起動が完了しました...メソッドでは、これらのインスタンスへのポインターを取得してから、2番目のオブジェクトのcamSetupプロパティを取得して、最初のオブジェクトを指す必要があります。これを行う方法を説明するには、アプリの詳細を知る必要があります。それでも、これは最善の方法ではありません。

ベストプラクティスは、ユーザーのデフォルトからこれらのデータを保存および取得するオブジェクトを作成することです。この将来は、後でこれらのデータの保存方法を変更したい場合に、実装を保証します。クラス内での保存/取得方法を変更するだけです。

于 2012-11-26T03:06:55.580 に答える
1

あなたの問題はここにあります:

CamSetup *camsetup; //here is an instance of the first class 

ユーザーからの入力を受け取っているクラスの同じインスタンスをcamsetup参照させるために何もしていません。変数は初期化されないため、NULLになります。したがって、変数から取得しようとするプロパティもNULLになります。CamSetupcamsetup

これをどの程度正確に修正するかは、プログラムの構造によって異なります。LiveView1つの可能性は、コントローラーを作成しているコードにcamsetup値を設定させることです。例えば:

LiveView *liveViewController  = [LiveView alloc] initWithNibName:@"LiveView" bundle:nil]];
liveViewController.camsetup = camSetupController;

camsetup(これを行うには、プロパティを作成する必要があります)。

ただし、設計の観点から、一方のビューコントローラにもう一方のビューコントローラへの参照を持たせることは、この問題を解決するための間違った方法である可能性があります。これにより、2つのコントローラ間に不要な依存関係が発生します。たとえばLiveView、保存した名前/パスワードを使用して、プログラムの起動時にコントローラーに直接アクセスできるようにすることを後で決定したとします。オブジェクトLiveViewからの入力の取得に依存している場合は、それを行うことはできません。CamSetup

したがって、より良いアプローチは、LiveViewから入力を取得するNSUserDefaultsか、呼び出しているコードLiveViewにユーザー名/パスワードのプロパティを設定させることです。

- 編集 -

たとえば、次のようなユーザーのデフォルトからデータを取得します。

self.address = [[NSUserDefaults standardUserDefaults] objectForKey:@"stringKey1"];
于 2012-11-26T02:28:24.807 に答える
0

camsetupは初期化されていますか?そうでない場合は、最初に初期化します。

于 2012-11-26T00:54:41.223 に答える
0

これを行うには多くの方法がありますが、そのほとんどは2つのコントローラーが互いにどのように関連しているかに依存します(最初から2番目にどのように進んでいるかなど)。

ただし、あなたの場合、文字列をユーザーのデフォルトで保存しているので、文字列を渡す必要はまったくありません。2番目のコントローラーでこれらのデフォルトの値を読み取るだけです。

于 2012-11-26T01:43:43.397 に答える
0

こんにちは私はあなたの問題を1つだけするようになりました。あなたがそれに値を設定しているとき、それ だけNSUserDefaultsが必要です。synchronizationsynchronize

[stringDefaultUsername synchronize];  

そして、を使用してデータを取得します

NSString *username =  [[NSUserDefaults standardUserDefaults] objectForKey:@"stringKey2"];

詳細については、アップルのNSUserDefaultsクラスリファレンスに従ってください。

于 2012-11-26T11:16:06.263 に答える