How to pass data from one view controller to another? - swift

How do I pass the data from an array of one view controller to another view controller?
FirstViewController:
var myArray = ["some data"]
override func prepare(for segue: UIStoryboardSegue, sender: Any?){
let destinationVC = segue.destination as! SecondViewController
destinationVC.passedArray = myArray
}
SecondViewController:
var passedArray = [String]()
override func viewDidLoad(){
super.viewDidLoad()
print(passedArray)
}

You can try this Solution for Data Transfer.
In FirstViewController.swift
let str = "Hello It's Done"
func callsecondViewController()
{
let controller = storyboard?.instantiateViewController(withIdentifier: "second") as! secondViewController
self.present(controller, animated: true, completion: nil)
}
func temp() -> NSString
{
return str as NSString
}
in SecondViewController.swift
var data = [NSString]()
override func viewDidLoad()
{
super.viewDidLoad()
let view = ViewController()
data = [view.temp()]
print(data)
}
and you get the output String as Hello It's Done

Related

Swift: my destinationVC segue is showing nil

I'm having users fill out some profile information via texts fields (name, email, etc.), which is used to set my ProfileContoller.shared.profile values. When I get to my navigation segue to pass the data over, my destinationVC.profile will not set its value to the sending profile object and I get nil instead.
My sendingVC is embedded in a navigation controller, while my destinationVC is embedded in Tab Bar Controller.
Segue SendingVC
Attributes Inspector SendingVC
DestinationVC
// Sending View Controller:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let profile = ProfileController.shared.profile else { return }
if segue.identifier == "signUpMemicTBC" {
let destinationVC = segue.destination as? ProfileViewController
destinationVC?.profile = profile
// Receiving ProfileViewController:
class ProfileViewController: UIViewController {
// MARK: - IBOutlets
#IBOutlet weak var fullNameLabel: UILabel!
#IBOutlet weak var usernameLabel: UILabel!
#IBOutlet weak var emailLabel: UILabel!
// MARK: - Landing Pad
var profile : Profile? {
didSet {
updateViews()
}
}
override func viewDidLoad() {
super.viewDidLoad()
updateViews()
}
func updateViews () {
guard let profile = profile else { return }
fullNameLabel.text = profile.firstName + " " + profile.lastName
usernameLabel.text = profile.username
emailLabel.text = profile.email
}
}
// ProfileController:
class ProfileController {
// MARK: - Properties
var profile : Profile?
// MARK: - Singleton
static let shared = ProfileController()
}
My sending object has data:
(lldb) po profile
Profile: 0x600000c873c0
The destination object is unexpectedly nil:
(lldb) po destinationVC?.profile
nil
didSet triggers while your vc in segue isn't loaded yet so all outlets are nil
you need to put updateViews() inside viewDidLoad
Plus your destination is a tabBar
let tab = segue.destination as! UITabBarController
let destinationVC = tab.viewControllers![2] as! ProfileViewController
I think all you have to do is call the updateViews() in the main thread.
didSet {
print("did set profile called")
DispatchQueue.main.async{[weak self] in
guard let self = self else {
return
}
self.updateViews()
}
}
Another option would be to update the views in viewDidLoad()
override func viewDidLoad() {
if let prof = self.profile {
self.updateViews()
}
}
You can use below code to safely pass data to the ProfileViewController.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let profile = ProfileController.shared.profile else { return }
if segue.identifier == "signUpMemicTBC" {
guard let tabBarController = segue.destination as? UITabBarController else { return }
guard let profileController = tabBarController.viewControllers?.index(at: 2) as? ProfileViewController else {
return
}
profileController.profile = profile
}
}

passing data from one view controller to other showing nil

//first viewController where Tvshowpath contains data. I print Tvshowpath2 in this viewController data is printed//
#objc var TvshowPath = NSDictionary()
override func viewDidLoad()
{
super.viewDidLoad()
let playerPage =
self.storyboard?.instantiateViewController(withIdentifier:
"playerLayer")
as! PlayerLayerViewController
playerPage.TvshowPath2 = TvshowPath
print(playerPage.TvshowPath2)
self.navigationController?.pushViewController(playerPage, animated: true)
}
//In the second viewController where Tvshowpath2 data getting nil
#objc var TvshowPath2 = NSDictionary()
override func viewDidLoad()
{
super.viewDidLoad()
print(TvshowPath2)
}

