关键点:
1、在podfile
pod 'Aspects'
2、引入
import Aspects
3、调试查看对象的属性:
// 这种方式才可以在开发调试时通过查看obj来了解包含的属性,如果只有是通过
let obj = aspectInfo.instance()
guard let vc = obj as? UIViewController else { return }
// 通过这种方式不能查看属性
guard let vc2 = aspectInfo.instance() as? UIViewController else { return }
4、在hook要知道某个类的名字,由于swift有命名空间,一般的类名为yyy
,使用一些三方库时类名为xxx.yyy
这样的格式,可以使用Xcode
来查看或者LookServer
这种好用的工具来获取
5、获取view的约束及修改约束
// top、left、right、bottom的constraints保存在父容器里
if let constraints = contextView.superview?.constraints {
for constraint in constraints {
if constraint.secondItem === contextView, constraint.secondAttribute == .bottom {
constraint.constant = 10
}
}
}
// 宽高约束在自己的constraints
let constraints = contextView.constraints
for constraint in constraints {
if constraint.firstItem === contextView, constraint.firstAttribute == .height {
constraint.constant = 56
}
}
完整使用示例
private func hookTestUI() {
do {
let wrappedBlock: @convention(block) (AspectInfo) -> Void = { aspectInfo in
// 这里要先用一个值来接收,方便调试查看obj里各个属性
let obj = aspectInfo.instance()
guard let vc = obj as? UIViewController else { return }
if let contextView = vc.value(forKeyPath: "contextView") as? UIView {
// 操作一般属性
contextView.backgroundColor = UIColor.red
// 修改约束
// top、left、right、bottom的constraints保存在父容器里
if let constraints = contextView.superview?.constraints {
for constraint in constraints {
if constraint.secondItem === contextView, constraint.secondAttribute == .bottom {
constraint.constant = 10
}
}
}
// 宽高约束在自己的constraints
let constraints = contextView.constraints
for constraint in constraints {
if constraint.firstItem === contextView, constraint.firstAttribute == .height {
constraint.constant = 56
}
}
}
}
let wrappedObject: AnyObject = unsafeBitCast(wrappedBlock, to: AnyObject.self)
let aspectToken = try (NSClassFromString("XX.YYY"))?.aspect_hook(#selector(UIViewController.viewDidAppear(_:)), with: AspectOptions.positionBefore, usingBlock: wrappedObject)
// 在特殊的时期类移除hook
print(aspectToken)
// aspectToken?.remove()
} catch {
print(error)
}
}
网友评论