(swift) do not let anonymous users in - swift

my app needs from the user to log in. okay i connected my app to parse, and in the login view controller i wrote these codes
import UIKit
class SigninPageViewController: UIViewController {
#IBOutlet weak var userNameTextField: UITextField!
#IBOutlet weak var userEmailTextField: UITextField!
#IBOutlet weak var userPasswordTextField: 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 doneButtonTapped(sender: AnyObject) {
let userEmail = userEmailTextField.text;
let userPassword = userPasswordTextField.text;
PFUser.logInWithUsernameInBackground(userEmail, password: userPassword) {
(user: PFUser?, error: NSError?) -> Void in
if user != nil {
// Login is successful
NSUserDefaults.standardUserDefaults().setBool(true, forKey:"isUserLoggedIn");
NSUserDefaults.standardUserDefaults().synchronize();
self.dismissViewControllerAnimated(true, completion: nil);
} else {
println("Could not find user")
}
}
}
}
the problem is when i tried my app and tried to write the wrong email and the wrong password, the app let me log in without checking if the user is exist or not and without printing line (Could not find user). So the question here is how to let my app check if the user is exist or not, and do not let anonymous users in.

You could establish your own requirements for logging in. If you do a fetch for the user with the email address they entered, you can allow log in only if the email address exists. If it doesn't, just send the user an alert, and don't go through with the login.

Related

Giving Usernames to users with Firebase & Swift

I am a new to programming, and right now I want to give my users a username and then store it in the firebase real time database. However, every time I run my code it comes up with:
Thread 1: signal SIGABRT
I have checked all of my #IB buttons etc for clashes but there is nothing that I can find. I think I have written code that may be out dated so I am hoping someone can shed some light on my situation and help out!
I think there error is coming from here:
import UIKit
import Firebase
class HandlerViewController: UIViewController {
#IBOutlet weak var username: UITextField!
var user : AnyObject?
var ref = DatabaseReference()
override func viewDidLoad() {
super.viewDidLoad()
self.user = Auth.auth().currentUser
ref = Database.database().reference()
// Do any additional setup after loading the view.
}
#IBAction func joinHaps(_ sender: Any) {
ref.child("Usernames").childByAutoId().setValue(username)
self.performSegue(withIdentifier:"HomeScreenOne", sender: nil)
}
}
In your crash log saying 'InvalidFirebaseData', reason: '(setValue:) Cannot store object of type UITextField at,
In this line your getting error, because setValue can't accept UITextField as input.
Change your code to :
#IBAction func joinHaps(_ sender: Any) {
//username is UITextfield, you can fetch text from it using .text
ref.child("Usernames").childByAutoId().setValue(username.text ?? "")
self.performSegue(withIdentifier:"HomeScreenOne", sender: nil)
}

xcode/Firebase fails to create user on Firebase

I'm new to Xcode and firebase.
I made this simple email login just to check if it works, but it doesn´t.
Firebase is set to public. And I can read and write data.
Now, when working authentication, do I need to change anything?
It doesn't display any errors, it just doesn't create any users in Firebase.
The code is:
import UIKit
import FirebaseAuth
class LoginViewController: UIViewController {
#IBOutlet weak var Username: UITextField!
#IBOutlet weak var Password: UITextField!
#IBAction func Register(_ sender: UIButton) {
Auth.auth().createUser(withEmail: Username.text!, password: Password.text!) { (User, Error) in
}
}
}
We found the problem.
We thought we could use a username instead of an email, but it needs to be an email.

Firebase swift ios login system error Assertion failed/Exec_BAD_INSTRUNCTION (code=EXC_i386_INVOP, subcode=0x0)

