TableView in a popup Swift - ios

please can someone tell me if i can put a tableView in a popup View. I have been using a function called showStandardDialog from PopupDialog, here some code:
func showStandardDialog(a: String, b:String) {
// Prepare the popup
let title = "¡ INFORMACIÓN !"
let message = "this is " + a + "and this is " + b
// Create the dialog
let popup = PopupDialog(title: title, message: message, buttonAlignment: .horizontal, transitionStyle: .zoomIn, gestureDismissal: true) {
print("Completed")
}
// Create first button
let buttonOne = CancelButton(title: "CANCEL") {
}
// Create second button
let buttonTwo = DefaultButton(title: "OK") {
}
// Add buttons to dialog
popup.addButtons([buttonOne, buttonTwo])
// Present dialog
self.present(popup, animated: true, completion: nil)
}
But i don´t know how i can use this same function and library sending a list.
Thanks to all :)

PopupDialog is a 3rd party lib and if you need something super custom you should consider doing it yourself.
That being said if you want to use this lib, take a look at how the RatingViewController is done in the examples:
//
// RatingViewController.swift
// PopupDialog
//
// Created by Martin Wildfeuer on 11.07.16.
// Copyright © 2016 CocoaPods. All rights reserved.
//
import UIKit
class RatingViewController: UIViewController {
#IBOutlet weak var cosmosStarRating: CosmosView!
#IBOutlet weak var commentTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
commentTextField.delegate = self
view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(endEditing)))
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#objc func endEditing() {
view.endEditing(true)
}
}
extension RatingViewController: UITextFieldDelegate {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
endEditing()
return true
}
}
There is no reason why you couldn't add a TableView in the xib and in the ViewController include the necessary delegate and data source.

Related

i want to triger navigationcontroller when i press button in UIView class

I want to trigger Navigation controller to some other screen when i press the button in UIView class. How can i do this?
//Code for UIView Class in Which Button Iboutlet is created
import UIKit
protocol ButtonDelegate: class {
func buttonTapped()
}
class SlidesVC: UIView {
var delegate: ButtonDelegate?
#IBAction func onClickFinish(_ sender: UIButton) {
delegate?.buttonTapped()
}
#IBOutlet weak var imgProfile: UIImageView!
}
//ViewController Class code in Which Button Protocol will be entertained
class SwipingMenuVC: BaseVC, UIScrollViewDelegate {
var slidesVC = SlidesVC()
override func viewDidLoad() {
super.viewDidLoad()
slidesVC = SlidesVC()
// add as subview, setup constraints etc
slidesVC.delegate = self
}
extension BaseVC: ButtonDelegate {
func buttonTapped() {
self.navigationController?.pushViewController(SettingsVC.settingsVC(),
animated: true)
}
}
A more easy way is to use typealias. You have to write code in 2 places. 1. your viewClass and 2. in your View Controller.
in your SlidesView class add a typealias and define param type if you need otherwise leave it empty.
class SlidesView: UIView {
typealias OnTapInviteContact = () -> Void
var onTapinviteContact: OnTapInviteContact?
#IBAction func buttonWasTapped(_ sender: UIButton) {
if self.onTapinviteContact != nil {
self.onTapinviteContact()
}
}
}
class SwipingMenuVC: BaseVC, UIScrollViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
let slidesView = SlidesView()
slidesView.onTapinviteContact = { () in
// do whatever you want to do on button tap
}
}
You can use the delegate pattern to tell the containing ViewController that the button was pressed and let it handle whatever is needed to do next, The view doesn't really need to know what happens.
A basic example:
protocol ButtonDelegate: class {
func buttonTapped()
}
class SomeView: UIView {
var delegate: ButtonDelegate?
#IBAction func buttonWasTapped(_ sender: UIButton) {
delegate?.buttonTapped()
}
}
class ViewController: UIViewController {
var someView: SomeView
override func viewDidLoad() {
someView = SomeView()
// add as subview, setup constraints etc
someView.delegate = self
}
}
extension ViewController: ButtonDelegate {
func buttonTapped() {
self.showSomeOtherViewController()
// or
let vc = NewViewController()
present(vc, animated: true)
}
}

