How can i get image to some imageView, which is in another Viewcontroller, and wasn't created(is nil) yet - swift

How can i get image to some imageView, which is in another Viewcontroller, and wasn't created(is nil) yet
let vc = SelectedCellViewController()
vc.nameLabel.text = MainViewController.dishesArray[indexPath.section].name
Fatal error: Unexpectedly found nil while implicitly unwrapping an
Optional value

Create a variable name and set that variable while creating the instance of SelectedCellViewController. Set the text to nameLabel in viewDidLoad().
class SelectedCellViewController: UIViewController {
#IBOutlet weak var nameLabel: UILabel!
var name: String?
override func viewDidLoad() {
super.viewDidLoad()
self.nameLabel.text = self.name
}
}
Usage:
if let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "SelectedCellViewController") as? SelectedCellViewController {
vc.name = MainViewController.dishesArray[indexPath.section].name
}

Related

How do I present ViewController programatically?

import UIKit
//EventList ViewController
class EventPage: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
}
class EventForm: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
//IBOutlets
#IBOutlet weak var eventNameField: UITextField!
#IBOutlet weak var fromTimePicker: UIDatePicker!
#IBOutlet weak var toTimePicker: UIDatePicker!
#IBOutlet weak var colorPreview: UIView!
#IBAction func cancel(_ sender: Any) {
//empty text field
eventNameField.text = ""
}
#IBAction func save(_ sender: Any) {
if (eventNameField.hasText) {
//fix error handling
eventNameField.backgroundColor = UIColor.systemGray2
//pull data from fields
let text = eventNameField.text!
let fromTime = fromTimePicker.date
let toTime = toTimePicker.date
//initialize object
let currentEvent = EventModel(eventName: text, fromTime: fromTime, toTime: toTime, color: storedColor)
//append to data model
EventDataArray.append(currentEvent)
//transition
present(EventPage(), animated:true)
}
else {
eventNameField.backgroundColor = UIColor.systemRed
}
}
}
I currently have an EventPage class declared as type UIViewController, but upon pressing the save button with a populated text field a transition to a blank ViewController occurs. I've attached the class to the correct ViewController in main.storyboard.
The problem in here is that you are creating a new EventPage but it doesn't inherit from Storyboard.
1
Go to the inspector in your storyboard, select your View Controller, and write an identifier for your View Controller (can be anything)
Write it in Storyboard ID:
2
Replace
present(EventPage(), animated:true)
With
(don't forget to replace 'MYIDENTIFIER' with the id you entered earlier)
let viewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "MYIDENTIFIER") as! EventPage
// If you need to do any configurations to your view controller, do that in here.
// For example:
// viewController.label.text = "Hello, world!"
present(viewController, animated:true)
Note
If the name of your Storyboard file name is not called Main, replace "Main" in step 2 with the name of your storyboard file (excluding .storyboard)

How to pass data of one label(mainStoryBoard) to another label(of second storyboard)

I have a label1 in a view controller of main.storyboard
i have another label2 in view controller of storyboard named Second.storyboard
how can I pass data from one storyboard to another all solutions I can find are about passing data within the same storyboard.Help me with my question.
make a Global variable in Second View Controller
var labelText = ""
While Pushing to secondViewController from First Controller
let secondVC = secondViewController()
secondVC.labelText = label.text // Pass label text from first VC
self.navigationController?.pushViewController(secondVC, animated: true)
Create the instance of Storyboard with the relevant name while creating the instance of SecondViewController in FirsViewController, i.e
class FirsViewController: UIViewController {
#IBOutlet weak var label1: UILabel!
func pushVC2(_ sender: UIButton) {
if let controller = UIStoryboard(name: "Storyboard-2", bundle: nil).instantiateViewController(withIdentifier: "SecondViewController") as? SecondViewController { //here....
controller.str = "Your_Text_Here"
self.navigationController?.pushViewController(controller, animated: true)
}
}
}
Your SecondViewController looks like,
class SecondViewController: UIViewController {
#IBOutlet weak var label2: UILabel!
var str: String?
override func viewDidLoad() {
super.viewDidLoad()
self.label2.text = str
}
}

NSLayoutConstraint: Found nil while unwrapping optional Value

having a bit of a problem here, so I was trying to cal a function of which it will change the height constraint constant, but it gives me an error :
"NSLayoutConstraint: Found nil while unwrapping optional Value"
Another catch is I can change the constant from the ViewDidLoad() function without any errors, while calling the function from another controller gives me the error.
I tried to clean the project, delete the outlet and re-outlet it again. No luck.
Hope you can help me, thanks!
MainController
var bottomContainerCon: CGFloat = 80
#IBOutlet var bottomContainerHeight: NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
bottomContainerHeight.constant = bottomContainerCon
}
func changeHeight() {
bottomContainerHeight.constant = self.bottomContainerCon
self.view.layoutIfNeeded()
}
PagerController
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = self.storyboard?.instantiateViewController(withIdentifier: "MainNeedPage") as! NeedDetailsController
let currentIndex = pages.index(of: previousViewControllers.first!)!
let nextIndex = abs((currentIndex + 1) % pages.count)
if(nextIndex == 0) {
vc.changeHeight(value:80)
} else {
vc.changeHeight(value:250)
}
override func viewDidLayoutSubviews() {
self.bottomContainerHeight.constant = self.bottomContainerCon
self.view.layoutIfNeeded()
}
Here's the storyboard Storyboard
Since you instantiate the VC , then the outlet is nil until view loads
#IBOutlet var bottomContainerHeight: NSLayoutConstraint!
you need to do this
var bottomContainerCon: CGFloat = 0
then assign the value inside
viewDidLoad / viewDidLayoutSubviews like this
bottomContainerHeight.constant = bottomContainerCon

Append text to NSScrollView - Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value

I am doing a Mac application, and I have a problem appending text to a NSScrollView when I call a function from a different class.
I have this function on my ViewController class:
import Cocoa
class PopoverVC1: NSViewController {
let popover1 = NSPopover()
class func loadView() ->PopoverVC1 {
let vc = NSStoryboard(name: NSStoryboard.Name(rawValue: "Main"),
bundle: nil).instantiateController(withIdentifier:
NSStoryboard.SceneIdentifier(rawValue: "Popover1")) as! PopoverVC1
vc.popover1.contentViewController = vc
return vc
}
override func viewDidLoad() {
super.viewDidLoad()
popover1.behavior = .transient
popover1.contentViewController = self
}
func showPopover (view: NSView){
popover1.show(relativeTo: view.bounds, of: view, preferredEdge: .maxY)
}
#IBOutlet weak var radioOption1: NSButton!
#IBOutlet weak var radioOption2: NSButton!
#IBOutlet weak var radioOption3: NSButton!
#IBAction func clickOption(_ sender: NSButton) {
switch sender {
case radioOption1: popover1.performClose(sender)
case radioOption2: let vc = ViewController()
vc.myPrint(string: "This is a test")
default: print ("hello")
}
}
}
Than I have a PopoverVC1 class, which is a class to a popover I am using:
import Cocoa
class ViewController: NSViewController {
#IBOutlet weak var oneYes: NSButton!
#IBOutlet weak var oneNo: NSButton!
#IBOutlet weak var notesArea: NSScrollView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded
}
}
func myPrint (string: String){
let mystring = string
let myNotes = notesArea.documentView as? NSTextView
let text = myNotes?.textStorage!
let attr = NSAttributedString(string: mystring)
text?.append(attr)
}
let popover1 = NSPopover()
#IBAction func oneClicked(_ sender: NSButton) {
switch sender {
case oneYes: let vc = PopoverVC1.loadView()
vc.showPopover(view: sender)
case oneNo:
let myNotes = notesArea.documentView as? NSTextView
let text = myNotes?.textStorage!
let attr = NSAttributedString(string: "test")
text?.append(attr)
default: print ("")
}
}
}
However, I got an error when I press the radio button "oneNo" that should call the function "myPrint" and pass the argument.
Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
I did some tests and when I call this same function "myPrint" from within the ViewCotroller class it works fine.
Any ideas?
Your issue is in clickOption when you are calling:
let vc = ViewController()
vc.myPrint(string: "This is a test")
When you call this method from code and the ViewController's UIViews are set up in a storyboard, the connection from the storyboard is not made. That is why the notesArea is nil when you call the function myPrint. In this case you are creating a new copy of ViewController and it will not be the same one that created the popover.
There are a few ways you can solve the problem that you are trying to accomplish. One of them is known as a delegate. This is a way for you to to call the ViewController's methods like your popover inherited them. You can check out a tutorial here. The idea is that we want to have a reference to the ViewController in your popover so that you can call the functions in the protocol. Then the ViewController that conforms to the protocol will be responsible for handling the method call.
So let's create a protocol called PrintableDelegate and have your ViewController class conform to it. Then in your popover, you will be able to have a reference to the ViewController as a weak var called delegate (you can use what ever name you want but delegate is standard). Then we can call the methods described in the protocol PrintableDelegate, by simply writing delegate?.myPrint(string: "Test"). I have removed some of your irrelevant code from my example.
protocol PrintableDelegate {
func myPrint(string: String)
}
class ViewController : UIViewController, PrintableDelegate {
func myPrint (string: String){
let mystring = string
let myNotes = notesArea.documentView as? NSTextView
let text = myNotes?.textStorage!
let attr = NSAttributedString(string: mystring)
text?.append(attr)
}
#IBAction func oneClicked(_ sender: NSButton) {
let vc = PopoverVC1.loadView()
// Set the delegate of the popover to this ViewController
vc.delegate = self
vc.showPopover(view: sender)
}
}
class PopoverVC1: NSViewController {
// Delegates should be weak to avoid a retain cycle
weak var delegate: PrintableDelegate?
#IBAction func clickOption(_ sender: NSButton) {
// Use the delegate that was set by the ViewController
// Note that it is optional so if it was not set, then this will do nothing
delegate?.myPrint(string: "This is a test")
}
}

passing value with protocol: ViewController to .xib file in swift

So i have a class "CalendarioViewController" with one protocol "DateSelectedDelegate".
Protocol:
protocol DateSelectedDelegate {
func dateSelected (date: String)}
I declare a variable protocol type:
var dateDelegate: DateSelectedDelegate? = nil
Into my class "CalendarioViewController" i have a #IBAction button:
#IBAction func gotoHotelVC(_ sender: Any) {
if dateDelegate != nil {
if fechaSelected.text != nil {
let data = fechaSelected.text
dateDelegate?.dateSelected(date: data!)
}
}
}
In my secondVC or "FechasViewController" i use the protocol define early, i call the CalendarioViewController with two button. The FechasViewController is a xib file:
#IBAction func fechaArribo(_ sender: Any) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc:CalendarioViewController = storyboard.instantiateViewController(withIdentifier: "calendario") as! CalendarioViewController
vc.dateDelegate = self
self.window!.rootViewController = vc
}
#IBAction func fechaSalida(_ sender: Any) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc:CalendarioViewController = storyboard.instantiateViewController(withIdentifier: "calendario") as! CalendarioViewController
vc.dateDelegate = self
self.window!.rootViewController = vc
}
my #IBOutlet:
#IBOutlet weak var fechaArriboLabel: UILabel!
Use protocol:
extension FechasViewController: DateSelectedDelegate {
func dateSelected(date: String) {
fechaArriboLabel.text = date
print(date)
print(fechaArriboLabel.text!)
}
}
The line print(date) or print(fechaArriboLabel.text!) is work just fine... but my xib label don't not change anything:
here my xib:
and this is my Storyboard:
Put here my entire code:
enter image description here
Please...help!