Sending array data from one view controller to another - swift

I am trying to copy an array from one view controller to another view controller, but somehow it does not work.. I have tried using this code:
let otherVC = TerningspilletViewController()
mineSpillere = otherVC.mineSpillere2
println("otherVC")
In the view controller i want to send the data from has this code:
var mineSpillere = ["Spiller 1", "Spiller 2", "Spiller 3"]
The view controller that is going to received this data, has this code:
var mineSpillere2 = [String]()
the "var mineSpillere" is going to show the text, but when i try to show it, it says that the "var mineSpillere" is empty. Any suggestions/ideas?

If you want to access array of another viewController then you can save it in memory and for that you can use NSUserDefaults this way:
//save
var mineSpillere = ["Spiller 1", "Spiller 2", "Spiller 3"]
var defaults = NSUserDefaults.standardUserDefaults()
defaults.setObject(mineSpillere, forKey: "YourKey")
Now you can read it from anywhere this way:
//read
if let testArray : AnyObject? = NSUserDefaults.standardUserDefaults().objectForKey("YourKey") {
var readArray : [NSString] = testArray! as! [NSString]
println(readArray)
}
And if you want to do with your old way here is code:
FirstViewController.swift
import UIKit
class FirstViewController: UIViewController {
var mineSpillere = ["Spiller 1", "Spiller 2", "Spiller 3"]
override func viewDidLoad() {
super.viewDidLoad()
}
}
SecondViewController.swift
import UIKit
class SecondViewController: UIViewController {
var mineSpillere2 = [String]()
override func viewDidLoad() {
super.viewDidLoad()
let otherVC = FirstViewController()
mineSpillere2 = otherVC.mineSpillere
println(mineSpillere2) //[Spiller 1, Spiller 2, Spiller 3]
}
}

first checkout are you using story board
if you are using storyboard
let otherVc = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle()).instantiateViewControllerWithIdentifier("storyboardIdendifier") as? TerningspilletViewController
otherVC.mineSpillere2 = mineSpillere
println(otherVc)
otherwise do like this
let otherVC = TerningspilletViewController()
otherVC.mineSpillere2 = mineSpillere
println("otherVC")

if you are using storyboards, I suggest passing the data in prepareForSegue:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "TerningspilletViewSegue" {
let otherVc = segue.destinationViewController as! TerningspilletViewController
otherVc.mineSpillere = mineSpillere
}
}

Try this code working fine sending data from one viewController to another viewcontroller.just reference of storyboard id you can send data from one view to another view .Then we create that class object based on that object reference we can access that array and those class properties then just append it.
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let secondView = storyBoard.instantiateViewController(withIdentifier: "tableView") as! TableViewController.
self.present(secondView, animated: true) {
let data = nameArray
secondView.models.append(data!)
secondView.tableView.reloadData()
}

Related

How do I reload UIScrollView containing ViewControllers to add/remove view controllers

I have a scrollView that contains a dynamic amount of WeatherViewControllers each displaying the weather data of a different city the user has saved. The user can segue from the WeatherViewControllers to a CityListViewController. Where they can add and remove cities from their list which in turn should add and remove WeatherViewControllers from the scrollView upon dismissing the CityListViewController, this is where I am running into a problem.
Currently I am trying to use a protocol to call viewDidLoad in the scrollViewController upon dismissing the CityListViewController but am getting an error:
Fatal error: Unexpectedly found nil while unwrapping an Optional
value: file)
when it gets to:
let weatherScreen = storyboard!.instantiateViewController(identifier: "View Controller") as! ViewController
Side Note: Upon initially opening the app the scrollView loads properly with all the correct WeatherViewControllers in the UIScrollView and the correct cities in the list.
class ScrollViewController: UIViewController, ScrollReloadProtocol {
func reloadScrollView() {
print("SCROLL RELOADED!!!!!*******")
self.viewDidLoad()
}
#IBOutlet weak var totalScrollView: UIScrollView!
var pages = [ViewController]()
var x = 0
var weatherScreensArray = [SavedCityEntity]()
var weatherScreenStringArray = [String]()
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
var horizString = "H:|[page1(==view)]"
let defaults = UserDefaults.standard
override func viewDidLoad() {
super.viewDidLoad()
//userDefaults used to keep track of which screen is which to put different cities on different viewControllers
defaults.set(0, forKey: "screenNumber")
//load cities to get number of cities saved
loadCities()
var views : [String: UIView] = ["view": view]
//create all weatherWeatherControllers
while x <= weatherScreensArray.count {
pages.append(createAndAddWeatherScreen(number: x))
weatherScreenStringArray.append("page\(x+1)")
views["\(weatherScreenStringArray[x])"] = pages[x].view
let addToHoriz = "[\(weatherScreenStringArray[x])(==view)]"
horizString.append(addToHoriz)
x+=1
}
horizString.append("|")
let verticalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "V:|[page1(==view)]|", options: [], metrics: nil, views: views)
let horizontalConstraints = NSLayoutConstraint.constraints(withVisualFormat: horizString, options: [.alignAllTop, .alignAllBottom], metrics: nil, views: views)
NSLayoutConstraint.activate(verticalConstraints + horizontalConstraints)
}
//Function to create and add weatherViewController
func createAndAddWeatherScreen(number: Int) -> ViewController {
defaults.set(number, forKey: "screenNumber")
let weatherScreen = storyboard!.instantiateViewController(identifier: "View Controller") as! ViewController
weatherScreen.view.translatesAutoresizingMaskIntoConstraints = false
totalScrollView.addSubview(weatherScreen.view)
addChild(weatherScreen)
weatherScreen.didMove(toParent: self)
return weatherScreen
}
}
You could try something like this:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let weatherScreen = storyboard.instantiateViewController(withIdentifier: "View Controller") as! ViewController
It's also probably better to use one word for the identifier: "ViewController", and give it the same name as the class. Make sure to set these values also in your actual storyboard.

Add custom view controller as root view controller in my mac application?

I already checked most of the answers to this question but mostly are for Cocoa Touch. I need to implement this in my appdelegate for mac application.
Once user is logged-in he will be redirected to the main screen else go to login screen.
let controller:NSWindowController = NSWindowController()
let viewController:NSViewController
let storyboard = NSStoryboard.init(name: "Main", bundle: nil)
let stringLoginStatus = NSUserDefaults.standardUserDefaults().objectForKey(Constants.Key_LoginStatus) as? String
if stringLoginStatus != nil
{
if stringLoginStatus == "true"
{
viewController = storyboard.instantiateControllerWithIdentifier("Channel") as! NSViewController
}
else{
viewController = storyboard.instantiateControllerWithIdentifier("ViewController") as! NSViewController
}
}
else{
viewController = storyboard.instantiateControllerWithIdentifier("ViewController") as! NSViewController
}
controller.window?.contentViewController = viewController
controller.window?.makeKeyAndOrderFront(self)
It shows and error as controller is not being initialized.
try this code to change your view controller:-
UIApplication.appWindow.rootViewController = UIStoryboard.main.instantiateViewController(withIdentifier: "customViewControl")
//MARK: Make UIApplication extension to get appWindow
extension UIApplication {
class var appWindow: UIWindow! {
return (UIApplication.shared.delegate?.window!)!
}
}
//MARK: Make Storyboard extension to get main screen
extension UIStoryboard {
class var main: UIStoryboard {
let storyboardName: String = Bundle.main.object(forInfoDictionaryKey: "UIMainStoryboardFile") as! String
return UIStoryboard(name: storyboardName, bundle: nil)
}
}

Call external function but no value