Im trying to use the built in authentication system in firebase and followed this TuT to do so
Firebase Login Tutorial
I am able to run my app but when i go to login and type in a valid (or invalid) login email and password it crashes with this error in the console:
Assertion failed: (request.URL), function -[FSRWebSocket initWithURLRequest:protocols:queue:andUserAgent:], file /Users/vikrum/dev/git/firebase-client-objc/Firebase/Firebase/Libraries/SocketRocket/FSRWebSocket.m, line 302.
(lldb)
When I don't type anything and hit login it crashes with this error (i have measures to prevent the app from crashing because of this, possiably side affect of the bigger issue):
<pre>fatal error: unexpectedly found nil while unwrapping an Optional value</pre>
The inline errors below are the same w/ both above console errors
Edit: I have noticed that in the pod directory in my app in the framework and then ios folders the contents are (My hierarchy with red error **LINKhttp://i.stack.imgur.com/IHCQw.png) highlighted in red. The directory for the 4 frameworks was iPhoneOS9.0.sdk for some reason i only have a iPhoneOS.sdk and iPhoneOS9.2.sdk also the firebase and the other framework below it have strange directory locations [(They all go to this location **LINKhttp://i.stack.imgur.com/Z6dX5.png) and i cant for the life of me figure out how to fix it (i'm not totally sure this is the error causing my app to crash after I try to log in but its the only error I have seen so it must be)
Edit 2: i've been looking around and every recent tut to make an app as of at least ios 9 has been confusing me because of this, i have seen 2 separate apps tuts where i downloaded the finale project and i wasn't able to run it because in the pod dir(all where for firebase and ios 9.2 when made and had all the frameworks for firebase) it said "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.0.sdk/System/Library/Frameworks/CFNetwork.framework" and i cant change it because when i go to the little dir change button i have to get into the package contents of xcode and it wont let me do that
The inline error when I am redirected
Second files inline error (same)
Here is where i get directed when the app crashes and i get the error(2 places)
import Foundation
import Firebase
let BASE_URL = "https://baseball-pitcher-app.firebaseIO.comΩΩ"
let FIREBASE_REF = Firebase(url: BASE_URL)
var CURRENT_USER: Firebase
{
***let userID = NSUserDefaults.standardUserDefaults().valueForKey("uid") as! String*** ERROR IN THIS LINE
let currentUser = Firebase(url: "\(FIREBASE_REF)").childByAppendingPath("users").childByAppendingPath(userID)
return currentUser!
}
One thing I did find odd was that the error was in the logout button which is weird because i've never pressed it since the error occurred.
import UIKit
import Firebase
class LoginViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var userUsernameTextField: UITextField!
#IBOutlet weak var userPasswordTextField: UITextField!
#IBOutlet weak var logoutButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.userUsernameTextField.delegate = self;
self.userPasswordTextField.delegate = self;
}
override func viewDidAppear(animated: Bool)
{
super.viewDidAppear(animated)
if NSUserDefaults.standardUserDefaults().valueForKey("uid") != nil && CURRENT_USER.authData != nil
{
self.logoutButton.hidden = false
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
self.view.endEditing(true)
return false
}
#IBAction func loginButtonTapped(sender: AnyObject) {
let email = self.userUsernameTextField.text
let password = self.userPasswordTextField.text
if email != "" && password != ""
{
FIREBASE_REF.authUser(email, password: password, withCompletionBlock: { error, authData in
if error == nil
{
NSUserDefaults.standardUserDefaults().setValue(authData.uid, forKey: "uid")
print("Logged In :)")
self.logoutButton.hidden = false
}
else
{
print(error)
}
})
}
else
{
let alert = UIAlertController(title: "Error", message: "Enter Email and Password.", preferredStyle: UIAlertControllerStyle.Alert)
let action = UIAlertAction(title: "Ok", style: .Default, handler: nil)
alert.addAction(action)
self.presentViewController(alert, animated: true, completion: nil)
}
}
#IBAction func logoutButtonTapped(sender: AnyObject) {
CURRENT_USER.unauth()**** ERROR IN THIS LINE
NSUserDefaults.standardUserDefaults().setValue(nil, forKey: "uid")
self.logoutButton.hidden = true
}
The userId id is most likely nil, and in general it's better to catch the cases in which is it nil, like this
if let userID = NSUserDefaults.standardUserDefaults().valueForKey("uid") as? String {
print(userID) //do something with the user id here
} else {
print("The userID was nil.") //avoid the user id.
}
And the reason for the second error is that CURRENT_USER, since it never Auth'd to start with is now nil. Not sure why the button's IBAction is being called but check the actions and outlets in IB.
Also, the
var CURRENT_USER
is a little suspect.
Based on the name of the var, I would expect it to contain the Current User (as maybe a User Class?).
However when called, it returns a Firebase object which contains a path to the current users node (/appPath/users/users node) and no other user data. It doesn't appear to be populated when a user authenticates either.
Not sure if that was the intention or if it's used somewhere else, but doing this
CURRENT_USER.unauth()
may be an issue since it doesn't contain any auth data.

