簡體   English   中英

如何在 Swift 5 中為多種類型進行擴展

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM