我正在尝试将数据传递回以前的viewController。
有谁知道如何将数据从ViewController B传回ViewController A?所以我想要一个字符串'从'BIDAddTypeOfDealViewController转到BIDDCCreateViewController。用户编辑了viewController B,我想在ViewController A中返回已编辑的数据然后我使用它。
我正在使用this answer的'传递数据'部分。我的不同之处:第3点和第6点只是在弹出视图时提及,所以我将该代码放在viewWillDisappear中。我认为这是正确的吗? 同样在Point 6,我没有使用nib进行初始化,因为它已经过时了。我正在使用故事板。而且我没有添加最后一行,因为我不相信我会推动它。按我的故事板上的按钮已经让我前进了。
我认为问题可能出现在BIDDCCreateViewController中,我有方法但我无法运行它。要运行一个方法,它应该[自我方法]。我无法做到这一点。那就是我猜的。
它编译并运行正常,没有任何记录,所以我不知道它是否有效。
更新:我无法获得'sendDataToA'方法来执行。
#import <UIKit/UIKit.h>
#import "BIDAddTypeOfDealViewController.h"
@interface BIDDCCreateViewController : UIViewController
@property (strong, nonatomic) NSString *placeId;
- (IBAction)gotoBViewController:(id)sender;
@end
#import "BIDDCCreateViewController.h"
#import "BIDAddTypeOfDealViewController.h"
@implementation BIDDCCreateViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
NSLog(@"SUCCESSFULLY PASSED PLACE ID: %@", self.placeId);
}
-(void)sendDataToA:(NSString *)myStringData
{
NSLog(@"Inside sendDataToA");
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Your string Data Showing" message:myStringData delegate:self cancelButtonTitle:@"Ok " otherButtonTitles:nil];
[alert show];
}
- (IBAction)gotoBViewController:(id)sender {
NSLog(@"pressed");
BIDAddTypeOfDealViewController *bidAddType = [[BIDAddTypeOfDealViewController alloc]init];
bidAddType.delegate = self;
}
@end
@protocol senddataProtocol <NSObject>
-(void)sendDataToA:(NSString *)myStringData;
@end
#import <UIKit/UIKit.h>
@interface BIDAddTypeOfDealViewController : UIViewController <UITextFieldDelegate>//Using this delegate for data a user inputs
@property(nonatomic,assign)id delegate;
//other textfield outlets not relevant
- (IBAction)chooseDiscountDeal:(id)sender;
@end
#import "BIDAddTypeOfDealViewController.h"
@interface BIDAddTypeOfDealViewController ()
@end
@implementation BIDAddTypeOfDealViewController
@synthesize delegate;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
-(void)viewWillDisappear:(BOOL)animated
{
[delegate sendDataToA:@"Apple"];
}
@end
答案 0 :(得分:90)
您可以使用委托。因此,在ViewController B中,您需要创建一个将数据发送回ViewController A的协议。您的ViewController A将成为ViewController B的委托。
如果您不熟悉目标C,请查看What is Delegate。
在ViewControllerB.h中创建协议:
#import <UIKit/UIKit.h>
@protocol senddataProtocol <NSObject>
-(void)sendDataToA:(NSArray *)array; //I am thinking my data is NSArray, you can use another object for store your information.
@end
@interface ViewControllerB : UIViewController
@property(nonatomic,assign)id delegate;
ViewControllerB.m
@synthesize delegate;
-(void)viewWillDisappear:(BOOL)animated
{
[delegate sendDataToA:yourdata];
}
ViewControllerA中的:当你转到ViewControllerB
时ViewControllerA *acontollerobject=[[ViewControllerA alloc] initWithNibName:@"ViewControllerA" bundle:nil];
acontollerobject.delegate=self; // protocol listener
[self.navigationController pushViewController:acontollerobject animated:YES];
并定义你的功能:
-(void)sendDataToA:(NSArray *)array
{
// data will come here inside of ViewControllerA
}
编辑:
您可以看到此示例:如何将数据传回上一个viewcontroller:Tutorial link
答案 1 :(得分:51)
在我的情况下发回一个字符串。 在ViewControllerA中:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let viewControllerB = segue.destination as? ViewControllerB {
viewControllerB.callback = { message in
//Do what you want in here!
}
}
}
在ViewControllerB中:
var callback : ((String) -> Void)?
@IBAction func done(sender: AnyObject) {
callback?("Hi")
self.dismiss(animated: true, completion: nil)
}
答案 2 :(得分:40)
我的完整答案涵盖了双向传递数据here。我解释委托模式的答案是here。
要将数据从第二个视图控制器传回第一个视图控制器,请使用协议和委托。这段视频是一个非常清晰的过程:
以下是基于视频的示例(稍作修改)。
在Interface Builder中创建故事板布局。再次,要制作segue,只需 Control 从按钮拖动到第二视图控制器。将segue标识符设置为showSecondViewController
。另外,不要忘记使用以下代码中的名称来连接出口和操作。
第一视图控制器
第一视图控制器的代码是
import UIKit
class FirstViewController: UIViewController, DataEnteredDelegate {
@IBOutlet weak var label: UILabel!
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showSecondViewController" {
let secondViewController = segue.destinationViewController as! SecondViewController
secondViewController.delegate = self
}
}
func userDidEnterInformation(info: String) {
label.text = info
}
}
请注意使用我们的自定义DataEnteredDelegate
协议。
第二个视图控制器和协议
第二个视图控制器的代码是
import UIKit
// protocol used for sending data back
protocol DataEnteredDelegate: class {
func userDidEnterInformation(info: String)
}
class SecondViewController: UIViewController {
// making this a weak variable so that it won't create a strong reference cycle
weak var delegate: DataEnteredDelegate? = nil
@IBOutlet weak var textField: UITextField!
@IBAction func sendTextBackButton(sender: UIButton) {
// call this method on whichever class implements our delegate protocol
delegate?.userDidEnterInformation(textField.text!)
// go back to the previous view controller
self.navigationController?.popViewControllerAnimated(true)
}
}
请注意,protocol
不在View Controller类中。
就是这样。现在运行应用程序,您应该能够将数据从第二个视图控制器发送回第一个。
答案 3 :(得分:2)
修改强> 使用@ Erhan的解决方案。不是这个。这不是一个好的解决方案。
这会有所帮助。在ViewControllerB中写下这个。
// Get array of current navigation stack
NSArray *arrayViewControllers = [self.navigationController viewControllers];
// Get previous viewController object from it
YOUR_VIEW_CONTROLLER_NAME *objViewController = (YOUR_VIEW_CONTROLLER_NAME *)[arrayViewControllers objectAtIndex:arrayViewControllers.count-2];
// For safety this check is needed. whether it the class that you want or not.
if ([objViewController isKindOfClass:[YOUR_VIEW_CONTROLLER_NAME class]])
{
// Access properties of YOUR_VIEW_CONTROLLER_NAME here
objViewController.yourProperty = YOUR_VALUE;
}
答案 4 :(得分:1)
正如Erhan Demirci回答的那样,你可以使用代表。如果要将数据传递给单个视图控制器,代理会很有帮助。
NSNotificationCenter
是另一种在viewcontrollers / objects之间传输数据的便捷方式。这对于在应用程序中广播数据非常有用。
阅读文档here。
答案 5 :(得分:1)
自定义委托是移动数据的最佳选择,但您也可以尝试。
您可以使用NSUserDefaults随时随地移动数据。
Swift 3 Code
UserDefaults.standard.set(<Value>, forKey: <Key>)
// To set data
UserDefaults.standard.object(forKey: <Key>)
// To get data
您还可以使用NSNotification来移动数据。
NotificationCenter.default.post(name: Notification.Name(rawValue: "refresh"), object: myDict)
NotificationCenter.default.addObserver(self, selector: #selector(refreshList(_:)), name: NSNotification.Name(rawValue: "refresh"), object: nil)
答案 6 :(得分:1)
有协议,有关闭。使用闭包时,我们需要通过使用弱自我(或未拥有自我)来避免内存泄漏。使用协议,每个viewController都需要一个“监视”对象,最终要实现数十个委托。这里是Swift中的另一个简单解决方案:
在新文件或现有文件(例如:UIViewController+Extensions.swift
)中,创建以下协议:
protocol ViewControllerBackDelegate: class {
func back(from viewController: UIViewController)
}
在LEVEL-2 viewController内部,当您从以下位置按下Back时,您要在其中进行回调:
class LevelTwoViewController: UIViewController {
// making this a weak variable so that it won't create a strong reference cycle
weak var delegate: ViewControllerBackDelegate? = nil
override func willMove(toParentViewController parent: UIViewController?) {
super.willMove(toParentViewController: parent)
if (parent == nil) {
delegate?.back(from: self)
}
}
}
由于delegate
是可选的,因此您可以将此代码添加到视图控制器的基类中。我将添加到需要的位置。
在您的LEVEL-1 viewController中,假设您通过情节提要中的segue调用LEVEL-2:
class LevelOneViewController: UIViewController {
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "Go to Level 2") {
if let vc = segue.destination as? LevelTwoViewController {
vc.selectedItems = self.selectedItems // passing data-in
vc.delegate = self
}
}
// repeat `if` for another sub-level view controller
}
}
extension LevelOneViewController: ViewControllerBackDelegate {
func back(from viewController: UIViewController) {
if let vc = viewController as? LevelTwoViewController {
self.selectedItems = vc.selectedItems
// call update if necessary
}
// repeat `if` for another sub-level view controller
}
}
prepare(for:sender:)
中的数据输入一样处理数据输出答案 7 :(得分:-3)
我会这样做。
@interface ViewControllerA:UIViewController
@property(strong, nonatomic) ViewControllerB * recieverB;
@end
@implementation ViewControllerA
//implement class
- (void)prepareForSegue:(UIStoryboardSegue *) sender:(id)sender
{
segue.destinationViewController.recieverA = self;
}
-(void)viewDidLoad
{
//stop strong refrence cycle
self.viewControllerB = nil;
}
@end
B类
@interface ViewControllerB:UIViewController
@property(strong, nonatomic, getter = parentClass) ViewControllerB * recieverA;
@end
@implementation ViewControllerB
//implement class
- (void)viewWillDisappear:(BOOL)animated
{
parentClass.recieverB = self;
//now class A will have an instance on class b
}
@end
我没有把#import