【问题标题】:Generic Function to Output to UITextField or UILabel输出到 UITextField 或 UILabel 的通用函数
【发布时间】:2016-01-19 17:04:11
【问题描述】:

我正在尝试在 iOS 的 Swift 2 中编写一个函数,该函数处理一些文本并将其写入UITextField UILabel。目前,我有以下工作:

@IBOutlet weak var textField: UITextField!
@IBOutlet weak var textLabal: UILabel!

​func writeSomeText(string: String, toOutput: UITextField) {
   // do some text processing
   toOutput.text = // processed string
}

​func writeSomeText(string: String, toOutput: UILabel) {
   // do some text processing
   toOutput.text = // processed string
}

如您所见,现在我正在重载该函数,本质上是为 UITextField 和 UILabel 复制它,并且由于我有一堆完全相同的文本处理,所以我正在复制代码。

有没有办法使用泛型编写一个函数来通过一个函数定义来实现这一点?

【问题讨论】:

  • 当然有,编写一个具有可设置文本属性的协议,并使您的第二个参数成为符合此协议的对象

标签: ios swift generics swift2


【解决方案1】:

试试看这个方法...

import UIKit

protocol P {
    func foo(str: String)->String
}
extension P {
    func foo(str: String)->String {
        // do some processing
        let res = str
        return res
    }
}
extension UILabel:P {
    func bar(str: String) {
        self.text = foo(str)
    }
}
extension UITextField:P {
    func bar(str: String) {
        self.text = foo(str)
    }
}

let l = UILabel()
l.text = "alfa"
l.bar("ALFA")

let t = UITextField()
t.text = "beta"
t.bar("BETA")

print(l.text, t.text) // Optional("ALFA") Optional("BETA")

顺便说一句,你根本不需要协议 P :-),它只是作为一个“命名空间”存在(没有全局 func foo)

另一种方法是定义一些通用协议并扩展 UILabel 和 UITextField

import UIKit

protocol P: class {
    var text: String? {get set}
}

extension UILabel: P {}
extension UITextField: P {}

func writeSomeText<T:P>(string: String, toOutput: T ){
    // do some text processing
    toOutput.text = string
}

let l = UILabel()
writeSomeText("label", toOutput: l)
l.text // "label"

let tv = UITextView()
tv.text = "text"
// but
writeSomeText("text view", toOutput: tv) // error: cannot invoke 'writeSomeText' with an argument list of type '(String, toOutput: UITextView)'

以后你可以用 text 属性扩展其他类,如果你愿意的话......而不改变 func writeSomeText 的实现

【讨论】:

  • 这是一个很好的解决方案,而且效果很好。非常感谢!
  • 不客气 :-),如果您对我的回答感到满意,也欢迎您接受它
【解决方案2】:

Swifty 方式(没有泛型)将是

@objc
protocol UITextOutputProtocol: class {
    func setOutputText(text: String)
}

extension UITextField : UITextOutputProtocol {
    func setOutputText(text: String) {
        self.text = text
    }
}

extension UILabel : UITextOutputProtocol {
    func setOutputText(text: String) {
        self.text = text
    }
}

class ViewController: UIViewController {
    //An outlet Collection containing Labels and TextField
    @IBOutlet var texts: [UITextOutputProtocol]!

    //An example function that will be replicating a text in all controls
    func setTexts() {
        for text in texts {
            text.setOutputText("example Text")
        }
    }

更新:

由于UILabelUITextField 现在正在实现协议UITextOutputProtocol,因此以下代码将起作用。

   @IBOutlet weak var textField: UITextField!
   @IBOutlet weak var textLabel: UILabel!

   ​func writeSomeText(string: String, toOutput: UITextOutputProtocol) {
     // do some text processing
     toOutput.setOutputText("example Text") // change the text here for your processed string
   }

   func doSomeProcessingOnText(text:String) {
     writeSomeText(text, textField)
     writeSomeText(text, textLabel)
   }
}

【讨论】:

  • Hugo,那么“......因为我有一个完全相同的文本处理,我正在复制代码......”呢?以及@IBOutlet var texts 的工作原理:[UITextOutputProtocol]!如何在情节提要中创建它???
  • 这只是一个示例,对于 Storyboard 中的这种情况,我只是将 Label 和 TextField 链接到 OutletCollection。
【解决方案3】:

这是一个小技巧,因为 UITextFieldUILabel 不符合任何用于文本编辑的共享协议,但您可以使用 KVO:

func writeSomeText(string: String, output: AnyObject) {
    // do some text processing
    if output.respondsToSelector("text") {
        output.setValue(string, forKey: "text")
    }
}

respondsToSelector 检查以确保您传入的对象具有属性text,然后再继续为该键设置值。如果您传入的对象不符合 KVO 的关键文本`,则此检查用于防止运行时崩溃。

【讨论】:

  • 所以 UITextView 是另一个“候选人”,不是吗?我不是 Cocoa 或 CocoaTouch 方面的专家,但可能有更长的具有 text 属性的对象列表
  • 也许吧,但这个问题与UITextView 无关(至少根据OP)。从理论上讲,此答案适用于任何包含 text 属性的对象,该属性是一个字符串。如果output 是一个具有text 属性而不是字符串的对象,这将崩溃。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-08-03
  • 2017-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多