以下内容来源于我的新blog idhong.com
新 blog 会不断更新,其他平台可能更新不及时哦。
1、单例
1.1、Objective-C 写法
<pre><code>
@interface IHUserManager : NSObject
- (instancetype)sharedInstance;
@end
@implementation IHUserManager - (instancetype)sharedInstance {
static IHUserManager *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
@end
</code></pre>
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)
(void)ih_addTouchUpInsideWithBlock:(dispatch_block_t)block {
objc_setAssociatedObject(self, @selector(_touchControlEvents), block, OBJC_ASSOCIATION_COPY_NONATOMIC);
[self addTarget:self action:@selector(_touchControlEvents) forControlEvents:UIControlEventTouchUpInside];
}(void)_touchControlEvents {
dispatch_block_t block = objc_getAssociatedObject(self, _cmd);
if (block) block();
}
@end
</code></pre>
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)
(void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{// 获取系统的方法的 方法对象 Method orignViewDidLoad = class_getInstanceMethod([UIViewController class], @selector(viewDidLoad)); // 获取准备用来替换的 方法对象 Method replacingMethod = class_getInstanceMethod([UIViewController class], @selector(_viewDidLoad_Swizzling)); BOOL didAddMethod = class_addMethod([self class], @selector(viewDidLoad), method_getImplementation(replacingMethod), method_getTypeEncoding(replacingMethod)); if (didAddMethod) { // 替换一下方法地址 class_replaceMethod([self class], @selector(_viewDidLoad_Swizzling), method_getImplementation(orignViewDidLoad), method_getTypeEncoding(orignViewDidLoad)); }else{ // 直接交换的调用 method_exchangeImplementations(orignViewDidLoad, replacingMethod); }
});
}(void)_viewDidLoad_Swizzling {
[self _viewDidLoad_Swizzling];
}
@end
</code></pre>
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>
参考资料
- http://nshipster.cn/swift-objc-runtime
- http://www.hmttommy.com/2015/12/11/AddCategoryProperty
- http://stackoverflow.com/questions/29106891/how-do-i-pass-in-a-void-block-to-objc-setassociatedobject-in-swift
- http://swifter.tips/singleton
~😁欢迎转载、转载请注明出处.