My app runs fine on simulator but when I run on device it hangs on the first view. It doesn't call anything in viewDidLoad or viewDidAppear. Running swift 3, iOS 10, device is a 6S updated to iOS 10.
import UIKit
import Firebase
import SwiftKeychainWrapper
class FirstVC: UIViewController {
override func viewDidLoad() {
}
override func viewDidAppear(_ animated: Bool) {
// MARK: Checks if you have an account and never logged out
if let userId = KeychainWrapper.defaultKeychainWrapper().stringForKey(KEY_UID) {
DataService.ds.REF_USERS.child(userId).observeSingleEvent(of: .value, with: { (FIRDataSnapshot) in
guard let dict = FIRDataSnapshot.value as? NSDictionary, let setup = dict["setup"] as? Bool else {
self.performSegue(withIdentifier: "firstToDemo", sender: nil)
return
}
if setup {
self.performSegue(withIdentifier: "firstToPollBar", sender: nil)
} else {
self.performSegue(withIdentifier: "firstToDemo", sender: nil)
}
})
} else {
self.performSegue(withIdentifier: "firstToLogin", sender: nil)
}
}
}
Related
I've been trying to get a UIPrinterPicker to show up but for some reason it just never does. The completion handler gets called immediately. The UIPrintInteractionController shows up just fine but this one refuses to show for some reason. This is the code I am using currently
let picker = UIPrinterPickerController(initiallySelectedPrinter: nil)
picker.present(animated: true) { (controller, complete, error) in
print("done")
}
Implement UIPrinterPickerControllerDelegate so it works for iOS 13
https://developer.apple.com/documentation/uikit/uiprinterpickercontroller/1620514-present
class ViewController: UIViewController {
#IBAction func btnTapped(_ sender: Any) {
let picker = UIPrinterPickerController(initiallySelectedPrinter: nil)
picker.delegate = self
picker.present(animated: true) { (controller, complete, error) in
print("done")
}
}
}
// MARK:- UIPrinterPickerControllerDelegate
extension ViewController: UIPrinterPickerControllerDelegate {
func printerPickerControllerParentViewController(_ printerPickerController: UIPrinterPickerController) -> UIViewController? {
return self
}
}
Main issue is checking if user has a child in the Firebase database so that I know if he is signing up or logging in.
Part 1: Part 1 (Child Database (this works) and making that a user default (I'm not sure how to check it that worked)
Part 2: in different .Swift file (Check if the User Default (aka Education Child) exists. I have pretty much nothing, except I know it must go into viewDidAppear
Part 1
#IBAction func SubmitPressed(_ sender: Any) {
let databaseRef = Database.database().reference()
let uid = Auth.auth().currentUser!.uid
databaseRef.child("Education").child(uid).setValue(self.Education.text!)
UserDefaults.standard.set("Education", forKey: "Education")
Part 2
func viewDidAppear(_ animated: String) {
??????
}
No error for part 1, though not sure if it created the user default. For part 2, I have tried a bunch of stuff, but hasn't worked.
Here is the updated code after first answer:
import Foundation
import UIKit
import SwiftKeychainWrapper
import Firebase
import CoreFoundation
import AVFoundation
import FirebaseDatabase
var educationCache : String {
get {
return (UserDefaults.standard.string(forKey: "Education")!)
} set {
UserDefaults.standard.set(newValue, forKey: "Education")
}
}
relavant part of education/personal info enter page
#IBAction func SubmitPressed(_ sender: Any) {
let databaseRef = Database.database().reference()
let uid = Auth.auth().currentUser!.uid
databaseRef.child("Education").child(uid).setValue(self.Education.text!)
// The following line will save it in userDefault itself. And you dont have to call the whole UserDefault Everywhere
educationCache = "Education"
self.performSegue(withIdentifier: "tohome", sender: nil)
}
homepage
import Foundation
import UIKit
import SwiftKeychainWrapper
import Firebase
import CoreFoundation
import AVFoundation
import FirebaseDatabase
class homepage:UITableViewController {
override func viewDidAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if educationCache.count < 0 {
self.performSegue(withIdentifier: "toFeed", sender: nil)
}
}
override func viewDidLoad() {
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Sign Out", style: .plain, target: self, action: #selector(signOut))
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#objc func signOut (_sender: AnyObject) {
KeychainWrapper.standard.removeObject(forKey: "uid")
do {
try Auth.auth().signOut()
} catch let signOutError as NSError {
print ("Error signing out: %#", signOutError)
}
dismiss(animated: true, completion: nil)
}
}
You dont want to check the condition is the viewController where you are performing specific actions. Also checking the userDefaults everytime is just putting extra views in heirarchy. Firebase provides .addStateDidChangeListener function to keep a check of it. Add the following code to your delegate. It will automatically switch between the users if there are any or not.
AppDelegate.swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
observeUser()
return true
}
func observeUser(){
Auth.auth().addStateDidChangeListener { (auth, user) in
if (user != nil) {
// If the user is not nil. Perform this block
self.showInitController(with identifier: "<add_your_storyboard_reusableID_for_homepage>", animated: false)
// The storyboard Id belongs to the HOMEPAGE/FEED, the view where user goes on signIn
} else {
//If there is no user. This block will perform
self.showInitController(with identifier: "<add_your_storyboard_reusableID_for_loginpage>", animated: false)
// The storyboard Id belongs to the SIGNUP PAGE, the view where user goes on signIn
}
}
}
func showInitController(with identifier: String, animated: Bool = false) {
DispatchQueue.main.async {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: identifier)
var topRootViewController: UIViewController = (UIApplication.shared.keyWindow?.rootViewController)!
while((topRootViewController.presentedViewController) != nil){
topRootViewController = topRootViewController.presentedViewController!
}
topRootViewController.present(vc, animated: animated, completion: nil)
}
}
In your swift file one. do the following and never look back. You can automatically redirect to view if you applied the other functions.
#IBAction func SubmitPressed(_ sender: Any) {
let databaseRef = Database.database().reference()
let uid = Auth.auth().currentUser!.uid
databaseRef.child("Education").child(uid).setValue(self.Education.text!)
self.performSegue(withIdentifier: "tohome", sender: nil)
}
In the second view dont bother to do anything anywhere. Just leave it, if nothing in that view is required again.
I've implemented screen recording with ReplayKit in foreground mode of the application. But when I'm going outside the app with home button app stops background record.
--> There is an app available In App Store which allows background screen record.
--> If I have to use Broadcast upload and UI extension then please provide me some programming guide. I've added both in my app but still it stops recording in background mode.
Below is my code
import UIKit
import ReplayKit
class ViewController: UIViewController {
let recorder = RPScreenRecorder.shared()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
#IBAction func btnStartRecord_Action(_ sender: UIButton) {
if recorder.isAvailable {
if !recorder.isRecording {
recorder.startRecording { (error) in
if let error = error {
print(error)
}
}
}
}
}
#IBAction func btnStopRecord_Action(_ sender: UIButton) {
if recorder.isAvailable {
if recorder.isRecording {
recorder.stopRecording { (previewVC, error) in
if let previewController = previewVC {
previewController.previewControllerDelegate = self
self.present(previewController, animated: true, completion: nil)
}
}
}
}
}
}
extension ViewController: RPPreviewViewControllerDelegate {
func previewControllerDidFinish(_ previewController: RPPreviewViewController) {
previewController.dismiss(animated: true) {
}
}
}
I am having issues trying to pass the data back to the ViewController (from BarCodeScannerViewController to TableViewController)
SecondVC (BarCodeScannerViewController.swift):
#objc func SendDataBack(_ button:UIBarButtonItem!) {
if let presenter = self.presentingViewController as? TableViewController {
presenter.BarCode = "Test"
}
self.dismiss(animated: true, completion: nil)
}
FirstVC (TableViewController.swift):
// The result is (BarCode - )
var BarCode: String = ""
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
print("BarCode - \(BarCode)")
}
Each time ViewWillAppear is running the value is not set, what could be causing this issue?
You should use the delegate pattern. I doubt in your code above that self.presentingViewController is actually set.
An example of using the delegate pattern for this:
// BarCodeScannerViewController.swift
protocol BarcodeScanningDelegate {
func didScan(barcode: String)
}
class BarCodeScannerViewController: UIViewController {
delegate: BarcodeScanningDelegate?
#objc func SendDataBack(_ button:UIBarButtonItem!) {
delegate?.didScan(barcode: "Test")
}
}
// TableViewController
#IBAction func scanBarcode() {
let vc = BarCodeScannerViewController()
vc.delegate = self
self.present(vc, animated: true)
}
extension TableViewController: BarcodeScanningDelegate {
func didScan(barcode: String) {
print("[DEBUG] - Barcode scanned: \(barcode)")
}
}
I'm trying to send data across another view controller once a button is pressed (I know this question looks repetitive), however, the button being pressed is processing some data. So when the button is clicked, the other view controller is popped up before the needed actual data is sent. I tried both segue calls (prepare for segue and the calling segue) but none seem to work. Here is my code:
#IBAction func login(sender: Any) {
SparkCloud.sharedInstance().login(withUser: email, password: password) { (error:Error?) -> Void in
if let _ = error {
print("Wrong credentials or no internet connectivity, please try again")
}
else {
print("Logged in")
var myPhoton : SparkDevice?
SparkCloud.sharedInstance().getDevices { (devices:[SparkDevice]?, error:Error?) -> Void in
if let _ = error {
print("Check your internet connectivity")
}
else {
if let d = devices {
for device in d {
myPhoton = device
print(myPhoton!)
}
}
}
}
}
}
}
And the segue:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "loggedIn" {
if let destinationVC = segue.destination as? testViewController {
destinationVC.myPhoton = sentDevice
}
}
}
And the other view controller that is receiving the data:
var myPhoton : SparkDevice?
override func viewDidLoad() {
super.viewDidLoad()
print(myPhoton)
}
I receive 'nil', which indicates that when the data has been set, it was before it got set to the data that I wanted from the server. Can someone help me please?
You can try
#IBAction func login(sender: Any) {
SparkCloud.sharedInstance().login(withUser: email, password: password) { (error:Error?) -> Void in
if let _ = error {
print("Wrong credentials or no internet connectivity, please try again")
}
else {
print("Logged in")
var myPhoton : SparkDevice?
SparkCloud.sharedInstance().getDevices { (devices:[SparkDevice]?, error:Error?) -> Void in
if let _ = error {
print("Check your internet connectivity")
}
else {
if let d = devices {
for device in d {
myPhoton = device
print(myPhoton!)
}
self.performSegue(withIdentifier: "loggedIn", sender: myPhoton)
}
}
}
}
}
}
and remove linking the segue directly to the button action in IB
Edit
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "loggedIn" {
if let destinationVC = segue.destination as? testViewController {
destinationVC.myPhoton = sender as! SparkDevice
}
}
}
Instead of using Segue, you can also try doing it with code, i.e.
#IBAction func login(_ sender: UIButton)
{
SparkCloud.sharedInstance().login(withUser: email, password: password) {
if let _ = error
{
print("Wrong credentials or no internet connectivity, please try again")
}
else
{
print("Logged in")
var myPhoton : SparkDevice?
SparkCloud.sharedInstance().getDevices { (devices:[SparkDevice]?, error:Error?) -> Void in
if let _ = error
{
print("Check your internet connectivity")
}
else
{
if let d = devices
{
for device in d
{
myPhoton = device
print(myPhoton!)
//HERE..!!!!!
DispatchQueue.main.async {[weak self] in
let anotherController = self.storyboard?.instantiateViewController(withIdentifier: "AnotherVC") as! AnotherVC
anotherController.myPhoton = myPhoton
self.navigationController?.pushViewController(anotherController, animated: true)
}
}
}
}
}
}
}
}
In the above code, if you want to push the controller, then use:
self.navigationController?.pushViewController(anotherController, animated: true)
otherwise, if you want to present the controller, then use:
self.present(anotherController, animated: true, completion: nil)
Let me know if you still face any issues.