good morning,
i have this class:
import Cocoa
class PopOverDetails: NSViewController {
var dID = String()
#IBOutlet weak var txtEmail: NSTextField!
public func fillDetails (ID:NSManagedObjectID) {
print("=== fillDetails ===")
print(ID)
dID = "\(ID)"
}
override func viewDidLoad() {
print("=== viewDidLoad ===")
print(dID)
}
}
i call the function from another view controller
let Controller = PopOverDetails()
Controller.fillDetails(ID: list[0].objectID)
al works fine, but the problem is:
in my function fillDetails, i get the objectID Value which i "send" from the view controller.
but i can't work with this value in the viedidload because it is empty.
this is my output:
=== fillDetails ===
0x40000b <x-coredata://7E006435-3E05-41F9-A3E4-CB8179A319A9/list/p1>
=== viewDidLoad ===
where is my mistake? :)
UPDATE
let vcDetails = NSStoryboard(name: "Main", bundle: nil).instantiateController(withIdentifier: "PopoverDetails") as! NSViewController
popover.contentViewController = vcDetails
popover.show(relativeTo: tblView.rect(ofRow: tblView.selectedRow) , of: tblView, preferredEdge: .maxX)
}
First declare variable in PopOverDetails i.e."id",then
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let secondViewController = storyBoard.instantiateViewController(withIdentifier: "your_identifier") as! PopOverDetails
secondViewController.id = list[0].objectID
self.navigationController?.pushViewController(secondViewController, animated: true)
Now you can get that variable in PopViewController's class

How do I pass data from a View controller into my pop up view controller (swift/ios)

I'm quite new with Swift and I'm making this mini game type app that counts the score and updates the label in the view controller. I want to pass that score from a view controller into another external pop up view controller I created.
#IBAction func Button7Tapped(_ sender: AnyObject)
{
if Index == 13 {
game.score += 1
} else {
let scorepopVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "finalScorePop") as! finalScoreViewController
self.addChildViewController(scorepopVC)
scorepopVC.view.frame = self.view.frame
self.view.addSubview(scorepopVC.view)
scorepopVC.didMove(toParentViewController: self)
}
updateGame()
}
Above is my code for the external pop up view controller I created, which also has a separated .swift file. How would I go about taking my game.score and passing that into my Popup view controller?
In your finalScoreViewController swift file add a new property.
final class FinalScoreViewController: UIViewController {
var score: Int?
}
And then just assign it when you're instantiating it.
#IBAction func Button7Tapped(_ sender: AnyObject) {
if Index == 13 {
game.score += 1
} else {
let scorepopVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "finalScorePop") as! finalScoreViewController
scorepopVC.score = game.score //THIS LINE
self.addChildViewController(scorepopVC)
scorepopVC.view.frame = self.view.frame
self.view.addSubview(scorepopVC.view)
scorepopVC.didMove(toParentViewController: self)
}
updateGame()
}
It is better to use storyboard to open the ViewController. In storyboard, right click and drag from you button to the second view controller (the one that you wish to open).
Choose the segue type that you wish to use. In your case, I think Present Modally will work fine.
You will see a line between the two UIViewControllers in storyboard. That is the segue. Tap on it. In the Attributes inspector give the segue an identifier. For instance "myFirstSegue".
Then in the code of the UIViewController that contains your button override prepare(for:sender:). This method is called when preparing for the segue to happen. I.o.w when you tap on the button. You have access to the destination UIViewController and can therefor access and set the properties on it.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "myFirstSegue" {
if let vc = segue.destination as? MyViewController {
//here you set your data on the destination view controller
vc.myString = "Hello World"
}
}
}
Note that we check the identifier, because all segues that go from this ViewController to other ViewControllers will call prepare(for:sender:)
It's quite simple, Just add a property in your finalScoreViewController (if you are not already done this) and -for example- call it score:
class finalScoreViewController: UIViewController {
var score: String?
// ...
Add this line to the Button7Tapped action (where you set a value for finalScoreViewController's score):
let scorepopVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "finalScorePop") as! finalScoreViewController
// add this line:
scorepopVC.score = "My score"
self.addChildViewController(scorepopVC)
scorepopVC.view.frame = self.view.frame
self.view.addSubview(scorepopVC.view)
scorepopVC.didMove(toParentViewController: self)
Finally, in finalScoreViewController:
override func viewDidLoad() {
super.viewDidLoad()
if let scr = score {
print(scr)
}
}
Hope that helped.
You do not actually have to pass the variable to the next view controller. All you have to do is create a variable outside of the View Controller class, and voila, you can access your variable from anywhere, in any swift file. For example:
var score = 0
class ViewController: UIViewController {
override func viewDidLoad(){
super.viewDidLoad()
}
#IBAction func Button7Tapped(_ sender: AnyObject){
score += 1
}
}
And then in the other View Controller, you would have something like this:
#IBOutlet weak var scoreLabel: UILabel!
class ViewController: UIViewController {
override func viewDidLoad(){
super.viewDidLoad()
var timer1 = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(updateScore), userInfo: nil, repeats: true)
}
#objc func updateScore() {
scoreLabel.text = "You have \(score) points!"
}

