How to make UIImage navigate to another ViewController? - ios

Is it possible to make UIImage navigate to another ViewController when I tap on it ?
Just like UIButton.
Thanks.

ya you can use
var tap = UITapGestureRecognizer(target: self, action: Selector("imageCliecked"))
yourimageView.addGestureRecognizer(tap)
yourimageView.userInteractionEnabled = true // this is must dont forget to add
method is
func imageCliecked()
{
println("Tapped on Image")
// navigate to another
self.performSegueWithIdentifier("yoursegueName", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender:AnyObject?)
{
if segue.identifier == "yoursegueName" {
var destViewController: ViewController = segue.destinationViewController as ViewController
destViewController.img = imageView.image // pass your imageview
}
}
another ViewController
class ViewController: UIViewController
{
strong var img: UIImage!
override function viewDidLoad()
{
if(self.img)
self.imageView.image = img;
}
}

UIImageView *imageView=[[UIImageView alloc]init];
//add gesture recogniser
UITapGestureRecognizer *tap=[[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(navigate)];
tap.delegate=self;
[imageView addGestureRecognizer:tap];
//call method
-(void)navigate{
//call the navigation ..
}

For your question I have tried below solution.Also it works fine.
override func viewDidLoad()
{
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
var tapGesture = UITapGestureRecognizer(target: self, action: "navigationFromImage:")
tapGesture.numberOfTapsRequired = 1
imageviewNavigation.userInteractionEnabled = true
imageviewNavigation.addGestureRecognizer(tapGesture)
}
func navigationFromImage(sender: UIGestureRecognizer)
{
var secondViewController = storyboard?.instantiateViewControllerWithIdentifier("navigatingSecondViewController") as SecondViewController
secondViewController.globalImage = imageviewNavigation.image!
navigationController?.pushViewController(secondViewController, animated: true)
//OR
presentViewController(secondViewController, animated: true, completion: nil)
}
Also in Storyboard click the required view controller
1.Go to or click show the Identity inspector
2.Click Identity
3.In StorybordId you must give "navigatingSecondViewController" or whatever you want.
4.Finally you must give same name in your storyboard?.instantiateViewControllerWithIdentifier("navigatingSecondViewController")
in SecondViewController
var globalImage: UIImage = UIImage()
override func viewDidLoad()
{
super.viewDidLoad()
// Do any additional setup after loading the view.
imageAccess.image = globalImage
}

yes it is possible to navigate one controller to another controller using property...
e.g.
// second Controller.....(you pass image on this controller)
#import <UIKit/UIKit.h>
#interface NewScreen : UITableViewController
{
}
#property(strong,nonatomic)UIImage *yourImage;
#end
/// First Controller where you pass your image...
- (IBAction)convertVideoButtonClicked:(id)sender
{
NewScreen *objNew=[self.storyboard instantiateViewControllerWithIdentifier:#"NewScreen"];
objNew.yourImage=imageNamed;
[self.navigationController pushViewController:objNew animated:YES];
// NSURL *videoPath = [NSURL fileURLWithPath:[[NSBundle mainBundle]pathForResource:#"part1" ofType:#"mov"]];
// [self convertVideoToMP4:videoPath];
}

Related

UIBarButton click to set flag value using Swift 4.2

My scenario, I am having Two UIBarButton with action method, Here, whenever I am clicking Done and Cancel button I am moving to another ViewController. Once user clicked the Done barbutton I need to set some flag value and validate it another ViewController for button clicked or not clicked.
My ViewController One
let barButtonItem = UIBarButtonItem(image: UIImage(named: "backImgs"),
style: .plain,
target: self,
action: #selector(menuButtonTapped))
self.navigationItem.rightBarButtonItem = barButtonItem
#objc fileprivate func menuButtonTapped() { // here I need to set flag value }
My ViewController Two
class ViewControllertwo: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//Here need to validate flag values to button clicked or not
}
}
I partially understand your question , in here you need to go with tag concept, for e.g
override func viewDidLoad() {
super.viewDidLoad()
let barButtonItem = UIBarButtonItem(image: UIImage(named: "backImgs"),
style: .plain,
target: self,
action: #selector(menuButtonTapped(_:)))
barButtonItem.tag = 20
let cancelButton = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(menuButtonTapped(_:)))
cancelButton.tag = 10
self.navigationItem.rightBarButtonItem = barButtonItem
self.navigationItem.leftBarButtonItem = cancelButton
}
handle your target function is like
#objc fileprivate func menuButtonTapped(_ sender: UIBarButtonItem) {
// if you dont want the tag concept, use title property for check which button tapped //print("get Tapped button title == \(sender.title)")
//if sender.tag == 20{
// clicked for another VC button, add your segue code here
// }else{
// pressed cancel button
// }
let vcTwo = self.storyboard?.instantiateViewController(withIdentifier: "ViewControllertwo") as! ViewControllertwo
vcTwo.getSelectedTag = sender.tag
self.navigationController?.pushViewController(vcTwo, animated: true)
}
on your VC2 create the one global Int for get the tag where its comes from,
** ViewControllertwo**
class ViewControllertwo : UIViewController {
var getSelectedTag = 0
override func viewDidLoad() {
super.viewDidLoad()
if getSelectedTag == 20 {
//pressed menu Tapped
}
}
}
It's hard to tell from your question, but assuming you are presenting ViewControllerOne from ViewControllerTwo, you're going to want to use the delegate pattern for this. This is similar to the way you use table/collection views, and you are essentially telling ViewControllerTwo to be ViewControllerOne's delegate so that it can react to the buttons being pressed.
Start by creating a protocol that defines the messages that ViewControllerOne can send to its delegate:
protocol ViewControllerOneDelegate: AnyObject {
func viewControllerOneDidTapDone(_ viewController: ViewControllerOne)
func viewControllerOneDidTapCancel(_ viewController: ViewControllerOne)
}
Then extend ViewControllerTwo to implement your protocol:
extension ViewControllerTwo: ViewControllerOneDelegate {
func viewControllerOneDidTapDone(_ viewController: ViewControllerOne) {
// Set your flag or do whatever you need to do on 'Done'.
// Then dismiss viewController.
}
func viewControllerOneDidTapCancel(_ viewController: ViewControllerOne) {
// Dismiss viewController
}
}
In ViewControllerOne, keep the delegate as a weak property and call the delegate methods on button press:
class ViewControllerOne: UIViewController {
weak var delegate: ViewControllerOneDelegate?
#objc private func donePressed() {
delegate?.viewControllerOneDidTapDone(self)
}
#objc private func cancelPressed() {
delegate?.viewControllerOneDidTapCancel(self)
}
}
Lastly, somewhere in ViewControllerTwo, you need to set yourself as ViewControllerOne's delegate. This will likely be when creating ViewControllerOne:
class ViewControllerTwo: UIViewController {
...
private func presentViewControllerOne() {
let viewControllerOne = ViewControllerOne(nibName:nil, bundle: nil)
viewControllerOne.delegate = self
// Present or push viewControllerOne
}
...
}
As I understand your question the solution is -
ViewContorllerOne
class ViewControllerOne : UIViewController {
var isMenubuttonTapped : Bool = false
override func viewDidLoad() {
super.viewDidLoad()
self.actionToPushOnViewControllerTwo()
NotificationCenter.default.addObserver(self, selector: #selector(actioFire), name: NSNotification.Name.init("MenuButtonTapped"), object: nil)
}
//Call from any where in viewControllerOne
func actionToPushOnViewControllerTwo() {
let viewControllerTwo : ViewControllerTwo = self.storyboard?.instantiateViewController(withIdentifier: "ViewControllerTwo") as! ViewControllerTwo
self.present(viewControllerTwo, animated: true, completion: nil)
}
#objc func actioFire(_ notification: Notification) {
print(notification.userInfo!["isMenuButtonTapped"] as Any)
if let isMenuButtonTapped = notification.userInfo!["isMenuButtonTapped"] as? Bool {
self.isMenubuttonTapped = isMenuButtonTapped
}
}
}
ViewControllerTwo
class ViewControllerTwo : UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let barButtonItem = UIBarButtonItem(image: UIImage(named: "backImgs"),
style: .plain,
target: self,
action: #selector(menuButtonTapped))
self.navigationItem.rightBarButtonItem = barButtonItem
}
#objc fileprivate func menuButtonTapped() {
// here I need to set flag value
self.dismiss(animated: true) {
NotificationCenter.default.post(name: Notification.Name("MenuButtonTapped"),
object: nil,
userInfo:["isMenuButtonTapped": true])
}
}
}
Another Easy Solution is
self.dismiss(animated: true) {
if let tabController = self.presentingViewController as? UITabBarController {
if let navController = tabController.selectedViewController as? UINavigationController {
if let secondTab = navController.viewControllers.first as? HomeViewController {
secondTab.tfData = "YES"
}
} else {
if let secondTab = tabController.selectedViewController as? HomeViewController {
secondTab.tfData = "YES"
}
}
}
}

