When I implement Parse I get "fatal error: unexpectedly found nil while unwrapping an Optional value" - ios

I am trying to use Parse to edit profile and after I put the code in when I launch the app I clicked the button I made to edit profile and I get this:
fatal error: unexpectedly found nil while unwrapping an Optional value
The Segue I have leading to the edit profile controller does not open and the app crashes. When the Parse code is not implemented the segue to the view controller opens just fine.
import UIKit
import Parse
class EditProfileViewController: UIViewController {
#IBOutlet weak var profilePictureImageView: UIImageView!
#IBOutlet weak var firstNameTextField: UITextField!
#IBOutlet weak var lastNameTextField: UITextField!
#IBOutlet weak var passwordTextField: UITextField!
#IBOutlet weak var repeatPasswordTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Load user details
let userFirstName = PFUser.currentUser()?.objectForKey("first_name") as! String
let userLastName = PFUser.currentUser()?.objectForKey("last_name") as!String
firstNameTextField.text = userFirstName
lastNameTextField.text = userLastName
if(PFUser.currentUser()?.objectForKey("profile_picture") != nil)
{
let userImageFile:PFFile = PFUser.currentUser()?.objectForKey("profile_picture") as! PFFile
userImageFile.getDataInBackgroundWithBlock({ (imageData: NSData?, error: NSError?) -> Void in
self.profilePictureImageView.image = UIImage(data: imageData!)
})
}
let image = UIImage(named: "navbar.png")
self.navigationController!.navigationBar.setBackgroundImage(image,forBarMetrics: .Default)
var nav = self.navigationController?.navigationBar
nav?.tintColor = UIColor.whiteColor()
let titleDict: NSDictionary = [NSForegroundColorAttributeName: UIColor.whiteColor()]; self.navigationController!.navigationBar.titleTextAttributes = titleDict as [NSObject : AnyObject]
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true;
}
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
self.view.endEditing(true)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func doneButtonTapped(sender: AnyObject) {
self.dismissViewControllerAnimated(true, completion: nil)
}
#IBAction func chooseProfileButtonTapped(sender: AnyObject) {
}
#IBAction func saveButtonTapped(sender: AnyObject) {
}
}

You need to find out which line exactly throws the error. Basically, this error means that you try to access a variable with optional value, but it turns out the variable is nil!
Why don't you set some break points and see if any of your variables (esp. the ones related to Parse) return nil?
EDIT (just a shot in the dark)
From what I can see in your code, it could be that you have not correctly linked the textfields to your interface builder file. Thus, since you are not initializing them before accessing them, they will return nil and the app will crash here:
firstNameTextField.text = userFirstName
lastNameTextField.text = userLastName
Make sure the textfields are linked to your interface builder file, or, if you are unsure about how to do it, just check if this is indeed the case and insert these two lines before the above ones:
//Initialize them before accessing them
UITextField* firstNameTextField = [[UITextField alloc] init];
UITextField* lastNameTextField = [[UITextField alloc] init];
//Now you can securely access them
firstNameTextField.text = userFirstName
lastNameTextField.text = userLastName
In case the app now doesn't crash anymore, you know it's been these textfields and you need to properly link them to your xib file

Related

Initializing AVAudioPlayer to be used in more than one function

