将Swift便利初始化程序转换为Objective-C

时间:2015-04-20 19:51:03

标签: ios objective-c swift closures

我需要将以下convenience初始值设定项从Swift转换为Objective-C

    convenience init(view: UIView, overlapHandler: (CGRect)->()) {
        self.init(view: view, handler: { overlap -> () in
            overlapHandler(overlap ?? CGRect.nullRect)
        })
    }

我的第一次尝试是:

-(instancetype) initWithView:(UIView*)view overlapHandler:(Handler)handler
{
    Handler overlapHandler = ^(CGRect overlap) {
        if (CGRectIsNull(overlap)) {
            return;
        }
        handler(overlap);
    };
    return [self initWithView:view andHandler:overlapHandler];
}

但由于我没有看到Objective-C块如何接收非可选的CGRect,因此效果不佳。

代码的上下文如下:

import UIKit

class KeyboardOverlapNotifier:NSObject {
    typealias Handler = (CGRect?) -> ()

    let view:UIView
    let handler:Handler

    init(view:UIView, handler:Handler) {
        self.view = view
        self.handler = handler
        super.init()
        beginListening()
    }

    deinit {
        stopListening()
    }

    func beginListening() {
        token = token ?? nc.addObserverForName(UIKeyboardWillChangeFrameNotification, 
                             object:nil, queue:nil, usingBlock:keyboardFrameDidChange)
    }

    func stopListening() {
        if let observer = token {
            nc.removeObserver(observer)
            token = nil
        }
    }

    private let nc:NSNotificationCenter = NSNotificationCenter.defaultCenter()
    private var token:NSObjectProtocol?
}

private extension KeyboardOverlapNotifier {
    func keyboardFrameDidChange(notification: NSNotification!) {
        let duration = notification.userInfo!
             [UIKeyboardAnimationDurationUserInfoKey] as NSTimeInterval

        UIView.animateWithDuration(duration,
            delay: 0,
            options: .BeginFromCurrentState,
            animations: {
                let keyboard:CGRect = {
                    let global = (notification.userInfo!
                     [UIKeyboardFrameEndUserInfoKey] as NSValue).CGRectValue()
                    let local = self.view.convertRect(global, fromView: nil)
                    return local
                }()
                let overlap = self.view.bounds.rectByIntersecting(keyboard)
                self.handler(overlap.nonEmptyOrNil)
            },
            completion: nil)
    }
}

extension KeyboardOverlapNotifier {
    convenience init(view: UIView, overlapHandler: (CGRect)->()) {
        self.init(view: view, handler: { overlap -> () in
            overlapHandler(overlap ?? CGRect.nullRect)
        })
    }
}

extension CGRect {
    var nonEmptyOrNil:CGRect? { return !self.isEmpty ? self : nil }
}

1 个答案:

答案 0 :(得分:1)

也许这应该有帮助?我仍然不确定你的问题究竟是什么,所以我唯一可以提供的是对每个问题的引用。

闭包是一个独立的功能块,可以在代码中传递和使用。 Swift中的闭包类似于C和Objective-C中的块以及其他编程语言中的lambdas。 闭包可以从定义它们的上下文中捕获和存储对任何常量和变量的引用。这被称为关闭那些常量和变量,因此称为“闭包”。 Swift为您处理捕获的所有内存管理。

Blocks vs Closures

https://www.codefellows.org/blog/writing-completion-blocks-with-closures-in-swift

https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Closures.html