【问题标题】:Swift Protocols: hiding some propertiesSwift 协议:隐藏一些属性
【发布时间】:2016-02-24 14:18:19
【问题描述】:

我想为UITextViewUITextField 创建一个trimmedText 属性。这是我所做的:

protocol TrimmedTextSupporting: class {
  var _text: String? { get }
  var trimmedText: String { get }
}

extension TrimmedTextSupporting {
  var trimmedText: String {
    let text = self._text ?? ""
    return text.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
  }
}

extension UITextField: TrimmedTextSupporting {

  var _text: String? {
    return self.text
  }
}

extension UITextView: TrimmedTextSupporting {

  var _text: String? {
    return self.text
  }
}

我需要_text 属性,因为textUITextField 中被声明为String?,在UITextView 中被声明为String!(为什么?!>_

这是我尝试过的:

1) 将其标记为private。编译器不允许这样做:'private' modifier cannot be used in protocols

2) 将其分离为私有协议:

private protocol TextExposing {
  var _text: String? { get }
}

extension UITextField: TextExposing {
  var _text: String? {
    return self.text
  }
}

extension UITextView: TextExposing {
  var _text: String? {
    return self.text
  }
}

///////

protocol TrimmedTextSupporting: class {
  var trimmedText: String { get }
}

extension UITextField: TrimmedTextSupporting {}

extension UITextView: TrimmedTextSupporting {}

extension TrimmedTextSupporting where Self: TextExposing {

  // compiler error
  var trimmedText: String {
    let text = self._text ?? ""
    return text.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
  }
}

但是编译器又报错了: Property 'trimmedText' must be declared internal because it matches a requirement in internal protocol 'TrimmedTextSupporting'

我没有想法。

【问题讨论】:

    标签: swift swift-protocols


    【解决方案1】:

    我倾向于选择:

    protocol TrimmedTextSupporting: class {
        var trimmedText: String { get }
    }
    
    extension TrimmedTextSupporting {
    
        private func trimText(text: String) -> String {
            return text.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
        }
    }
    
    extension UITextField: TrimmedTextSupporting {
    
        var trimmedText: String {
            return trimText(text ?? "")
        }
    }
    
    extension UITextView: TrimmedTextSupporting {
    
        var trimmedText: String {
            return trimText(text ?? "")
        }
    }
    

    因此,您通过在共享和私有函数中完成这项工作避免了重复繁重的工作,UITextFieldUITextView 上的扩展完成了他们需要做的最少工作。

    【讨论】:

      【解决方案2】:

      您将TrimmedTextSupporting 声明为内部协议。如果您不想将trimmedText 声明为internal,请将TrimmedTextSupporting 声明为私有协议:

      private protocol TrimmedTextSupporting: class {
          var trimmedText: String { get }
      }
      

      这编译得很好。

      let textView = UITextView()
      textView.text = "hello  "
      print(textView.trimmedText) // "hello"
      
      let textField = UITextField()
      textField.text = "  world "
      print(textField.trimmedText) // "world"
      

      【讨论】:

      • TrimmedTextSupporting 协议的属性在文件被声明为私有的情况下是否可以在文件外部使用?
      • @deville 不,它必须在同一个文件中......我现在看到你的问题了。让我继续努力寻找更好的答案。
      【解决方案3】:

      或者你可以让 trimmedText 不是必需的,设置为可选的。

      (如果你想在 Swift 中使用 optional,你应该让协议为 @objc)

      @objc protocol TrimmedTextSupporting: class {
           optional var trimmedText: String { get }
      }
      

      【讨论】:

        猜你喜欢
        • 2018-07-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多