Swift - change variable in another view controller, without knowing the class name?
This is what protocols are for: defining a common language between classes when you don't want to share their exact name.
You could define a CommonVariable
protocol that describes a variable
string:
protocol CommonVariable: class {
var variable: String { get set }
}
Then edit your ViewController2
definition to conform to this protocol:
class ViewController2: UIViewController, CommonVariable {
var variable = ""
}
And edit your ViewController1
method to accept a CommonVariable
as the parameter:
class ViewController1: UIViewController {
func changeVariable(controller: CommonVariable) {
controller.variable = "Hello"
}
}
Now this method knows nothing about controller
except that it's a class with a string called variable
.
As a result, you will be able to call the method from ViewController2
without knowing the class name:
func someFunc() {
viewController1.changeVariable(controller: self)
}
As a side note, CommonVariable
, variable
, ViewController1
, and ViewController2
are all bad names. Not sure if you're actually using these names, but you should aim for something more descriptive.
Modifing one variable from another view controller swift
2 - "prepareForSegue" is called when you push a new view controller via the segue, but not when you dismiss it. No segue is called upon dismissal.
1 - A good way to do this would be the delegate pattern.
So the main view controller would be the delegate for the currencyViewController, and would receive a message when that controller is dismissed.
In the start of the currencyViewController file you prepare the delegate:
protocol CurrencyViewControllerDelegate {
func currencyViewControllerDidSelect(value: String)
}
and you add a variable to the currencyViewController:
var delegate : CurrencyViewControllerDelegate?
Now, the mainViewController has to conform to that protocol and answer to that function:
class MainViewController : UIViewController, CurrencyViewControllerDelegate {
//...
func currencyViewControllerDidSelect(value: String) {
//do your stuff here
}
}
And everything is prepared. Last steps, in prepareForSegue (MainViewController), you will set the delegate of the currencyViewController:
var currencyVC = segue.destinationViewController as CurrencyViewController
currencyVC.delegate = self;
And when the user selects the value in currencyViewController, just call that function in the delegate:
self.delegate?.currencyViewControllerDidSelect("stuff")
A bit complex maybe, but it's a very useful pattern :) here is a nice tutorial with more info if you want it:
http://www.raywenderlich.com/75289/swift-tutorial-part-3-tuples-protocols-delegates-table-views
Receive changing data into another controller Swift
You need to add an observer and keep reference to the destination view controller to keep passing in the new value that has been changed to the destination view controller. Here's how:
class ViewController: UIViewController, CBCentralManagerDelegate, CBPeripheralDelegate {
var distanta1 = String(byteArray[0]) {
didSet {
destinatieVC?.distance1 = distanta1
}
}
//...
var destinatieVC: SensorViewViewController?
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToSenzori" {
destinatieVC = segue.destination as? SensorViewViewController
}
}
}
In SensorViewViewController:
var distance1: String? {
didSet {
print(distance1 ?? "")
}
}
Better approach: Set the destinatieVC?.distanta1.text = distanta1
directly if you're not doing anything else in the didSet
block avoid the distance1
property entirely.
Using variables from one View Controller in another
I'd suggest a 3rd class to abstract Player info and make it Singleton. Something like this:
class Players {
static let shared = Players()
var one: String {
get {
return UserDefaults.standard.object(forKey: "playerone") as? String ?? ""
}
set(newValue) {
UserDefaults.standard.set(newValue, forKey: "playerone")
}
}
}
And access/set same like this:
Players.shared.one = "Name one"
print(Players.shared.one)
Swift: Change value of another ViewController with delegation programmatically
You should not create a new ViewController
instance each time you call ViewController2.addCreditsToCounter
, you already have a ViewController
that creates a ViewController2
instance in ViewController.changeView
. Just store a weak reference to ViewController
in ViewController2
using delegate. In such case ViewController
(not ViewController2
) should conform to AddCreditsDelegate
.
First of all, replace
protocol AddCreditsDelegate {
func addCreditsToCounter()
}
with
protocol AddCreditsDelegate: AnyObject {
func addCreditsToCounter()
}
Then add weak var delegate: AddCreditsDelegate?
to ViewController2
and remove ViewController.delegate
. Remove ViewController2.addCreditsToCounter
, ViewController2
should not conform to AddCreditsDelegate
. It means that in ViewController2.addCreditsButton
you should call delegate?.addCreditsToCounter()
, not addCreditsToCounter()
.
ViewController
should conform to AddCreditsDelegate
:
extension ViewController: AddCreditsDelegate {
func addCreditsToCounter() {
counterView.creditPointValue += 5
print("pressed")
}
}
And don't forget to initialize ViewController2.delegate
. Replace your ViewController.changeView
implementation with
let controller = ViewController2()
controller.delegate = self
navigationController?.pushViewController(controller, animated: true)
How to pass a (changing) variable between two view controllers?
Use a delegate pattern.
In VC2:
protocol VC2Delegate: AnyObject {
var id2: Int { get }
}
class VC2 {
weak var delegate: VC2Delegate?
override func viewDidLoad() {
super.viewDidLoad()
print(delegate?.id2)
}
}
In VC1:
class VC1: UIViewController, VC2Delegate {
...
var id2: Int = 0
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let vc2 = segue.destination as? navigationScreenVC else { return }
vc2.delegate = self
}
...
}
Variable value of a ViewController is changed by forward ViewController when passed parameter
When you assign a SaleOrder to the second view controller you are passing a reference to the SaleOrder instead of a copy.
That means whenever you update the SaleOrder on the second screen you are updating the same SaleOrder used by the first one.
I think simply changing it to let instead of var in the first screen might fix it.
You can also try passing a copy of the object instead of a reference with saleOrder!.copy(), though I think your SaleOrder class will need to conform to the NSCopying protocol.
If you want to learn more about reference types you can read this topic Is Swift Pass By Value or Pass By Reference
Related Topics
Iad Interstitials Not Showing Consistently? and Not at All on the Simulator
How to Make App Wait Until Firebase Request Is Finished
How to Change Pin Color in Mapkit Under the Same Annotationview (Swift3)
Problems with Cropping a Uiimage in Swift
Turn Swift Object into a JSON String
My Reachability Notifier Is Only Able to Be Called Once
How to Parse a Iso 8601 Duration Format in Swift
Multiple Image Pickers in One Controller
Uitableviewcell Custom Class - Reload Cell Height After Change in Subview Height Constraint
Swift - Uitableview Didselectrowatindexpath & Diddeselectrowatindexpath Add & Remove Indexpath Ids
How to Indicate a View Which Has Created with Uikit from a Skscene
Mysterious "Cryptographic Verification Failure" Error on MACos Sierra, Xcode 8
How to Create a "Hyperlink" with Swift
How to Get Camera Calibration Data on iOS? Aka Avcameracalibrationdata
The Array Value Should Be Sort Like (Alphabetic, Numbers and Special Characters)