블록 콜백

5969 단어
  • 블록 콜백

    본 강좌는 주로 코드 블록 리셋 모델에 대해 설명하고 다른 리셋의 각종 장단점과 적합한 사용 장면을 분석했다.
  • 코드 블록 메커니즘
  • 블록 변수 유형
  • 블록 코드 캡슐화 및 호출
  • 블록 변수가 일반 변수 작용역에 미치는 영향
  • 블록 리셋 인터페이스 사용

    1, 코드 블록 메커니즘

    애플은 iOS4 SDK에서 처음으로 코드 블록 메커니즘을 지원했다. 그 다음에 코드 블록 메커니즘은 각종 인코딩 장면에 광범위하게 응용되었고 가장 흔히 볼 수 있는 리셋 메커니즘도 블록 리셋이 되었다.코드 블록은 블록이라고도 합니다.코드를 봉인하는 메커니즘으로 익명 함수라고도 부른다.이런 메커니즘을 사용하면 코드를 블록 변수에 넣고 저장할 수 있다. 이 변수는 매개 변수로 전달할 수도 있고 이 변수를 통해 저장된 코드를 호출할 수도 있다.

    2, 블락 변수 유형

    OC 문법에서 변수를 만들려면 먼저 그 유형을 명확히 해야 한다.블록은 코드를 저장할 수 있는 변수로서 그 유형이 상대적으로 특수하다.Block 변수의 유형을 확정하는 데는 두 가지 요소가 있다.
  • 기호로 Block 패키지를 시작합니다.
  • ^ 뒤에 있는 작은 괄호에 이 코드에 필요한 매개 변수를 쓴다.이 매개 변수는 호출자가 값을 부여합니다.
  • 작은 괄호 뒤에 있는 큰 괄호에 봉인할 코드를 쓰고 코드는 작은 괄호 안에 있는 파라미터를 사용할 수 있다.다음은 두 수의 합을 구하는 코드 봉인 과정을 들겠습니다.
    typedef int (^BlockType)(int a,int b);
    
    BlockType varBlock;
    
    varBlock = ^(int a,int b){return a+b;};
    코드를 ^ 변수에 저장하면 이 변수로 코드를 호출할 수 있다.
    int a = 4;
    int b = 6;
    int sum = varBlock(a,b);
    NSLog(@"sum = %d",sum);//     10
    블록 변수도 같은 유형의 변수에 값을 부여할 수 있다
    BlockType varBlockTemp;
    varBlockTemp = varBlock;
    int sum = varBlockTemp(1,2);
    NSLog(@"sum = %d",sum);//     3
    는 코드를 하나의 변수로 전달할 수 있다. 블록이라는 특성은 우리의 다음 인코딩 작업

    3, Block 변수가 일반 변수 역할 영역에 미치는 영향

    을 블록 대상을 통해 코드를 봉인하는 데 매우 중요한 문제이다. 즉, 블록 변수가 일반 변수 역할 영역에 미치는 영향에 대해 명확하게 논의해야 한다.간단한 사례를 통해 이 문제를 해결하다.다음과 같은 코드를 보십시오:
    main()
    {
        {
            int a = 1;
            {
                a = 2;
            }
            //    a   2
        }
        //        a    ,  a     。
    }
    이 코드는 매우 간단하고 큰 확장을 통해 변수의 작용역 범위를 나타냅니다.다음 코드를 보십시오:
    typedef void (^ BlockType)(void);
    
    BlockType var;
    
    void fun1()
    {
        int a = 10;
        var = ^(){NSLog(@"a = %d",a)};
    }
    
    void fun2()
    {
        var();
    }
    
    main()
    {
        fun1();
        fun2();
    }
    fun2 함수에서 varBlock 변수를 호출할 때fun1에 저장된 var 변수의 코드를 실행하고 코드에 사용된 변수var도fun1의 국부 변수입니다.정상적인 상태에서 변수a의 작용역은fun1 함수체 괄호 안에 있다.함수체 대괄호 밖에서 사용a은 무의미하다.그러나 이 상황은 특수하다. 변수a는 Block 변수a에 의해 사용되기 때문에 var 변수는 a를 복제 조작했다. 즉, 우리가 var의 코드에서 사용한 a는 사실 a의 복사본이다.다음 코드를 보십시오:
    typedef void (^ BlockType)(void);
    
    BlockType var;
    
    void fun1()
    {
        int a = 10;
        var = ^(){NSLog(@"a = %d",a)};
        a = 20;
    }
    
    void fun2()
    {
        var();
    }
    
    main()
    {
        fun1();
        fun2();
    }
    이 코드의 출력은 이전 코드와 마찬가지로fun1 함수에서 a의 값이 변해서 Block 안의 a의 값이 변하지 않습니다.왜냐하면 블록 변수가 국부 변수를 사용하는 이유는 국부 변수를 복제하는 것이다. 블록 변수에 저장된 코드가 사용될 때 국부 변수의 복사본이다.그러나 일부 특수한 상황에서 우리는 국부 변수를 바꾸면 Block 변수에서 코드의 변화를 일으킬 수 있다.이때 우리는 Block 전경 변수를 사용해야 한다.Block 전경 변수는: var를 통해 설명합니다.
    typedef void (^ BlockType)(void);
    
    BlockType var;
    
    void fun1()
    {
        __block int a = 10;
        var = ^(){NSLog(@"a = %d",a)};
        a = 20;
    }
    
    void fun2()
    {
        var();
    }
    
    main()
    {
        fun1();
        fun2();
    }
    상기 코드에서fun1의 변수 a는 Block 전경 변수 식별자에 의해 수식되었다. 즉, 변수 a는 Block 전경 변수가 된다.그 역할은 이때 Block이 코드를 봉인할 때 a 변수를 사용하고 복제 작업을 하지 않는다는 것이다. 또한 국부 변수 a와 Block 코드 중의 a가 같은 변수라는 것을 의미한다.그래서 현재 코드의 운행 결과는 a=20이다.

    4, 블락 콜백 커넥터 사용

    리셋의 본질은 컨트롤러가 자신의 정보를 피드백하는 것이다. 대상을 대상으로 프로그래밍할 때 컨트롤러는 방법을 호출하여 자신의 정보를 피드백해야 하고 방법은 반드시 특정한 대상에 속해야 한다.그래서 이전의 리셋 인터페이스는 반드시 두 개의 매개 변수, 하나의 피드백 대상, 하나의 피드백 방법을 설정해야 한다.
  • 목표 동작에서 피드백 대상은 target이고 피드백 방법은 action이며 SEL 형식의 변수이다.
  • 위탁 리셋에서 피드백 대상은delegate이고 피드백 방법은 구성 요소 프로토콜에서 설명하는 방법이다.블록 리셋에서 블록 메커니즘은 코드를 하나의 변수로 직접 봉인할 수 있고 이 변수는 매개 변수로 전달할 수 있다.이 메커니즘을 이용하여 구성 요소는 이 코드를 저장할 수 있고 이벤트를 촉발할 때 이 코드를 직접 호출할 수 있으며 피드백 대상과 피드백 방법을 설정할 필요가 없다.이것은 여전히 이전의 스위치를 사용합니다.
    typedef enum : NSUInteger {
        SwitchStateOff,//default
        SwitchStateOn,
    } SwitchState;
    
    typedef void(^SBlockType)(SwitchState state);
    
    @interface SwitchB : NSObject
    
    @property(nonatomic,assign,readonly)SwitchState currentState;
    
    @property(nonatomic,strong)SBlockType changeStateBlockHandle;
    
    @end
    성명 중의 __block 속성은 바로 리셋 코드를 저장하는 것입니다.리셋을 설정합니다. 이 속성에 값만 부여하면 됩니다.
    @interface Room : NSObject
    @property (strong, nonatomic) Light *lightA;
    @property (strong, nonatomic) SwitchB *s;
    
    @end
    
    
    @implementation Room
    - (instancetype)init
    {
        self = [super init];
        if (self) {
            self.lightA = [[Light alloc] init];
            self.s = [[SwitchB alloc] init];
    
            __weak __block Room * copy_self = self;//       ,         
    
            self.s.changeStateBlockHandle = ^(SwitchState state)
            {
                if (state == SwitchStateOff)
                {
                    [self.lightA turnOff];
                }
                else
                {
                    [self.lightA turnOn];
                }
            };
        }
        return self;
    }
    @end
    스위치의 상태가 변할 때 스위치는 자신의 상태를 사용자에게 피드백해야 한다.블록 리셋 인터페이스의 구성 요소를 사용할 때, 리셋 코드를 직접 봉하여 구성 요소가 응답하는 블록 형식의 속성에 값을 부여하면 됩니다.상태가 바뀌면 봉인된 코드가 구성 요소에 호출됩니다.
  • 저장된 코드의 반환값 유형
  • 코드를 저장하는 매개 변수 목록은 이 두 요소가 같다면 우리는 같은 Block 형식이라고 할 수 있다.이제 간단한 예를 들어 반환값이 없고 인자가 입력되지 않은 코드를 저장하는 Block 형식을 만듭니다.
    void (^ varBlock)(void);
    위의 코드는 Block 변수를 성명했다. 변수의 이름은 changeStateBlockHandle이고 저장 코드의 유형은 반환값이 없고 인자가 입력되지 않았다.되돌아오는 값이 있고 입력된 파라미터가 있는 코드를 저장하려면 응답을 설명하는 Block 변수를 사용할 수 있습니다.
    int (^ varBlock1)(int a,int b);
    위의 코드는 Block 변수를 설명했고 변수 이름은 varBlock이며 저장 코드 형식은 int형 반환값이고 두 개의 int형 파라미터가 있다.Block 변수의 유형은 비교적 복잡하다. 만약 직접 이런 방식으로 변수를 성명한다면 저장하기 매우 쉽다.일반적으로 우리는 varBlock1 키워드로 블록 형식의 이름을 바꾸고, 비교적 간단한 형식 이름으로 변수를 설명하는 작업을 한다.
    typedef void (^ BlockType1)(void);
    
    BlockType1 var1;//var1 varBlock1     

    3, 블록 코드 캡슐화 및 호출

    에 블록 변수가 생겼으니 다음에 우리는 변수에 값을 부여해야 한다.
    typedef void (^ BlockType1)(void);
    
    BlockType1 var1;
    
    var1 = ^(){NSLog(@"test")};
    상기 문법 형식을 통해 코드를 괄호 안에 봉하고 typedef 변수로 저장한다.코드를 봉인하는 과정에서 몇 가지를 주의해야 한다.
  • 좋은 웹페이지 즐겨찾기