Can't pass value from FirstVC to SecondVC using segue

I have two ViewControllers connected via Show segue. I need to pass NSSlider's value from ViewController to SecondViewCotroller.
So, moving slider in ViewController a variable updates in SecondViewController.
How to update a value of imagesQty variable?
// FIRST VIEW CONTROLLER
import Cocoa
class ViewController: NSViewController {
#IBOutlet weak var slider: NSSlider!
#IBOutlet weak var photosLabel: NSTextField!
#IBAction func segueData(_ sender: NSSlider) {
photosLabel.stringValue = String(slider.intValue) + " photos"
self.performSegue(withIdentifier: NSStoryboardSegue.Identifier(rawValue: "SegueIdentifierForSecondVC"), sender: slider)
}
func prepare(for segue: NSStoryboardSegue, sender: NSSlider?) {
if segue.identifier!.rawValue == "SegueIdentifierForSecondVC" {
if let secondViewController =
segue.destinationController as? SecondViewController {
secondViewController.imagesQty = slider.integerValue
}
}
}
}
and
// SECOND VIEW CONTROLLER
import Cocoa
class SecondViewController: NSViewController {
var imagesQty = 30
override func viewWillAppear() {
super.viewWillAppear()
self.view.wantsLayer = true
print("viewWillAppear – Qty:\(imagesQty)")
//let arrayOfViews: [NSImageView] = [view01...view12]
let url = URL(fileURLWithPath: NSHomeDirectory()).appendingPathComponent("Desktop/ArrayOfElements")
do {
let fileURLs = try FileManager.default.contentsOfDirectory(at: url, includingPropertiesForKeys: nil, options: [.skipsHiddenFiles]).reversed()
let photos = fileURLs.filter { $0.pathExtension == "jpg" }
for view in arrayOfViews {
//"imagesQty" is here
let i = Int(arc4random_uniform(UInt32(imagesQty-1)))
let image = NSImage(data: try Data(contentsOf: photos[i]))
view.image = image
view.imageScaling = .scaleNone
}
} catch {
print(error)
}
}
First of all the purpose and benefit of NSStoryboardSegue.Identifier is to create an extension to be able to avoid literals.
extension NSStoryboardSegue.Identifier {
static let secondVC = NSStoryboardSegue.Identifier("SegueIdentifierForSecondVC")
}
Then you can write
self.performSegue(withIdentifier: .secondVC, sender: slider)
and
if segue.identifier! == .secondVC { ...
This error occurs because imagesQty is declared in viewWillAppear rather than on the top level of the class.
Change it to
class SecondViewController: NSViewController {
var imagesQty = 30 // Int is inferred
// override func viewWillAppear() {
// super.viewWillAppear()
// }
}
There is another mistake: The signature of prepare(for segue is wrong. It must be
func prepare(for segue: NSStoryboardSegue, sender: Any?) {
You can‘t change the value because the var is defined in the function and not in the class.
Make your var a class property and it should work.
class SecondViewController: UIViewController {
var imagesQty: Int = 30
...
}

pass NSArray to next viewcontroller in swift

New to swift, hope I will get my answer. I need to pass NSArray to next view controller and in random order when button is pressed. I have UILabel and one variable declared in second view controller and segue seems working. Only peoblem is it does not pass any value. Here is my code.
#IBAction func ressedbutton(_ sender: Any) {
let quotes: NSArray = ["Quote 000", "Quote 001", "Quote 002"]
let range: UInt32 = UInt32(quotes.count)
let randomNumber = Int(arc4random_uniform(range))
let QuoteString = quotes.object(at: randomNumber)
// self.resul.text = QuoteString as? String
performSegue(withIdentifier: "showresult", sender: QuoteString)
let myVC = storyboard?.instantiateViewController(withIdentifier: "result") as! result
myVC.stringPassed =
(QuoteString as? String)!
}
and code for second view is
class result: UIViewController {
var stringPassed = ""
#IBOutlet weak var ResultLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
ResultLabel.text = stringPassed
I think my problem is in myvc.stringpassed=...? How to pass the arry I have and in randomly?
Thanks in Advance.
What you need to do is pass that value with sender in performSegue and after that access that value in prepare(for:sender:) and pass the value to destinationController.
performSegue(withIdentifier: "showresult", sender: QuoteString)
Now use this sender argument in prepare(for:sender:)
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let vc = segue.destination as? result, let data = sender as? String {
vc.stringPassed = data
}
}
You have to use prepare(for segue: UIStoryboardSegue, sender: Any?) method to assign data to toViewController.UIStoryboardSegue object segue have properties like identifier ,destination and source.
In this method first you check the identifier,if it matches cast the destination controller to your custom view controller and assign the data to the view controller object.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showresult"{
if let toViewController = segue.destination as? result {
vc.stringPassed = QuoteString
}
}
}
try this way remove segue give Storyboard ID to your view controller where u want to pass data and paste that same Storyboard Id below (YourIdentifier)
#IBAction func ressedbutton(_ sender: Any) {
let quotes: NSArray = ["Quote 000", "Quote 001", "Quote 002"]
let range: UInt32 = UInt32(quotes.count)
let randomNumber = Int(arc4random_uniform(range))
let QuoteString = quotes.object(at: randomNumber)
// self.resul.text = QuoteString as? String
let vc = storyboard?.instantiateViewController(withIdentifier:"YourIdentifier") as! YourNextViewController
vc.stringPassed = (QuoteString as? String)!
self.present(vc, animated: true, completion: nil)
}

