6

私はAppleだけでなく他の人からの例をたどろうとしています。道に迷いました。

ユーザーのログインを処理するために使用するシングルトンクラスがあります(Webサーバーへのチャレンジなど)。

呼び出すことができるブロックを作成し、ユーザー名/パスワードを渡します。ブロックはWebサービス呼び出しを実行し、成功したかどうかにかかわらず戻ります。

これは私がこれまでに何とか仕事をすることができたものです:

私のシングルトンクラスは次のようになります。

.h

typedef void (^AMLoginBlock)(NSString *userName, NSString *password);

@interface AuthManager : NSObject
+ (id)sharedManager;

+ (bool)loginUserWithBlock:(AMLoginBlock)block;

@end

.m

@implementation AuthManager

+ (id)sharedManager
{
    static dispatch_once_t pred = 0;
    __strong static id _sharedObject = nil;
    dispatch_once(&pred, ^{
        _sharedObject = [[self alloc] init]; // or some other init method
    });
    return _sharedObject;
}

+ (bool)loginUserWithBlock:(AMLoginBlock)block {
    NSLog(@"im printing from AM");
    return true;
}

@end

次に、次のようにメソッドを呼び出します。

bool rtn = [AuthManager loginUserWithBlock:^(NSString *userName, NSString *password) {
        NSLog(@"im here in the block LVC.");
    }];

私の質問は3つの部分です:

  1. ブロックと同様に、ブロックの完了ハンドラーを作成するにはどうすればよいですかUIView animation...

  2. ブロックベースの実装からこれらのWebサービス呼び出しを実行することは良い考えですか?

  3. 次のようにブロックメソッドを宣言する必要があります。

    - (bool)loginUserWithBlock:(AMLoginBlock)block;

+(bool)loginUser..シングルトンクラスであるため、使用する代わりに。これにより、シングルトンの複数のインスタンスが作成されるかどうかはわかりません。

私の目標は、あなたが呼ぶようにこのブロックを呼び出すことができるようにすることです[UIView animation..]。だから私は簡単に行うことができます:

[AuthManager loginUserWithUsername:foo
                          password:bar1
                        completion:^(BOOL finished) {
                            if (finished)
                                //push new view controller.
                            else
                                //spit out error
                   }];
4

1 に答える 1

6

完了ハンドラ

完了ブロックをクラス iVar にコピーします。

@property (nonatomic, copy) void (^completionHandler)(bool *);

ブロックを保存しているため、非クラス メソッドにブロックを取得させる必要があります (シングルトンに違反せずにこれを行う方法については、以下を参照してください)。メソッドの例は次のとおりです。

- (void)loginUserWithUsername:(NSString *)username 
                     password:(NSString *)password 
                   completion:(void(^)(bool *finished))completionBlock
{
    // Copy the blocks to use later
    self.completionHandler = completionBlock;

    // Run code
    [self doOtherThings];
}

次に、ログイン コードが作業を終了したら、ブロックを呼び出すことができます。ここでは、ブロックに self.error, a を渡しboolます。

- (void)finishThingsUp
{
    // We are done with all that hard work. Lets call the block!
    self.completionHandler(self.error);

    // Clean up the blocks
    self.completionHandler = nil;
}

良いアイデア

これは哲学的な質問ですが、こう言いたいと思います。Objective-C のブロックを使用すると、単一のタスクを実行するコードを記述して、それを多くのプログラムに簡単に統合できます。ログイン コードで完了ハンドラを使用しないことを選択した場合は、次の操作を行うためにログイン コードが必要になります。

  • それを使用するクラスがプロトコルを実装することを要求する (のようにLoginDelegate)
  • キー値の監視や通知など、コードに通知する他のシステムを使用します
  • 1 つのタイプの呼び出しクラスでのみ機能するようにハードコーディングする

上記のアプローチはどれも問題ありません。ブロックベースのコールバック システムが最もシンプルで柔軟だと思います。追加のインフラストラクチャ (通知の設定、プロトコルへの準拠など)​​ を気にせずにクラスを使用することができ、他のクラスやプログラムで再利用することもできます。

シンゲルトン

Objective-Cで a で始まるメソッド+はクラス メソッドです。クラス メソッドを使用して iVar を操作することはできません。誰がそのデータを所有するのでしょうか?

できることは、そのクラスの同じインスタンスを常に返すクラスメソッドを使用することです。これにより、データを所有できるオブジェクトを持つことができますが、複数のオブジェクトを持つことは避けてください。

この優れたスタック オーバーフローの回答には、サンプル コードがあります

幸運を!

于 2013-01-11T16:07:37.180 に答える