Having issues setting delegate with Observer Pattern

I'm trying to realize the Observer Pattern and I'm experiencing some difficulty as my delegate doesn't seem to be setting properly.
In my Main.storyboard I have a ViewController with a container view. I also have an input box where I'm capturing numbers from a number keypad.
Here's my storyboard:
I'm trying to implement my own Observer Pattern using a protocol that looks like this:
protocol PropertyObserverDelegate {
func willChangePropertyValue(newPropertyValue:Int)
func didChangePropertyValue(oldPropertyValue:Int)
}
My main ViewController.swift
class ViewController: UIViewController {
#IBOutlet weak var numberField: UITextField!
// observer placeholder to be initialized in implementing controller
var observer : PropertyObserverDelegate?
var enteredNumber: Int = 0 {
willSet(newValue) {
print("//Two: willSet \(observer)") // nil !
observer?.willChangePropertyValue(5) // hard coded value for testing
}
didSet {
print("//Three: didSet")
observer?.didChangePropertyValue(5) // hard coded value for testing
}
}
#IBAction func numbersEntered(sender: UITextField) {
guard let inputString = numberField.text else {
return
}
guard let number : Int = Int(inputString) else {
return
}
print("//One: \(number)")
self.enteredNumber = number // fires my property observer
}
}
My ObservingViewController:
class ObservingViewController: UIViewController, PropertyObserverDelegate {
// never fires!
func willChangePropertyValue(newPropertyValue: Int) {
print("//four")
print(newPropertyValue)
}
// never fires!
func didChangePropertyValue(oldPropertyValue: Int) {
print("//five")
print(oldPropertyValue)
}
override func viewDidLoad() {
super.viewDidLoad()
print("view loads")
// attempting to set my delegate
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let pvc = mainStoryboard.instantiateViewControllerWithIdentifier("ViewController") as! ViewController
print("//six \(pvc)")
pvc.observer = self
}
}
Here's what my console prints:
What's happening
As you can see when my willSet fires, my observer is nil which indicates that I have failed to set my delegate in my ObservingViewController. I thought I set my delegate using these lines:
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let pvc = mainStoryboard.instantiateViewControllerWithIdentifier("ViewController") as! ViewController
print("//six \(pvc)")
pvc.observer = self
However, I must be setting my delegate incorrectly if it's coming back nil.
Question
How do I properly set my delegate?
You are calling into the storyboard to instantiate a view controller and setting it as the observer, however that instantiates a new instance of that view controller, it doesn't mean that it is referencing the one single "view controller" that is in the storyboard. ObservingViewController needs another way to reference the ViewController that has already been created.
So #Chris did reenforce my suspicions which helped me to figure out a solution for assigning my delegate to my view controller properly.
In my ObservingViewController I just need to replace the code in my viewDidLoad with the following:
override func viewDidLoad() {
let app = UIApplication.sharedApplication().delegate as! AppDelegate
let vc = app.window?.rootViewController as! ViewController
vc.observer = self
}
Rather than creating a new instance of my view controller, I'm now getting my actual view controller.