iOS blockアプリケーションのチェーンプログラミングと関数プログラミング

4167 ワード

1.背景
プロジェクトの必要性のため、アンドロイド実装はチェーン呼び出しであり、コードは直感的に見えると同時に、コード言語のスタイルをできるだけ一致させるためでもある.私も以前OC blockチェーン呼び出しに触れたことがありますが、チェーン呼び出しが可能であることを確定することができ、最後にOCのメソッド呼び出しもJavaのような点文法チェーン呼び出しに改造することにしました.
2.チェーンプログラミング
2.1一般青年の方法呼び出し
OCを例にとると、呼び出し方法の一般的な文式は以下の通りである.
[self getCode];

2.2文芸青年のチェーンコール
swift
普通の青年の呼び出し方法を紹介しましたが、文芸青年なら、もっと優雅な方法を追求しなければなりません.まずswiftを例にとると、以下のようになります.
class A {
        fileprivate var successClosure: (() -> Void)?
        fileprivate var errorClosure: ((_ err: NSError) -> Void)?
        
        func success(_ closure: @escaping () -> Void) -> Self {
            successClosure = closure
            return self
        }
        
        func error(_ closure: @escaping (_ err: NSError) -> Void) -> A {
            errorClosure = closure
            return self
        }
        
        func request(url: String) -> A {
            print("    \(url)    ")
            ///    ,          , 
            DispatchQueue.global().asyncAfter(deadline: DispatchTime.now() + DispatchTimeInterval.seconds(2)) {
                self.successClosure?()
            }
            
            DispatchQueue.global().asyncAfter(deadline: DispatchTime.now() + DispatchTimeInterval.seconds(4)) {
                self.errorClosure?(NSError(domain: "      ", code: 1, userInfo: nil))
            }
            return self
        }
    }


使用するとこうなります
let a = A().request(url: "http://  .com").success {
                print("   ,,")
            }.error { (err) in
                print("   。。。。\(err.domain)")
            }

Objective-C
a.パラメータなし+チェーンコール
Person.h:

- (Person * (^)())eat4;
- (Person * (^)())sleep4;

Person.m:

- (Person *(^)())eat4
{
    Person * (^eat4Block)() = ^ {
        NSLog(@"%s",__FUNCTION__);
        return self;
    };
    return eat4Block;
}
//        
- (Person *(^)())sleep4
{
    return ^ {
        NSLog(@"%s",__FUNCTION__);
        return self;
    };
}

ViewController.m:

person.eat4().sleep4();
person.sleep4().eat4();

チェーン呼び出しは、メソッドを現在のクラスの独自のインスタンスに戻すことです.self/this、これで「.」を続けることができます.次のメソッドを呼び出します.
b.パラメータなし+関数呼び出し
関数呼び出しだけで簡単であれば、block内部でreturn selfをキャンセルし、selfインスタンスを渡さないと、再びポイント構文で呼び出されません.
Person.h:

- (void (^)())eat3;
- (void (^)())sleep3;

Person.m:

- (void (^)())eat3
{
    //  block
    void (^eat3Block)() = ^ {
        NSLog(@"%s",__FUNCTION__);
    };
    return eatBlock;
}
- (void (^)())sleep3
{
    return ^ {
        NSLog(@"%s",__FUNCTION__);
    };;
}

ViewController.m:

person.eat3();
person.sleep3();

c.関数式+パラメータ付きチェーン呼び出しの場合は、次のようになります.
Person.h:

- (Person * (^)(NSString *foodName))eat5;
- (Person * (^)(NSInteger hour))sleep5;

Person.m:

- (Person *(^)(NSString *))eat5
{
    Person * (^eat5Block)() = ^(NSString *foodName) {
        NSLog(@" : %@",foodName);
        return self;
    };
    return eat5Block;
}
//        
- (Person *(^)(NSInteger))sleep5
{
    return ^(NSInteger hour) {
        NSLog(@"  %ld  ",(long)hour);
        return self;
    };
}

ViewController.m:

person.eat5(@"  ").sleep5(8);
person.sleep5(8).eat5(@"  ");

3.block使用上の注意点
  • 注意blockがnil
  • であるか否かを判断する
    if (block){
      block(@"hahah",YES);
    }
    
  • block内selfのループリファレンスの問題に注意するiOS開発者は、weakSelfの使用、strongSelfの使用がこのような問題を回避できることを共通認識しているはずです.
  •  __weak typeof(self) weakSelf = self;
     self.block = ^{
         __strong typeof(weakSelf) strongSelf = weakSelf;
         [strongSelf print];
    };
    

    外部ではweakSelfが使用されていますが、strongSelfを使用してもループは発生しません.なぜなら、weakSelfはblockキャプチャのプロパティであり、strongSelfはローカル変数であり、「関数」で解放が完了するからです.
    4.結語
    これで基本的にチェーンプログラミングを終わり、その核心的な思想は実例を伝え、次のチェーンが次の方法を呼び出し続けることができるようにすることであり、熟知すれば理解しにくくない.実はOC内の中括弧呼び出しと同じですが、チェーン呼び出しがよりはっきり見えるだけです.
    以上です.
    参考文献
    1.iOSのチェーンプログラミングと関数プログラミングの理解と実現を一歩一歩教えます.
    2.iOSはblockを利用してチェーンプログラミング方法を実現する(Objective-Cチェーンプログラミング)
    3.iOS __weakと_strong修飾語