在基class或扩展Swift的静态方法中获取派生类型的类型名称
Get the type name of derived type in a static method of base class or extension Swift
TL:DR
将其粘贴到 Swift 游乐场:
import UIKit
public protocol NibLoadable {
static var nibName: String { get }
}
extension NibLoadable where Self: UIView {
public static var nibName: String {
return String(describing: self)
}
func printName(){
print(Self.nibName)
}
}
public class Shoes: UIView, NibLoadable {
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
printName()
}
override init(frame: CGRect) {
super.init(frame: frame)
printName()
}
}
public class Cake: Shoes {
}
let cake = Cake() // this line prints 'Shoes'
如何打印 Cake
,而不是 Shoes
?
完整解释:
我找到了将 xib 文件加载到故事板中的方法,如下所示:
效果惊人,但是我必须将样板 NibLoadable
代码放入每个视图中,如下所示:
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupFromNib()
}
override init(frame: CGRect) {
super.init(frame: frame)
setupFromNib()
}
当您以这种方式获得 20-30 次观看时,这显然很烦人。
所以我正在尝试设置一个基础 class 来处理这个问题,然后让所有内容继承它。
不幸的是,无论我尝试什么,String(describing: Self.self)
总是 returns 我的基础 class 的名称,而不是派生 class 的名称。
当我在 XCode:
中打开 Storyboard 时,控制台日志中出现了这个异常
[MT] IBSceneUpdate: [scene update, delegate=] Error Domain=IBMessageChannelErrorDomain Code=3 "Failed to communicate with helper tool" UserInfo={NSLocalizedFailureReason=The agent raised a "NSInternalInconsistencyException" exception: Could not load NIB in bundle: 'NSBundle (loaded)' with name 'BaseNibLoadable.Type', IBMessageSendChannelException=Could not load NIB in bundle: 'NSBundle (loaded)' with name 'BaseNibLoadable.Type', NSLocalizedDescription=Failed to communicate with helper tool}
示例:
@IBDesignable
class BaseNibLoadable: UIView, NibLoadable {
// MARK: - NibLoadable
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupFromNib()
}
override init(frame: CGRect) {
super.init(frame: frame)
setupFromNib()
}
}
@IBDesignable
class SomeHeader: BaseNibLoadable {
@IBOutlet fileprivate weak var headerLabel: UILabel!
@IBInspectable var header: String? {
didSet {
self.headerLabel.text = header
}
}
}
显然我的主包(两者相同)包含 SomeHeader.xib
文件。
所以我正在寻找的是以某种方式获取在 nibName
静态方法中实例化的实际类型的名称。
更新
根据要求,这是我在问题顶部 link 编辑的原始答案(更确切地说,只是它的代码,因为它很长,否则......请遵循 link):
public protocol NibLoadable {
static var nibName: String { get }
}
public extension NibLoadable where Self: UIView {
public static var nibName: String {
return String(describing: Self.self) // defaults to the name of the class implementing this protocol.
}
public static var nib: UINib {
let bundle = Bundle(for: Self.self)
return UINib(nibName: Self.nibName, bundle: bundle)
}
func setupFromNib() {
guard let view = Self.nib.instantiate(withOwner: self, options: nil).first as? UIView else { fatalError("Error loading \(self) from nib") }
addSubview(view)
view.translatesAutoresizingMaskIntoConstraints = false
view.leadingAnchor.constraint(equalTo: self.safeAreaLayoutGuide.leadingAnchor, constant: 0).isActive = true
view.topAnchor.constraint(equalTo: self.safeAreaLayoutGuide.topAnchor, constant: 0).isActive = true
view.trailingAnchor.constraint(equalTo: self.safeAreaLayoutGuide.trailingAnchor, constant: 0).isActive = true
view.bottomAnchor.constraint(equalTo: self.safeAreaLayoutGuide.bottomAnchor, constant: 0).isActive = true
}
}
更新 2
我确实知道 subclass 那时肯定在堆栈中,因为如果我记录 Thread.callStackSymbols
实际的具体视图 class 名称就在那里。
How do i make it print Cake, not Shoes?
改变
print(Self.nibName)
至
print(type(of:self).nibName)
TL:DR 将其粘贴到 Swift 游乐场:
import UIKit
public protocol NibLoadable {
static var nibName: String { get }
}
extension NibLoadable where Self: UIView {
public static var nibName: String {
return String(describing: self)
}
func printName(){
print(Self.nibName)
}
}
public class Shoes: UIView, NibLoadable {
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
printName()
}
override init(frame: CGRect) {
super.init(frame: frame)
printName()
}
}
public class Cake: Shoes {
}
let cake = Cake() // this line prints 'Shoes'
如何打印 Cake
,而不是 Shoes
?
完整解释:
我找到了将 xib 文件加载到故事板中的方法,如下所示:
效果惊人,但是我必须将样板 NibLoadable
代码放入每个视图中,如下所示:
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupFromNib()
}
override init(frame: CGRect) {
super.init(frame: frame)
setupFromNib()
}
当您以这种方式获得 20-30 次观看时,这显然很烦人。
所以我正在尝试设置一个基础 class 来处理这个问题,然后让所有内容继承它。
不幸的是,无论我尝试什么,String(describing: Self.self)
总是 returns 我的基础 class 的名称,而不是派生 class 的名称。
当我在 XCode:
中打开 Storyboard 时,控制台日志中出现了这个异常[MT] IBSceneUpdate: [scene update, delegate=] Error Domain=IBMessageChannelErrorDomain Code=3 "Failed to communicate with helper tool" UserInfo={NSLocalizedFailureReason=The agent raised a "NSInternalInconsistencyException" exception: Could not load NIB in bundle: 'NSBundle (loaded)' with name 'BaseNibLoadable.Type', IBMessageSendChannelException=Could not load NIB in bundle: 'NSBundle (loaded)' with name 'BaseNibLoadable.Type', NSLocalizedDescription=Failed to communicate with helper tool}
示例:
@IBDesignable
class BaseNibLoadable: UIView, NibLoadable {
// MARK: - NibLoadable
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupFromNib()
}
override init(frame: CGRect) {
super.init(frame: frame)
setupFromNib()
}
}
@IBDesignable
class SomeHeader: BaseNibLoadable {
@IBOutlet fileprivate weak var headerLabel: UILabel!
@IBInspectable var header: String? {
didSet {
self.headerLabel.text = header
}
}
}
显然我的主包(两者相同)包含 SomeHeader.xib
文件。
所以我正在寻找的是以某种方式获取在 nibName
静态方法中实例化的实际类型的名称。
更新 根据要求,这是我在问题顶部 link 编辑的原始答案(更确切地说,只是它的代码,因为它很长,否则......请遵循 link):
public protocol NibLoadable {
static var nibName: String { get }
}
public extension NibLoadable where Self: UIView {
public static var nibName: String {
return String(describing: Self.self) // defaults to the name of the class implementing this protocol.
}
public static var nib: UINib {
let bundle = Bundle(for: Self.self)
return UINib(nibName: Self.nibName, bundle: bundle)
}
func setupFromNib() {
guard let view = Self.nib.instantiate(withOwner: self, options: nil).first as? UIView else { fatalError("Error loading \(self) from nib") }
addSubview(view)
view.translatesAutoresizingMaskIntoConstraints = false
view.leadingAnchor.constraint(equalTo: self.safeAreaLayoutGuide.leadingAnchor, constant: 0).isActive = true
view.topAnchor.constraint(equalTo: self.safeAreaLayoutGuide.topAnchor, constant: 0).isActive = true
view.trailingAnchor.constraint(equalTo: self.safeAreaLayoutGuide.trailingAnchor, constant: 0).isActive = true
view.bottomAnchor.constraint(equalTo: self.safeAreaLayoutGuide.bottomAnchor, constant: 0).isActive = true
}
}
更新 2
我确实知道 subclass 那时肯定在堆栈中,因为如果我记录 Thread.callStackSymbols
实际的具体视图 class 名称就在那里。
How do i make it print Cake, not Shoes?
改变
print(Self.nibName)
至
print(type(of:self).nibName)