Disable / Enable a button in Xcode

Hi i'm new with Swift programming.
What im trying to do is Disable my button (signIn) in viewDidLoad and only enable when the textfields have text in them. Here's what i've achieved so far. (not much though!)
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
signIn.isEnabled = false
// Do any additional setup after loading the view, typically from a nib.
}
#IBOutlet weak var emailtxt: UITextField!
#IBOutlet weak var passwordtxt: UITextField!
#IBOutlet weak var signIn: UIButton!
I need help to create a function in signIn that keeps button disabled until text fields (emailtxt & passwordtxt) have text in them and then proceed.
Glad if anyone can sort me.
Thanks in advance!
First add these for all of your textFields in viewDidLoad():
emailtxt.addTarget(self, action: #selector(textFieldDidChange(_:)),
for: UIControlEvents.editingChanged)
passwordtxt.addTarget(self, action: #selector(textFieldDidChange(_:)),
for: UIControlEvents.editingChanged)
Then use this:
#objc func textFieldDidChange(_ textField: UITextField) {
self.buttonIsEnabled()
}
func buttonIsEnabled() {
var buttonIsEnabled = true
defer {
self.signIn.isEnabled = buttonIsEnabled
}
guard let emailtxt = self.emailtxt.text, !emailtxt.isEmpty else {
addButtonIsEnabled = false
return
}
guard let passwordtxt = self. passwordtxt.text, ! passwordtxt.isEmpty else {
addButtonIsEnabled = false
return
}
}
I use this way in my codes and it works well.
Even you can add more methods for additional checking to buttonIsEnabled, like:
self.checkEmailIsValid(for: emailtxt)
Of course you should handle this method before:
func checkEmailIsValid(for: String) {
//...
}
Set ViewController as delegate for emailtxt and passwordtxt like this,
override func viewDidLoad() {
super.viewDidLoad()
signIn.isEnabled = false
emailtxt.delegate = self
passwordtxt.delegate = self
// Do any additional setup after loading the view, typically from a nib.
}
Conform your ViewController to UITextFieldDelegate and enable/disable as the text input is finished,
extension ViewController: UITextFieldDelegate {
func textFieldDidEndEditing(_ textField: UITextField) {
if emailtxt.text?.isEmpty == false && passwordtxt.text?.isEmpty == false {
signIn.isEnabled = true
} else {
signIn.isEnabled = false
}
}
}
Here is the fix for your code you shared.
import UIKit
extension UIViewController {
func hideKeyboardWhenTappedAround() {
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(UIViewController.dismissKeyboard))
tap.cancelsTouchesInView = false
view.addGestureRecognizer(tap)
}
#objc func dismissKeyboard() {
view.endEditing(true)
}
}
extension SignInVC: UITextFieldDelegate {
func textFieldDidEndEditing(_ textField: UITextField) {
if emailtxt.text?.isEmpty == false && passwordtxt.text?.isEmpty == false {
signIn.isEnabled = true
} else {
signIn.isEnabled = false
}
}
}
class SignInVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
signIn.isEnabled = false
emailtxt.delegate = self
passwordtxt.delegate = self
self.hideKeyboardWhenTappedAround()
// 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.
}
#IBOutlet weak var emailtxt: UITextField!
#IBOutlet weak var passwordtxt: UITextField!
#IBOutlet weak var signIn: UIButton!
}
What I would do is create an IBAction from one of your text fields, and set the event to Editing Changed:
The code should look like this:
#IBAction func textFieldEditingDidChange(_ sender: UITextField) {
}
You can then connect that same outlet to both of your text fields by dragging from the outlet to your remaining field. If you've connected both correctly, clicking on the circle to the left of your IBAction should show two text fields:
The action will now be fired every time text changes in either of your fields.
Then, at the top of the file, I'd create a computed property that returns false unless there is something in both fields:
var shouldEnableButton: Bool {
guard let text1 = textField1.text, let text2 = textField2.text else {
return false
}
return text1.isEmpty && text2.isEmpty ? false : true
}
Finally, we add shouldEnableButton to our IBAction:
#IBAction func textFieldEditingDidChange(_ sender: UITextField) {
button.isEnabled = shouldEnableButton
}
Important
When you connect your second text field to the outlet, it will incorrectly assign Editing Did End as its event:
Delete this event and click and drag from Editing Changed to your IBAction:
Use SwiftValidator
https://github.com/SwiftValidatorCommunity/SwiftValidator
by this, you will set validation of email & password like below
import SwiftValidator
let validator = Validator()
validator.registerField(emailTextField, errorLabel: emailErrorLabel, rules: [RequiredRule(), EmailRule(message: "Invalid email")])
// MARK: - ValidationDelegate
extension ViewController: ValidationDelegate {
func validationSuccessful() {
self.loginUser()
}
func validationFailed(_ errors:[(Validatable ,ValidationError)]) {
for (field, error) in errors {
//Handle as per need - show extra label - shake view etc
/*
if let field = field as? UITextField {
Utilities.shakeTheView(shakeView: field)
}
error.errorLabel?.text = error.errorMessage
error.errorLabel?.isHidden = false
*/
}
}
}