What's wrong with my delegate?

I am new to swift and right now I am learning delegate. I think I already do the right things but it is still not working.
What I am doing was passing data from my ViewController to TestViewController
ViewController:
protocol viewControllerDelegate: class {
func viewcontrollerdelegate(setviewcontrollerdelegate: ViewController)
}
class ViewController: UIViewController ,UITextFieldDelegate {
weak var delegate: viewControllerDelegate?
#IBAction func nextViewandDelegate(sender: AnyObject) {
self.delegate?.viewcontrollerdelegate(self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showTestSegue" {
if let testViewController = segue.destinationViewController as? TestViewController {
testViewController.address = address.text!
testViewController.phone = phone.text!
}
}
}
}
TestViewController:
class TestViewController: UIViewController {
var name: String?
var address: String?
var phone: String?
var trydelegate: String?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let VC = storyboard.instantiateViewControllerWithIdentifier("viewcontroller") as! ViewController
VC.delegate = self
}
override func viewWillAppear(animated: Bool) {
addressLabel.text = address!
phoneLabel.text = phone!
trydelegateLabel.text = trydelegate //always nil here
}
}
extension TestViewController:viewControllerDelegate {
func viewcontrollerdelegate(setviewcontrollerdelegate: ViewController) {
self.trydelegate = setviewcontrollerdelegate.address.text!
}
}
I used segue to pass address and phone and they worked well.
But I am suck with delegate. Can anyone help me a little bit with it? I know the question is a little easy for you here.
Thank you very much.
In TestViewController in viewDidLoad you create new object vc which is not he same as the one which call prepareForSegue so that's why it doesn't work.
To fix this remove the code from viewDidLoad:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("viewcontroller") as! ViewController
vc.delegate = self
And in prepareForSegue add one line:
testViewController.phone = phone.text!
// New line
self.delegate = testViewController
That should help.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showTestSegue" {
if let testViewController = segue.destinationViewController as? TestViewController {
testViewController.address = address.text!
testViewController.phone = phone.text!
self.delegate = testViewController
self.delegate?.viewcontrollerdelegate(self)
}
}
}
remove #IBAction func nextViewandDelegate(sender: AnyObject) and change that prepareforsegue
I fixed it......it is working right now but I dont know why