【问题标题】:How to refactor my code to avoid duplicating如何重构我的代码以避免重复
【发布时间】:2018-07-11 13:47:57
【问题描述】:

我有一个函数可以修改 UILabel 的文本并对其进行处理。 这样做,我在 UILabel 扩展中创建了我的函数。 效果很好

extension UILabel {

   let replaced = self.text.doSomething()

   func animate() {

      UIView.transition(with: self, duration: duration,options:[], animations: {
        self.text = replaced
      }

   }    
}

我需要完全相同的东西,但对于 UIButton 的文本。

有没有办法在 UIButton Extension 中不复制相同的代码?

【问题讨论】:

    标签: swift uibutton uilabel refactoring extension-methods


    【解决方案1】:

    制定一个协议怎么样?

    protocol AnimationProtocol {}
    
    class SomeUIButton: UIButton, AnimationProtocol {}
    
    class SomeUILabel: UILabel, AnimationProtocol {}
    
    extension AnimationProtocol {
    
       let replaced = self.text.doSomething()
    
       func animate() {
    
          UIView.transition(with: self, duration: duration,options:[], animations: {
            self.text = replaced
          }
    
       }    
    }
    

    【讨论】:

    • 按钮有标题,标签有文字。这不适用于按钮
    • 该死,我忘了。可以在方法内执行检查,例如if self is UIButton {} else {}
    • @BenjaminBreiby 我建议不要使用这样的硬编码类型
    【解决方案2】:

    一种可能的方法是制定一个协议并创建一个可以跨类型使用的公共属性

    import UIKit
    
    protocol textSettable: class {
        var textValue: String { get set }
    
        func doSomething() -> String
        func animate()
    }
    
    extension textSettable where Self: UIButton {
        var textValue: String? {
            get {
                return self.titleLabel?.text
            }
            set {
                self.titleLabel?.text = newValue
            }
        }
    }
    
    extension textSettable where Self: UILabel {
        var textValue: String? {
            get {
                return self.text
            }
            set {
                self.text = newValue
            }
        }
    }
    
    extension textSettable {
    
        func doSomething() -> String {
            return String(textValue.reversed())
        }
    
        func animate() {
            UIView.transition(with: self, duration: duration,options:[], animations: {
                 self.text = doSomething()
            }
        }
    }
    

    通过这种方式,您可以“装饰”您要使用的每种类型的文本值。

    【讨论】:

    • in UIView.transition(with:self self 应该是 UILabel 或 UIButton
    • 添加一个保护语句来检查self是UILabel还是self是UIButton
    • 我不确定如何设置标签/按钮的文本部分:mylabel.textValue = "test"?但我有一个错误'UILabel' has no member 'textValue'
    【解决方案3】:

    第一部分是 UILabel 和 UIButton 都有一个 text 属性。

    protocol TextProtocol: class {
        var text: String? { get set }
    }
    extension UIButton: TextProtocol {
        var text: String? {
            get {
                return self.titleLabel?.text
            } set {
                self.titleLabel?.text = newValue
            }
        }
    }
    extension UILabel: TextProtocol {}
    

    第二部分以第一部分为基础,确保 UILabel 和 UIButton 都具有animate(text:duration:) 函数。

    protocol AnimatableTextProtocol: TextProtocol where Self: UIView {}
    extension AnimatableTextProtocol {
        func animate(text: String, duration: TimeInterval) {
            UIView.transition(with: self, duration: duration, options: [], animations: { 
                self.text = text
                })
        }
    }
    extension UILabel: AnimatableTextProtocol {}
    extension UIButton: AnimatableTextProtocol {}
    

    注意:如果您从 TextProtocol 中删除 class,则 animate 函数会将其 self 视为不可变的,因为值类型也可以从协议继承。通过 class 部分,AnimatableTextProtocol 知道它可以与使 self 可变的引用类型一起工作,因此文本属性可分配给。

    func yeah(button: UIButton, label: UILabel) {
        button.text = "hello"
        label.text = "world"
    
        button.animate(text: "hello2", duration: 0.5)
        label.animate(text: "world", duration: 1.5)
    }
    

    【讨论】:

      猜你喜欢
      • 2019-09-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多