一、前言
先看一下Swift標準庫中對CustomStringConvertible
協議的定義
public protocol CustomStringConvertible {
/// A textual representation of this instance.
///
/// Calling this property directly is discouraged. Instead, convert an
/// instance of any type to a string by using the `String(describing:)`
/// initializer. This initializer works with any type, and uses the custom
/// `description` property for types that conform to
/// `CustomStringConvertible`:
///
/// struct Point: CustomStringConvertible {
/// let x: Int, y: Int
///
/// var description: String {
/// return "(\(x), \(y))"
/// }
/// }
///
/// let p = Point(x: 21, y: 30)
/// let s = String(describing: p)
/// print(s)
/// // Prints "(21, 30)"
///
/// The conversion of `p` to a string in the assignment to `s` uses the
/// `Point` type's `description` property.
var description: String { get }
}
從宣告中我們可以看到協議中只包含了一個 description
的只讀屬性 ,而且透過協議命名也可以窺探到它的作用 Custom+String+Convertible (所作用的型別去自定義String的轉換)
實現CustomStringConvertible
協議類似於在Objective-C中重寫description
方法, 可用於:
- 自定義作用型別的print輸出
- 作用的型別可自定義轉換成String
如標準庫中給的示例,拿出來分析一下:
struct Point: CustomStringConvertible {
let x: Int, y: Int
var description: String {
return "(\(x), \(y))"
}
}
let p = Point(x: 21, y: 30)
let s = String(describing: p)
print(s)
// Prints "(21, 30)"
上例中結構體Point 實現了CustomStringConvertible協議, 完成了description屬性的實現, 返回自定義字串 "((x), (y))"。 接著使用String型別的
String(describing: p )
初始化方法完成了 Point結構體轉成指定String型別格式的轉換。
透過上面的介紹,我們基本上了解了CustomStringConvertible協議的用法, 接下來介紹幾種使用場景。
首先要知道的是 -- 在Swift中可以實現協議的型別有
結構體
、類
、列舉
。 也就是說只有結構體、 類、 列舉等型別都可以實現CustomStringConvertible協議
二、使用場景
1. 整型型別的列舉使用
enum AudioStatus: Int {
case stopped = 0, playing, recording, interruptionPlaying, interruptionRecording
}
如果在使用列舉時,除了需要訪問列舉的整型值
外,還需要可以方便的輸出每個列舉對應的字串型別的狀態。 那麼在這種場景下,透過extension
擴充套件列舉,並實現CustomStringConvertible
協議將會很合適
extension AudioStatus : CustomStringConvertible {
var description: String {
switch self {
case .stopped:
return "Audio: Stopped"
case .playing:
return "Audio: Playing"
case .recording:
return "Audio: Recording"
case .interruptionPlaying:
return "Audio: interruptionPlaying"
case .interruptionRecording:
return "Audio: interruptionRecording"
}
}
}
使用:
let status:AudioStatus = .stopped
let audioName = String(describing:status) //取整型列舉對應的 字串值
print(“audioName:\(audioName)”)
2. Class型別的使用
定義一個類的話, 當我們使用print 時候並不會輸出類中的變數
class Wheel {
var spokes: Int = 0
var diameter: Double = 0.0
init(spokes:Int = 32,diameter:Double = 26.0) {
self.spokes = spokes
self.diameter = diameter
}
func removeSpokes() {
spokes = spokes > 0 ? spokes-- : spokes
}
}
var wheel = Wheel(spokes: 36,diameter: 29)
print(wheel)
/**
* "Wheel\n"
*/
如果想要改變 print 的輸出結果,我們需要讓類遵守這個協議,最好用 extension擴充套件
extension Wheel: CustomStringConvertible {
var description: String {
return "wheel has \(spokes) spokes"
}
}
var wheel = Wheel(spokes: 36,diameter: 29)
print(wheel)
/**
* "wheel has 36 spokes\n"
*/
如果想了解更多內容,可以參見專欄 《ios開發你需要知道的》