How to resize ScrollView when keyboard appears?

I'm trying to create this post feature which would allow you to insert text as well as images (similar to Note app on iOS devices). However, I can't figure out how to move or resize my ScrollView when the keyboard appears when I press on the light-grey area (it's a text view field), so the grey area would resize and the add button would move above the keyboard when it appears.
// PostViewController.swift
//
// Created by Martynas on 09/12/2016.
// Copyright © 2016 Martynas. All rights reserved.
//
import UIKit
import Firebase
class PostViewController: UIViewController, UITextFieldDelegate {
#IBOutlet var ScrollView: UIScrollView!
#IBOutlet var titleTextField: UITextField!
#IBOutlet var contentTextField: UITextView!
#IBOutlet var Menu: UIView!
#IBAction func hideKeyboardWhenSwippedDown(_ sender: Any) {
contentTextField.endEditing(true)
}
override func viewDidLoad() {
super.viewDidLoad()
// Hide keyboard when...
self.hideKeyboardWhenTappedAround() // ...press anywhere outside the keyboard
self.titleTextField.delegate = self
self.contentTextField.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func sendTapped(_ sender: Any) {
if let uid = FIRAuth.auth()?.currentUser?.uid {
if let title = titleTextField.text {
if let content = contentTextField.text {
let postObject: Dictionary<String, Any> = [
"uid": uid,
"title": title,
"content": content
]
FIRDatabase.database().reference().child("posts").childByAutoId().setValue(postObject)
}
}
}
}
#IBAction func addTapped(_ sender: Any) {
}
func textFieldDidBeginEditing(_ textField: UITextField) {
if textField == contentTextField {
ScrollView.setContentOffset(CGPoint(x: 0, y: 0), animated: true)
} else {
return
}
}
func textFieldDidEndEditing(_ textField: UITextField) {
if textField == contentTextField {
ScrollView.setContentOffset(CGPoint(x: 0, y: 250), animated: true)
} else {
return
}
}
// Hide keyboard when user presses 'return' key on the keyboard...
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
titleTextField.resignFirstResponder()
return true
}
}
This is the Controller View:
You need to listen to the keyboardDidShow/Hide notification and adjust the scroll view's height accordingly. The keyboardDidShow notification userInfo contains the keyboard's frame and therefore height.
Presuming your scroll view has a constraint at the bottom of the super view, you can make it an IBOutlet and animate it's constant to the height of the keyboard and back to 0 when the keyboard show and hide notifications are fired respectively.

how to hide button when clicked from another view