Usual AVAudioPlayer tutorials online creates a AVAudioPlayer within a function to where the play and stop functions of the AVAudioPlayer object aren't available to the object directly from other functions. The problem is that I would like another function to stop the sound from the AVAudioPlayer. This seems pretty simple by initializing the objects at the top of the class in hopes it would be accessible however in Swift3 the init function for AVAudioPlayer includes a throw and a parameter for the sound file. Swift doesn't allow us to use an instance member within a property initializer so I'm stuck on my thought process of how this could be written.
The only error I'm running into at this point is not being allowed to use an instance member in the property initializer when creating "backgroundMusicPlayer":
import UIKit
import AVFoundation
class MadLibOneViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var thePlace: UITextField!
#IBOutlet weak var theVerb: UITextField!
#IBOutlet weak var theNumber: UITextField!
#IBOutlet weak var theTemplate: UITextView!
#IBOutlet weak var theStory: UITextView!
#IBOutlet weak var generateStoryButton: UIButton!
#IBOutlet weak var proceedToNextMadLib: UIButton!
//var backgroundMusicPlayer = AVAudioPlayer()
var error:NSError?
var path = Bundle.main.path(forResource: "bensound-cute", ofType: "mp3")
var url: NSURL {
return NSURL(fileURLWithPath: path!)
}
var backgroundMusicPlayer: AVAudioPlayer = try AVAudioPlayer(contentsOf: url as URL, error: &error)
#IBAction func createStory(_ sender: AnyObject) {
theStory.text=theTemplate.text
theStory.text=theStory.text.replacingOccurrences(of: "<place>", with: thePlace.text!)
theStory.text=theStory.text.replacingOccurrences(of: "<verb>", with: theVerb.text!)
theStory.text=theStory.text.replacingOccurrences(of: "<number>", with: theNumber.text!)
generateStoryButton.isHidden=true
proceedToNextMadLib.isHidden=false
}
#IBAction func showNextStory(_ sender: AnyObject) {
view.backgroundColor=UIColor.green
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let resultViewController = storyBoard.instantiateViewController(withIdentifier: "MadLibTwoViewController") as! MadLibTwoViewController
self.present(resultViewController, animated:true, completion:nil)
}
#IBAction func hideKeyboard(_ sender: AnyObject) {
thePlace.resignFirstResponder()
theVerb.resignFirstResponder()
theNumber.resignFirstResponder()
theTemplate.resignFirstResponder()
}
override func viewDidLoad() {
super.viewDidLoad()
proceedToNextMadLib.isHidden=true
view.backgroundColor = UIColor.purple
// Do any additional setup after loading the view.
self.theVerb.delegate = self
self.thePlace.delegate = self
self.theNumber.delegate = self
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
self.view.endEditing(true)
return false
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
You need to use Lazy initialisation/instantiation for that. In your case this is all you need to do.
lazy var player: AVAudioPlayer = {
[unowned self] in
do {
return try AVAudioPlayer.init(contentsOf: self.url)
}
catch {
return AVAudioPlayer.init()
}
}()
For more about Lazy Initialisation this is a good read. The interesting thing in your case is that the initialiser throws. I think this forum discussion is helpful to have a slight idea.

Xcode Swift 2 Weather App problems

import UIKit
class ViewController: UIViewController {
#IBOutlet weak var cityNameTextField: UITextField!
#IBOutlet weak var cityNameLabel: UILabel!
#IBOutlet weak var cityTempLabel: UILabel!
#IBAction func getDataButtonClicked(sender: AnyObject) {
getWeatherData("http://api.openweathermap.org/data/2.5/weather?q=\(cityNameTextField.text)&APPID=6de03a1d1554874e7594a89fad719dd0")
}
override func viewDidLoad() {
super.viewDidLoad()
getWeatherData("http://api.openweathermap.org/data/2.5/weather?q=London&APPID=6de03a1d1554874e7594a89fad719dd0")
// 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.
}
func getWeatherData(urlString: String) {
let url = NSURL(string: urlString)
let task = NSURLSession.sharedSession().dataTaskWithURL(url!) {(data, response, error) in
dispatch_async(dispatch_get_main_queue(), {
self.setLabels(data!)
})
}
task.resume()
}
var jsonData: AnyObject?
func setLabels(weatherData: NSData) {
do {
self.jsonData = try NSJSONSerialization.JSONObjectWithData(weatherData, options: []) as! NSDictionary
} catch {
//error handle here
}
if let name = jsonData!["name"] as? String {
cityTempLabel.text = "\(name)"
}
if let main = jsonData!["main"] as? NSDictionary {
if let temp = main["temp"] as? Double {
cityTempLabel.text = String(format: "%.1f", temp)
}
}
}
};
Yesterday I had the app running and this morning I've just been getting new error messages that won't even allow the code to be compiled. They say 'Missing "Default-568h#2x.png" launch image' and 'Command /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftcode'. Thanks in advance.
You need to add something to your info.plist file:
It's because the URL link you're trying to get data from is not a secured link, so adding this to you info.plist allows you to access that link. Just go to you info.plist and right-click and select Add Row, then add exactly what you see in the image above.
Also, remove the getWeatherData function from the viewDidLoad method, as you don't need that, as you call it when you press your button.
Also, I've noticed one of your labels isn't set correctly in your setLabels function, as they both try to set the cityTempLabel label, so update the other one to be cityNameLabel.
Build and run and it should all work.

Why is my data is not writing to Firebase - App crashes due to setObjectForKey: key cannot be nil

