Accessing image from prepare segue error [duplicate] - ios

This question already has answers here:
Passing Image to another View Controller (Swift)
(4 answers)
Closed 5 years ago.
Normally, we link the image from storyboard to viewcontroller by IBOutlet by this code:
#IBOutlet private weak var resultImage: UIImageView!
we can update the image by calling this: resultImage.image = UIImage(named: "image"). It works ok
However, when i call this in the prepare for segue, it found nil:
let destinationDetail = segue.destination as! RestaurantViewController
destinationDetail.restaurantImage.image = UIImage(named: "image")
restaurantImage is an Outlet in RestaurantViewController: #IBOutlet weak var restaurantImage: UIImageView!
I dont understand why it found nil, please help!

Because view controlle haven't been set up yet. you can use IBOutlet after view is load.
In viewDidLoad or viewDidAppear of your destination viewController you will do something like this:
override func viewDidLoad() {
super.viewDidLoad()
resultImage.image = newImage
}

Related

IBOutlet References found nil when containing view controller is presented programmatically [duplicate]

This question already has answers here:
Instantiate and Present a viewController in Swift
(18 answers)
Closed 2 years ago.
I am building a running app and am trying to programmatically present a view controller when the start run button is tapped. However, when I tap the button after setting up the presenting view controller, any reference to an IBOutlet is found nil when unwrapping in the order that they are called.
It's worth noting that when I connect the two view controllers with "show" via storyboard instead, that everything works fine, but I want to present the view controller programmatically and in fullscreen rather than the cardlike presentation by default.
From the presenting view controller:
#IBAction func startRunTapped(_ sender: Any) {
let inRunVC = CurrentRunVC()
inRunVC.modalPresentationStyle = .fullScreen
self.present(inRunVC, animated: true, completion: nil)
}
From the presented view controller:
import UIKit
import MapKit
class CurrentRunVC: LocationVC {
#IBOutlet weak var sliderImageView: UIImageView!
#IBOutlet weak var swipeBGImageView: UIImageView!
#IBOutlet weak var durationLabel: UILabel!
#IBOutlet weak var paceLabel: UILabel!
#IBOutlet weak var distanceLabel: UILabel!
#IBOutlet weak var pauseButton: UIButton!
var startLocation: CLLocation!
var lastLocation: CLLocation!
var timer = Timer()
var runDistance = 0.0
var pace = 0
var counter = 0
override func viewDidLoad() {
super.viewDidLoad()
let swipeGesture = UIPanGestureRecognizer(target: self, action: #selector(endRunSwiped(sender:)))
sliderImageView.addGestureRecognizer(swipeGesture) //error unwrapping here
sliderImageView.isUserInteractionEnabled = true // and here
swipeGesture.delegate = self as? UIGestureRecognizerDelegate
}
//errors also on any other reference to an IBOutlet
I've confirmed that all IBOutlets are connected properly.
Storyboard:
Thanks in advance
You are not grabbing the correct storyboard instance of CurrentVC but you are creating a new one. Instead of let inRunVC = CurrentRunVC(), use
let runVC = self.storyboard?.instantiateViewController(withIdentifier: "CurrentRunVC") as! CurrentRunVC //set the identifier in the storyboard identity inspector
Your view controller's outlets are defined in the storyboard, and created when the view controller is loaded from the storyboard. When you just initialise a new view controller in this line:
let inRunVC = CurrentRunVC()
Then the system will look for a xib file with the same name as the view controller, which doesn't exist, which means it just loads a blank view with no connected outlets. All those implicitly unwrapped optionals are now nil.
Either make a new segue from the button to the same view controller, but a modal presentation, or add a reference to the presented view controller in the storyboard and then load it using the instatiate with identifier method of the current storyboard.

Swift load UIViewController from xib IBOutlets nil [duplicate]

This question already has answers here:
IBOutlet is nil, but it is connected in storyboard, Swift
(31 answers)
Closed 4 years ago.
I'm pulling out what little hair I have left!
I have a UIViewController with a matching .xib file. In the .xib, I have an IBOutlet that I made in interface builder called "titleText"
In a section of my code, I have the following lines:
let fooVC = FooViewController(nibName: "FooViewController", bundle: Bundle.main)
fooVC.titleText = "TEST"
The viewController "seems" to load fine, I get an object of the correct type, but the IBOutlets are not initialized.
Is there an additional step that I need to do to initialize any IBOutlets that I may have?
This has got to be something really simple, right?!
Outlets are nil until the view loads. So just make another variable and store title string like below
class FooViewController: UIViewController {
#IBOutlet titleText:UILable!
var titleString:String?
override func viewDidLoad() {
super.viewDidLoad()
titleText.text = titleString
}
}
Use:
let fooVC = FooViewController()
fooVC.titleString = "TEST"

Set the UIImageView of a view controller instance

I am currently trying to set the UImageView of a UIViewController class I defined called MyViewController. In the MyViewController class I have an outlet for the UIImage like so:
#IBOutlet weak var img: UIImageView?
I then try to set it in another class by using:
let vc:MyViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "test") as! MyViewController
vc.imgView!.image = UIImage(named: "wonders1.png")
The problem is imgView is nil when I force unwrap and I'm not sure why since I'm instantiating the view controller
image of my storyboard:
https://i.stack.imgur.com/ubpQN.png
Error I'm getting:
fatal error: unexpectedly found nil while unwrapping an Optional value
You are trying to add image to an UIImageView instance which isn't initialized yet, the views on UIViewController instance is loaded only after func viewDidLoad() function gets called (read more on iOS life cycle here).
So in order to complete your task you should implement this inside MyViewController:
override func viewDidLoad() {
super.viewDidLoad()
vc.imgView.image = UIImage(named: "wonders1.png")
}

ImageView retuning nil

I have a view controller OtherUserAccountViewController containing a button with a "profile picture" as its background. When this button is tapped, I would like to push a new view controller ImageTappedViewController onto the stack to simply present a bigger ImageView of this said profile picture. Please note the Storyboard identifier for the screenshot seen below is in fact "imageTapped" and the class is ImageTappedViewController
Below is my function for instantiating and pushing the new view controller:
In OtherUserAccountViewController.swift:
#IBAction func profilePicButtonTapped() {
let sb = UIStoryboard(name: "SuccessfulLogin", bundle: nil) //SB name: SuccessfulLogin
let cc = (sb.instantiateViewController(withIdentifier: "imageTapped")) as! ImageTappedViewController
if cc.imageView == nil || cc.imageView == UIImage() {
print("Nil") //<- Nil is printed upon firing this function
} else {
print("not nil")
}
//cc.imageView.image = self.profilePicButton.currentBackgroundImage <- breaks because the imageView is nil
self.navigationController?.pushViewController(cc, animated: true)
}
ImageTappedViewController.swift:
import UIKit
class ImageTappedViewController: UIViewController {
#IBOutlet weak var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}
I am totally lost as to why this imageView is returning nil.
I set the imageView to display the lovely Taylor Swift on default as seen below; but regardless, nil is being returned.
Any help is much appreciated!
When view controllers are first initialized their IBOutlets will not be initialized. Only after viewDidLoad will all of their outlets be non-nil. Pass the image as a UIImage then in viewDidLoad set image view's image property.

How to pass an image between view controllers without using segue

I'm getting an error :
Thread 1:EXC_BAD_INSTRUCTION(code=EXC_1386_INVOP,subcode=0x0)
while trying to pass the image that is selected from Photo library, to the other view controller.
Source ViewController -
#IBAction func myButtonTapped(_ sender: UIButton)
{
let secondVC = storyboard?.instantiateViewController(withIdentifier: "secondVC") as! secondVC
secondVC.passedVName = VNameTextField.text!
secondVC.passedCcName = DropTextBox.text!
secondVC.passedVImage = VImageView.image!
navigationController?.pushViewController(secondVC, animated: true)
}
Destination ViewController -
class secondVC: UIViewController
{
#IBOutlet weak var DisplayPassedImage: UIImageView!
#IBOutlet weak var ccNameDisplayLabel: UILabel!
#IBOutlet weak var VNameDisplayLabel: UILabel!
var passedVName = ""
var passedCcName = ""
var passedVImage = UIImage()
override func viewDidLoad()
{
super.viewDidLoad()
VNameDisplayLabel.text = passedVName
ccNameDisplayLabel.text = passedCcName
DisplayPassedImage.image = passedVImage // Error- Thread 1:EXC_BAD_INSTRUCTION(code=EXC_1386_INVOP,subcode=0x0)
}
}
Note: 'PassedVName' and 'passedCcName' data are successfully passed to destination ViewController. if I try to pass 'passedVImage',I get an error.
You can use NotificationCenter to pass action/message to any viewController. Here you need to take UIImage object in AppDelegate (Means Globally) so you can pass it any where.
Ex.
1) You are in firstVC
2) In the firstVC choose the Image and add this image in the image object that you took in AppDelegate
3) Post your Notification in firstVC that you want to pass action
4) Add Observe on your SecondVC
5) You can get image from AppDelegate object (Global object).
Otherwise you can use Protocol.
In my limited experience with you should change .jpg to .png image

Resources