I am trying to build out a collection group query.
It is for the iOS swift environment. I have the latest Xcode, Swift, firebase, and firestore all running on my machine.
When I try to create a collection group query, the compiler does not offer the collectionGroup() method and throws an error as unrecognized when I type it out myself.
Any else running into this?
Help please?
I wonder if I skipped a step in terminal, but I have followed all google provided documentation to the letter.
Thanks in advance.
EDIT: here is the relevant code in my ViewController:
import UIKit
import Firebase
class FindYourAcademyViewController: UIViewController, UITableViewDelegate,
UITableViewDataSource {
#IBOutlet weak var searchStackView: UIStackView!
#IBOutlet weak var nameSearchTextField: UITextField!
#IBOutlet weak var locationSearchTextField: UITextField!
#IBOutlet weak var pleaseFindAcademyLabelOutlet: UILabel!
#IBOutlet weak var searchResultsTableViewOutlet: UITableView!
#IBOutlet weak var nextButtonOutlet: DesignableButton!
var db: Firestore!
override func viewDidLoad() {
super.viewDidLoad()
nameSearchTextField.delegate = self
locationSearchTextField.delegate = self
searchResultsTableViewOutlet.isHidden = true
searchResultsTableViewOutlet.delegate = self
searchResultsTableViewOutlet.dataSource = self
let settings = FirestoreSettings()
Firestore.firestore().settings = settings
db = Firestore.firestore()
}
}
// MARK: - UITextField Delegate methods and Keyboard handling
extension FindYourAcademyViewController: UITextFieldDelegate {
// UITextField Delegate methods
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
if textField == nameSearchTextField {
textField.resignFirstResponder()
locationSearchTextField.becomeFirstResponder()
print("Next button tapped")
} else if textField == locationSearchTextField {
textField.resignFirstResponder()
print("Search button tapped")
isSearching = false
// keyboard search button fires off the firestore query and returns the query search results
db.collectionGroup() /* <-- THIS WHERE THE ERROR IS THROWN */
}
return true
}
}
i ran a pod update and the issue was resolved, so lesson learned, be sure to update those pods in addition to installing the desired ones!
Related
I'm completely new to programming. Trying to learn Swift. I've created the UI for my app. A simple data entry app for weight lifting PB's. However when I close the app my data doesn't update to new stored values. How do assign a variable string to each UITextfield entry, which when I close the app it will display its last stored value?
import UIKit
class ViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var benchPressPB: UITextField!
#IBOutlet weak var squatPB: UITextField!
#IBOutlet weak var deadliftPB: UITextField!
#IBOutlet weak var ohpPB: UITextField!
#IBOutlet weak var rackPullPB: UITextField!
#IBOutlet weak var legPressPB: UITextField!
#IBOutlet weak var pullUpsPB: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
self.benchPressPB.delegate = self
self.squatPB.delegate = self
self.deadliftPB.delegate = self
self.ohpPB.delegate = self
self.rackPullPB.delegate = self
self.legPressPB.delegate = self
self.pullUpsPB.delegate = self
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
}
P.S this may completely wrong and long already, but currently its achieving what I want it do, just not saving new inputted data. If there's any shorter way to get the keyboard to hide on return, let me know!
Your current code doesn't do anything with the values a user enters into your text fields.
You should
Set up a model object to hold the values that the user enters.
In your textFieldShouldReturn, collect the user input and save it
into your model.
Decide on how you want to persist your app's state so it restores
when the app is launched. At it's simplest, this could be saving each
string to a different key/value pair in UserDefaults, or grouped
together in a dictionary or an array.
The code might look something like this: (not tested. Not even compiled. It will need cleanup before you can use it:
#IBOutlet weak var benchPressPB: UITextField!
#IBOutlet weak var squatPB: UITextField!
#IBOutlet weak var deadliftPB: UITextField!
#IBOutlet weak var ohpPB: UITextField!
#IBOutlet weak var rackPullPB: UITextField!
#IBOutlet weak var legPressPB: UITextField!
#IBOutlet weak var pullUpsPB: UITextField!
var textFields = [UITextField]
var textFieldKeys = [
"benchPressPB",
"squatPB",
"deadliftPB",
"ohpPB",
"rackPullPB",
"legPressPB",
"pullUpsPB"
]
var textFieldStrings = [String]()
override func viewDidLoad() {
super.viewDidLoad()
// Note that you can hook up the delegates for your
// text fields in your Storyboard.
self.benchPressPB.delegate = self
self.squatPB.delegate = self
self.deadliftPB.delegate = self
self.ohpPB.delegate = self
self.rackPullPB.delegate = self
self.legPressPB.delegate = self
self.pullUpsPB.delegate = self
textFields = [benchPressPB, squatPB, deadliftPB, ohpPB, rackPullPB, legPressPB, pullUpsPB]
// Read values from UserDefaults into the text fields.
for (index, key) in textFieldKeys.enumerated() {
let aValue = UserDefaults.standard.string(forKey: key)
textFields[index].text = aValue
textFieldStrings.append(aValue ?? "")
}
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
let newText = textField.text
if let index = textFields.firstIndex(of: textField) {
textFieldStrings[index] = newText
UserDefaults.standard.set(newText, forKey: textFieldKeys[index])
}
return true
}
You can subclass UITextField and add a target for editing changed. Every time your text changes you can simply save its new value into user defaults. To make sure you use a unique key for each field you can override the accessibilityIdentifier and implement didSet to load the old values when you set its identifier:
import UIKit
class PersistentTextField: UITextField, UITextFieldDelegate {
override var accessibilityIdentifier: String? {
didSet {
text = UserDefaults.standard.string(forKey: accessibilityIdentifier ?? "")
}
}
override func didMoveToSuperview() {
addTarget(self, action: #selector(editingChanged), for: .editingChanged)
autocapitalizationType = .none
autocorrectionType = .no
delegate = self
}
#objc func editingChanged(_ textField: UITextField) {
UserDefaults.standard.set(text ?? "", forKey: accessibilityIdentifier ?? "")
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
resignFirstResponder()
return true
}
}
Then in your view controller just make sure to set their id when your view loads:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var benchPressPB: PersistentTextField!
#IBOutlet weak var squatPB: PersistentTextField!
#IBOutlet weak var deadliftPB: PersistentTextField!
#IBOutlet weak var ohpPB: PersistentTextField!
#IBOutlet weak var rackPullPB: PersistentTextField!
#IBOutlet weak var legPressPB: PersistentTextField!
#IBOutlet weak var pullUpsPB: PersistentTextField!
override func viewDidLoad() {
super.viewDidLoad()
benchPressPB.accessibilityIdentifier = "bench press"
squatPB.accessibilityIdentifier = "squat"
deadliftPB.accessibilityIdentifier = "dead lift"
ohpPB.accessibilityIdentifier = "ohp"
rackPullPB.accessibilityIdentifier = "rack pull"
legPressPB.accessibilityIdentifier = "leg press"
pullUpsPB.accessibilityIdentifier = "pull ups"
}
}
I am using the following UIView extension:
https://github.com/snoozelag/GoneVisible
I have successfully downloaded the file and added the Swift file and I am using the extension to hide (gone method) and show (visible method) buttons on the navigation bar. When the app first opens, I call this extension in an attempt to hide certain buttons if the user is already logged in. However, this has not been working. Strangely, it DOES work and hides the buttons after I segue to a different view and go back.
Here is the code:
import UIKit
import Parse
class ViewController: UIViewController {
#IBOutlet weak var signUpButton: UIButton!
#IBOutlet weak var logInButton: UIButton!
#IBOutlet weak var myAccountButton: UIButton!
#IBOutlet weak var bigGame: UIImageView!
private func setUpPage(){
let currentUser = PFUser.current()
if currentUser != nil {
// Do stuff with the user
self.myAccountButton.visible()
self.signUpButton.gone()
self.logInButton.gone()
} else {
// Show the signup or login screen
self.myAccountButton.gone()
self.signUpButton.visible()
self.logInButton.visible()
}
}
override func viewDidLoad() {
setUpPage()
super.viewDidLoad()
self.navigationItem.hidesBackButton = true;
}
override func viewWillAppear(_
animated: Bool) {
setUpPage()
}
My question is, how can I get this extension to fire when the app is first opened?
Thanks a lot for your help :)
Don't forget to call super.viewWillAppear(...) when you override the inherited implementation.
This might solve your issue - but even if not it is correct to do it.
Update:
try calling setUpPage() only once and only after you call super.viewDidLoad()
I have a formulary of login, with 3 fields and a button to login. I wants set a button in the keyboard do jump of UITextField to next when user ends write the content. Besides that, when user put text on last field, the button login is hidden behind keyboard! I tried choose the options on the attributes inspector, but I don't know how use this.
class ViewControllerAuthentication: UIViewController {
#IBOutlet weak var btEntrar: UIButton!
#IBOutlet weak var textPassword: UITextField!
#IBOutlet weak var textEmail: UITextField!
#IBOutlet weak var textURL: UITextField!
let alert = Alerta()
var url : String?
var email : String?
var password : String?
override func viewDidLoad() {
self.btEntrar.addTarget(self, action: #selector(clickEntrar), for: .touchUpInside)
}
#objc func clickEntrar(_ sender : UIButton) {
// Do anything
}
}
You can do it, using UITextFieldDelegate, like...
class ViewControllerAuthentication: UIViewController, UITextFieldDelegate {
#IBOutlet weak var textPassword: UITextField!
#IBOutlet weak var textEmail: UITextField!
#IBOutlet weak var textURL: UITextField!
override func viewDidLoad() {
textPassword.delegate = self
textEmail.delegate = self
textURL.delegate = self
textURL.returnKeyType = .next
textEmail.returnKeyType = .next
textPassword.returnKeyType = .default // or .done
}
public func textFieldShouldReturn(_ textField: UITextField) -> Bool {
switch textField {
case textURL:
textEmail.becomeFirstResponder()
case textEmail:
textPassword.becomeFirstResponder()
case textPassword:
textField.resignFirstResponder()
default:
textField.resignFirstResponder()
}
return true
}
}
I suggest IQKeyboardManager, if you don't want to handle each field manually.
I'm new in Swift 3, and I just notice that we need to scroll a view since the keyboard can go over the some widgets as we type in text fields, like in this video. Fixing UITextField-Keyboard Problems (Swift in Xcode).
However, I am having an unfortunate behaviour even before programmatically scrolling the view. My view keeps being reset to its initial position. I made a video showing this behaviour.
I can't find mentions for this problem. Would someone have a clue?
[EDITED]
Here is the widgets are structured
Here is my View Controller code:
import UIKit
import AVFoundation
class SignUpController: UIViewController, UITextFieldDelegate
{
#IBOutlet var scrollView: UIScrollView!
#IBOutlet var stackView: UIStackView!
#IBOutlet var usernameTextField: UITextField!
#IBOutlet var passwordTextField: UITextField!
#IBOutlet var confirmationTextField: UITextField!
#IBOutlet var emailTextField: UITextField!
#IBOutlet var phoneTextField: UITextField!
#IBOutlet var firstNameTextField: UITextField!
#IBOutlet var lastNameTextField: UITextField!
#IBOutlet var signUpButton: UIButton!
var keyboardHeigh:CGFloat!
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
self.scrollView.contentSize = self.stackView.frame.size
self.scrollView.contentSize.height += self.stackView.frame.minY + 20
}
override func viewDidLoad() {
super.viewDidLoad()
let textFields :[UITextField] =
[
usernameTextField,
passwordTextField,
confirmationTextField,
emailTextField,
phoneTextField,
firstNameTextField,
lastNameTextField,
]
for i in 0..<textFields.count
{
textFields[i].delegate = self
textFields[i].tag = i
}
NotificationCenter.default.addObserver(self,
selector: #selector(keyboardWillShow),
name: .UIKeyboardWillShow, object: nil)
}
func keyboardWillShow(notification: NSNotification)
{
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue
{
keyboardHeigh = keyboardSize.height
}
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool
{
// Try to find next responder
if let nextField = textField.superview?.viewWithTag(textField.tag + 1) as? UITextField
{
nextField.becomeFirstResponder()
}
else
{
// Not found, so remove keyboard.
textField.resignFirstResponder()
}
return false
}
}
1.You can take UItableViewController with static cell,
2.Put textField inside cell.
3.Make selection for cell none.
4.Make separator none.
It will work fine.
I need the stepper and label to reset back to 0 at the same time that my variables reset. The problem is the steppers and labels are in a different class and are not resetting when the variables do. I tried using delegates(if someone can show me the best way that would be great) instead of an instance of my view controller, but I can't get anything to work. Thanks for any help in advance.
ViewController:
class ViewController: UIViewController
{
var colors = CircleView()
#IBOutlet weak var circleView1: CircleView!
#IBOutlet weak var blueStepper: UIStepper!
#IBOutlet weak var greenStepper: UIStepper!
#IBOutlet weak var redStepper: UIStepper!
#IBAction func stepperChange(sender: UIStepper)
{
circleView1.redd1 = Int(redStepper.value);
redValue.text = Int(sender.value).description;
}
#IBAction func stepperChange1(sender: UIStepper)
{
circleView1.greenn1 = Int(greenStepper.value);
greenValue.text = Int(sender.value).description;
}
#IBAction func stepperChange2(sender: UIStepper)
{
circleView1.bluee1 = Int(blueStepper.value);
blueValue.text = Int(sender.value).description;
}
}
UIView:
class CircleView: UIView
{
var colors1=ViewController()
func updateStepper
{
if(redd1==Int(red1)&&greenn1==Int(green1)&&bluee1==Int(blue1))
{
redd1=0;
greenn1=0;
bluee1=0;
colors1.redStepper.value=0.0;//
colors1.greenStepper.value=0.0;//
colors1.blueStepper.value=0.0;//
}
}
}
I do not quite understand your code, like the "if" condition in your CircleView, the lack of parameters to the method "updateStepper". I am assuming you just wrote some "swift-pseucode" and I will ignore some parts of it to explain how you could implement a delegate for it. Below is an example code:
import UIKit
protocol CircleViewDelegate: class {
func updateStepper(view: CircleView)
}
class ViewController: UIViewController, CircleViewDelegate{
#IBOutlet weak var circleView1: CircleView!
#IBOutlet weak var blueStepper: UIStepper!
#IBOutlet weak var greenStepper: UIStepper!
#IBOutlet weak var redStepper: UIStepper!
var circleViewDelegate: CircleView!
override func viewDidLoad() {
super.viewDidLoad()
circleViewDelegate = circleView1
circleViewDelegate!.delegate = self
}
func updateStepper(view: CircleView) {
//code you want to execute when you call updateStepper() in the CircleView()
}
}
class CircleView: UIView {
weak var delegate: CircleViewDelegate?
func updateStepper() {
//whenever you want your viewController to updated other views based
//on a condition inside an element like UIView, you can use a delegate
//this way, your code is executed by the ViewController whenever you want
delegate?.updateStepper(self)
}
}
A callback in your UIView must be set to call "updateStepper" when you want. Unfortunately, I didn't quite understand the time it should be called according to your question.
I hope this helps!
Have you tried NSNotification?
If it's always going to reset to zero, then create a func without the if statement in CircleView:
func resetStepper(not: NSNotification) {
r1 = 0
g1 = 0
b1 = 0
c1.rStep.value = 0.0
c1.bStep.value = 0.0
c1.gStep.value = 0.0
}
Also in CircleView's createView func, add:
NSNotificationCenter.defaultCenter().addObserver(self, selector: "resetStepper:", name: "ResetStepper", object: nil)
Then in the view controller, post a notification from whichever button is calling it.
#IBAction func callReset(sender: AnyObject) {
NSNotificationCenter.defaultCenter().postNotificationName("ResetStepper", anObject: nil)
}
That will send the notification that CircleView is listening for to call the function.
Hope that works for you.