Swift에서 클로저를 변수로 저장


141

Objective-C에서 블록의 입력 및 출력을 정의하고 메소드에 전달 된 블록 중 하나를 저장 한 다음 나중에 해당 블록을 사용할 수 있습니다.

// in .h

    typedef void (^APLCalibrationProgressHandler)(float percentComplete);
    typedef void (^APLCalibrationCompletionHandler)(NSInteger measuredPower, NSError *error);

    // in .m

    @property (strong) APLCalibrationProgressHandler progressHandler;
    @property (strong) APLCalibrationCompletionHandler completionHandler;

    - (id)initWithRegion:(CLBeaconRegion *)region completionHandler:(APLCalibrationCompletionHandler)handler
    {
        self = [super init];
        if(self)
        {
            ...
            _completionHandler = [handler copy];
            ..
        }

        return self;
}

- (void)performCalibrationWithProgressHandler:(APLCalibrationProgressHandler)handler
{
    ...

            self.progressHandler = [handler copy];

     ...
            dispatch_async(dispatch_get_main_queue(), ^{
                _completionHandler(0, error);
            });
     ...
}

그래서 Swift에서 동등성을 수행하려고합니다.

var completionHandler:(Float)->Void={}


init() {
    locationManager = CLLocationManager()
    region = CLBeaconRegion()
    timer = NSTimer()
}

convenience init(region: CLBeaconRegion, handler:((Float)->Void)) {
    self.init()
    locationManager.delegate = self
    self.region = region
    completionHandler = handler
    rangedBeacons = NSMutableArray()
}

컴파일러는 completionHandler 선언을 좋아하지 않습니다. 내가 그것을 비난하지는 않지만 나중에 Swift에서 설정하고 사용할 수있는 클로저를 어떻게 정의합니까?


1
컴파일 할 때 어떤 오류가 발생합니까?
TheLazyChap

답변:


335

컴파일러는

var completionHandler: (Float)->Void = {}

오른쪽은 적절한 서명의 종결, 즉 부동 인수를 취하는 종결이 아니기 때문입니다. 다음은 완료 처리기에 "아무것도하지 않음"폐쇄를 지정합니다.

var completionHandler: (Float)->Void = {
    (arg: Float) -> Void in
}

이 단축 될 수 있습니다

var completionHandler: (Float)->Void = { arg in }

자동 유형 유추로 인해.

그러나 원하는 것은 완료 처리기가 nil Objective-C 인스턴스 변수가 초기화 되는 것과 같은 방식으로 초기화되는 것입니다 nil. Swift에서는 옵션으로 다음을 수행 할 수 있습니다 .

var completionHandler: ((Float)->Void)?

이제 속성이 자동으로 초기화됩니다 nil( "값 없음"). Swift에서는 선택적 바인딩을 사용하여 완료 핸들러에 값이 있는지 확인합니다.

if let handler = completionHandler {
    handler(result)
}

또는 옵션 체인 :

completionHandler?(result)

1
"Swift에서 이것은 암시 적으로 래핑되지 않은 옵션으로 실현 될 수 있습니다"또는 "명시 적으로 래핑되지 않은"(즉, 정규) 옵션
newacct

1
((Float)->Void)!와 다른 것을 사용 하고 ((Float)->Void)?있습니까? 초기화되지 않은 옵션을 ?기본값으로 nil이미 선언하지 않았 습니까?
Suragch

43

목표 -C

@interface PopupView : UIView
@property (nonatomic, copy) void (^onHideComplete)();
@end

@interface PopupView ()

...

- (IBAction)hideButtonDidTouch:(id sender) {
    // Do something
    ...
    // Callback
    if (onHideComplete) onHideComplete ();
}

@end

PopupView * popupView = [[PopupView alloc] init]
popupView.onHideComplete = ^() {
    ...
}

빠른

class PopupView: UIView {
    var onHideComplete: (() -> Void)?

    @IBAction func hideButtonDidTouch(sender: AnyObject) {
        // Do something
        ....
        // Callback
        if let callback = self.onHideComplete {
            callback ()
        }
    }
}

var popupView = PopupView ()
popupView.onHideComplete = {
    () -> Void in 
    ...
}

1
그러나 메모리 관리가 자동으로 올바르게 처리됩니까? Obj-C에서 해당 속성을 "복사"로 지정했지만 신속하게 해당 옵션이없는 것으로 보이며 대신 "strong"으로 정의되어 있습니까?
Paulius Vindzigelskis

왜 복사해야합니까?
Dmitry

9

이것이 당신이 추구하는 것인지 확실하지 않은 예를 제공했습니다.

var completionHandler: (_ value: Float) -> ()

func printFloat(value: Float) {
    print(value)
}

completionHandler = printFloat

completionHandler(5)

completionHandler선언 된 변수를 사용하여 단순히 5를 인쇄합니다 .


7

에서는 스위프트 (4, 5) . 두 개의 매개 변수 사전과 bool을 포함하는 클로저 변수를 만들었습니다.

 var completionHandler:([String:Any], Bool)->Void = { dict, success  in
    if success {
      print(dict)
    }
  }

클로저 변수 호출

self.completionHandler(["name":"Gurjinder singh"],true)

5

폐쇄는 typealias아래와 같이 선언 될 수 있습니다

typealias Completion = (Bool, Any, Error) -> Void

코드의 어느 곳에서나 함수에 사용하려면 보통 변수처럼 쓸 수 있습니다

func xyz(with param1: String, completion: Completion) {
}

3

이것도 작동합니다.

var exeBlk = {
    () -> Void in
}
exeBlk = {
    //do something
}
//instead of nil:
exeBlk = {}

-1

나를 위해 다음과 같이 일했습니다.

var completionHandler:((Float)->Void)!
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.