How can I pass data from a VC to another in Swift 3 without a segue? - ios

I have an issue passing data trough a segue because I'm using protocols to show my data. But I need to find a way to pass the data I have in a View Controller to a second one. The big issue is that I need the information in Swift 3 because the solutions that I have found are only in Onjective-C.
Well, please forget the example that I showed you. The only thing that I need to do is to pass the information inside a uilabel in my first View Controller to another uilabel in the second View Controller but without using a segue.
So I would really appreciate if somebody has a solution in Swift 3.
Thanks in advance!

You can pass data with Navigation in Swift 3 like this: -
Current Class
let editProfile = self.storyboard?.instantiateViewController(withIdentifier: "editProfile") as? EditProfileVc
if detailsModel.count != 0 {
editProfile?.accModel = detailsModel[0] //Passing data here with the array
}
self.navigationController?.pushViewController(editProfile!, animated: true)
and target class (here using model class variable)
class EditProfileVc: BaseNotifyM, PickerDelegate {
// Data Variable
var accModel:AccountModel? //-- Here you can use [String] or [[String: Any]] or as per you choice for data passing
//MARK: - Life Cycle
override func viewDidLoad() {
super.viewDidLoad()
//Do some thing with your data
print(accModel)
}
}

Related

Pass array to another View Controller

I have Tab Bar Controller, where I have few view controllers, but I want to pass array of values (workoutNames) to another view in my Tab Bar Controller. I wonder what's best option to do this and I've decided to use way of passing data with property. But when I try to retrieve data I get empty array. I could also use firestore to retrieve data in my Second View Controller, but It lasts too long, so I decided to passing data between views than retrieve data from firestore every time.
First View Controller
class HomeTableViewController: UIViewController
// I need to pass this array to another view
var workoutsName: [String] = []
...
func sendDataToCalendar() {
// IN THIS FUNCTION I RETRIEVE DATA FROM FIRESTORE AND UPDATE ARRAY WITH VALUES
// After all I print this array to check if everything is correct, and my data is here
print("\(workoutsName)")
}
Here is my Second View Controller when I want to use array from First View Controller
class CalendarViewController: UIViewController {
var arrayOfTitles = [String]()
.
.
.
func getArrayFromHome() {
let homeVC = HomeTableViewController()
homeVC.workoutsName = arrayOfTitles
// NOW I PRINT TO CHECK IF DATA EXISTS
print("\(arrayofTitles)"
}
And its empty, so data didn't pass.
Maybe it's not the best way to pass data, but main idea of this is that I will need to use this array in few view controllers. These controllers won't be connected by segue, so I can't use prepareforSegue. It's not one to one relationship (in future I will need this array in few controllers), so I shouldn't use delegate. I don't think that notification will be ok too, so I think that it's best option to pass data by property. But maybe I am wrong, so please correct me.
The reason why it doesn't work is that you instantiate a new HomeTableViewController with empty data.
If this data will be used on lots of place, why not save it locally? user default seems like it fit your needs.
func sendDataToCalendar() {
UserDefaults.standard.set(workoutsName, forKey: "workoutsName")
}
Then you can read it later on
func getWorkoutNameArray() {
let workoutName = UserDefaults.standard.object(forKey: "workoutsName") as? [String]
}
In your getArrayFromHome() function you are not accessing HomeTableViewController instance where you got the data but creating a new instance. That's why the array is empty. You end up with 2 instances of HomeTableViewController, one in use with the correct array and the dummy one created in the function with an empty array.
Would be better if you pass the data in the same place where you have a reference to CalendarViewController.
Let's say that you are creating and presenting CalendarViewController in your HomeTableViewController like:
let calendarViewController = CalendarViewController()
calendarViewController.arrayOfTitles = workoutNames
// Here is the presentation or push of calendarViewController
It will be useful for you to read this SO question

swift; xcode 9.2 - Passing arguments over TabBar & navigation controller

In my storyboard I got:
UIView -> UITabBarController -> UINavigationController -> UITableView
Now I want to pass an object from UIView into UITableview. I do get the object to the TabBarController from the prepare for segue func, but from there I kind of get lost.
How to identify what segue you have on the itemlist from the TabBarController?
Could somebody give some example code for the UITabBar and Navigation controller to pass the data?
Phillip is right.
You can do it as following:
class Model {
static let shared = Model()
var data: String // or anything else
}
in UIView:
Model.shared.data = "some data"
in UITableView
let data = Model.shared.data
//do smth with data...
Anton is suggesting the Singleton pattern. It is important to understand what it is when you decide to use it has both its benefits and potential pitfalls. https://thatthinginswift.com/singletons/ is a place to start reading up.
There are ways to just pass an object from one view to the other and that is useful knowledge to know. Both TabBarVC's and NavigationVC's have their viewControllers property which allows you to access an array of their child vc's. You can use this to pass information to specific child vc's. Depending on your needs this may be more appropriate than creating a singleton.
For example:
let childVC = tabBarVC.viewControllers[0] as! MyCustomVCClass
childVC.inheretedObject = objectIWantToSend
This would pass an object to the vc that ocupies the first tab of a tab bar vc.

IOS - I want to recycle the server data on Viewcontroller

When we move the a segue from A view to B view or from b view to A view, viewdidload get data from server all the time
So, can we keep the data that viewdidload get at first excute, without starting viewdidload each page?
It's waste of time to get data all the time, when we open each page.
From now we using pageviewcontroller, I think it is inappropriate it.
I using swift language.
If you have good idea, please let me know.
There are very many tutorials on the internet that show how to do what you want. Try a google search on swift pass data between view controllers.
At its very simplest, the second controller needs to have one or properties that can hold data from the first controller. The first controller must implement the following function:
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
let secondVC = segue.destinationViewController as! ViewControllerClass
// Pass data to the second view controller.
secondVC.dataFromServer = dataFromServer
secondVC.otherData = otherData // etc.
}
The data will then be passed from the first controller to the second.

Sending data through Unwind Segues

I have a custom unwind segue issue. Let me explain my controller setup:
I have a main screen which is a navigation controller with a cell view inside. Within this view, there is a button to add data, and in that view is 4 buttons for additional "types" of data to add. Once a user selects one of those four options, they are presented with a view controller specific to their choice that lets them enter data with a done button. The three screens respectively I will from now on refer to them as Main View, Options View, then Data View(all 4 options follow this convention).
After some tutorials I made a custom unwind segue in Main View's controller class, as follows:
#IBAction func unwindToTables(segue: UIStoryboardSegue) {
//function proto for adding data here
//populateTableWithData(data :ItemData)
}
In the storyboard editor, anytime I control + click from any View Controller to it's exit, it lists my unwind segue properly and this works fine.
I would now like to send data through the unwind. In Data View, I have a Done button that constructs and initializes a class of data, called ItemData to which I would like to pass through the segue.
Most of the questions I found on SO or other sites with this deals with normal segues, and when I try to implement them anyways the application causes a runtime error / does not compile.
Has anyone come into the issue before, and have a solution for said issue? Any help or points in the right direction would be much appreciated!
Edit:
I edited my unwind function as follows:
#IBAction func unwindToTables(segue: UIStoryboardSegue) {
let dataC = segue.sourceViewController as? DataVC
let data : ItemData = dataC!.SubmittedData! //unwrapping error
print(data.Name)
//save data
}
and on top of every New{1-4}ViewController I have the following:
import UIKit
class New1ViewController: DataVC,
and I made a new superclass DataVC:
import Foundation
class DataVC: UITableViewController {
var SubmittedData: ItemData?
}
but now I am getting an unwrapping issue... must I initialize SubmittedData prior?
Edit 2:
Thought I might add the Done button press I am doing...
#IBAction func DonePressed(sender: AnyObject) {
let n = ...
...
let d = ...
super.SubmittedData = ItemData(FieldType: "1", CName: n!, CPhone: p!, CAddress: a!, ShouldBe: s!, Repeats: r!, Starts: b, RemindMe: m!, AdditionalNotes: d!)
}
The UIStoryboardSegue that is passed to your unwindToTables: function has a property sourceViewControllee this will be the instance of your Data view controller.
You need all of your view controllers to inherit from a common superclass, so that you can add the property you need:
class DataVC: UITableViewController {
var submittedData: ItemData?
}
Then you would have something like:
class New1ViewController: DataVC,... {
...
}
Then in your unwind method you can retrieve the submittedData property
#IBAction func unwindToTables(segue: UIStoryboardSegue) {
if let dataVC = segue.sourceViewController as? DataVC {
if let info = dataVC.submittedData {
...
}
}
}

