I try to pass an image from one ViewController1 to another ViewController2 when a button is tapped. I am using segues in my Storyboard.
ViewController1
import UIKit
class ViewController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
var imagePicker: UIImagePickerController!
#IBAction func editPhoto(_ sender: UIButton) {
let editViewController = storyboard?.instantiateViewController(withIdentifier: "EditImageViewController") as! EditImageViewController
editViewController.imageForEdit = imageView.image!
print(imageView)
print(imageView.image!)
navigationController?.pushViewController(editViewController, animated: true)
}
#IBOutlet weak var imageView: UIImageView! {
didSet {
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
print(imageView) results in
some(UIImageView: 0x7fc34df0e630; frame = (8 29; 303 443); clipsToBounds = YES; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = CALayer: 0x60000023e520)
and print(imageView.image!) in
size {3000, 2002} orientation 0 scale 1.000000
ViewController2
import UIKit
class EditImageViewController: UIViewController {
var imageForEdit = UIImage()
#IBOutlet weak var editingImage: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
editingImage.image = imageForEdit
print(imageForEdit)
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
print(imageForEdit) results in
size {0, 0} orientation 0 scale 1.000000
Why is that? Why isnt the image passed to ViewController2?
It seems to me that this could be a lot simpler. If you're using a Storyboard with a segue, you can easily accomplish this in prepare(for segue: UIStoryboardSegue, sender: Any?). Here's a sample storyboard:
In this case, ViewController has a segue on the Edit Image button to the EditImageViewController.
When you push that button, you get your prepare(for segue: call. Here's a sample ViewController:
class ViewController: UIViewController {
var imagePath = Bundle.main.path(forResource: "icon8", ofType: "png")
var anEditableImage:UIImage?
override func viewDidLoad() {
super.viewDidLoad()
if let imagePath = imagePath {
anEditableImage = UIImage(contentsOfFile: imagePath)
}
}
// MARK: - Navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destination = segue.destination as? EditImageViewController {
destination.imageForEdit = anEditableImage
}
}
}
And here's the EditImageViewController:
class EditImageViewController: UIViewController {
var imageForEdit:UIImage?
override func viewDidLoad() {
super.viewDidLoad()
print(imageForEdit ?? "Image was nil")
}
}
Using prepare(for segue: UIStoryboardSegue, sender: Any?) is the preferred way for a Storyboard-based app to pass data between View Controllers. It's very simple and it works.
Sample project is here if you want to see the working code:
https://www.dropbox.com/s/eog01bmha67c5mv/PushImage.zip?dl=0
var imageForEdit: UIImage? {
didSet {
editingImage.image = imageForEdit
}
}
Replace var imageForEdit = UIImage() with var imageForEdit : UIImage?
i test code my self , make sure that imageView have image
#IBOutlet weak var imageView: UIImageView! {
didSet {
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
}
}
You can create an public variable so you can pase data from one viewcontroller to another view controller.
class variables
{
static var image = UIImage()
}
the 2 controller:
#IBOutlet weak var anotherviewcontroller: UIImageView!
anotherviewcontroller.image = variables.image
Related
I am trying to pass an object with data from one view to another view using Swift4. However, I get this problem when trying to print.
Here is the message that I get:
2018-03-21 21:47:03.542578-0400 Sudoku[64427:1070575] <UIView:
0x7fd28bc0b4c0; frame = (0 0; 414 736); autoresize = W+H; layer =
<CALayer: 0x604000038500>>'s window is not equal to
<Sudoku.setupSudoku: 0x7fd28bf256c0>'s view's window!
Here is the picture of my View. Identifier for segue: setupScreen
Here is the code in setPlayer:
class setPlayer: UIViewController {
var singleUser:playerInfor=playerInfor()
var randomGame:Int = -1
var playerName:String=""
#IBOutlet weak var txtPlayerName: UITextField!
var sizeOfSudoku:Int = 9 //for project 1, let take one size of sudoku
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor(patternImage: UIImage(named: "Communication-Network-Vector-Illustration.jpg")!)
self.txtPlayerName.layer.borderWidth=2.0
self.txtPlayerName.layer.borderColor=UIColor.blue.cgColor
// Do any additional setup after loading the view.
}
func randomNumber(){
self.randomGame=Int(arc4random_uniform(3)+1)
}
func initialize(){
//if(size)
if txtPlayerName.text?.isEmpty ?? true {
self.playerName="Player1"
} else {
self.playerName=self.txtPlayerName.text!
}
self.singleUser=playerInfor(playerName:self.playerName,size:self.sizeOfSudoku,time:0, randomSudoku:self.randomGame)
//print (self.singleUser.size)
}
#IBAction func startButton(_ sender: Any) {
initialize()
performSegue(withIdentifier: "setupScreen", sender: self.singleUser)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "setupScreen"{
if let destination=segue.destination as?setupSudoku{
destination.objectPlayer=sender as?playerInfor
print(singleUser.playerName)
}
}
}
#IBAction func size9(_ sender: Any) {
self.sizeOfSudoku=9
}
#IBAction func Size6(_ sender: Any) {
self.sizeOfSudoku=9
}
Here is playerInfor
import Foundation
import UIKit
class playerInfor{
var playerName:String=""
var size:Int=0
var time:Int=var randomSudoku:Int=0
init(playerName:String,size:Int,time:Int,randomSudoku:Int) {
self.playerName=playerName
self.size=size
self.time=time
self.randomSudoku=randomSudoku
}
}
Here is setupSudoku
class setupSudoku: UIViewController , UICollectionViewDelegate, UICollectionViewDataSource{
#IBOutlet weak var stackViewButtons: UIStackView!
#IBOutlet weak var myCollectionView: UICollectionView!
var newNumber=0
var objectPlayer:playerInfor!
override func viewDidLoad() {
super.viewDidLoad()
print(self.objectPlayer?.time)
}
}
You have setup your segue incorrectly in your storyboard, and it is attempting to segue twice. To confirm this is the case, select your segue in your storyboard and check if your button highlights, like this:
To resolve, delete this segue and create a new one, by control-dragging from the view controller (not the button) to the destination, like so:
Make sure to reset the new segues identifier back to setupScreen. Then you should be good to go!
I am trying to pass this UI Image View from one view controller to another on the same storyboard. I have already passed a UI TextField to a UI Label and UI Button. Now I need to do it with a UI Image View.
Here are my two view controllers.
import UIKit
class PhotoShareViewController: UIViewController {
#IBOutlet weak var imageView: UIImageView!
#IBOutlet weak var contentTextView: UITextView!
#IBOutlet weak var thatTextField: UITextField!
#IBOutlet weak var thisTextField: UITextField!
var presenter: PhotoShareModuleInterface!
var image: UIImage!
#IBAction func thisUploadPhoto(_ sender: Any) {
if thisTextField.text != "" && thatTextField.text != ""
{
performSegue(withIdentifier: "segue", sender: nil)
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
var photoShareLabelViewController = segue.destination as! PhotoShareLabelViewController
photoShareLabelViewController.thisString = thisTextField.text!
photoShareLabelViewController.thatString = thatTextField.text!
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
imageView.image = image
}
override var prefersStatusBarHidden: Bool {
return true
}
#IBAction func didTapCancel(_ sender: AnyObject) {
presenter.cancel()
presenter.pop()
}
/* #IBAction func didTapDone(_ sender: AnyObject) {
guard let message = thatTextField.text, !message.isEmpty else {
return
}
guard let messageOne = thisTextField.text, !messageOne.isEmpty else {
return
}
presenter.finish(with: image, content:message)
presenter.dismiss()
}
}
*/
}
extension PhotoShareViewController: PhotoShareViewInterface {
var controller: UIViewController? {
return self
}
}
if someone could tell me how to send the image from one view controller into another that would be awesome!
You didn't show PhotoShareLabelViewController, but presumably it has:
var thisString: String?
Add
var thisImage: UIImage?
And then pass it along the same way as thisString
photoShareLabelViewController.thisImage = imageView.image
And pick it up in the viewDidLoad of PhotoShareLabelViewController (which is probably where you pick up thisString). Something like:
self.imageView.image = self.thisImage
But, using whatever variable name you are using.
In short, just copy what you are doing for thisString, but use a UIImage as the type instead of String.
NOTE: You are not passing a UIImageView from one VC to another (that is impossible). You are passing the image from an imageview from one VC to another.
I am trying to pass data between my two view controllers in my UIscrollview. I am trying to use delegation to send data between Viewcontroller1 and Viewcontroller2. The delegate is Viewcontroller, while the delegator is Viewcontroller1 and Viewcontroller2.
In the code posted below, when the switch in Viewcontroller1 is toggled, it makes the switch in Viewcontroller2 put to the "off" state. I keep on getting the
fatal error: unexpectedly found nil while unwrapping an Optional value
error when I run it, but I have no clue what is causing this problem. Any ideas why?
Below is the Viewcontroller that contains the Uiscrollview and the subviews/childviews
import UIKit
class ViewController: UIViewController, testing {
var vc1 = ViewController1(nibName: "ViewController1", bundle: nil)
var vc2 = ViewController2(nibName: "ViewController2", bundle: nil)
#IBOutlet weak var scrollView: UIScrollView!
func test1() {
vc2.switch2.on = false
}
override func viewDidLoad() {
super.viewDidLoad()
self.addChildViewController(vc1)
self.scrollView.addSubview(vc1.view)
vc1.didMoveToParentViewController(self)
var frame1 = vc2.view.frame
frame1.origin.x = self.view.frame.size.width
vc2.view.frame = frame1
self.addChildViewController(vc2)
self.scrollView.addSubview(vc2.view)
vc2.didMoveToParentViewController(self)
self.scrollView.contentSize = CGSizeMake(self.view.frame.size.width * 2, self.view.frame.size.height);
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
here is the Viewcontoller1 code
protocol testing{
func test1()
}
class ViewController1: UIViewController {
var delegate:testing?
#IBOutlet weak var switch1: UISwitch!
override func viewDidLoad() {
super.viewDidLoad()
let vc = ViewController()
self.delegate = vc
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func switch1toggled(sender: AnyObject) {
delegate?.test1()
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}
and here is the Viewcontroller 2 code
import UIKit
class ViewController2: UIViewController {
#IBOutlet weak var switch2: UISwitch!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func switch2toggled(sender: AnyObject) {
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}
sorry for the long post, I have been stuck for a week on how to change the state of another switch from toggling a switch in another class, and this was the most efficient way that I found
Try This:
ViewController1
class ViewController1: UIViewController {
let defaults = NSUserDefaults.standardUserDefaults()
let switch1Key = "view1Switch"
override func viewWillAppear(animated: Bool) {
view1Switch.on = defaults.boolForKey(switch1Key)
}
#IBOutlet weak var view1Switch: UISwitch!
#IBAction func view1SwitchChanged(sender: UISwitch) {
defaults.setBool(view1Switch.on, forKey: switch1Key)
}
}
ViewController2
class ViewController2: UIViewController {
let defaults = NSUserDefaults.standardUserDefaults()
let switch1Key = "view1Switch"
override func viewWillAppear(animated: Bool) {
view2Switch.on = defaults.boolForKey(switch1Key)
}
#IBOutlet weak var view2Switch: UISwitch!
#IBAction func view2SwitchChanged(sender: UISwitch) {
defaults.setBool(view2Switch.on, forKey: switch1Key)
}
}
This method syncs the state of the two UISwitches using viewWillAppear and NSUserdefaults. The basic thought pattern is that you save the state of the switch to NSUserdefaults so that when either ViewController1 or ViewController2 is instantiated the view1Switch or view2Switch outlet's .on property is set to the saved value.
Caveats:
The first value for the switch when ViewController1 is instantiated (in the first app run) will be off because boolForKey returns false when there is no saved value. This can be hacked by using view1Switch.on = true directly after view1Switch.on = defaults.boolForKey(switch1Key)
This method makes the switches have the same value. In order to make them have different values, you can use a ! operator like so in ViewController2 view2Switch.on = !defaults.boolForKey(switch1Key). This way switch 1 will always be the opposite of switch 2.
I recommend this method over delegation because, while delegation is powerful, its power doesn't seem needed here.
If you have any questions please ask! :D
my code works fine in choosing the picture from the gallery and display it in the same view,
what am stuck into now, is transferring that UIImageView chosen to the next activity when "next" button is clicked
here is the code that opens the gallery
#IBAction func gallery(sender: AnyObject) {
if UIImagePickerController.availableMediaTypesForSourceType(.PhotoLibrary) != nil {
picker.allowsEditing = false
picker.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
presentViewController(picker, animated: true, completion: nil)
}
}
this is the code that displays the image in the same view
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) {
var chosenImage = info[UIImagePickerControllerOriginalImage] as! UIImage
imageChosen.contentMode = .ScaleAspectFit
imageChosen.image = chosenImage
dismissViewControllerAnimated(true, completion: nil)
}
now after the UIImageView saved in the imageChosen, here is the code am using to pass that image to the next view
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
var pass:postView = segue.destinationViewController as! postView
if(segue.identifier == "next"){
pass.imgv.image = imageChosen.image
}
}
this line of code that causes the program to crash
pass.imgv.image = imageChosen.image
the imgv in the second view is declared like this
#IBOutlet weak var imgv: UIImageView!
what am i doing wrong here, please direct me
You cannot set data in a view which is not rendered yet . So pass image to second view and set that Image to ImageView in secondView's viewDidLoad
override func prepareForSegue(segue: (UIStoryboardSegue!), sender: AnyObject!) {
if segue.identifier == "next" {
var pass:second = segue.destinationViewController as! second
pass.currentImage=myImageView.image;
}
}
//Second view
class second: UIViewController {
#IBOutlet weak var tempImgView: UIImageView!
var currentImage:UIImage!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
if((currentImage) != nil){
tempImgView.image=currentImage;
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
You are using weak reference for image view and trying to get it in other controllers . do as following .
#IBOutlet Strong var imgv: UIImageView
Secondly your way of fetching view controller wrong ... Try it as following
if segue.identifier == "ShowCounterSegue"
{
if let destinationVC = segue.destinationViewController as? OtherViewController{
destinationVC.numberToDisplay = counter
}
}
You can't access the UIImageView directly in second View Controller. Instead create variable UIImage in second View Controller and assign your selected UIImage to it. Later in viewdidload of second View Controller set the UIImageView.
First View
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let pass:postView = segue.destinationViewController as! postView
if(segue.identifier == "next"){
pass.tempImage = imageChosen.image
}
}
Second View
#IBOutlet weak var imgv: UIImageView!
var tempImage:UIImage!
override func viewDidLoad() {
super.viewDidLoad()
self.imgv.image=tempImage
}
In the PostView, just create variable like var img: UIImage!
Replace this line pass.imgv.image = imageChosen.image with pass.img = imageChosen.image
In viewDidLoad() of PostView, add this line, imgv.image = image
We can not set properties of IBOutlets of secondView from the firstView, because IBOutlets of ViewController will get memory after execution of viewDidLoad()
So you have to create appropriate data variable to pass data to IBOutlet.
Here is the example code.
class FirstViewController: UIViewController {
#IBOutlet weak var imageViewInput: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
//check the condition for your segue.identifier, if any
var destination : NewViewContrller! = segue.destinationViewController as NewViewContrller ;
if let image = imageViewInput?.image {
destination.outputImage = image;
}
}
}
class NewViewContrller: UIViewController {
#IBOutlet weak var outputImageView: UIImageView!
var outputImage: UIImage!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
if let image = outputImage {
outputImageView.image = image;
}
}
}
depending on a few parameters I am trying to set an Image on the second VC, but somehow it always returns null??
this is what i do:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showDetail" {
println("going forth!")
println(self.myButton.selected)
let controller = segue.destinationViewController as? DetailVC
if myButton.selected == true {
var newImage = UIImage(named:"Test1")
var oldImage = controller?.imageView.image
println(oldImage)
oldImage = newImage
} else {
var newImage = UIImage(named:"Test2")
var oldImage = controller?.imageView.image
println(oldImage)
oldImage = newImage
}
} else {
println("roflcopter")
}
}
the detail VC basically has "nothing":
import UIKit
class DetailVC: UIViewController {
#IBOutlet weak var imageView: UIImageView!
var testString:String!
#IBAction func goBacktoMain(segue: UIStoryboardSegue) {
println("going back")
}
override func viewDidLoad() {
super.viewDidLoad()
println("view Did Load")
println(testString)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
the second VC has a default image set via Storyboard but when I stop with a breakpoint #let controller it will tell me that imageview actually is null, does this only get set once the detail vc was shown once?
€dit: setting the string and printing it out on the second VC works perfectly fine
Where are you setting the image?
Inside the prepareForSegue the UIImageView IBOutlet will not have loaded. You have to declare an image variable in your DetailVC class like below and set that image in viewDidLoad.
class DetailVC
{
var image:UIImage? = nil
#IBOutlet weak var imageView: UIImageView!
override func viewDidLoad()
{
imageView.image = image
}
}
In your prepareSegue function, set
let controller = segue.destinationViewController as? DetailVC
controller?.image = //Your Image according to conditions.
Declare a UIImage variable in the destination segue, pass the image object to it.
On viewDidLoad on the destination object, assign the image to the imageView.Image property
Most probably the Outlet is not yet initialized