Data sharing between two view controllers by using segue is not working in for loop. I am using Xcode9 and Swift
swift4
ViewController.swift
import UIKit
import SwiftyJSON
import Alamofire
class ViewController: UIViewController {
var distnames = [String]()
var distcodes = [String]()
var data1: [AnyObject] = []
var values = [String]()
var values1 = [String]()
var current_arr :[String] = []
var ofcnames = " ";
var ofccodes = " ";
var code = " ";
var testtext = "";
var id = "";
var tiTle = "";
var releaseYear = "";
#IBOutlet weak var Verticalstackview: UIStackView!
#IBOutlet weak var scrollview: UIScrollView!
#IBOutlet weak var testlabel: UILabel!
#IBOutlet weak var mainView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
print("code is \(code)")
self.values = [String]()
self.values1 = [String]()
self.ofcnames = "";
self.ofccodes = "";
Alamofire.request("https://facebook.github.io/react-native/movies.json")
.responseJSON { (response) in
if ((response.result.value) != nil) {
let jsondata = JSON(response.result.value!)
// print(jsondata)
if let da = jsondata["movies"].arrayObject
{
self.data1 = da as [AnyObject]
print("resp is \(da) ")
}
print("respcode count is \(self.data1.count) ")
self.Verticalstackview.height(constant: 40)
self.mainView.height(constant: CGFloat(40 * self.data1.count))
self.scrollview.height(constant: CGFloat(40 * self.data1.count))
for distics in self.data1 {
if let resp = distics as? NSDictionary {
self.id = resp["id"] as! String
self.tiTle = resp["title"] as! String
self.releaseYear = resp["releaseYear"] as! String
let stackView = UIStackView()
stackView.height(constant: 40)
stackView.distribution = .fill
stackView.alignment = .fill
stackView.axis = .horizontal
stackView.spacing = 5
let lblId = UILabel()
lblId .text = "\(self.id)"
lblId .font = UIFont(name: "verdana", size: 15.0)
lblId .textAlignment = .center
lblId .textColor = .gray
lblId .numberOfLines = 0
lblId .width(constant: 55)
let lbltiTle = UILabel()
lbltiTle.text = "\(self.tiTle)"
lbltiTle.font = UIFont(name: "verdana", size: 15.0)
lbltiTle.textAlignment = .left
lbltiTle.textColor = .black
lbltiTle.numberOfLines = 0
lbltiTle.width(constant: 120)
let tap = UITapGestureRecognizer.init(target:self,action: #selector(self.tapFunction) )
lbltiTle.isUserInteractionEnabled = true
lbltiTle.addGestureRecognizer(tap)
self.testtext = lbltiTle.text!
let lblRYear = UILabel()
lblRYear.text = "\(self.releaseYear)"
lblRYear.font = UIFont(name: "verdana", size: 15.0)
lblRYear.textAlignment = .right
lblRYear.textColor = .black
lblRYear.numberOfLines = 0
lblRYear.width(constant: 100)
stackView.addArrangedSubview(lblId )
stackView.addArrangedSubview(lbltiTle)
stackView.addArrangedSubview(lblRYear)
self.Verticalstackview.addArrangedSubview(stackView)
}
}
}
print(self.values1)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#objc func tapFunction(sender:UITapGestureRecognizer) {
print("tap working")
self.performSegue(withIdentifier: "Segue", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let secondcntroller = segue.destination as! SecondViewController
secondcntroller.mystring = self.testtext
}
}
extension UIView{
func height(constant : CGFloat){
setConstraint(value: constant,attribute: .height)
}
func width(constant : CGFloat){
setConstraint(value: constant,attribute: .width)
}
private func removeConstraint(attribute: NSLayoutAttribute){
constraints.forEach {
if $0.firstAttribute == attribute
{
removeConstraint($0)
}
}
}
private func setConstraint(value:CGFloat ,attribute: NSLayoutAttribute){
removeConstraint(attribute: attribute)
let Constraint =
NSLayoutConstraint(item: self,
attribute: attribute,
relatedBy: NSLayoutRelation.equal,
toItem: nil,
attribute: NSLayoutAttribute.notAnAttribute,
multiplier: 1,
constant: value)
self.addConstraint(Constraint)
}
}
SecondViewController.swift
import UIKit
class SecondViewController: UIViewController {
#IBOutlet weak var label: UILabel!
var mystring = String()
override func viewDidLoad() {
super.viewDidLoad()
label.text=mystring
}
}
When I click the movie name text, I want that to be displayed on the second view using segue.
https://i.stack.imgur.com/dvm8j.png
But always it displays the last movie name. Please assist me sorting this issue.
https://i.stack.imgur.com/UqyqM.png
You should update your tapFunction
#objc func tapFunction(sender:UITapGestureRecognizer) {
let touchedLabel = sender.view as! UILabel
self.testtext = touchedLabel.text
self.performSegue(withIdentifier: "Segue", sender: self)
}
Hope it helps
EDIT
Now as you wants to pass the multiple values, what you can do is:
First change your for in loop from
for distics in self.data1 {
To
for (index, distics) in self.data1.enumerated() {
Now, set the tag to your label below this line
lbltiTle.addGestureRecognizer(tap)
// Add tag to your label
lbltiTle.tag = index
//**TIP: You should name the variables in camelCase format**
Now modify your function, that detects the tap on label and get the object with index being passed with the label in form of it's tag. Modify it to.
#objc func tapFunction(sender:UITapGestureRecognizer) {
let touchedLabel = sender.view as! UILabel
let touchedIndex = touchedLabel.tag
let selectedDict: NSDictionary = self.data1[touchedIndex]
print("selectedDict:\(selectedDict)")
self.performSegue(withIdentifier: "Segue", sender: self)
}
You can print the required values from it.
NOTE: For the pure swift approach, you should Avoid using NSDictionary, better use [String: Any] which is a key value pair.
Hope it helps
The self.testtext property from ViewController is not set properly. It should be set every time the tapFunction() is called.
Any way I recomand you to use UITabiewViewController and a data source array which should hold all your elements to display.
Issue
That is because you are passing testtext as a parameter to the next ViewController.mystring. testtext is being changed every time on the loop and the last time it is being changed it is on the last element. Therefore you need to save an index to know where you pressed.
Solution
Change your for loop to get the index of the element you're iterating as above
for index in 0..<self.data1.count {
let distics = self.data1[index]
// Other lines of code
lbltiTle.tag = index
}
Change your handler as below
#objc func tapFunction(sender:UITapGestureRecognizer) {
print("tap working")
guard let index = sender.view?.tag,
let title = (self.data1[index] as? NSDictionary)["title"] else { return }
testtext = title
self.performSegue(withIdentifier: "Segue", sender: self)
}
Add one more function for your label.
lbltiTle.target(forAction: onClickLabel, withSender:)
Definition -
func onClickLabel(sender: UILabel) {
self.testtext = sender.text
}
Call this in your tap function
Related
I m building a chat View in xCode with swift language.
I m create two custom cell one to sender message and another one to received message. The problem is when the text of message is greater than the width of the screen of iPhone. Then I need to configure the two views to increase the height if the text is too big.
So this is my view:
I configured the height of View Lbl Message >= 30 but if you see xCode set to RED that constraint and for me the error is in that part.
Anyway this is the result of my iPhone when application stil running:
If you check with more attention after the text "mio" in the blue cell you can see that there are other text but it is not displayed.
EDIT
I added ChatVC controller where is the UITableView:
//
// ChatVC.swift
// appUser
//
// Created by mac on 11/10/21.
// Copyright © 2021 Michele Castriotta. All rights reserved.
//
import UIKit
import SDWebImage
import SwiftyJSON
import AVFoundation
class ChatVC: UIViewController, UITableViewDelegate, UITableViewDataSource {
var aggiorna:Bool = false
var arrMsgs:[ChatModel] = []
var receiverId = ""
var storeName = ""
var userName = ""
var userId = ""
var strReason = ""
var strReasonID = ""
var strType = "User"
var strRighTitle = ""
var strPrname = ""
var daNotifica:Bool = false
#IBOutlet weak var viewWriteMessage: UIView!
#IBOutlet weak var lblTitleChat: UILabel!
#IBOutlet weak var txtMessage: UITextField!
#IBOutlet weak var tableViewChat: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.showProgressBar()
self.tableViewChat.separatorColor = UIColor.clear
self.viewWriteMessage.setCornerRadius(cornerRadius: 22, borderColor: nil, borderWidth: nil)
userId = kUserDefault.value(forKey: USERID) as! String
self.lblTitleChat.text = self.storeName
wsGetChatAgain()
}
func wsGetChatAgain() {
// showProgressBar()
var paramDict : [String:AnyObject] = [:]
paramDict["receiver_id"] = receiverId as AnyObject
paramDict["sender_id"] = userId as AnyObject
CommunicationManeger.callPostServiceReturnJson(apiUrl: RouterProd.get_chat.url(), parameters: paramDict, parentViewController: self, successBlock: { (responseData, message) in
DispatchQueue.main.async {
do {
let chats = try JSONDecoder().decode(ResponseChatModel.self, from: responseData as! Data)
if(chats.status == "1") {
self.arrMsgs = chats.result
DispatchQueue.main.async {
// Main thread, called after the previous code:
// hide your progress bar here
self.tableViewChat.reloadData()
self.hideProgressBar()
}
//self.scrollToBottom()
//self.lbl_ChatReason.text = self.strReason
}
}catch{
print("errore durante la decodifica dei dati: \(error)")
self.hideProgressBar()
//Utility.noDataFound("Errore", tableViewOt: self.tableViewChat, parentViewController: self)
}
}
}, failureBlock: { (error : Error) in
Utility.showAlertMessage(withTitle: EMPTY_STRING, message: (error.localizedDescription), delegate: nil,parentViewController: self)
self.hideProgressBar()
})
self.aggiorna = true
self.aggiornaChat()
}
func aggiornaChat(){
if(aggiorna){
DispatchQueue.main.asyncAfter(deadline: .now() + 15.0, execute: wsGetChatAgain)
}
}
#IBAction func btnBack(_ sender: Any) {
self.aggiorna = false
if(self.daNotifica == false){
self.navigationController?.popViewController(animated: true)
}else{
Switcher.updateRootVC()
}
}
//MARK: - Table View Methods
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.arrMsgs.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let message = self.arrMsgs[indexPath.row]
var messaggio = message.chatMessage
var orario = Utility.getDateStringFromString(dateString: message.date, inputFormate: "yyyy-MM-dd HH:mm:ss", outputFormate: "HH:mm")
if(message.senderID == userId){
//messaggio inviato dal utente
let cell = tableView.dequeueReusableCell(withIdentifier: "ChatCell", for: indexPath) as! ChatCell
cell.lblMessage.text = messaggio
cell.lblTime.text = orario
var maximumLabelSize: CGSize = CGSize(width: 280, height: 9999)
var expectedLabelSize: CGSize = cell.lblMessage.sizeThatFits(maximumLabelSize)
// create a frame that is filled with the UILabel frame data
var newFrame: CGRect = cell.lblMessage.frame
// resizing the frame to calculated size
newFrame.size.height = expectedLabelSize.height
// put calculated frame into UILabel frame
cell.lblMessage.frame = newFrame
return cell
}else{
//messaggio inviato dallo o runner
let cell = tableView.dequeueReusableCell(withIdentifier: "ChatCell2", for: indexPath) as! ChatCell2
cell.lblMessage.text = messaggio
var maximumLabelSize: CGSize = CGSize(width: 280, height: 9999)
var expectedLabelSize: CGSize = cell.lblMessage.sizeThatFits(maximumLabelSize)
// create a frame that is filled with the UILabel frame data
var newFrame: CGRect = cell.lblMessage.frame
// resizing the frame to calculated size
newFrame.size.height = expectedLabelSize.height
newFrame.size.width = expectedLabelSize.width
// put calculated frame into UILabel frame
cell.lblMessage.frame = newFrame
cell.lblTime.text = orario
return cell
}
}
#IBAction func sendMessage(_ sender: Any) {
if txtMessage.text == "Scrivi qui..." || txtMessage.text!.count == 0 {
GlobalConstant.showAlertMessage(withOkButtonAndTitle: APPNAME, andMessage: "Per favore scrivi del testo...", on: self)
} else {
wsSendMessage()
}
}
func wsSendMessage() {
self.showProgressBar()
var localTimeZoneIdentifier: String { return TimeZone.current.identifier }
var paramDict : [String:AnyObject] = [:]
paramDict["receiver_id"] = receiverId as AnyObject
paramDict["sender_id"] = userId as AnyObject
paramDict["chat_message"] = self.txtMessage.text! as AnyObject
paramDict["timezone"] = localTimeZoneIdentifier as AnyObject
paramDict["request_id"] = strReasonID as AnyObject
paramDict["type"] = strType as AnyObject
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
var dataOra = formatter.string(from:Date())
paramDict["date_time"] = "\(dataOra)" as AnyObject
CommunicationManeger.callPostService(apiUrl: RouterProd.insert_chat.url(), parameters: paramDict, parentViewController: self, successBlock: { (responseData, message) in
DispatchQueue.main.async {
let swiftyJsonVar = JSON(responseData)
print(swiftyJsonVar)
if(swiftyJsonVar["result"].stringValue == "successful") {
self.txtMessage.text = ""
self.view.endEditing(true)
self.wsGetChatAgain()
}
self.hideProgressBar()
}
}, failureBlock: { (error : Error) in
Utility.showAlertMessage(withTitle: EMPTY_STRING, message: (error.localizedDescription), delegate: nil,parentViewController: self)
self.hideProgressBar()
})
}
}
This is chatCell class
import UIKit
class ChatCell: UITableViewCell {
#IBOutlet weak var lblMessage: UILabel!
#IBOutlet weak var viewLblMessage: UIView!
#IBOutlet weak var lblTime: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
self.viewLblMessage.setCornerRadius(cornerRadius: 10, borderColor: nil, borderWidth: nil)
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
If you don't know the size of the text, don't add height to the view. You should add your constraints without adding height
I have one UIViewController that I am trying to send the titleLabel of a UIButton to a UILabel held within a different UIView Controller.
I have followed the same steps and pattern as within a previous method that worked fine, but the Title Text is just not getting passed onto the next VC.
I have a Button class called MtsCardsButton, but this just sets the animation and appearance of the button.
Thank you for reviewing.
Here is my code for the Button in the first VC:
import UIKit
class MTSCardsPage: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//This is to make mtsCardsSetArray available to this ViewController
let otherVC = MTSDiscriminators()
mtsCardsSetArray2 = otherVC.mtsCardsSetArray
let otherVC2 = MTSDiscriminators()
allMtsDescriminatorsArray2 = otherVC2.allMtsDescriminatorsArray
//Set Card Titles from Array
Card1ButtonOutlet.setTitle(mtsCardsSetArray2[0], for: .normal)
Card2ButtonOutlet.setTitle(mtsCardsSetArray2[1], for: .normal)
Card3ButtonOutlet.setTitle(mtsCardsSetArray2[2], for: .normal)
Card4ButtonOutlet.setTitle(mtsCardsSetArray2[3], for: .normal)
Card5ButtonOutlet.setTitle(mtsCardsSetArray2[4], for: .normal)
//Do any additional setup after loading the view.
}
var mtsCardsButton = MtsCardsButton()
func addActionToMtsCardsButton() {
mtsCardsButton.addTarget(self, action: #selector(CardButton), for: .touchUpInside)
}
//This is to TELL the Button to do something AND to goto
//the MTS Discriminators UIView.
var cardButtonPressed = ""
#IBAction func CardButton(_ sender: MtsCardsButton) {
let secondVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(identifier: "DiscrimUIViewCollection") as! DiscrimUIViewCollection
cardButtonPressed = sender.currentTitle!
secondVC.updateTheLabel2 = cardButtonPressed
////I'VE TRIED THIS SECTION INSTEAD OF ABOVE AND IT STILL DOESN'T WORK.
// func prepare(for segue: UIStoryboardSegue, sender: Any?)
// {
// if segue.destination is DiscrimUIViewCollection
// {
// let vc = segue.destination as? DiscrimUIViewCollection
// vc?.updateTheLabel2 = cardButtonPressed
// }
// }
//switch area to make button move when pressed
switch cardButtonPressed {
case mtsCardsSetArray2[0]:
Card1ButtonOutlet.shakeMtsCardsButton()
case mtsCardsSetArray2[1]:
Card2ButtonOutlet.shakeMtsCardsButton()
case mtsCardsSetArray2[2]:
Card3ButtonOutlet.shakeMtsCardsButton()
case mtsCardsSetArray2[3]:
Card4ButtonOutlet.shakeMtsCardsButton()
case mtsCardsSetArray2[4]:
Card5ButtonOutlet.shakeMtsCardsButton()
default:
print("Error, unrecognised button pressed!")
}
guard let destinationVC = storyboard?.instantiateViewController(withIdentifier: "DiscrimUIViewCollection") as? DiscrimUIViewCollection else {
return
}
present(destinationVC, animated: true, completion: nil)
}
//Outlet for sending anything to the MTS Card Button
#IBOutlet weak var Card1ButtonOutlet: MtsCardsButton!
#IBOutlet weak var Card2ButtonOutlet: MtsCardsButton!
#IBOutlet weak var Card3ButtonOutlet: MtsCardsButton!
#IBOutlet weak var Card4ButtonOutlet: MtsCardsButton!
#IBOutlet weak var Card5ButtonOutlet: MtsCardsButton!
}
Here is the code for the second receiving VC:
class DiscrimUIViewCollection: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
#IBOutlet weak var discriminatorTitle: UILabel!
var updateTheLabel2: String?
#IBAction func discrimButtonPressed(_ sender: UIButton) {
//action here to name what discriminator means.
print(sender.currentTitle!)
}
#IBOutlet weak var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
Card1ButtonOutlet.setTitle(mtsCardsSetArray2[0], for: .normal)
Card2ButtonOutlet.setTitle(mtsCardsSetArray2[1], for: .normal)
Card3ButtonOutlet.setTitle(mtsCardsSetArray2[2], for: .normal)
Card4ButtonOutlet.setTitle(mtsCardsSetArray2[3], for: .normal)
Card5ButtonOutlet.setTitle(mtsCardsSetArray2[4], for: .normal)
collectionView.dataSource = self
collectionView.delegate = self
self.collectionView.backgroundColor = .black
discriminatorTitle.text = updateTheLabel2
discriminatorTitle.font = UIFont(name: "Mukta Mahee", size: 18)
discriminatorTitle.font = UIFont.boldSystemFont(ofSize: 18)
discriminatorTitle.numberOfLines = 2
discriminatorTitle.minimumScaleFactor = 0.1
discriminatorTitle.baselineAdjustment = .alignCenters
discriminatorTitle.textAlignment = NSTextAlignment.center
discriminatorTitle.clipsToBounds = true
discriminatorTitle.backgroundColor = colourYellow
discriminatorTitle.textColor = .black
discriminatorTitle.layer.borderColor = UIColor.black.cgColor
discriminatorTitle.layer.borderWidth = 2.0
discriminatorTitle.layer.cornerRadius = 7
discriminatorTitle.layer.shadowColor = UIColor.black.cgColor
discriminatorTitle.layer.shadowOffset = CGSize(width: 0.0, height: 6.0)
discriminatorTitle.layer.shadowRadius = 7
discriminatorTitle.layer.shadowOpacity = 0.5
discriminatorTitle.clipsToBounds = false
discriminatorTitle.layer.masksToBounds = true
let layout = self.collectionView.collectionViewLayout as! UICollectionViewFlowLayout
layout.sectionInset = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
layout.minimumInteritemSpacing = 2
layout.itemSize = CGSize(width: (self.collectionView.frame.size.width - 0)/1, height:self.collectionView.frame.size.height/3)
//Do any additional setup after loading the view.
func numberOfSections(in collectionView: UICollectionView) -> Int {
// 1
return 1
}
}
So, after many hours of studying up various websites I found the answer. I needed to add code and re-position the code. I Changed the Storyboard ID to match the DiscrimUIViewCollection.swift file.
I place the following code at the bottom of the 'switch' statement in the MTSCardsPage.swift file.
//To capture the card title and store it for
//preparation for changing based on Label.
guard let DiscrimUIViewCollection : DiscrimUIViewCollection = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "DiscrimUIViewCollection") as? DiscrimUIViewCollection else {
return
}
DiscrimUIViewCollection.updateTheLabel = sender.currentTitle!
present(DiscrimUIViewCollection, animated: true, completion: nil)
}
And to my delight, it all works fine!
The website I used to help me the most was this one:
https://fluffy.es/3-ways-to-pass-data-between-view-controllers/
Thanks for your assistance guys, each little comment made me think.
It's big learning curve!
I am using this dropdown box in my project: https://github.com/kirkbyo/Dropper
I want to enter the selected item from the drop-down box into the text of the button. However, I have 3 buttons which all with drop down boxes and to find out what item has been pressed you use the func DropperSelectedRow(_ path: IndexPath, contents: String) method which will give you the index path and string of what was clicked. in which case you just place the content into the button text but I don't know which button to place it in. How would I find this out?
this is my code:
class ListComposerTableViewController: UITableViewController, UITextViewDelegate, DropperDelegate {
#IBOutlet weak var typeButton: UIButton!
#IBOutlet weak var dateButton: UIButton!
#IBOutlet weak var publicButton: UIButton!
let typeDropper = Dropper(width: 105, height: 105)
let typeOptions = ["Event", "Birthday", "Christmas", "Charity"]
let publicDropper = Dropper(width: 105, height: 105)
let publicOptions = ["Public", "Private"]
let dueDropper = Dropper(width: 105, height: 130)
let dueOptions = ["Bithday", "Christmas", "Custom Date"]
override func viewDidLoad() {
super.viewDidLoad()
//set up the droppers
typeDropper.items = typeOptions // Item displayed
typeDropper.maxHeight = 105
typeDropper.theme = Dropper.Themes.black(UIColor.white)
typeDropper.delegate = self
typeDropper.cornerRadius = typeButton.layer.cornerRadius
typeDropper.cellColor = Colours.flatColour.main.headings
typeDropper.cellBackgroundColor = UIColor.white
typeDropper.width = 105
typeDropper.height = 105
publicDropper.items = publicOptions // Item displayed
publicDropper.maxHeight = 105
publicDropper.theme = Dropper.Themes.black(UIColor.white)
publicDropper.delegate = self
publicDropper.cornerRadius = publicButton.layer.cornerRadius
publicDropper.cellColor = Colours.flatColour.main.headings
publicDropper.cellBackgroundColor = UIColor.white
publicDropper.width = 105
publicDropper.height = 105
dueDropper.items = dueOptions // Item displayed
dueDropper.maxHeight = 130
dueDropper.theme = Dropper.Themes.black(UIColor.white)
dueDropper.delegate = self
dueDropper.cornerRadius = publicButton.layer.cornerRadius
dueDropper.cellColor = Colours.flatColour.main.headings
dueDropper.cellBackgroundColor = UIColor.white
dueDropper.width = 105
dueDropper.height = 105
}
#IBAction func typeDidPress(_ sender: Any) {
if typeDropper.status == .hidden {
typeDropper.showWithAnimation(0.15, options: Dropper.Alignment.center, button: typeButton)
} else {
typeDropper.hideWithAnimation(0.1)
}
}
#IBAction func dueDidPress(_ sender: Any) {
if dueDropper.status == .hidden {
dueDropper.showWithAnimation(0.15, options: Dropper.Alignment.center, button: dateButton)
} else {
dueDropper.hideWithAnimation(0.1)
}
}
#IBAction func publicDidPress(_ sender: Any) {
if publicDropper.status == .hidden {
publicDropper.showWithAnimation(0.15, options: Dropper.Alignment.center, button: publicButton)
} else {
publicDropper.hideWithAnimation(0.1)
}
}
func DropperSelectedRow(_ path: IndexPath, contents: String) {
print(path)
print(contents)
}
How would I place the contents of what was clicked into the button text of where the dropper came from? Thank you.
Use func DropperSelectedRow(_ path: IndexPath, contents: String, tag: Int) instead.
You can assign a tag for your buttons and check this property when delegate method is invoked.
For example: typeDropper.tag = 1
And
func DropperSelectedRow(_ path: IndexPath, contents: String, tag: Int) {
if tag == 1 {
typeButton.setTitle(contents, for: .normal)
}
}
When i tapped on my TabBar's first image it should be highlighted like the below image -
enter image description here
But when i tap on the first icon it's doing nothing, tap on the second icon it's highlighting the first icon, tap on the 3rd icon highlighting it's previous icon (second icon) and so on. It might be an indexing problem. Need some help to find this issue. Thank you. My TabBar current view-
enter image description here
Here is my code -
import UIKit
class ViewController: BaseViewController {
//MARK: Outlets
#IBOutlet var warningsIcon: UIImageView!
#IBOutlet var incidentsIcon: UIImageView!
#IBOutlet var notificationsIcon: UIImageView!
#IBOutlet var myMessagesIcon: UIImageView!
#IBOutlet var warningsTitle: UILabel!
#IBOutlet var incidentsTitle: UILabel!
#IBOutlet var notificationsTitle: UILabel!
#IBOutlet var myMessagesTitle: UILabel!
#IBOutlet var containerView: UIView!
//MARK: PROPERTIES
var previousSelectedIcon:UIImageView!
var previousSeelctedTitle:UILabel!
var previousIndex:Int!
var currentIndex:Int!
var previousVc:UIViewController!
fileprivate var i = 0
open var subViewController:UIViewController?
var unTappedIcon = ["warnings","incidents","notifications","my-messages"]
var tappedIcon = ["warnings_tapped","Incidents_tapped","notifications_tapped","myMessages_tapped"]
override func viewDidLoad() {
super.viewDidLoad()
addSlideMenuButton()
// Do any additional setup after loading the view, typically from a nib.
previousVc = self;
previousSelectedIcon = warningsIcon
previousSeelctedTitle = warningsTitle
previousIndex = 0;
currentIndex = 0;
//place sub view controller if any
placeSubViewControllerIfNeeded()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//place sub view controller if needed
func placeSubViewControllerIfNeeded() -> Void{
if let vc = subViewController {
vc.view.frame = self.containerView.frame
self.addChildViewController(vc)
//vc.view.frame = self.view.frame
self.containerView.addSubview(vc.view)
self.view.sendSubview(toBack: vc.view)
}
}
//MARK: For Tab bar
func updateTapView(title:UILabel, icon:UIImageView) {
previousSeelctedTitle.textColor = UIColor(red:0.60, green:0.60, blue:0.60, alpha:1.0)
previousSelectedIcon.image = UIImage.init(named: unTappedIcon[previousIndex])
title.textColor = UIColor(red:0.26, green:0.18, blue:0.49, alpha:1.0)
icon.image = UIImage.init(named: tappedIcon[currentIndex])
}
func removePreviousViewController() {
previousVc.willMove(toParentViewController: nil)
previousVc.view.removeFromSuperview()
previousVc.removeFromParentViewController()
}
func getStoryBoardByIndentifier(identifier:String)->UIStoryboard {
return UIStoryboard.init(name: identifier, bundle: nil)
}
func showSubViewContrller(subViewController:UIViewController) {
self.addChildViewController(subViewController)
subViewController.view.frame = containerView.frame
self.containerView.addSubview(subViewController.view)
subViewController.didMove(toParentViewController: self)
previousVc = subViewController
}
//Mark:- Action button for warnings
#IBAction func onClickWarnings(_ sender: UITapGestureRecognizer) {
print("Hi there i am just a warning")
self.warningsIcon.image = UIImage.init(named: "warnings_tapped")
previousIndex = currentIndex
currentIndex = 0
updateTapView( title: warningsTitle, icon: warningsIcon)
previousSeelctedTitle = warningsTitle
previousSelectedIcon = warningsIcon
if i > 0{
removePreviousViewController()
print("i am already removed")
}
let storyBoard = getStoryBoardByIndentifier(identifier: "warnings")
let vc = storyBoard.instantiateViewController(withIdentifier: "WarningsViewController") as! WarningsViewController
showSubViewContrller(subViewController: vc)
i += 1
}
//Mark:- Action button for warnings
#IBAction func onClickIncidents(_ sender: UITapGestureRecognizer) {
print("Hi there i am just a warning")
self.incidentsIcon.image = UIImage.init(named: "Incidents_tapped")
previousIndex = currentIndex
currentIndex = 1
updateTapView( title: incidentsTitle, icon: incidentsIcon)
previousSeelctedTitle = incidentsTitle
previousSelectedIcon = incidentsIcon
if i > 0{
removePreviousViewController()
print("i am already removed")
}
let storyBoard = getStoryBoardByIndentifier(identifier: "incidents")
let vc = storyBoard.instantiateViewController(withIdentifier: "IncidentsViewController") as! IncidentsViewController
showSubViewContrller(subViewController: vc)
i += 1
}
//Mark:- Action button for warnings
#IBAction func onClickNotifications(_ sender: UITapGestureRecognizer) {
print("Really true")
self.notificationsIcon.image = UIImage.init(named: "notifications_tapped")
previousIndex = currentIndex
currentIndex = 2
updateTapView(title: notificationsTitle, icon: notificationsIcon)
previousSeelctedTitle = notificationsTitle
previousSelectedIcon = notificationsIcon
if i > 0 {
removePreviousViewController()
print("I am already removed")
}
let storyBoard = getStoryBoardByIndentifier(identifier: "notifications")
let vc = storyBoard.instantiateViewController(withIdentifier: "NotificationsViewController") as! NotificationsViewController
showSubViewContrller(subViewController: vc)
i += 1
}
//Mark:- Action button for warnings
#IBAction func onClickMyMessages(_ sender: UITapGestureRecognizer) {
print("ha ha..i believe in that")
self.myMessagesIcon.image = UIImage.init(named: "myMessages_tapped")
previousIndex = currentIndex
currentIndex = 3
updateTapView(title: myMessagesTitle , icon: myMessagesIcon)
previousSeelctedTitle = myMessagesTitle
previousSelectedIcon = myMessagesIcon
if i > 0 {
removePreviousViewController()
print("i am alreday removed")
}
let storyBoard = getStoryBoardByIndentifier(identifier: "myMessages")
let vc = storyBoard.instantiateViewController(withIdentifier: "MyMessagesViewController") as! MyMessagesViewController
showSubViewContrller(subViewController: vc)
i += 1
}
}
Looks like you are adding view ineach viewcotroller which you want to show as if a tab bar item.. this might not be the right way to do.. what you can do is make your custom tabbar controller
class SampleViewController: UITabBarController {
#IBOutlet var tabBarView: UIView!
#IBOutlet weak var item1Btn: UIButton!
#IBOutlet weak var item2Btn: UIButton!
#IBOutlet weak var item3Btn: UIButton!
#IBOutlet weak var item4Btn: UIButton!
#IBOutlet weak var item5Btn: UIButton!
let item1Image = #imageLiteral(resourceName: "profileUnselected")
let item1Selected = #imageLiteral(resourceName: "profile")
let item2Image = #imageLiteral(resourceName: "notificationUnselected")
let item2Selected = #imageLiteral(resourceName: "notificationSelected")
let item3Image = #imageLiteral(resourceName: "game")
let item3Selected = #imageLiteral(resourceName: "game")
let item4Image = #imageLiteral(resourceName: "cookbooksUnselected")
let item4Selected = #imageLiteral(resourceName: "cookbooks")
let item5Image = #imageLiteral(resourceName: "searchTabUnselected")
let item5Selected = #imageLiteral(resourceName: "searchTabSelected")
let unSelectedColor = UIColor.lightGray
let selectedColor = UIColor.white
let appColor = UIColor(red: 22.0/255.0, green: 168.0/255.0, blue: 225.0/255.0, alpha: 1.0)
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
if UIDevice().userInterfaceIdiom == .phone {
switch UIScreen.main.nativeBounds.height {
case 2436:
offsetHeight = 44.0
default:
print("unknown")
}
}
addTabView()
}
func addTabView() {
Bundle.main.loadNibNamed("TabBarView", owner: self, options: nil)
tabBarView.frame = CGRect(x:
0 , y: Helper.getScreenHeight() - AppConstants.kTabBarheight - offsetHeight, width: Helper.getScreenWidth(), height: AppConstants.kTabBarheight)
self.view.addSubview(tabBarView)
self.item3Btn.sendActions(for: .touchUpInside) //here i showed my third tab bar item initially
}
#IBAction func tabBarBtnClick(_ sender: UIButton) {
var isViewToChange = false
let currentIndex = self.selectedIndex
var tochangeIndex = sender.tag
self.item1Btn.setImage(item1Image, for: .normal)
self.item2Btn.setImage(item2Image, for: .normal)
self.item3Btn.setImage(item3Image, for: .normal)
self.item4Btn.setImage(item4Image, for: .normal)
self.item5Btn.setImage(item5Image, for: .normal)
switch sender.tag {
case 0:
self.item1Btn.setImage(item1Selected, for: .normal)
if currentIndex != 0{
isViewToChange = true
tochangeIndex = 0
}
else{
(self.viewControllers?[currentIndex] as! UINavigationController).popToRootViewController(animated: true)
}
case 1:
self.item2Btn.setImage(item2Selected, for: .normal)
if currentIndex != 1{
isViewToChange = true
tochangeIndex = 1
}
else{
(self.viewControllers?[currentIndex] as! UINavigationController).popToRootViewController(animated: true)
}
case 2:
if currentIndex != 2{
isViewToChange = true
tochangeIndex = 2
}
else{
(self.viewControllers?[currentIndex] as! UINavigationController).popToRootViewController(animated: true)
}
case 3:
self.item4Btn.setImage(item4Selected, for: .normal)
if currentIndex != 3{
isViewToChange = true
tochangeIndex = 3
}
else{
(self.viewControllers?[currentIndex] as! UINavigationController).popToRootViewController(animated: true)
}
case 4:
self.item5Btn.setImage(item5Selected, for: .normal)
if currentIndex != 4{
isViewToChange = true
tochangeIndex = 4
}
else{
(self.viewControllers?[currentIndex] as! UINavigationController).popToRootViewController(animated: true)
}
default:
break
}
if isViewToChange {
let _ = self.selectedViewController?.view
let _ = self.viewControllers?[tochangeIndex].view
self.selectedIndex = tochangeIndex
}
}
func hideTabbar() {
self.tabBar.isHidden = true
var frame = tabBarView.frame
frame.origin.y = Helper.getScreenHeight() + 200
tabBarView.frame = frame
}
func showTabbar() {
self.tabBar.isHidden = false
var frame = tabBarView.frame
frame.origin.y = Helper.getScreenHeight() - AppConstants.kTabBarheight - offsetHeight
tabBarView.frame = frame
}
}
here i have aded methods for you to either show the tab bar of hide as we push into the stack of each tab bar item..
Here added few images for your understanding
and also dont forgot to set the tag for each button in tab bar view, so that when any button clicked, same method is called and we handle it from there
Is there any way i can pass parameters with UITapGestureRecognizer?
I've seen this answered for objective-c but couldn't find an answer for swift
test.userInteractionEnabled = true
let tapRecognizer = UITapGestureRecognizer(target: self, action: Selector("imageTapped4:"))
// Something like text.myParamater
test.addGestureRecognizer(tapRecognizer)
And then receive myParameter under func imageTapped4(){}
One approach would be to subclass UITapGestureRecognizer and then set a property, I've posted an example below. You could also do some check on the sender and check if equal to some tag, class, string, e.t.c
class ViewController: UIViewController {
#IBOutlet weak var label1: UILabel!
#IBOutlet weak var image: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
image.userInteractionEnabled = true;
let tappy = MyTapGesture(target: self, action: #selector(self.tapped(_:)))
image.addGestureRecognizer(tappy)
tappy.title = "val"
}
func tapped(sender : MyTapGesture) {
print(sender.title)
label1.text = sender.title
}
}
class MyTapGesture: UITapGestureRecognizer {
var title = String()
}
There are lots of examples on SO, have a look, good luck.
For Swift 4
In Viewdidload
let label = UILabel(frame: CGRect(x: 0, y: h, width: Int(self.phoneNumberView.bounds.width), height: 30))
label.textColor = primaryColor
label.numberOfLines = 0
label.font = title3Font
label.lineBreakMode = .byWordWrapping
label.attributedText = fullString
let phoneCall = MyTapGesture(target: self, action: #selector(self.openCall))
phoneCall.phoneNumber = "\(res)"
label.isUserInteractionEnabled = true
label.addGestureRecognizer(phoneCall)
Function as
#objc func openCall(sender : MyTapGesture) {
let number = sender.phoneNumber
print(number)
}
Write Class as
class MyTapGesture: UITapGestureRecognizer {
var phoneNumber = String()
}
Follow Step Properly and make change according to your variable , button ,label . It WORKS PROPERLY
Without subclassing, you can also add the parameter in the view layer (where the gesture is attached):
let tappy = UITapGestureRecognizer(target: self, action: #selector(self.tapped(_:)))
image.addGestureRecognizer(tappy)
image.layer.setValue(title, forKey: "anyKeyName")
Later in the handler
#objc private func tapped(_ sender: UIGestureRecognizer) {
guard let title = sender.view?.layer.value(forKey: "anyKeyName") as? String else { return }
// Do something with the title
}
The best way is to determind the parameter when the func imageTapped64is fired. You can get you params via the view (take a look to #Developer Sheldon answer)
or in many other ways.