for the past two weeks i've been having a struggle to write data to firebase, although the tutorials seem so simple :/....My app has a view controller and a tableview controller. users can add an event Title, event date and description (strings) and add a picture as well. Whenever i try to run the simulator it crashes on me! See code below. Please please help me out this is really getting frustrating.. Even if I place breakpoints in the code on top it crashes.. If someone can help me in a chat that would be awesome or maybe send the file to cause its been too long seriously I need an answer so i understand the problem.
import UIKit
import Firebase
import FirebaseDatabaseUI
class EventViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
//outlets for text & image
#IBOutlet weak var photoImageView: UIImageView!
#IBOutlet weak var eventName: UITextField!
#IBOutlet weak var eventDate: UITextField!
#IBOutlet weak var eventDes: UITextView!
//Database connection
let rootref = FIRDatabase().reference()
var imagePicker: UIImagePickerController = UIImagePickerController()
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func submitEvent(sender: AnyObject) {
let name = eventName.text
let date = eventDate.text
let text = eventDes.text
var data: NSData = NSData()
var user = NSDictionary()//declare here
if let image = photoImageView.image {
data = UIImageJPEGRepresentation(image,0.1)!
}
let base64String = data.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.Encoding64CharacterLineLength)
if let unwrappedName = name , unwrappedDate = date, unwrappedText = text{
//use your declared dictionary
user = ["name":unwrappedName, "date":unwrappedDate, "text":unwrappedText, "photoBase64":base64String]
}
//Add firebase child node
//let event = FIRDatabase().reference().child(name!)
//Do not create one more reference to database
rootref.child(name!)
rootref.child(name!).setValue(user)
navigationController?.popViewControllerAnimated(true)
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
view.endEditing(true)
super.touchesBegan(touches, withEvent: event)
}
//UIImagePickerControllerDelegate methods
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
imagePicker.dismissViewControllerAnimated(true, completion: nil)
photoImageView.image = info[UIImagePickerControllerOriginalImage] as? UIImage
}
func imagePickerControllerDidCancel(picker: UIImagePickerController) {
dismissViewControllerAnimated(true, completion: nil)
}
#IBAction func addPicture(sender: AnyObject) {
if(UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera)) {
imagePicker = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = .Camera
presentViewController(imagePicker, animated: true, completion: nil)
} else {
imagePicker.allowsEditing = false
imagePicker.sourceType = .PhotoLibrary
imagePicker.delegate = self
presentViewController(imagePicker, animated: true, completion:nil)
}
}
}

Unresolved identifier using segue when passing data

In my app I am using segue to pass data between two viewcontrollers and that should be easy enough, but for som reason I can`t see there I keep getting "Unresolved Identifier"
Her are some of the code that has to do with that function.
from ViewController 1
import UIKit
import CoreData
class ViewController: UIViewController, UITextFieldDelegate
{
#IBOutlet var panelWidthTextField: UITextField!
#IBOutlet var panelHightTextField: UITextField!
#IBOutlet var panelsWideTextField: UITextField!
#IBOutlet var panelsHightTextField: UITextField!
#IBOutlet var panelPitchTextField: UITextField!
#IBOutlet var calculateButton: UIButton!
#IBOutlet var resultWithLabel: UILabel!
#IBOutlet var resultHightLabel: UILabel!
#IBOutlet var fillAllFieldsLabel: UILabel!
var pawidth:String!
var pahight:String!
var papitch:String!
override func viewDidLoad()
{
super.viewDidLoad()
panelWidthTextField.text = pawidth
panelHightTextField.text = pahight
panelPitchTextField.text = pap itch
From Second ViewController
import UIKit
import CoreData
class DataBase: UIViewController, UITextFieldDelegate
{
#IBOutlet var makerTextField: UITextField!
#IBOutlet var modelTextField: UITextField!
#IBOutlet var stPanelWidthTextField: UITextField!
#IBOutlet var stPanelHightTextField: UITextField!
#IBOutlet var stPitchTextField: UITextField!
let moc = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
// Removes keyboard when touch outside edit field.
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?)
{
view.endEditing(true)
super.touchesBegan(touches, withEvent: event)
}
#IBAction func saveButton(sender: UIButton)
{
let ed = NSEntityDescription.entityForName("Ledinfo", inManagedObjectContext: moc)
let model = Ledinfo(entity:ed!, insertIntoManagedObjectContext:moc)
model.manufactor = makerTextField.text
model.model = modelTextField.text
model.panelwidth = stPanelWidthTextField.text
model.panelhight = stPanelHightTextField.text
model.pitch = stPitchTextField.text
do {
try moc.save()
makerTextField.text = ""
modelTextField.text = ""
stPanelWidthTextField.text = ""
stPanelHightTextField.text = ""
stPitchTextField.text = ""
Alert.show("Succsess", message: "Your Record Is Saved", vc: self)
}
catch _ as NSError
{
Alert.show("Failed", message: "Something Went Wrong", vc: self)
}
}
#IBAction func searchButton(sender: UIButton)
{
let ed = NSEntityDescription.entityForName("Ledinfo", inManagedObjectContext: moc)
let req = NSFetchRequest()
req.entity = ed
let cond = NSPredicate(format: "manufactor = %#", makerTextField.text!)
req.predicate = cond
do {
let result = try moc.executeFetchRequest(req)
if result.count > 0
{
let model = result[0] as! Ledinfo
makerTextField.text = model.manufactor
modelTextField.text = model.model
stPanelWidthTextField.text = model.panelwidth
stPanelHightTextField.text = model.panelhight
stPitchTextField.text = model.pitch
} else
{
Alert.show("Failed", message: "No Record Is Found", vc: self)
}
} catch _ as NSError!
{
Alert.show("Failed", message: "No Record Is Found" , vc: self)
}
}
#IBAction func transfereButton(sender: UIButton) {
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if (segue.identifier == "transfereButton") {
let svc = segue.destinationViewController as! ViewController
svc.pawidth = stPanelWidthTextField.text
svc.pahight = stPanelHightTextField.text
svc.papitch = stPitchTextField.text
}
}
}
It can not find panelWidthTextField.text, panelHightTextField.text and panelPitchTextField.text as identifier.
I have check spelling and just can`t seem to be able to find what is missing.
Any help is appreciated
"Segue" means, that in "prepareForSegue" method you set the property of ViewController to some data in your DataBase controller. In your example, this can be done like this:
svc.pawidth = someDataFromDataBaseWhichYouWantToPassToSecondVC
svc.pahight = someDataFromDataBaseWhichYouWantToPassToSecondVC
svc.papitch = someDataFromDataBaseWhichYouWantToPassToSecondVC
And then, you can manipulate this data from your ViewController class.
You mistake that you are not passing the data from one VC to another, instead of that you are trying to set the property of 1stVC to another property of 1stVC, and there is no segue needed.
This has nothing to do with segues. do you have 3 text fields in your DataBase class with names panelWidthTextField, panelHightTextField and panelPithcTextField? It's complaining about not being able to find those variables.
You should call the performSegueWithIdentifier("transfereButton", sender: nil) inside your transfereButton IBOutlet action to actually make the prepareForSegue to run.

