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;
}
}
}
Related
I am using segue to pass the data between the controllers. I have three view controller .I was able to push the the data from first view controller to second one without any error . But I tried to use same process from second to third , It is showing following errors in build time . For third controller
file:///Users/test/Desktop/XcodeProject/HomeWork/PraticeSession/MovieDBHomeWork/MovieDBHomeWork/Base.lproj/Main.storyboard: error: Illegal Configuration: The view3 outlet from the DetailsViewController to the UILabel is invalid. Outlets cannot be connected to repeating content.
file:///Users/test/Desktop/XcodeProject/HomeWork/PraticeSession/MovieDBHomeWork/MovieDBHomeWork/Base.lproj/Main.storyboard: error: Illegal Configuration: The view2 outlet from the DetailsViewController to the UILabel is invalid. Outlets cannot be connected to repeating content.
file:///Users/test/Desktop/XcodeProject/HomeWork/PraticeSession/MovieDBHomeWork/MovieDBHomeWork/Base.lproj/Main.storyboard: error: Illegal Configuration: The view1 outlet from the DetailsViewController to the UIImageView is invalid. Outlets cannot be connected to repeating content.
Here is the screenshot of the properties not be repeated .
Here is the screenshot for third controller .
I do not see the same property of the repeated again from trigger .I do not why it is compelling.
Here is the code in first view controller.
class ViewController: UIViewController {
#IBOutlet weak var text: UITextField!
var nameText = ""
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func logIn(_ sender: Any) {
// guard text.text != nil else {return}
self.nameText = text.text!
performSegue(withIdentifier: "show", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
var vc = segue.destination as! NewViewController
vc.finalname = self.nameText
}
}
Here is the code seconds view controller.
class NewViewController: UIViewController {
var mc : MovieViewCell!
#IBOutlet weak var tableView: UITableView!
private var presenter: MoviePresenter!
#IBOutlet weak var name: UILabel!
var finalname = ""
var movieTitleDetail = ""
var movieOverviewDeatil = ""
var movieImageDetail : UIImage?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
name.text = "Hello: " + finalname
setUpUI()
// configure presenter
presenter = MoviePresenter(view: self)
presenter.getMovies()
}
#IBAction func showDetail(_ sender: Any) {
self.movieTitleDetail = mc.movieTtile.text!
self.movieOverviewDeatil = mc.movieOverview.text!
self.movieImageDetail = mc.movieImage.image
performSegue(withIdentifier: "details", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
var vc = segue.destination as! DetailsViewController
vc.finalmovieTitle = self.movieTitleDetail
vc.finalmovieOverview = self.movieOverviewDeatil
vc.finalmovieImage = self.movieImageDetail
}
}
Here is the third View controller code .
import UIKit
class DetailsViewController: UIViewController {
var finalmovieTitle = ""
var finalmovieOverview = ""
var finalmovieImage: UIImage?
#IBOutlet weak var view2: UILabel!
#IBOutlet weak var view1: UIImageView!
#IBOutlet weak var view3: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
view3.text = finalmovieTitle
view2.text = finalmovieOverview
view1.image = finalmovieImage
}
}
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
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'm kinda new to swift and i'm having trouble implementing this segue between "ViewController" and "PopUpViewController." I'm trying to pass over an array of quotes between the view but keep getting the "Receiver has no segue with identifier 'popUpSegue' error."
I made absolutely sure that my segue's identifier was written correctly across my code and storyboard, i've done the "product --> clean" resolution proposed on another post, nothing has worked.
Something to note: I'm not performing this segue using a button, I had manually set it from the ViewController storyboard (ctrl-clicked the yellow button on the view controller). I'm not sure if that might have anything to with my issue.
ViewController.swift
import UIKit
class ViewController: UIViewController {
// MARK: Properties
#IBOutlet weak var toucanTut: UIImageView!
#IBOutlet weak var canTooLabel: UILabel!
let quoteArray: NSMutableArray = NSMutableArray()
let tapRecon = UITapGestureRecognizer()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
tapRecon.addTarget(self, action: #selector(ViewController.tappedView))
toucanTut.isUserInteractionEnabled = true;
toucanTut.addGestureRecognizer(tapRecon)
let urlPath: String = "https://web.njit.edu/~mid6/service.php"
//Retrieves data from DB and handles it
if let url = URL(string: urlPath){
if let data = try? Data(contentsOf: url){
let json = try? JSON(data: data)
//print(json!)
parse(json: json!)
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//MARK: Actions
func tappedView(){
let popOverVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "quotePopUp") as! PopUpViewController
self.addChildViewController(popOverVC)
popOverVC.view.frame = self.view.frame
self.view.addSubview(popOverVC.view)
popOverVC.didMove(toParentViewController: self)
}
func parse(json: JSON) {
for(i , object) in json{
let quote = object["quote"].stringValue
let author = object["author"].stringValue
//print(quote)
let data = IncomingData()
data.quote = quote
data.author = author
quoteArray.add(data)
//print(data)
}
self.performSegue(withIdentifier: "popUpSegue", sender: quoteArray)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "popUpSegue"
{
if let destinationVC = segue.destination as? PopUpViewController {
destinationVC.newArray = sender as! NSMutableArray
}
}
}
}
PopUpViewController.swift
import UIKit
class PopUpViewController: UIViewController {
//Properties
var feedItems: NSArray = NSArray()
var selectedLocation : IncomingData = IncomingData()
var newArray: NSMutableArray = NSMutableArray()
#IBOutlet weak var quoteText: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.white.withAlphaComponent(0.8)
checkQuotes()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//Actions
#IBAction func closePopUp(_ sender: AnyObject) {
self.view.removeFromSuperview()
}
// check is quoteArray passed over
func checkQuotes(){
print(newArray.count)
}
}
sender The object that you want to use to initiate the segue.
This object is made available for informational purposes during the
actual segue.
Change these lines
self.performSegue(withIdentifier: "popUpSegue", sender: quoteArray)
destinationVC.newArray = sender as! NSMutableArray
To
self.performSegue(withIdentifier: "popUpSegue", sender: self)
destinationVC.newArray = quoteArray
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