Passing data between two View Controllers which aren't connected by a segue [duplicate]

This question already has answers here:
Passing data between view controllers
(45 answers)
Closed 7 years ago.
I know that you can pass information between two view controllers if they are connected by a segue using
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
guard let destinationViewController = segue.destinationViewController as? searchTermViewController else { return }
destinationViewController.courseCodes = selectedCourses
}
}
The above code gives an error if there is no segue because of the .destinationViewController. How do i pass information between to arbitrary view controllers without having to set up a global variable?
You can set up a delegate pattern in order to do this.
Here are the steps for setting up the delegate pattern between two objects, where object A is the delegate for object B, and object B will send messages back to A. The steps are:
Define a delegate protocol for object B.
Give object B an optional delegate variable. This variable should be weak.
Make object B send messages to its delegate when something interesting happens, such as when it needs a piece of information. You write delegate?.methodName(self, . . .)
Make object A conform to the delegate protocol. It should put the name of the protocol in its class line and implement the methods from the protocol.
Tell object B that object A is now its delegate.
Here is a tutorial to give you a working example https://www.youtube.com/watch?v=9LHDsSWc680
Go to your storyboard, select the second view controller, go to the Identity inspector tab and give a StoryBoard ID value. This should be a unique value to identify your view controller.
Now in your first view controller', you can run this code. This will basically create an object of the second view controller, set the property value (for transferring data) and push it (same as the segue does)
let ctrl = self.storyboard?.instantiateViewControllerWithIdentifier("detailsView")
as? SecondViewController
ctrl?.userId = 250 // data to pass.
self.navigationController?.pushViewController(ctrl!, animated: true)
provided userId is a variable in your SecondViewController class. Replace
detailsView with the storyboard id value you gave earlier.
class SecondViewController: UIViewController {
var userId : Int = 0
override func viewDidLoad() {
super.viewDidLoad()
// do something with self.userId
}
}

Resources