when following the instructions for FirebaseUI to display the LoginViewController it only shows a black screen.
As you can see it kind of replaces the current viewcontroller instead of presenting it.
Here is the code from the presenting viewcontroller
import UIKit
import Firebase
import FirebaseUI
class FirstViewController: UIViewController {
#IBOutlet weak var logoutButton: UIButton!
var rootRef = Firebase(url: Constants.FireBaseUrl)
var loginViewController: FirebaseLoginViewController!
override func viewDidLoad() {
super.viewDidLoad()
loginViewController = FirebaseLoginViewController(ref: rootRef)
loginViewController.enableProvider(.Facebook)
loginViewController.enableProvider(.Password)
loginViewController.didDismissWithBlock { (user: FAuthData!, error: NSError!) -> Void in
if (user != nil) {
// user
} else if (error != nil) {
// error
} else {
// cancel
}
}
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
if (loginViewController.currentUser() == nil) {
presentViewController(loginViewController, animated: true, completion: nil)
}
}
// MARK: - Actions
#IBAction func logoutTouched(sender: AnyObject) {
rootRef.unauth()
}
}
Related
I am trying to keep the user logged in. I tried with the code below. The app uses Firebase for storing data and logging in users.
import UIKit
import Firebase
class WelcomeViewController: UIViewController {
#IBOutlet weak var logInButton: UIButton!
#IBOutlet weak var signUpButton: UIButton!
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.isNavigationBarHidden = true
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
navigationController?.isNavigationBarHidden = false
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
logInButton.backgroundColor = .clear
logInButton.layer.cornerRadius = 27
logInButton.layer.borderWidth = 1
logInButton.layer.borderColor = UIColor.systemGreen.cgColor
if Auth.auth().currentUser != nil {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let secondVC = storyboard.instantiateViewController(identifier: "EcoMapViewController")
show(secondVC, sender: self)
} else {
do {
try Auth.auth().signOut()
navigationController?.popToRootViewController(animated: true)
} catch let signOutError as NSError {
print("Error signing out: %#", signOutError)
}
}
}
}
Userdefault in this case is not a viable solution as they are not encrypted and can be accessed and modified by anyone. A good solution is to use Apple's keychain. I would recommend using this open source keyChain Api module, so that it becomes easier to interface with it.
I have an app that uses a main screen (below) and then a barcode scanner framework to scan in a barcode and then I will code an action to perform. However, the problem I am having is that in the code it takes me back to the scanning screen. I have tried to use present(VC1, animated: true, completion: nil) and it does not know what VC1 is.
I assigned VC1 in Xcode under storyboard id (see below):
Below is my code here for view controller.swift. Now the code takes you back to the scanning screen, but I want to go back to VC1 the main view controller.
import UIKit
import BarcodeScanner
var presentedViewController: UIViewController?
final class ViewController: UIViewController {
#IBOutlet var pushScannerButton: UIButton!
//Present view and handle barcode scanning
#IBAction func handleScannerPush(_ sender: Any, forEvent event: UIEvent) {
let viewController = makeBarcodeScannerViewController()
viewController.title = "Barcode Scanner"
present(viewController, animated: true, completion: nil)
}
private func makeBarcodeScannerViewController() -> BarcodeScannerViewController {
let viewController = BarcodeScannerViewController()
viewController.codeDelegate = self
viewController.errorDelegate = self
viewController.dismissalDelegate = self
return viewController
}
}
// MARK: - BarcodeScannerCodeDelegate
extension ViewController: BarcodeScannerCodeDelegate {
func scanner(_ controller: BarcodeScannerViewController, didCaptureCode code: String, type: String) {
print("Barcode Data: \(code)")
print("Symbology Type: \(type)")
controller.dismiss(animated: true, completion: nil)
// DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
// controller.resetWithError()
// }
}
}
// MARK: - BarcodeScannerErrorDelegate
extension ViewController: BarcodeScannerErrorDelegate {
func scanner(_ controller: BarcodeScannerViewController, didReceiveError error: Error) {
print(error)
}
}
// MARK: - BarcodeScannerDismissalDelegate
extension ViewController: BarcodeScannerDismissalDelegate {
func scannerDidDismiss(_ controller: BarcodeScannerViewController) {
controller.dismiss(animated: true, completion: nil)
}
}
I read this and tried to build a location picker app, where the below code worked perfectly:
import UIKit
import GooglePlacePicker
class ViewController: UIViewController {
// Add a pair of UILabels in Interface Builder, and connect the outlets to these variables.
#IBOutlet var nameLabel: UILabel!
#IBOutlet var addressLabel: UILabel!
// Add a UIButton in Interface Builder, and connect the action to this function.
#IBAction func pickPlace(_ sender: UIButton) {
let center = CLLocationCoordinate2D(latitude: 37.788204, longitude: -122.411937)
let northEast = CLLocationCoordinate2D(latitude: center.latitude + 0.001, longitude: center.longitude + 0.001)
let southWest = CLLocationCoordinate2D(latitude: center.latitude - 0.001, longitude: center.longitude - 0.001)
let viewport = GMSCoordinateBounds(coordinate: northEast, coordinate: southWest)
let config = GMSPlacePickerConfig(viewport: viewport)
let placePicker = GMSPlacePicker(config: config)
placePicker.pickPlace(callback: {(place, error) -> Void in
if let error = error {
print("Pick Place error: \(error.localizedDescription)")
return
}
if let place = place {
self.nameLabel.text = place.name
self.addressLabel.text = place.formattedAddress?.components(separatedBy: ", ")
.joined(separator: "\n")
} else {
self.nameLabel.text = "No place selected"
self.addressLabel.text = ""
}
})
}
}
Apparently the GMSPlacePicker is deprecated, and replaced by GMSPlacePickerViewController, so I tried the example here:
import UIKit
import GooglePlacePicker
class ViewController: UIViewController {
// Add a pair of UILabels in Interface Builder, and connect the outlets to these variables.
#IBOutlet var nameLabel: UILabel!
#IBOutlet var addressLabel: UILabel!
// The code snippet below shows how to create and display a GMSPlacePickerViewController.
#IBAction func pickPlace(_ sender: UIButton) {
let config = GMSPlacePickerConfig(viewport: nil)
let placePicker = GMSPlacePickerViewController(config: config)
present(placePicker, animated: true, completion: nil)
}
// To receive the results from the place picker 'self' will need to conform to
// GMSPlacePickerViewControllerDelegate and implement this code.
func placePicker(_ viewController: GMSPlacePickerViewController, didPick place: GMSPlace) {
// Dismiss the place picker, as it cannot dismiss itself.
viewController.dismiss(animated: true, completion: nil)
print("Place name \(place.name)")
print("Place address \(place.formattedAddress)")
print("Place attributions \(place.attributions)")
}
func placePickerDidCancel(_ viewController: GMSPlacePickerViewController) {
// Dismiss the place picker, as it cannot dismiss itself.
viewController.dismiss(animated: true, completion: nil)
print("No place selected")
}
}
But it is not functioning properly, am I missing anything here? The location picker is poping up, but neither the cancel button is clickable, nor the location picker is closed upon picking the required location, and accordingly nothing is printed!
Thanks for the comments from #tassinai below the full working code:
import UIKit
import GooglePlacePicker
class ViewController: UIViewController, GMSPlacePickerViewControllerDelegate {
#IBOutlet weak var placeNameLabel: UILabel!
#IBAction func placePicker(_ sender: Any) {
let config = GMSPlacePickerConfig(viewport: nil)
let placePicker = GMSPlacePickerViewController(config: config)
placePicker.delegate = self
present(placePicker, animated: true, completion: nil)
}
func placePicker(_ viewController: GMSPlacePickerViewController, didPick place: GMSPlace) {
viewController.dismiss(animated: true, completion: nil)
print("Place name \(place.name)")
placeNameLabel.text = place.name
}
func placePicker(_ viewController: GMSPlacePickerViewController, didFailWithError error: Error) {
// In your own app you should handle this better, but for the demo we are just going to log
// a message.
NSLog("An error occurred while picking a place: \(error)")
}
func placePickerDidCancel(_ viewController: GMSPlacePickerViewController) {
// Dismiss the place picker, as it cannot dismiss itself.
viewController.dismiss(animated: true, completion: nil)
print("No place selected")
placeNameLabel.text = "No place selected"
}
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.
}
}
Below another way of writing the above code:
import UIKit
import GooglePlacePicker
class ViewController: UIViewController {
#IBOutlet weak var placeNameLabel: UILabel!
#IBAction func placePicker(_ sender: Any) {
let config = GMSPlacePickerConfig(viewport: nil)
let placePicker = GMSPlacePickerViewController(config: config)
placePicker.delegate = self
present(placePicker, animated: true, completion: nil)
}
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.
}
}
extension ViewController : GMSPlacePickerViewControllerDelegate {
func placePicker(_ viewController: GMSPlacePickerViewController, didPick place: GMSPlace) {
viewController.dismiss(animated: true, completion: nil)
print("Place name \(place.name)")
placeNameLabel.text = place.name
}
func placePicker(_ viewController: GMSPlacePickerViewController, didFailWithError error: Error) {
// In your own app you should handle this better, but for the demo we are just going to log
// a message.
NSLog("An error occurred while picking a place: \(error)")
}
func placePickerDidCancel(_ viewController: GMSPlacePickerViewController) {
// Dismiss the place picker, as it cannot dismiss itself.
viewController.dismiss(animated: true, completion: nil)
print("No place selected")
placeNameLabel.text = "No place selected"
}
}
After the user logs in SUCCESSFULLY, I need to switch view controllers to the timeline section of my app, this is also going to be a tab bar view controller with 5 different tabs at the bottom. Here is the code I have so far, it works and is connected to the parse database I have setup.
import UIKit
import Parse
class LoginViewController: UIViewController {
#IBOutlet var usernameField: UITextField!
#IBOutlet var passwordField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func loginTapped(sender: AnyObject) {
let username = usernameField.text
let password = passwordField.text
PFUser.logInWithUsernameInBackground(username, password:password) {
(user: PFUser?, error: NSError?) -> Void in
if user != nil {
println("Success")
} else {
var loginError:UIAlertView = UIAlertView(title: "Invalid Login", message: "I did not recognize your credentials. Try again?", delegate: self, cancelButtonTitle: "Dismiss")
loginError.show()
}
}
}
#IBAction func closeTapped(sender: AnyObject) {
dismissViewControllerAnimated(true, completion: nil)
}
}
In the line println("sucessful"), instead of printing out the sucessful login I need to switch to their timeline home (the tab bar view controller).
Use a segue to transition to new view controller if the login was successful:
if user != nil {
self.performSegueWithIdentifier("successfulLoginPage", sender: self)
}
What I am trying to do is have a settings page in my app and when a switch is clicked on (its original state is off) then it will mute the entire app. So far what my code can do is mute only the current view and it works great until I either segue to my main view then that music is still playing that is associated with that and when I segue back to the settings page the mute switch is returned to its original off state and the music is playing once again. I was wondering how to fix my code so that when turned on it mutes all noise. Here is my code thank you for reading and helping:
import UIKit
import AVFoundation
var songs = ""
var backgroundMusicPlayer: AVAudioPlayer!
func playBackgroundMusic(filename: String) {
let url = NSBundle.mainBundle().URLForResource(
filename, withExtension: nil)
if (url == nil) {
println("Could not find file: \(filename)")
return
}
var error: NSError? = nil
backgroundMusicPlayer =
AVAudioPlayer(contentsOfURL: url, error: &error)
if backgroundMusicPlayer == nil {
println("Could not create audio player: \(error!)")
return
}
backgroundMusicPlayer.numberOfLoops = -1
backgroundMusicPlayer.prepareToPlay()
backgroundMusicPlayer.play()
}
class settingsView: UIViewController {
#IBOutlet weak var mySwitch: UISwitch!
#IBAction func switchPressed(sender: AnyObject) {
playBackgroundMusic(songs)
if mySwitch.on {
backgroundMusicPlayer.pause()
} else {
backgroundMusicPlayer.play()
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do view setup here.
songs = "settingsBackground.mp3"
switchPressed(self)
}
}
You can do it like this way:
MainViewController.swift
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do view setup here.
let status = NSUserDefaults().stringForKey("playerStatus")
if status == "Off"{
if (backgroundMusicPlayer?.playing != nil){
backgroundMusicPlayer?.stop()
}
}else{
songs = "1.mp3"
playBackgroundMusic(songs)
}
}
}
settingsView.swift
import UIKit
class settingsView: UIViewController {
#IBOutlet weak var mySwitch: UISwitch!
#IBAction func switchPressed(sender: AnyObject) {
if mySwitch.on {
NSUserDefaults().setObject("on", forKey: "playerStatus")
playBackgroundMusic(songs)
} else {
NSUserDefaults().setObject("Off", forKey: "playerStatus")
backgroundMusicPlayer!.stop()
}
}
override func viewDidLoad() {
super.viewDidLoad()
let status = NSUserDefaults().stringForKey("playerStatus")
if status == "Off" {
mySwitch.setOn(false, animated: false)
}
}
}
Here is complete working project : https://github.com/DharmeshKheni/Switch-with-AudioPlayer