一.关联对象
简单给UIButton添加一个分类,功能为按钮添加一个block处理按钮的点击事件。
objc_setAssociatedObject(id _Nonnull object, const void * _Nonnull key,
id _Nullable value, objc_AssociationPolicy policy)第一个参数为对象 相当于 setValue:forKey 进行关联value对象
第二个为需要存储的对象的key值,
第三个为值,value
第四个 属性 是设定该value在object内的属性,即 assgin, (retain,nonatomic)...等
objc_setAssociatedObject(self, &KUibuttonBlockKey, block, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
objc_getAssociatedObject 获取数据,相当于forkey来获取value
let block:btnBlock? = objc_getAssociatedObject(self, &KUibuttonBlockKey) as? btnBlock
import UIKit
typealias btnBlock = ((Any?)->Void)
private var KUibuttonBlockKey = "KUibuttonBlockKey"
extension UIButton{
func actionBlock(with block:btnBlock?) {
if block != nil {
objc_setAssociatedObject(self, &KUibuttonBlockKey, block, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
addTarget(self, action: #selector(butClick(_ :)), for: .touchUpInside)
}
@objc func butClick(_ sender:Any?){
let block:btnBlock? = objc_getAssociatedObject(self, &KUibuttonBlockKey) as? btnBlock
block?(sender)
}
}
override func viewDidLoad() {
super.viewDidLoad()
let bt = UIButton()
bt.frame = CGRect(x: 100, y: 100, width: 100, height: 100)
bt.backgroundColor = #colorLiteral(red: 0.5725490451, green: 0, blue: 0.2313725501, alpha: 1)
bt.setTitle("ok", for: .normal)
bt.setTitleColor(#colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0), for: .normal)
view.addSubview(bt)
bt.actionBlock { (bt) in
print("bt \(bt as! UIButton)")
}
}
点击界面按钮,控制台打印:
bt >
二.黑魔法
let mettod = class_getInstanceMethod(UIViewController.classForCoder(), #selector(UIViewController.viewWillAppear(_:)))
let mettod2 = class_getInstanceMethod(UIViewController.classForCoder(), #selector(UIViewController.swizzlingViewWillAppear(_:)))
method_exchangeImplementations(mettod!, mettod2!)//替换这两个方法
import UIKit
var kHasBeenPoppedKey = "kHasBeenPoppedKey"
extension UIViewController{
@objc func swizzlingViewWillAppear(_ animated : Bool){
swizzlingViewWillAppear(animated)
objc_setAssociatedObject(self, &kHasBeenPoppedKey, false, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
@objc func swizzlingViewDidDisappear(_ animated:Bool){
swizzlingViewDidDisappear(animated)
let isOK:Bool = (objc_getAssociatedObject(self, &kHasBeenPoppedKey) as? Bool) ?? false
if isOK {
DispatchQueue.global().asyncAfter(deadline: .now() + 5) {
print("sss \(NSStringFromClass(self.classForCoder))")
}
}
}
}
extension NSObject{
static func swizzlingload(){
let mettod = class_getInstanceMethod(UIViewController.classForCoder(), #selector(UIViewController.viewWillAppear(_:)))
let mettod2 = class_getInstanceMethod(UIViewController.classForCoder(), #selector(UIViewController.swizzlingViewWillAppear(_:)))
method_exchangeImplementations(mettod!, mettod2!)
let mettod1 = class_getInstanceMethod(UIViewController.classForCoder(), #selector(UIViewController.viewDidDisappear(_:)))
let mettod11 = class_getInstanceMethod(UIViewController.classForCoder(), #selector(UIViewController.swizzlingViewDidDisappear(_:)))
method_exchangeImplementations(mettod1!, mettod11!)
let mettod3 = class_getInstanceMethod(UINavigationController.classForCoder(), #selector(UINavigationController.popViewController(animated:)))
let mettod33 = class_getInstanceMethod(UINavigationController.classForCoder(), #selector(UINavigationController.swzzlingPopViewController(_:)))
method_exchangeImplementations(mettod3!, mettod33!)
}
}
extension UINavigationController{
@objc func swzzlingPopViewController(_ animated: Bool) -> UIViewController?{
let vc:UIViewController = swzzlingPopViewController(animated)!
objc_setAssociatedObject(vc, &kHasBeenPoppedKey, true, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
return vc
}
}
import UIKit
class PuthViewController: UIViewController {
var timer:Timer?
override func viewDidLoad() {
super.viewDidLoad()
print("viewDidLoad")
test3()
}
func test3(){
timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true, block: { (timer) in
print("qqq")
})
}
override func didMove(toParent parent: UIViewController?) {
if parent == nil {
print("界面消失")
}
}
deinit {
timer?.invalidate()
timer = nil
print("\(self.classForCoder)")
}
}
进入界面然后返回:
viewDidLoad
qqq
qqq
qqq
界面消失
qqq
qqq
qqq
qqq
qqq
qqq
sss test1.PuthViewController
PuthViewController
swift中 线程正在执行任务,会等待线程执行完毕之后才销毁对象。