[英]How to make an extension for multiple types in Swift 5
我有以下擴展,我想讓它同時用於 UITextView 和 UILabel。
extension UITextView {
func setTextWithTypeAnimation(typedText: String, characterDelay: TimeInterval = 2.5) {
text = ""
var writingTask: DispatchWorkItem?
writingTask = DispatchWorkItem { [weak weakSelf = self] in
for character in typedText {
DispatchQueue.main.async {
weakSelf?.text!.append(character)
}
Thread.sleep(forTimeInterval: characterDelay/100)
}
}
if let task = writingTask {
let queue = DispatchQueue(label: "typespeed", qos: DispatchQoS.userInteractive)
queue.asyncAfter(deadline: .now() + 0.05, execute: task)
}
}
}
我試圖將類型設置為 UIView 在這里找到: Stack Overflow: Single extension for UITextView and UITextField in Swift
extension UIView {
func setTextWithTypeAnimation(typedText: String, characterDelay: TimeInterval = 2.5) {
if self is UILabel || self is UITextView {
text = ""
var writingTask: DispatchWorkItem?
writingTask = DispatchWorkItem { [weak weakSelf = self] in
for character in typedText {
DispatchQueue.main.async {
weakSelf?.text!.append(character)
}
Thread.sleep(forTimeInterval: characterDelay/100)
}
}
if let task = writingTask {
let queue = DispatchQueue(label: "typespeed", qos: DispatchQoS.userInteractive)
queue.asyncAfter(deadline: .now() + 0.05, execute: task)
}
}
}
}
這當然不起作用,因為 UIView 沒有 text 屬性,所以我收到以下錯誤:
Use of unresolved identifier 'text'
我該如何解決這個問題?
這當然不起作用,因為 UIView 沒有 text 屬性
這正是您想要考慮的部分。 為了編寫這個方法,你需要什么? 兩件事:它需要一個text
屬性。 並且它需要是一個類類型(因為你在它上面使用了一個weak
修飾符)。 所以這么說。
protocol TypeAnimated: AnyObject {
var text: String? { get set }
}
除了歷史原因,UITextView 有一個String!
而UILabel
有一個String?
. 這非常令人沮喪,但我們可以用一個新屬性將兩者連接起來:
protocol TypeAnimated: AnyObject {
var animatedText: String { get set }
}
現在,鑒於該協議,您可以編寫方法:
extension TypeAnimated {
func setTextWithTypeAnimation(typedText: String, characterDelay: TimeInterval = 2.5) {
animatedText = ""
var writingTask: DispatchWorkItem?
writingTask = DispatchWorkItem { [weak weakSelf = self] in
for character in typedText {
DispatchQueue.main.async {
weakSelf?.animatedText!.append(character)
}
Thread.sleep(forTimeInterval: characterDelay/100)
}
}
if let task = writingTask {
let queue = DispatchQueue(label: "typespeed", qos: DispatchQoS.userInteractive)
queue.asyncAfter(deadline: .now() + 0.05, execute: task)
}
}
}
現在,您只需要標記您想要符合此協議的任何類型,它們就會獲得擴展名。
extension UILabel: TypeAnimated {
var animatedText: String {
get { return text ?? "" }
set { text = newValue }
}
}
extension UITextView: TypeAnimated {
var animatedText: String {
get { return text ?? "" }
set { text = newValue }
}
}
作為旁注,每次執行時生成一個新隊列幾乎肯定不是您的意思。 您可能應該將其設置為對主隊列的一系列asyncAfter
調用,或使用計時器,或在asyncAfter
塊內調用asyncAfter
。 但這一切都不會真正影響您的問題。
我還沒有測試過這個,但這就是我可能會解決這個問題的方式:
extension TypeAnimated {
func setTextWithTypeAnimation(typedText: String, characterDelay: TimeInterval = 2.5/100) {
func addNextCharacter(from string: Substring) {
DispatchQueue.main.asyncAfter(deadline: .now() + characterDelay) { [weak self] in
if let self = self, let nextChar = string.first {
self.animatedText.append(nextChar)
addNextCharacter(from: string.dropFirst())
}
}
}
animatedText = ""
addNextCharacter(from: typedText[...])
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.