iOS知识集Swift知识集iOS OC 学习手册

Objective-C 与 Swift 方法的类比系列(一)

2016-09-11  本文已影响108人  liangdahong

以下内容来源于我的新blog idhong.com

新 blog 会不断更新,其他平台可能更新不及时哦。

1、单例

1.1、Objective-C 写法

<pre><code>

@interface IHUserManager : NSObject

Swift 写法

<pre><code>
import Foundation
class IHUserManager {
static let sharedInstance = IHUserManager()
}
</code></pre>

block和闭包在对象绑定时的坑

分析

oc 中,使用 runtime 的对象绑定相信大家都使用过,而且在 block 上的使用也经常看到,在 oc 中可以把 block 直接使用 runtime 通过 key 和其他的对象绑定起来,但在 swift 中闭包不是:AnyObject 类型 使用在进行对象绑定时无法进行。
参考:
1.stackoverflow.com
2、http://nshipster.cn
需要使用:
public func unsafeBitCast<T, U>(x: T, _: U.Type) -> U
函数

代码实现

对 UIControl 增加 Block 属性和 Closure 属性

swift 具体的实现如下:

<pre><code>
typealias IHClosure = @convention(block)() -> ()

extension UIControl {

private struct ClosureKey {
    static var touchUpInsideKey = "touchUpInsideKey"
}

func ih_addTouchUpInsideClosure(closure: IHClosure) {
    let obj: AnyObject = unsafeBitCast(closure, AnyObject.self)
    objc_setAssociatedObject(self, &ClosureKey.touchUpInsideKey, obj, .OBJC_ASSOCIATION_COPY_NONATOMIC)
    
    self.addTarget(self, action: #selector(UIControl._touchUpInside), forControlEvents: .TouchUpInside)
}

@objc private func _touchUpInside() {
    let obj: AnyObject = objc_getAssociatedObject(self, &ClosureKey.touchUpInsideKey)
    let closure: IHClosure = unsafeBitCast(obj, IHClosure.self)
    closure()
}

}
</code></pre>

Objective-C 具体的实现如下:

<pre><code>

import "UIControl+Block.h"

import <objc/runtime.h>

const char kTouchUpInside = '\0';

@implementation UIControl (Block)

swift 和 oc 之 load方法不同以及处理方案

分析

在 oc 开发中,APP统计时,自然会使用到 方法的替换,下面方法

OBJC_EXPORT void method_exchangeImplementations(Method m1, Method m2)
__OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_2_0);

通常会为 vc 添加一个 category 同时在 load 方法里面的其做相应的处理。但在 swift 中系统不允许使用 load 方法。那么我们可以想办法使用:
initialize 方法

代码实现

oc 具体的实现如下:

<pre><code>

import "UIViewController+Swizzle.h"

import <objc/runtime.h>

@implementation UIViewController (Swizzle)

swift 具体的实现如下:

<pre><code>
extension UIViewController {

public override class func initialize() {

    struct Static {
        static var token: dispatch_once_t = 0
    }

    if self !== UIViewController.self {
        return
    }

    dispatch_once(&Static.token) {
        let originalSelector = #selector(UIViewController.viewWillAppear(_:))
        let swizzledSelector = #selector(UIViewController.nsh_viewWillAppear(_:))

        let originalMethod = class_getInstanceMethod(self, originalSelector)
        let swizzledMethod = class_getInstanceMethod(self, swizzledSelector)
        
        let didAddMethod = class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))
        if didAddMethod {
            class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod))
        } else {
            method_exchangeImplementations(originalMethod, swizzledMethod);
        }
    }
}

func nsh_viewWillAppear(animated: Bool) {
    self.nsh_viewWillAppear(animated)
}

}
</code></pre>

参考资料

~😁欢迎转载、转载请注明出处.

上一篇 下一篇

猜你喜欢

热点阅读