0Day Forums
Passing data between view controllers - Printable Version

+- 0Day Forums (https://0day.red)
+-- Forum: Coding (https://0day.red/Forum-Coding)
+--- Forum: Swift (https://0day.red/Forum-Swift)
+--- Thread: Passing data between view controllers (/Thread-Passing-data-between-view-controllers)

Pages: 1 2 3 4 5


Passing data between view controllers - mediatory818 - 07-18-2023

I'm new to iOS and Objective-C and the whole [MVC][1] paradigm and I'm stuck with the following:

I have a view that acts as a data entry form and I want to give the user the option to select multiple products. The products are listed on another view with a `UITableViewController` and I have enabled multiple selections.

How do I transfer the data from one view to another? I will be holding the selections on the `UITableView` in an array, but how do I then pass that back to the previous data entry form view so it can be saved along with the other data to Core Data on submission of the form?

I have surfed around and seen some people declare an array in the app delegate. I read something about [singletons][2], but I don't understand what these are and I read something about creating a data model.

What would be the correct way of performing this and how would I go about it?

[1]:

[To see links please register here]

[2]:

[To see links please register here]





RE: Passing data between view controllers - homocoelous459492 - 07-18-2023

The OP didn't mention view controllers but so many of the answers do, that I wanted to chime in with what some of the new features of the LLVM allow to make this easier when wanting to pass data from one view controller to another and then getting some results back.

Storyboard segues, ARC and LLVM blocks make this easier than ever for me. Some answers above mentioned storyboards and segues already but still relied on delegation. Defining delegates certainly works but some people may find it easier to pass pointers or code blocks.

With UINavigators and segues, there are easy ways of passing information to the subservient controller and getting the information back. ARC makes passing pointers to things derived from NSObjects simple so if you want the subservient controller to add/change/modify some data for you, pass it a pointer to a mutable instance. Blocks make passing actions easy so if you want the subservient controller to invoke an action on your higher level controller, pass it a block. You define the block to accept any number of arguments that makes sense to you. You can also design the API to use multiple blocks if that suits things better.

Here are two trivial examples of the segue glue. The first is straightforward showing one parameter passed for input, the second for output.

// Prepare the destination view controller by passing it the input we want it to work on
// and the results we will look at when the user has navigated back to this controller's view.

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
[[segue destinationViewController]

// This parameter gives the next controller the data it works on.
segueHandoffWithInput:self.dataForNextController

// This parameter allows the next controller to pass back results
// by virtue of both controllers having a pointer to the same object.
andResults:self.resultsFromNextController];
}

This second example shows passing a callback block for the second argument. I like using blocks because it keeps the relevant details close together in the source - the higher level source.

// Prepare the destination view controller by passing it the input we want it to work on
// and the callback when it has done its work.

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
[[segue destinationViewController]

// This parameter gives the next controller the data it works on.
segueHandoffWithInput:self.dataForNextController

// This parameter allows the next controller to pass back results.
resultsBlock:^(id results) {
// This callback could be as involved as you like.
// It can use Grand Central Dispatch to have work done on another thread for example.
[self setResultsFromNextController:results];
}];
}



RE: Passing data between view controllers - hyperphoria685855 - 07-18-2023

**NewsViewController**

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tbl_View deselectRowAtIndexPath:indexPath animated:YES];
News *newsObj = [newstitleArr objectAtIndex:indexPath.row];
NewsDetailViewController *newsDetailView = [[NewsDetailViewController alloc] initWithNibName:@"NewsDetailViewController" bundle:nil];

newsDetailView.newsHeadlineStr = newsObj.newsHeadline;

[self.navigationController pushViewController:newsDetailView animated:YES];
}


**NewsDetailViewController.h**

@interface NewsDetailViewController : UIViewController
@property(nonatomic,retain) NSString *newsHeadlineStr;
@end

**NewsDetailViewController.m**

@synthesize newsHeadlineStr;






RE: Passing data between view controllers - tritoconid692381 - 07-18-2023

There are many answers to this questions offering many different ways to perform view controller communication that would indeed work, but I don't see anywhere mentioned which one are actually best to use and which ones to avoid.

### In practice, in my opinion only a few solutions are recommended: ###

- To pass data forward:
- override the `prepare(for:sender:)` method of `UIViewController` when using a storyboard and segues
- pass data through an initializer or through properties when performing view controller transitions thtough code
- To pass data backwards
- update the app shared state (which you can pass forward between view controllers with either one of the methods above)
- use delegation
- use an unwind segue

### Solutions I recommend NOT to use: ###

- Referencing the previous controller directly instead of using delegation
- Sharing data through a singleton
- Passing data through the app delegate
- Sharing data through the user defaults
- Passing data through notifications

These solutions, although working in the short term, introduce too many dependencies that will garble the architecture of the app and create more problems later.