I am a beginner of xcode programming. I am trying to do an action, when i click button from A view, the button of B view will be hidden. I already know i can use button.hidden = true; for self view controller but I don't know how to control button from other view.
Thanks
#IBAction func TestBut(sender: UIButton) {
setting.hidden = false
}
Before, you create a custom view with button, button action and a protocol as:
protocol CustomViewDelegate {
func buttonPressed (sender: AnyObject)
}
class CustomView: UIView {
#IBOutlet weak var button: UIButton!
var delegate: CustomViewDelegate!
override func awakeFromNib() {
super.awakeFromNib()
}
class func loadViewFromXib() -> CustomView {
return NSBundle.mainBundle().loadNibNamed("CustomView", owner: self, options: nil)[0] as! CustomView
}
#IBAction func buttonPressed(sender: AnyObject) {
self.delegate.buttonPressed(sender)
}
}
In your ViewController.
class ViewController: UIViewController, CustomViewDelegate {
var firstView: CustomView?
var secondView: CustomView?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.firstView = CustomView.loadViewFromXib()
self.secondView = CustomView.loadViewFromXib()
firstView!.frame = CGRectMake(0, 0, 100, 100)
secondView!.frame = CGRectMake(0, 200, 100, 100)
firstView!.delegate = self
secondView!.delegate = self
self.view.addSubview(firstView!)
self.view.addSubview(secondView!)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func buttonPressed(sender: AnyObject) {
if (sender as! UIButton) == self.firstView!.button {
self.secondView?.button.hidden = true
}else {
self.firstView?.button.hidden = true
}
}
}
the button has to be a property of the view( or view controller).
A call would look like this:
view.button.hidden = true

Changing label text inside method

I'm using delegation to pass back information from a view controller.
This is the method
func writeValueBack(value: String) {
self.label.text = value
}
The function gets called and all is great apart from the label doesn't update.
The label has a value and is not returning nil, I checked with this line
println(self.label.text)
It prints the value of 'value'
So that means that the label's text is being set to 'value' but it's not updating.
I even tried using the main thread but no luck
func writeValueBack(value: String) {
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.label.text = value
})
}
I just don't know what the problem is.
Any help would be great.
Protocol:
protocol writeValueBackDelegate {
func writeValueBack(value: String)
}
EDIT:
Code for my view controller:
//
// ViewController.swift
// DelegateTesting
//
// Created by Alex Catchpole on 30/11/2014.
// Copyright (c) 2014 Alex Catchpole. All rights reserved.
//
import UIKit
class ViewController: UIViewController, writeValueBackDelegate {
#IBOutlet weak var label: UILabel!
#IBOutlet weak var textField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "MainSegue" {
var vc = segue.destinationViewController as SecondViewController
vc.labelText = textField.text
vc.delegate = self
}
}
func writeValueBack(value: String) {
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.label.text = value
})
}
#IBAction func button(sender: AnyObject) {
self.label.text = textField.text
}
#IBAction func segue(sender: AnyObject) {
performSegueWithIdentifier("MainSegue", sender: self)
}
}
Second ViewController source:
//
// SecondViewController.swift
// DelegateTesting
//
// Created by Alex Catchpole on 30/11/2014.
// Copyright (c) 2014 Alex Catchpole. All rights reserved.
//
import UIKit
class SecondViewController: UIViewController {
#IBOutlet weak var label: UILabel!
#IBOutlet weak var textField: UITextField!
var labelText: String!
var delegate: writeValueBackDelegate? = nil
override func viewDidLoad() {
super.viewDidLoad()
label.text = labelText
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func button(sender: AnyObject) {
label.text = textField.text
}
#IBAction func segueBack(sender: AnyObject) {
var editedText = label.text
performSegueWithIdentifier("SecondSegue", sender: self)
if (delegate != nil) {
delegate?.writeValueBack(editedText)
println("working")
}
}
}
The issue is in your second view controller, which as rdelmar pointed out creates a new instance of your first view controller instead of navigating back to the original instance.
To fix this, you could use dismissViewControllerAnimated:completion instead of performing your second segue. But an unwind segue would lead to simpler code, and can be achieved by adding this to your first view controller:
#IBAction func unwindFromSecond(unwindSegue: UIStoryboardSegue) {
if let secondViewController = unwindSegue.sourceViewController as? SecondViewController {
label.text = secondViewController.label.text
// Or whatever you need to retrieve data from the second controller
}
}
Then in your storyboard create an unwind segue from the second view controller. For example if you have a Dismiss button, control-drag from this button to the Exit icon in your second view controller scene and choosing unwindFromSecond. For detailed steps see the answer to this other question: What are Unwind segues for and how do you use them?
You can now remove the writeValueBackDelegate declaration and associated variables, the writeValueBack method and the second view controller's segueBack method

Resources