How to call performSegueWithIdentifier in Swift

I have created a prepareForSegue method and I am trying to call it from a button that I created by using the performSegueWithIdentifier method. The app is crashing when I load the simulator and it's not getting me a complete error message. Can someone please lead me in the right direction?
import Foundation
import UIKit
import Alamofire
import FBSDKCoreKit
import FBSDKShareKit
import FBSDKLoginKit
class PageContentViewController: UIViewController {
#IBOutlet weak var logoImageView: UIImageView!
#IBOutlet weak var contentLabel: UILabel!
#IBOutlet weak var backgroundImageView: UIImageView!
#IBOutlet weak var pageControl: UIPageControl!
#IBOutlet weak var facebookButton: UIButton!
var index : Int = 0
var logoFile: String = ""
var content: String = ""
var backgroundFile: String = ""
let facebookReadPermissions = ["public_profile", "email", "user_friends"]
override func viewDidLoad() {
super.viewDidLoad()
pageControl.currentPage = index
facebookButton.hidden = (index == 3 ) ? false : true
pageControl.hidden = (index == 3) ? true: false
logoImageView.image = UIImage(named: logoFile)
contentLabel.text = content
backgroundImageView.image = UIImage(named: backgroundFile)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if let destinationController = segue.destinationViewController as? PaymentSubViewController
where segue.identifier == "payment" {
// Do something with `destinationController`
}
}
#IBAction func test(sender: AnyObject) {
self.performSegueWithIdentifier("payment", sender: self)
}
#IBAction func fbTouched(sender: AnyObject) {
FBSDKLoginManager().logInWithReadPermissions(self.facebookReadPermissions, handler: { (result:FBSDKLoginManagerLoginResult!, error:NSError!) -> Void in
if error != nil {
//According to Facebook:
//Errors will rarely occur in the typical login flow because the login dialog
//presented by Facebook via single sign on will guide the users to resolve any errors.
// Process error
FBSDKLoginManager().logOut()
} else if result.isCancelled {
// Handle cancellations
FBSDKLoginManager().logOut()
} else {
let fbToken = result.token.tokenString
Alamofire.request(Router.FacebookAuth(fbToken)).validate(statusCode: 200 ..< 300).responseJSON(completionHandler: { (request, response, JSON, error) in
if let json = JSON as? Dictionary<String, AnyObject> {
if let token = json["token"] as? String {
Router.OAuthToken = token
self.performSegueWithIdentifier("showHomeFeed", sender: self)
}
}
})
}
})
}
}
Because you are force unwrapping the destinationViewController using as!, if that value is nil or not a PaymentSubViewController, the app will crash.
The better way to implement this is with an optional binding (if let) and a conditional downcast (as?):
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if let destinationController = segue.destinationViewController as? PaymentSubViewController
where segue.identifier == "payment" {
// Do something with `destinationController`
}
}
Of course, that'll stop the crash but won't answer the question of why segue.destinationViewController is nil or of another type. Make sure that you segue is configured properly in interface builder and that the destination view controller actually has segue.destinationViewController for its Class value in the identity inspector tab.
I had a map object on the storyboard and I did not add an outlet for the object which was creating an error message.

Resources