-10

さて、これは昨夜私がした質問の延長です。さまざまな手法を使用して、View Controller 間でデータを渡す方法を少ししっかりと把握しています。私は MVC ルートに行きたかったのですが、Singleton クラスの作成は MVC に似た最も近い概念のようです。

基本的に、2 つのビュー コントローラーとシングルトン クラスを備えた単純なアプリを作成しました。テキスト フィールドの値を UILabel に渡そうとしています。何らかの理由で機能していません。これは私のコードがどのように見えるかです。

ViewController.h

#import <UIKit/UIKit.h>
#import "Model.h"
#import "ViewController2.h"

@interface ViewController : UIViewController {

NSString *text2pass;
}

@property (weak, nonatomic) IBOutlet UITextField *tf;
@property (weak, nonatomic) IBOutlet UILabel *btn;
- (IBAction)go:(id)sender;
@end

ViewController.m

 #import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController
@synthesize tf = _tf;
@synthesize btn = _btn;

- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.

NSString *tfstring = _tf.text;
NSLog(@"string = %@",tfstring);
}

 - (void)viewDidUnload
{
[self setTf:nil];
[self setBtn:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
}

- (IBAction)go:(id)sender {
NSLog(@"btn pressed");

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
ViewController2 *vc2 = (ViewController2 *) [storyboard instantiateViewControllerWithIdentifier:@"home"];

text2pass = _tf.text;

[self passValues];

[self presentModalViewController:vc2 animated:YES];
}

-(void) passValues {
Model *model = [Model sharedModel];
model.passedText = text2pass;
}
@end

ViewController2.h

#import <UIKit/UIKit.h>
#import "ViewController.h"

@interface ViewController2 : UIViewController {

NSString *passedText;
}

@property (nonatomic)NSString *passedValue;

@property (weak, nonatomic) IBOutlet UILabel *lbl;

- (IBAction)back:(id)sender;

@end

ViewController2.m

#import "ViewController2.h"

@interface ViewController2 () {
NSString *passedtext;
}
@end
@implementation ViewController2
@synthesize lbl = _lbl;
@synthesize passedValue = _passedValue;
 - (void)viewDidLoad
{

 // do code stuff here
NSLog(@"passedText = %@",passedText);
_lbl.text = passedText;

[super viewDidLoad];
}
- (void)viewDidUnload
{
[self setLbl:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (IBAction)back:(id)sender {

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
ViewController *vc = (ViewController *) [storyboard instantiateViewControllerWithIdentifier:@"welcome"];
[self presentModalViewController:vc animated:YES];
}
@end

Model.h

#import <Foundation/Foundation.h>

@interface Model : NSObject {

NSString *passedText;
}

@property (nonatomic, strong) NSString* passedText;

+ (Model *) sharedModel;

@end

モデル.m

#import "Model.h"

@implementation Model

@synthesize passedText = _passedText;

static Model *sharedModel = nil;

+ (Model *) sharedModel {
@synchronized(self){
    if (sharedModel == nil){
        sharedModel = [[self alloc] init];
    }
}
return sharedModel;
}

@end

プロジェクト全体は、ここからダウンロードできますhttp://chrisrjones.com/files/KegCop-Test.zip

UILabel がテキスト フィールドのテキストを表示しない理由がわかっている場合は、お知らせください。ああ、私はこれをかなりフォローしました-> http://www.youtube.com/watch?v=ZFGgMPcwYjg&feature=plcp

4

2 に答える 2

5

あなたのアドレス指定とメモリ管理は単純です...オフです。まず、このためにシングルトンを作成する理由はまったくありませんが、それはここでは重要ではありません。

第二に、プロパティを宣言するとき、 (atomic, assign) は、特に指定されていない場合、デフォルトで設定されます。これは、文字列を意味します。

@property (nonatomic)NSString *passedValue;

弱いソースであり、すぐに割り当て解除と破壊の準備ができています。copystrong、またはと宣言しretainます。

第三に、プッシュされたView Controllerにはシングルトンへの参照はまったくありませんが、異なるクラスで同じ名前のオブジェクトが値を保持していると信じているようです(特に#importされた場合)。そうではありません。[Model sharedModel].passedTextシングルトンを参照し、そのテキスト フィールドに値をプルする必要があります。

実際、サンプルを 2 行で修正しました。

//ViewController2.m
#import "ViewController2.h"

//actually import the singleton for access later
#import "Model.h"

@interface ViewController2 () {
    NSString *passedtext;
}
@end
@implementation ViewController2
@synthesize lbl = _lbl;
@synthesize passedValue = _passedValue;
- (void)viewDidLoad
{

 // do code stuff here
    NSLog(@"passedText = %@",passedText);
    //actually reference the singleton this time
    _lbl.text = [Model sharedModel].passedText;

    [super viewDidLoad];
}
- (void)viewDidUnload
{
    [self setLbl:nil];
    [super viewDidUnload];
    // Release any retained subviews of the main view.
}
- (IBAction)back:(id)sender {

    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
    ViewController *vc = (ViewController *) [storyboard instantiateViewControllerWithIdentifier:@"welcome"];
    [self presentModalViewController:vc animated:YES];
}
@end

これにより、次のようになります。

コードを修正しました

于 2012-07-10T02:58:12.970 に答える
1

アプリケーションでデータを渡す良い方法としてシングルトンを使用することはお勧めしません。ほとんどのアプリは、この種の中央アクセスが必要ないほどシンプルであり、通常はメンテナンスの悪夢を引き起こします...しかし、シングルトンを使用しているという事実は、コードを機能させるために実際には重要ではないと思います.

ViewController1 のデータにアクセスできると仮定すると、Model のシングルトン インスタンス (よりわかりやすい名前が必要です) を介して、データを作成して表示するときにデータを ViewController2 に渡すだけで済みます。シングルトンの必要性をまったく排除します。

コントローラーを作成したら、必要なデータを設定してから、ビュー コントローラーを提示します。

動作しない理由について: ビュー コントローラーが表示されていますが、正しいデータが表示されていませんか? それとも、実際にコントローラーを提示する問題がありますか? go:ViewController1のアクションにブレークポイントを設定し、期待するデータがテキストフィールドにあり、モデルに正しく入力され、値が ViewController2 のモデルから正しく引き出されることを確認します。

コードの一部を削除しない限り、ViewController1 の Model プロパティを正しく設定しているように見えますが、ViewController2 ではpassedTextモデルからプルするのではなく、ローカルの ivar を参照しています。

別の注意として、提示されたモーダルView Controllerから戻る方法は、通常、最初のコントローラーを再作成してそれを上に提示するのではなく、そのコントローラーを閉じることです。

于 2012-07-10T03:04:11.247 に答える