Why is my prepareForSegue code activating the wrong button?

I'm learning how to program and am playing with a Swift project in Xcode. The main storyboard has two view controllers. The first view controller is simply called ViewController and the second view controller is called HelpScreenViewController.
In ViewController I have a "help" button that switches the user to HelpScreenViewController. This button uses a segue called "goToHelpScreenSegue".
In HelpScreenViewController I have three buttons:
"Close" button to dismisses the view (no segue used)
"Send Feedback" button to generate a new email in the Mail app (no segue used)
"Reset Game" button to call a function that is coded within the first ViewController. This third button uses a segue called "resetGameSegue".
What I'm trying to do is...
...Get the "Reset Game" button on the HelpScreenViewController to reset the game by calling a function that's coded within the first view controller.*
To try and get this to work the way I want, I've used the following code:
WITHIN first main ViewController
import UIKit
import iAd
import AdSupport
import AVFoundation //audio
import GameplayKit
class ViewController: UIViewController, ADBannerViewDelegate, MyResetGameProtocol {
#IBOutlet weak var Banner: ADBannerView!
#IBOutlet weak var buttonA: UIButton!
#IBOutlet weak var buttonB: UIButton!
#IBOutlet weak var buttonC: UIButton!
#IBOutlet weak var buttonD: UIButton!
#IBOutlet weak var labelQuestion: UILabel!
#IBOutlet weak var labelScore: UILabel!
#IBOutlet weak var labelTotalQuestionsAsked: UILabel!
#IBOutlet weak var labelFeedback: UILabel!
#IBOutlet weak var buttonNext: UIButton!
var score :Int! = 0
var totalquestionsasked :Int! = 0
var allEntries : NSArray!
var shuffledQuestions: [AnyObject]!
var nextQuestion = -1
var currentCorrectAnswerIndex : Int = 0
var audioPlayer = AVAudioPlayer()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.Banner?.delegate = self
self.Banner?.hidden = true
LoadAllQuestionsAndAnswers()
if #available(iOS 9.0, *) {
shuffledQuestions = GKRandomSource.sharedRandom().arrayByShufflingObjectsInArray(allEntries as [AnyObject])
nextQuestion++
LoadQuestion(nextQuestion)
// Fallback on earlier versions
}else{
let randomNumber = Int(arc4random_uniform(UInt32(allEntries.count)))
LoadQuestionPreiOS9(randomNumber)
}
LoadScore()
AdjustInterface()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let viewController = segue.destinationViewController as! HelpScreenViewController
viewController.controller = self
}
func ResetGame() {
PlaySoundReset()
score = 0
totalquestionsasked = 0
SaveScore()
LoadScore()
}
func PlaySoundReset()
{
let alertSound = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("pcbeep", ofType: "wav")!)
do {
audioPlayer = try AVAudioPlayer(contentsOfURL: alertSound)
} catch {
}
audioPlayer.prepareToPlay()
audioPlayer.play()
}
func SaveScore()
{
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setInteger(score, forKey: "Score")
defaults.setInteger(totalquestionsasked, forKey: "Out of")
}
func LoadScore()
{
let defaults = NSUserDefaults.standardUserDefaults()
score = defaults.integerForKey("Score")
totalquestionsasked = defaults.integerForKey("Out of")
labelScore.text = "Score: \(score)"
labelTotalQuestionsAsked.text = "out of \(totalquestionsasked)"
}
and so on....
WITHIN the second HelpScreenViewController
import UIKit
protocol MyResetGameProtocol {
func ResetGame()
}
class HelpScreenViewController: UIViewController, MyResetGameProtocol {
var controller: MyResetGameProtocol? // reference to the delegate alias First Controller
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.
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
#IBAction func SendFeedback(sender: AnyObject) {
UIApplication.sharedApplication().openURL(NSURL(string: "mailto:feedback#felice.ws?")!)
}
#IBAction func DismissView(sender: AnyObject) {
self.dismissViewControllerAnimated(true, completion: nil) }
#IBAction func buttonResetGame(sender: AnyObject) {
controller.ResetGame()
}
}
Now, at the moment with the above code what happens is that if the user taps the "help" button in the first main ViewController (i.e. goToHelpScreenSegue), not only does it take the user to the help screen, but it also calls the function I want activated when the user taps on the "Reset Game" button instead. That is, at the moment, it's the "help" button that resets the game before taking the user to the help screen.
Now, within the help screen, the first two buttons work normally (but they're not using segues). Tapping on the third button (the Reset Game one) simply returns the user back to the main screen. It doesn't call the function, doesn't reset the game.
I've lost count of the times I've changed the code around to try and get it to work right, but I've obviously missed something really obvious.
In particular, I've tried using the following code instead within the main ViewController:
override func prepareForSegue(segue: UIStoryboardSegue?, sender: AnyObject?) {
if segue?.identifier == "resetGameSegue" {
let viewController = segue!.destinationViewController as! HelpScreenViewController
viewController.controller = self
}
However, this results in nothing happening. What I mean is that the button on the main screen works properly (taking the user to the help screen and not incorrectly calling the resetGame function). And, within the help screen the first two buttons work as expected, but the "Reset Game" button just returns the user to the first screen but without calling the ResetGame function.
I also tried removing the IBActions from both my code and the connections inspector for the "Reset Game" button, but that made no difference either.
Any assistance would be most appreciated as I'm just not getting it! :(
I'm agree with MikeG, that you should probably learn about how delegates should be implemented. But the thing you're doing wrong inside this code is that you're not actually calling ResetGame() function on your delegate. Try to implement your #IBAction function in this way:
#IBAction func buttonResetGame(sender: AnyObject) {
controller?.ResetGame()
}
And yeah, if I understand your logic correctly your HelpScreenViewController should not implement MyResetGameProtocol cause your ViewController is the one who's implementing it.

fatal error with message post using parse

So I am new to using Parse and having some issues with posting a message through the back-end. I am able to set up a user account but when I try to submit the post I am getting an error that says..."fatal error: unexpectedly found nil while unwrapping an Optional value" ...?
Here is my code:
class ComposeViewController: UIViewController {
#IBOutlet var travelTextView: UITextView!
#IBOutlet var charRemainingLabel: UILabel!
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 sendPost(sender: AnyObject) {
var travelPost:PFObject = PFObject(className: "travelposts")
travelPost["content"] = travelTextView.text
travelPost["poster"] = PFUser.currentUser()
travelPost.saveInBackgroundWithTarget(nil, selector: nil)
self.navigationController?.popToRootViewControllerAnimated(true)
}
you cannot pass nil for selector.
travelPost.saveInBackgroundWithTarget(nil, selector: nil);
do this to just save the object.
travelPost.saveInBackground();
But you want to get notified when the object is saved use