For those interested, I wrote some articles that address these points more in depth and highlight the various drawbacks:

- [How iOS View Controllers Communicate With Each Other](

[To see links please register here]

)
- [How to Structure the Code of iOS Apps](

[To see links please register here]

)
- [Understanding the Core Architectural Principles of iOS Development with a Practical Example](

[To see links please register here]

)


RE: Passing data between view controllers - ricercar81 - 07-18-2023

There are multiple methods for sharing data.

1. You can always share data using `NSUserDefaults`. Set the value you want to share with respect to a key of your choice and get the value from `NSUserDefault` associated to that key in the next view controller.

[[NSUserDefaults standardUserDefaults] setValue:value forKey:key]
[[NSUserDefaults standardUserDefaults] objectForKey:key]

2. You can just create a property in `viewcontrollerA`. Create an object of `viewcontrollerA` in `viewcontrollerB` and assign the desired value to that property.

3. You can also create custom delegates for this.


RE: Passing data between view controllers - vikkynrpyvhgpp - 07-18-2023

I recommend blocks/closures and custom constructors.

Suppose you have to pass string from FirstViewController to SecondViewController.

Your First View Controller.

class FirstViewController : UIViewController {

func moveToViewControllerB() {

let second_screen = SecondViewController.screen(string: "DATA TO PASS", call_back: {
[weak self] (updated_data) in
///This closure will be called by second view controller when it updates something
})
self.navigationController?.pushViewController(second_screen, animated: true)
}


}


Your Second View Controller

class SecondViewController : UIViewController {

var incoming_string : String?
var call_back : ((String) -> Void)?

class func screen(string: String?, call_back : ((String) -> Void)?) -> SecondViewController {

let me = SecondViewController(nibName: String(describing: self), bundle: Bundle.main);
me.incoming_string = string
me.call_back = call_back
return me
}

// Suppose its called when you have to update FirstViewController with new data.
func updatedSomething() {

//Executing block that is implemented/assigned by the FirstViewController.
self.call_back?("UPDATED DATA")
}

}




RE: Passing data between view controllers - whyness519077 - 07-18-2023

> There are 3 types for passing data one ViewController to another
> ViewController.

1. Programatically
2. Segue
3. UserDefaults

**Demo Project Link Here** -

[To see links please register here]



**Programatically**
[![enter image description here][1]][1]


**Segue**
[![enter image description here][2]][2]


**UserDefaults**
[![enter image description here][3]][3]


**Demo Project Link Here** -

[To see links please register here]



[1]:

[2]:

[3]:



RE: Passing data between view controllers - ruru189388 - 07-18-2023

I prefer to make it without delegates and segues. It can be done with custom init or by setting optional values.

**1. Custom init**

```
class ViewControllerA: UIViewController {
func openViewControllerB() {
let viewController = ViewControllerB(string: "Blabla", completionClosure: { success in
print(success)
})
navigationController?.pushViewController(animated: true)
}
}

class ViewControllerB: UIViewController {
private let completionClosure: ((Bool) -> Void)
init(string: String, completionClosure: ((Bool) -> Void)) {
self.completionClosure = completionClosure
super.init(nibName: nil, bundle: nil)
title = string
}

func finishWork() {
completionClosure()
}
}
```

**2. Optional vars**

```
class ViewControllerA: UIViewController {
func openViewControllerB() {
let viewController = ViewControllerB()
viewController.string = "Blabla"
viewController.completionClosure = { success in
print(success)
}
navigationController?.pushViewController(animated: true)
}
}

class ViewControllerB: UIViewController {
var string: String? {
didSet {
title = string
}
}
var completionClosure: ((Bool) -> Void)?

func finishWork() {
completionClosure?()
}
}
```


RE: Passing data between view controllers - hoghood548364 - 07-18-2023

**For SwiftUI**


Think of `@EnvironmentObject` as a smarter, simpler way of using `@ObservedObject` on lots of views. Rather than creating some data in view A, then passing it to view B, then view C, then view D before finally using it, you can create it in view and put it into the environment so that views B, C, and D will automatically have access to it.

Note: Environment objects must be supplied by an ancestor view – if **SwiftUI** can’t find an environment object of the correct type you’ll get a crash. This applies for previews too, so be careful.

As an example, here’s an observable object that stores user settings:

class UserSettings: ObservableObject {
@Published var score = 0
}


RE: Passing data between view controllers - kristelahl - 07-18-2023

In my case, I used a singleton class which could work as a global object allowing accesses to the data from almost everywhere in the app.

The first thing is to build a singleton class. Please refer to the page *https://stackoverflow.com/questions/145154/what-should-my-objective-c-singleton-look-like*.

And to make the object globally accessible, I simply imported it in `appName_Prefix.pch` which was for applying import statement in every classes.

To access this object and to use it, I simply implemented a class method to return the shared instance, which contains its own variables.