Swift 3 - 将数据传递回以前的视图控制器

Posted

技术标签:

【中文标题】Swift 3 - 将数据传递回以前的视图控制器【英文标题】:Swift 3 - passing data back to previous viewcontroller 【发布时间】:2017-03-02 19:06:53 【问题描述】:

我知道之前有人问过这个问题,但我似乎无法弄清楚为什么在单击按钮并将字符串从 ViewControllerB 传递到 ViewController A 时应用程序崩溃时收到以下错误消息:

2017-03-02 12:42:02.485320 APPNAME[1111:2345678] -[ViewControllerA pressedNextButtonWithMessage:]:无法识别的选择器发送到实例 0x11fd7eb90 2017-03-02 12:42:02.589949 APPNAME[1111:2345678] 提供给 CFRunLoopRunSpecific 的无效模式 'kCFRunLoopCommonModes' - 中断 _CFRunLoopError_RunCalledWithInvalidMode 以进行调试。此消息每次执行只会出现一次。 2017-03-02 12:42:07.586960 APPNAME[1111:2345678] * 由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“-[ViewControllerA pressedNextButtonWithMessage:]:无法识别的选择器发送到实例 0x11fd7eb90” * 首先抛出调用栈: (0x1819201c0 0x18035855c 0x181927278 0x181924078 0x18181e59c 0x100287824 0x1002878a0 0x18779e7b0 0x1879125ec 0x18779e7b0 0x18779e730 0x187788be4 0x187788d4c 0x18779e01c 0x18779db44 0x187798d8c 0x187769858 0x100159aec 0x187f56cb8 0x187f50720 0x1818ce278 0x1818cdbc0 0x1818cb7c0 0x1817fa048 0x18327d198 0x1877d4628 0x1877cf360 0x100077ef0 0x1807dc5b8) libc++abi.dylib:以 NSException 类型的未捕获异常终止

我的应用是 Swift 3 和传统 Objective-C 的混合体:

ViewControllerA.m

@interface ViewControllerA () <ViewControllerBDelegate>
@property (nonatomic, strong) NavViewController * navVC;

@end

@implementation ViewControllerA
- (void)viewDidLoad
    ...
    self.navVC = [NavViewController instantiate]; // instantiate is a function that inits the storyboard and instantiates the viewcontroller from the NavViewController class
    ViewControllerB *vcB = [self.navVC.viewControllers firstObject]; // ViewControllerB is actually the rootviewcontroller of navVC
    vcB.delegate = self; 
    ...


- (void)pressedNextButton:(NSString *)message

    NSLog(@"Button worked: %@", message);

@end

ViewControllerB.swift

@objc protocol ViewControllerBDelegate 
    func pressedNextButton(message: String)


@objc class ViewControllerB: UIViewController, NSFetchedResultsControllerDelegate, UITableViewDataSource, UITableViewDelegate 

    var delegate: ViewControllerBDelegate?
    var passedMessage: String = "Pass this message back to ViewControllerA"

    @IBAction func nextButton(_ sender: UIBarButtonItem)  // this is the button that causes the app to crash
        self.delegate?.pressedNextButton(message: passedMessage) // app crashes after executing this line
    

错误发生在

之后

self.delegate?.pressedNextButton(message:passedMessage)

被执行。此外,如果我从代码中删除了 'passedMessage' 变量和相关参数,控制台会确认 pressNextButton 函数正在执行而没有问题(即我可以在控制台中看到日志“Button working”)。任何人都可以看到导致应用崩溃的原因以及我该如何解决这个问题?

这是我的 nextButton IBOutlet 的 Connections Inspector 的屏幕截图:

【问题讨论】:

检查所有插座是否连接正确。 我猜你指的是'@IBAction func nextButton?如果是这样,我右键单击情节提要中的按钮并在 Connections Inspector 下,我可以确认“nextButton”按钮已连接到“Sent Actions”部分下的 ViewControllerB。我会用截图更新问题。 将您的 viewDidLoad 代码放入 prepareforsegue 方法中。我猜您的委托将为零。 我没有通过 segues 传递数据。相反,我使用委托将数据传递回之前的视图控制器(即 ViewControllerA)。 是的,我知道,但您的 var 委托:ViewControllerBDelegate?是可选的,因此它拥有 nil 值,当您点击 @IBAction func nextButton(_ sender: UIBarButtonItem) 您的委托为 nil.you 必须给您的委托一个值。 【参考方案1】:

您的 Objective-C 和 Swift 消息签名不匹配。你有两个选择:

修复 Objective-C 代码

在你的 Objective-C 代码中,改变

- (void)pressedNextButton:(NSString *)message

- (void)pressedNextButtonWithMessage:(NSString *)message

或者,修复 Swift 代码

在你的 Swift 代码中,改变

func pressedNextButton(message: String)

func pressedNextButton(_ message: String)

【讨论】:

你好,马特。像魅力一样工作。您能解释一下为什么该解决方案有效以及您是如何发现问题的吗?非常感谢! 我发现了这个问题,因为 (1) 您发布了错误消息并且我阅读了它,并且 (2) 我知道方法签名是如何在 Swift 和 Objective-C 之间转换的。如果您想了解 (2),请阅读我的书:apeth.com/swiftBook/apa.html#_objective_c_methods — 请注意这里的真正寓意:不要谈论错误消息。 显示错误信息。对您来说,它可能看起来像 gobbledegook,但它可能包含其他人知道如何阅读的重要信息。 好点。谢谢你的提示。此外,如果选择在您的解决方案中遵循 Swift 更改,请务必更改:self.delegate?.pressedNextButton(message:passedMessage) 为 self.delegate?.pressedNextButton(passedMessage) 当然,签名的更改必须始终如一地进行,直到整个编译完成。但这在我的回答中被认为是理所当然的。 :)

以上是关于Swift 3 - 将数据传递回以前的视图控制器的主要内容,如果未能解决你的问题,请参考以下文章

Swift:如何将数据传递给嵌入在 ContainerView 中的 PageViewController?

如何将数据传递给嵌套控制器(UIContainerView)?

Swift segue 不会将数据传递给旧的 ViewController

Swift:将数据传递给 segue

使用 performSegue 将数据传递给目标视图控制器

将数据传递给表视图控制器