领导提了个定时替换icon的需求,简单记录一下
怎么把备用icon添加到项目就不多说了
1.替换icon的方法
class func replaceAppIcon(iconName: String) {
if #available(iOS 10.3, *) {
if UIApplication.shared.supportsAlternateIcons {
debugPrint("you can change this app's icon")
} else {
debugPrint("you cannot change this app's icon")
return
}
if let name = UIApplication.shared.alternateIconName {
// 传 nil 恢复默认 icon 也就是Assets里AppIcon
// UIApplication.shared.setAlternateIconName(nil) { (err:Error?) in
// print("set icon error:\(String(describing: err))")
// }
debugPrint("the alternate icon's name is \(name)")
} else {
// 指定icon图标 备用icon
UIApplication.shared.setAlternateIconName(iconName) { (err:Error?) in
debugPrint("set icon error:\(String(describing: err))")
}
}
}
}
2.禁止系统弹窗提示
交换方法还是得慎用,不得已用修改完后一定要充分测试,不然线上出问题就难受了
// 替换AppIcon禁止弹框
extension UIViewController {
public class func replaceSystemPresent(){
let originalSelector = #selector(UIViewController.hzpresent(viewControllerToPresent:animated:completion:))
let swizzledSelector = #selector(UIViewController.present(_:animated:completion:))
let originalMethod = class_getInstanceMethod(self, originalSelector)
let swizzledMethod = class_getInstanceMethod(self, swizzledSelector)
//在进行 Swizzling 的时候,需要用 class_addMethod 先进行判断一下原有类中是否有要替换方法的实现
let didAddMethod: Bool = class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod!), method_getTypeEncoding(swizzledMethod!))
//如果 class_addMethod 返回 yes,说明当前类中没有要替换方法的实现,所以需要在父类中查找,这时候就用到 method_getImplemetation 去获取 class_getInstanceMethod 里面的方法实现,然后再进行 class_replaceMethod 来实现 Swizzing
if didAddMethod {
class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod!), method_getTypeEncoding(originalMethod!))
} else {
method_exchangeImplementations(originalMethod!, swizzledMethod!)
}
}
@objc func hzpresent(viewControllerToPresent: UIViewController, animated: Bool, completion: (() -> Void)?) {
if let alertC = viewControllerToPresent as? UIAlertController {
if alertC.title == nil && alertC.message == nil {
// 查看私有属性
if let contentViewController = alertC.value(forKey: "_contentViewController") {
// 判断_contentViewController的值是否为_UIAlternateApplicationIconsAlertContentViewController
let tempStr = "_UIAlternateApplicationIconsAlertContentViewController"
let classStr = String(describing: contentViewController.self)
if classStr.contains(tempStr) {
if completion != nil {
completion!()
}
return
}
}
}
}
self.hzpresent(viewControllerToPresent: viewControllerToPresent, animated: animated, completion: completion)
}
}
3.获取私有属性
func getBridgedPropertyList(anyClass: AnyClass) -> Set<String> {
var propertyList = Set<String>()
if let superClass = class_getSuperclass(anyClass), superClass != NSObject.self {
propertyList = propertyList.union(getBridgedPropertyList(anyClass: superClass))
}
let count = UnsafeMutablePointer<UInt32>.allocate(capacity: 1)
if let props = class_copyPropertyList(anyClass, count) {
for i in 0 ..< count.pointee {
let name = String(cString: property_getName(props.advanced(by: Int(i)).pointee))
propertyList.insert(name)
}
free(props)
}
#if swift(>=4.1)
count.deallocate()
#else
count.deallocate(capacity: 1)
#endif
return propertyList
}