UIView 到 UIViewController 通过协议的通信不起作用
UIView to UIViewController communication via protocol not working
也许我在这里遗漏了一些真正基本的东西,但在盯着代码看了一个小时左右之后,我的大脑正在经历低谷循环,我希望能重新审视这个问题。
我有以下 UIView
:
import UIKit
protocol DetailViewWillShowUpDelegate {
func sendDetailOpened(_ openedBool: Bool)
}
class locationXIBController: UIView {
@IBOutlet weak var loationLabel: UILabel!
@IBOutlet weak var vsedniOteviraciDobaLabel: UILabel!
@IBOutlet weak var prijmajiKartyLabel: UILabel!
@IBOutlet weak var detailViewButtonOutlet: UIButton!
@IBOutlet weak var backgroundViewButton: UIButton!
let openedBool = true
var detailViewWillShowUpDelegate: DetailViewWillShowUpDelegate?
override func awakeFromNib() {
super.awakeFromNib()
}
@IBAction func vecerkaDetailButtonPressed(_ sender: UIButton) {
detailViewWillShowUpDelegate?.sendDetailOpened(openedBool)
print("pressed")
}
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
if let result = detailViewButtonOutlet.hitTest(convert(point, to: detailViewButtonOutlet), with: event) {
return result
}
return backgroundViewButton.hitTest(convert(point, to: backgroundViewButton), with: event)
}
}
现在的问题是,当我 call/press vecerkaDetailButtonPressed
函数时,我在控制台中得到 "pressed" 输出,但由于某种原因协议没有通过。
另一面看起来像这样(为简单起见已剥离):
class MapViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
let locationXIB = locationXIBController()
let isVecerkaDetailOpened = false
override func viewDidLoad() {
locationXIB.detailViewWillShowUpDelegate = self
}
extension MapViewController: DetailViewWillShowUpDelegate {
func sendDetailOpened(_ openedBool: Bool) {
isVecerkaDetailOpened = openedBool
print("success")
}
}
我知道执行时的协议值为零。正如我所说,任何帮助都将不胜感激,谢谢!
首先,几个命名约定问题:
名称 locationXIBController
对于 UIView
对象来说是一个错误的选择。它是一个视图对象,而不是控制器对象。
其次,class Swift 中的名称应以大写字母开头。所以 LocationXIBView
将是该视图更好的名称 class.
接下来,你的代码
let locationXIB = locationXIBController()
...错了。这会创建一个全新的 locationXIBController class 实例,您永远不会将其安装在视图层次结构中。您应该将该行设为 IBOutlet:
@IBOutlet weak var locationXIB: locationXIBController!
然后你应该从 StoryBoard 中的 locationXIBController
控件拖动到视图控制器中的插座上。这将导致 Interface Builder 连接插座。
现在,当您 运行 您的程序时,变量 locationXIB
将在加载时从您的 storyboard/XIB 连接到 locationXIBController
视图。
除了@Duncan C 的回答,您可能会检查 MapViewController
class 中 viewDidLoad()
方法顶部是否需要 super.viewDidLoad()
?不这样做可能会导致您的应用出现古怪的事情。
我问:
So does detailViewWillShowUpDelegate actually point at anything, or is it nil?
你回复了:
I just tried debugging and it is actually nil
这就是问题所在...您需要设置 detailViewWillShowUpDelegate
以指向有效的委托对象。这通常在 .xib 文件或情节提要中完成,有时人们会忘记建立这种联系,因此请检查它是否有意义。否则,您只需要在相关代码可以 运行 并设置它之前的某个时刻获得对委托的引用。
@Paulw11 的回答
我终于通过这样的交流设法让它工作了:
步骤 1) 1:1 通过 MKAnnotation 和 MKAnnotationView 之间的协议通信
步骤 2) 1:1 通过 MKAnnotationView 和 MapViewController 之间的协议通信传递相同的数据
终于成功了,谢谢!
也许我在这里遗漏了一些真正基本的东西,但在盯着代码看了一个小时左右之后,我的大脑正在经历低谷循环,我希望能重新审视这个问题。
我有以下 UIView
:
import UIKit
protocol DetailViewWillShowUpDelegate {
func sendDetailOpened(_ openedBool: Bool)
}
class locationXIBController: UIView {
@IBOutlet weak var loationLabel: UILabel!
@IBOutlet weak var vsedniOteviraciDobaLabel: UILabel!
@IBOutlet weak var prijmajiKartyLabel: UILabel!
@IBOutlet weak var detailViewButtonOutlet: UIButton!
@IBOutlet weak var backgroundViewButton: UIButton!
let openedBool = true
var detailViewWillShowUpDelegate: DetailViewWillShowUpDelegate?
override func awakeFromNib() {
super.awakeFromNib()
}
@IBAction func vecerkaDetailButtonPressed(_ sender: UIButton) {
detailViewWillShowUpDelegate?.sendDetailOpened(openedBool)
print("pressed")
}
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
if let result = detailViewButtonOutlet.hitTest(convert(point, to: detailViewButtonOutlet), with: event) {
return result
}
return backgroundViewButton.hitTest(convert(point, to: backgroundViewButton), with: event)
}
}
现在的问题是,当我 call/press vecerkaDetailButtonPressed
函数时,我在控制台中得到 "pressed" 输出,但由于某种原因协议没有通过。
另一面看起来像这样(为简单起见已剥离):
class MapViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
let locationXIB = locationXIBController()
let isVecerkaDetailOpened = false
override func viewDidLoad() {
locationXIB.detailViewWillShowUpDelegate = self
}
extension MapViewController: DetailViewWillShowUpDelegate {
func sendDetailOpened(_ openedBool: Bool) {
isVecerkaDetailOpened = openedBool
print("success")
}
}
我知道执行时的协议值为零。正如我所说,任何帮助都将不胜感激,谢谢!
首先,几个命名约定问题:
名称 locationXIBController
对于 UIView
对象来说是一个错误的选择。它是一个视图对象,而不是控制器对象。
其次,class Swift 中的名称应以大写字母开头。所以 LocationXIBView
将是该视图更好的名称 class.
接下来,你的代码
let locationXIB = locationXIBController()
...错了。这会创建一个全新的 locationXIBController class 实例,您永远不会将其安装在视图层次结构中。您应该将该行设为 IBOutlet:
@IBOutlet weak var locationXIB: locationXIBController!
然后你应该从 StoryBoard 中的 locationXIBController
控件拖动到视图控制器中的插座上。这将导致 Interface Builder 连接插座。
现在,当您 运行 您的程序时,变量 locationXIB
将在加载时从您的 storyboard/XIB 连接到 locationXIBController
视图。
除了@Duncan C 的回答,您可能会检查 MapViewController
class 中 viewDidLoad()
方法顶部是否需要 super.viewDidLoad()
?不这样做可能会导致您的应用出现古怪的事情。
我问:
So does detailViewWillShowUpDelegate actually point at anything, or is it nil?
你回复了:
I just tried debugging and it is actually nil
这就是问题所在...您需要设置 detailViewWillShowUpDelegate
以指向有效的委托对象。这通常在 .xib 文件或情节提要中完成,有时人们会忘记建立这种联系,因此请检查它是否有意义。否则,您只需要在相关代码可以 运行 并设置它之前的某个时刻获得对委托的引用。
@Paulw11 的回答
我终于通过这样的交流设法让它工作了:
步骤 1) 1:1 通过 MKAnnotation 和 MKAnnotationView 之间的协议通信
步骤 2) 1:1 通过 MKAnnotationView 和 MapViewController 之间的协议通信传递相同的数据
终于成功了,谢谢!