Pass data to TabBar Controller

I want pass data between two ViewControllers throw the TabBarController.
Inside the first ViewController I located textField and button.
Inside the second I located Label.
When I write some text in textField and push button, I expect that this text appear in the Label in the second ViewController. But nothing happens.
And my code:
First ViewController:
import UIKit
class FirstViewController: UIViewController {
#IBOutlet weak var textField: UITextField!
#IBAction func enter(_ sender: Any) {
if textField.text != "" {
if let window = UIApplication.shared.delegate?.window, let tabBarController = window?.rootViewController as? UITabBarController, let second = tabBarController.viewControllers?.first as? SecondViewController {
second.label.text = textField.text
tabBarController.selectedIndex = 0
}
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
}
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.
}
}
Second ViewController:
import UIKit
class SecondViewController: UIViewController {
#IBOutlet weak var label: UILabel!
var myString = String()
override func viewDidLoad() {
super.viewDidLoad()
label.text = myString
// 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.
}
}
I think the problem is in
tabBarController.viewControllers?.first as? SecondViewController
You probably want to do this instead:
tabBarController.viewControllers?[1] as? SecondViewController
Don't forget arrays are indexed from 0, so viewControllers?[1] actually returns the second element in the array.
I'm not recommending that you do it this way. This is an explanation for understanding.
The viewControllers in a tabBarController know their tabBarController. You can access it with self.tabBarController.
The secondViewController is the second one in the list of viewControllers so let second = tabBarController.viewControllers?[1] as? SecondViewController.
If you haven't visited the secondViewController yet, its view will not have loaded, so the outlets will still be nil. You can force the view to load with _ = second.view.
If you want to switch to the second tab, then you need to use tabBarController.selectedIndex = 1.
#IBAction func enter(_ sender: Any) {
if textField.text != "" {
if let tabBarController = self.tabBarController as? UITabBarController, let second = tabBarController.viewControllers?[1] as? SecondViewController {
// make sure view has loaded
_ = second.view
second.label.text = textField.text
// change to second tab
tabBarController.selectedIndex = 1
}
}
}
A better way...
Instead of setting the outlet directly, you should instead pass the string to a property of the SecondViewController:
second.myString = textField.text ?? ""
and then assign that string to the label in an override of viewWillAppear.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
label.text = myString
}
The reason to set it in viewWillAppear is that viewWillAppear will run every time before the view is displayed. viewDidLoad will only run once when the view is first loaded. Since you want the functionality to work multiple times, viewWillAppear is the correct override.
First i think your view controllers that are representing tabs should be embedded into navigation controllers which would then be linked to the TabBarController.
Secondly, the preferred and recommended way to send data between controllers is through protocols (delegates). Here is a good example you can check out, step by step: https://medium.com/#jamesrochabrun/implementing-delegates-in-swift-step-by-step-d3211cbac3ef
However if you're looking for a quick fix of your solution i think that Bruno Phillipe's answer gets it to some extent, but not quite. We can't really be sure what controller is at what index in the view controller list. I think this should work:
#IBAction func enter(_ sender: Any) {
if textField.text != "" {
if let window = UIApplication.shared.delegate?.window, let tabBarController = window?.rootViewController as? UITabBarController {
//check if there are view controllers in the tabBarController
guard let vcList = tabBarController.viewControllers else {
return
}
for controller in vcList {
if let second = controller as? SecondViewController {
//this will be executed only when a controller is SeconfViewController
second.label.text = textField.text
tabBarController.selectedIndex = 0
}
}
}
}
}
EDIT:
I tried it myself and the problem is that you were trying to set the label.text when in fact the label component was never initialised. I think if you simply stored the textField value into myString variable in SecondViewController it would work (not sure).
However here's the solution using a protocol (delegate) which is the right way to send data between controllers. Ask any questions you might have. This should work:
FirstViewController:
import Foundation
import UIKit
protocol LabelChangeDelegate: class {
func changeLabelWithText(_ text: String?)
}
class FirstViewController: UIViewController {
weak var delegate: LabelChangeDelegate?
#IBOutlet weak var textField: UITextField!
#IBAction func enter(_ sender: UIButton) {
if textField.text != "" {
if let window = UIApplication.shared.delegate?.window, let tabBarController = window?.rootViewController as? UITabBarController {
//check if there are view controllers in the tabBarController
guard let vcList = tabBarController.viewControllers else {
return
}
for controller in vcList {
if let second = controller as? SecondViewController {
//this will be executed only when a controller is SeconfViewController
//set the delegate - who needs the data
delegate = second
//call the delegate function which will commmunicate with the delegate
delegate?.changeLabelWithText(textField.text!)
//don't know why you need this
tabBarController.selectedIndex = 0
}
}
}
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
}
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.
}
}
SecondViewController:
import Foundation
import UIKit
class SecondViewController: UIViewController, LabelChangeDelegate {
#IBOutlet weak var label: UILabel!
//lazy init
lazy var myString = String()
override func viewDidLoad() {
super.viewDidLoad()
//set label when the view loads, not in the first controller
label.text = myString
// 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.
}
//delegate function
func changeLabelWithText(_ text: String?) {
guard let sentText = text else {
//no text sent
return
}
myString = sentText
}
}

