swift 带有默认参数的函数也是一个选择器?
swift functions with default parameters also a selector?
我希望能够从两个地方调用这个函数:当我完成文本字段的编辑时,我想在 stackView
中有 none 时添加一个新的 webView
=],我也希望能够使用 barButtonItem
来做到这一点。
我有两个问题。当条形按钮调用此函数时,参数 'url' 变为一个对象,类型为 UIBarButtonItem
。当它从 textFieldShouldReturn
调用时,它正确地以 NSURL
的形式出现。如果用户未在地址字段中键入任何内容并按下回车键,则会出现空白 NSURL
,并且不使用默认值。 (我希望它是)
textfieldShouldReturn
函数的调用应该是什么样子的,以便空白会触发默认值?
我如何处理我的函数或按钮将调用该函数的事实,以及为什么我的命名参数 'url' 变成我猜想的 'sender?'
override func viewDidLoad() {
super.viewDidLoad()
setDefaultTitle()
let add = UIBarButtonItem(barButtonSystemItem: .Add, target: self, action: #selector(ViewController.addWebView))
let delete = UIBarButtonItem(barButtonSystemItem: .Trash, target: self, action: #selector(ViewController.deleteWebView))
navigationItem.rightBarButtonItems = [delete, add]
}
func addWebView(url: NSURL = NSURL(string: "https://www.google.com")!) {
let webView = UIWebView()
webView.delegate = self
stackView .addArrangedSubview(webView)
webView.loadRequest(NSURLRequest(URL: url))
webView.layer.borderColor = UIColor.blueColor().CGColor
selectWebView(webView)
let recognizer = UITapGestureRecognizer(target: self, action: #selector(ViewController.webViewTapped))
recognizer.delegate = self
webView.addGestureRecognizer(recognizer)
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
if let webView = activeWebView, address = addressBar.text {
if let url = NSURL(string: address) {
webView.loadRequest(NSURLRequest(URL: url))
}
} else if stackView.arrangedSubviews.count == 0 {
let address = NSURL(string: addressBar.text!)!
addWebView(address)
}
textField.resignFirstResponder()
return true
}
没错,您正在获取实际上是 UIBarButtonItem 的发送者对象。你听说过 Target-Action Cocoa 模式吗?如果没有,您可以在这里阅读更多内容:
https://developer.apple.com/library/ios/documentation/General/Conceptual/Devpedia-CocoaApp/TargetAction.html
与您特别相关的部分是 "An Action Method Must Have a Certain Form"。
考虑引入 addWebView 重载:
func addWebView(sender: NSObject) {
addWebView(url: NSURL(string: "https://www.google.com")!)
}
private func addWebView(url: NSURL) {
//left as is ...
}
这是根据 Dave 的评论进行的更新。
必须为实际的实现方法使用不同的名称。否则 Swift 编译器无法解析指定的选择器名称。
有用的代码,它演示了下面的问题:
class Notifier: NSObject {
private var _target: NSObject!
private var _action: Selector!
func addObserver(target: NSObject, action: Selector) {
_target = target
_action = action
}
func invokeMethod() {
guard let t = _target else {
print("target must be set")
return
}
guard let a = _action else {
print("action must be set")
return
}
if t.respondsToSelector(a) {
t.performSelector(a, withObject: self)
}
}
}
class Observer: NSObject {
func subscribe(notifier: Notifier) {
notifier.addObserver(self, action: #selector(Observer.callback))
}
func callback(sender: NSObject) {
callbackImpl(NSURL(string: "https://www.google.com")!)
}
private func callbackImpl(url: NSURL) {
print("url\(url)")
}
}
//client's code
let n = Notifier()
let o = Observer()
o.subscribe(n)
n.invokeMethod()
我希望能够从两个地方调用这个函数:当我完成文本字段的编辑时,我想在 stackView
中有 none 时添加一个新的 webView
=],我也希望能够使用 barButtonItem
来做到这一点。
我有两个问题。当条形按钮调用此函数时,参数 'url' 变为一个对象,类型为 UIBarButtonItem
。当它从 textFieldShouldReturn
调用时,它正确地以 NSURL
的形式出现。如果用户未在地址字段中键入任何内容并按下回车键,则会出现空白 NSURL
,并且不使用默认值。 (我希望它是)
textfieldShouldReturn
函数的调用应该是什么样子的,以便空白会触发默认值?
我如何处理我的函数或按钮将调用该函数的事实,以及为什么我的命名参数 'url' 变成我猜想的 'sender?'
override func viewDidLoad() {
super.viewDidLoad()
setDefaultTitle()
let add = UIBarButtonItem(barButtonSystemItem: .Add, target: self, action: #selector(ViewController.addWebView))
let delete = UIBarButtonItem(barButtonSystemItem: .Trash, target: self, action: #selector(ViewController.deleteWebView))
navigationItem.rightBarButtonItems = [delete, add]
}
func addWebView(url: NSURL = NSURL(string: "https://www.google.com")!) {
let webView = UIWebView()
webView.delegate = self
stackView .addArrangedSubview(webView)
webView.loadRequest(NSURLRequest(URL: url))
webView.layer.borderColor = UIColor.blueColor().CGColor
selectWebView(webView)
let recognizer = UITapGestureRecognizer(target: self, action: #selector(ViewController.webViewTapped))
recognizer.delegate = self
webView.addGestureRecognizer(recognizer)
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
if let webView = activeWebView, address = addressBar.text {
if let url = NSURL(string: address) {
webView.loadRequest(NSURLRequest(URL: url))
}
} else if stackView.arrangedSubviews.count == 0 {
let address = NSURL(string: addressBar.text!)!
addWebView(address)
}
textField.resignFirstResponder()
return true
}
没错,您正在获取实际上是 UIBarButtonItem 的发送者对象。你听说过 Target-Action Cocoa 模式吗?如果没有,您可以在这里阅读更多内容: https://developer.apple.com/library/ios/documentation/General/Conceptual/Devpedia-CocoaApp/TargetAction.html
与您特别相关的部分是 "An Action Method Must Have a Certain Form"。
考虑引入 addWebView 重载:
func addWebView(sender: NSObject) {
addWebView(url: NSURL(string: "https://www.google.com")!)
}
private func addWebView(url: NSURL) {
//left as is ...
}
这是根据 Dave 的评论进行的更新。 必须为实际的实现方法使用不同的名称。否则 Swift 编译器无法解析指定的选择器名称。
有用的代码,它演示了下面的问题:
class Notifier: NSObject {
private var _target: NSObject!
private var _action: Selector!
func addObserver(target: NSObject, action: Selector) {
_target = target
_action = action
}
func invokeMethod() {
guard let t = _target else {
print("target must be set")
return
}
guard let a = _action else {
print("action must be set")
return
}
if t.respondsToSelector(a) {
t.performSelector(a, withObject: self)
}
}
}
class Observer: NSObject {
func subscribe(notifier: Notifier) {
notifier.addObserver(self, action: #selector(Observer.callback))
}
func callback(sender: NSObject) {
callbackImpl(NSURL(string: "https://www.google.com")!)
}
private func callbackImpl(url: NSURL) {
print("url\(url)")
}
}
//client's code
let n = Notifier()
let o = Observer()
o.subscribe(n)
n.invokeMethod()