XCode 8.3.2 Storyboard UI elements won't appear in simulator

disclaimer: I've found a number of these questions but none of them helped.
Just like the title says, the storyboard UI elements for my CarDetailViewController won't appear in the simulator, but they do in other view controllers in the project.
vc in question
overall project
code:
import UIKit
import EventKit
import CoreData
class CarDetailViewController: UIViewController,
UIImagePickerControllerDelegate, UINavigationControllerDelegate,
NSFetchedResultsControllerDelegate {
/* -------------------------------------------------------------------------------------------------------- */
let managedObjectContext = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
/* -------------------------------------------------------------------------------------------------------- */
#IBOutlet weak var myImageView: UIImageView!
let picker = UIImagePickerController()
#IBOutlet weak var carLabel: UILabel!
#IBAction func photoFromLibrary(_ sender: UIButton) {
picker.allowsEditing = false
picker.sourceType = .photoLibrary
picker.mediaTypes = UIImagePickerController.availableMediaTypes(for: .photoLibrary)!
present(picker, animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
picker.delegate = self
self.view = UIImageView(image: UIImage(named: "Landing.png"))
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#nonobjc func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String: AnyObject])
{
let chosenImage = info[UIImagePickerControllerOriginalImage]
myImageView.contentMode = .scaleAspectFit //3
myImageView.image = chosenImage as? UIImage //4
dismiss(animated: true, completion: nil) //5
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController)
{
dismiss(animated: true, completion: nil)
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}
Try this :
Remove this Line :
self.view = UIImageView(image: UIImage(named: "Landing.png"))
You need to set background image as
self.view.backgroundColor = UIColor(patternImage: UIImage(named:"Landing.png")!)
you donot assign an imageview into a uiview
so instead of
self.view = UIImageView(image: UIImage(named: "Landing.png"))
You have the following options:
You should add a uiimageview into your uiview and assign it that image.
you can create a gradient background color with this image.
IMHO use the first approach, as the second might cause resolution issues with different devices
Edit update:
Instead of initializing the vc as following
let destination = CarDetailViewController() // Your destination
try doing the following
let storyboard = UIStoryboard(name: <Storyboard-name>, bundle: nil)
let inquireViewController = storyboard.instantiateViewController(withIdentifier: String(describing:CarDetailViewController.self)) as! CarDetailViewController

How to add action to UIBarButtonItem which is created by storyboard in swift?

Create a UIBarButtonItem which name is nextVc on my navigationBar, and set its action by nextVc.action = #selector(self.gotoVC4), but it does not work.
my code is below:
class ViewController3: UIViewController {
#IBOutlet weak var nextVc: UIBarButtonItem!
override func viewDidLoad() {
super.viewDidLoad()
nextVc.action = #selector(self.gotoVC4)
}
func gotoVC4() -> Void {
print("go to vc4")
let vc4 = ViewController4()
self.navigationController!.pushViewController(vc4, animated: true)
}
}
and the image of storyboard is here:
Since you have a storyboard, simply ctrl-drag from the bar button to the "View Controller 4" scene to create a segue. No code needed.
You can omit self in selector expression
Method should be dynamic or #objc
override func viewDidLoad() {
super.viewDidLoad()
nextVc.action = #selector(gotoVC4)
}
dynamic func gotoVC4() -> Void {
print("go to vc4")
let vc4 = ViewController4()
self.navigationController!.pushViewController(vc4, animated: true)
}

How to perform segue from inside UIView

How can a prepare a segue properly from inside a UIView NOT UIViewController
My UIViewController has a container view and inside that container view has a button.
class myInnerView: UIView {
...
func myButton(gesture: UIGestureRecognizer){
//calling a perform segue from another UIViewController does not recognize the SegueID
//ViewController().self.showProfile(self.id) -- DOES NOT WORK
}
}
class ViewController: UIViewController {
...
func showProfile(id: String){
...
self.performSegueWithIdentifier("toViewProfile", sender: self)
}
}
Your view should not handle a button tap. That should be handled by the controller. (This is why it is called "controller", while the UIView is called "view").
MVC as described by Apple.
If the button is a subview of your view controller's view, you should be able to drag an IBAction onTouchUpInside from the button to your view controller. You can then initiate the segue from that method.
One of the solution is to add UITapGestureRecognizer to your button but from inside the UIViewController :
class ViewController: UIViewController {
var myInnerView = myInnerView()
override func viewDidLoad() {
let tap = UITapGestureRecognizer(target: self, action: #selector(ViewController.handleTapGesture))
self.myInnerView.myButton.addGestureRecognizer(tap)
}
#objc func handleTapGesture(){
performSegue(withIdentifier: "toViewProfile", sender: nil)
}
}
class myInnerView: UIView {
// make outlet of your button so you can add the tapGestureRecognizer from your ViewController and thats all
#IBOutlet public weak var myButton: UIButton!
}
You need to tap gesture for view to navigate
let customView = myInnerView()
let gestureRec = UITapGestureRecognizer(target: self, action: #selector (self.someAction (_:)))
myView.addGestureRecognizer(customView)
func someAction(_ sender:UITapGestureRecognizer){
let controller = storyboard?.instantiateViewController(withIdentifier: "someViewController")
self.present(controller!, animated: true, completion: nil)
// swift 2
// self.presentViewController(controller, animated: true, completion: nil)
}

Resources