Good Night;
Im creating an app that would save the name of people in a Core Data file, when I run the app and save what the user typed it works fine when I load (fetch ) the data it also works fine, the problem comes when I close or go to a different view controller when I hit the load data(fetch) the app crashed with : 'NSInvalidArgumentException',
reason: 'executeFetchRequest:error:
is not a valid NSFetchRequest.'
this is my code
#IBOutlet var PresidentTxt: UITextField!
#IBOutlet var SecDefenseTxt: UITextField!
let dataStack = CoreDataStack()
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func Save(_ sender: Any) {
let database = dataStack.persistenContainer.viewContext
let dbrRecord = Command(context: database)
dbrRecord.potus = PresidentTxt.text
dbrRecord.defsec = SecDefenseTxt.text
do{
try database.save()
}catch {}
}
func didTapView(){
self.view.endEditing(true)
}
#IBAction func Load(_ sender: Any) {
let database = dataStack.persistenContainer.viewContext
do{
let results = try database.fetch(Command.fetchRequest()) as! [Command]
for presidentUS in results{
if let _ = presidentUS.potus {
PresidentTxt.text = presidentUS.potus
}
}
for DefenseSec in results {
if let _ = DefenseSec.defsec {
SecDefenseTxt.text = DefenseSec.defsec
}
}
}catch {}
}
Related
I currently have 2 views in my project: a ViewController with a TableView that shows a list of Transactions and a ViewController for creating a new Transaction.
The issue that I am having is that after creating a new Transaction, it successfully loads onto my TableView, but when I force close and reopen the app, the value is duplicated. As far as I can tell and know, the save() function is only being called once and nothing of the sort is going on in AppDelegate/SceneDelegate. See GIF for an example of what's going on.
GIF Demonstrating Issue
This is my TranasctionsTableViewController:
class TransactionsTableViewController: UIViewController {
// MARK: - Properties
var entries: [NSManagedObject] = []
var container: NSPersistentContainer!
// MARK: - IBOutlets
#IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// setup persistent container
container = NSPersistentContainer(name: "expenses")
// load store
container.loadPersistentStores { storeDescription, error in
if let error = error {
print("Unresolved error \(error)")
}
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
switch segue.identifier! {
case "NewTransactionSegue":
// pass an entry to the destination segue
let destination = segue.destination as! UINavigationController
let targetController = destination.topViewController as! NewTransactionViewController
let managedContext = container.viewContext
let entity = NSEntityDescription.entity(forEntityName: "Entry", in: managedContext)!
let entry = NSManagedObject(entity: entity, insertInto: managedContext)
targetController.entry = entry as? Entry
default:
print("Unknown segue: \(segue.identifier!)")
}
}
#IBAction func unwindToTransactionList(sender: UIStoryboardSegue) {
print("unwind segue called!")
if let sourceViewController = sender.source as? NewTransactionViewController, let entry = sourceViewController.entry {
print(entry)
self.save(entryDescription: entry.entryDescription, amount: entry.amount, date: entry.date, id: entry.id)
// reset the tableView to defaults if no data message was displayed before loading data.
if self.tableView.backgroundView != nil {
self.tableView.backgroundView = nil
self.tableView.separatorStyle = .singleLine
}
self.tableView.reloadData()
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// load managedCOntext
let managedContext = container.viewContext
// try to fetch data from CoreData. If successful, load into entries.
do {
entries = try managedContext.fetch(Entry.fetchRequest())
} catch let error as NSError {
print("Could not fetch. \(error), \(error.userInfo)")
}
}
// save a new entry to the data store
func save(entryDescription: String, amount: Double, date: Date, id: UUID) {
print("save called!!")
let managedContext = container.viewContext
let entity = NSEntityDescription.entity(forEntityName: "Entry", in: managedContext)!
let entry = NSManagedObject(entity: entity, insertInto: managedContext)
entry.setValue(entryDescription, forKey: "entryDescription")
entry.setValue(amount, forKey: "amount")
entry.setValue(date, forKey: "date")
entry.setValue(id, forKey: "id")
do {
try managedContext.save()
entries.append(entry)
} catch let error as NSError {
print("Could not save. \(error), \(error.userInfo)")
}
}
// save the current container context
func saveContext() {
if container.viewContext.hasChanges {
do {
try container.viewContext.save()
} catch {
print("An error occurred while saving: \(error)")
}
}
}
}
This is my NewTransactionViewController:
class NewTransactionViewController: UIViewController, UITextFieldDelegate {
/*
This value is either passed by `TransactionTableViewController` in `prepare(for:sender:)`
or constructed as part of adding a new transaction.
*/
var entry: Entry?
// MARK: - IBOutlets
#IBOutlet weak var transactionDescriptionLabel: UILabel!
#IBOutlet var transactionDescriptionTextField: UITextField!
#IBOutlet var transactionAmountLabel: UILabel!
#IBOutlet var transactionAmountTextField: UITextField!
#IBOutlet weak var cancelButton: UIBarButtonItem!
#IBOutlet weak var saveButton: UIBarButtonItem!
// MARK: Constants
let TRANSACTION_DESCRIPTION_TEXT_FIELD_TAG = 0
let TRANSACTION_AMOUNT_TEXT_FIELD_TAG = 1
override func viewDidLoad() {
super.viewDidLoad()
// Handle textfield input through delegate callbacks.
transactionDescriptionTextField.delegate = self
transactionAmountTextField.delegate = self
// Adds done button to keypad
transactionAmountTextField.addDoneButtonToKeyboard(myAction: #selector(self.transactionAmountTextField.resignFirstResponder))
}
// MARK: - UITextFieldDelegate
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
// If the First Responder is the Description Text Field, transfer First Responder to Amount Text Field
if (textField.tag == TRANSACTION_DESCRIPTION_TEXT_FIELD_TAG) {
transactionAmountTextField.becomeFirstResponder()
}
textField.resignFirstResponder()
return true
}
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: segue)
// Configure the destination view controller only when the save button is pressed.
guard let button = sender as? UIBarButtonItem, button === saveButton else {
os_log("The save button was not pressed, cancelling", log: OSLog.default, type: .debug)
return
}
let transactionDescription = transactionDescriptionTextField.text ?? ""
let transactionAmount = Double(transactionAmountTextField.text!) ?? 0.00
// Set the entry to be passed to TransactionTableViewController after the unwind segue.
entry?.setValue(transactionDescription, forKey: "entryDescription")
entry?.setValue(transactionAmount, forKey: "amount")
entry?.setValue(UUID(), forKey: "id")
entry?.setValue(Date(), forKey: "date")
}
// MARK: - IBActions
#IBAction func cancelButtonTapped(sender: UIBarButtonItem) {
}
#IBAction func saveButtonTapped(sender: UIBarButtonItem) {
}
}
I hope that this question is not duplicate because I couldn't find any thing similar.
I have two view controllers:
NEWPhoneAuthViewController
NEWVerifyCodeViewController
NEWPhoneAuthViewController Code:
import UIKit
import Firebase
class NEWPhoneAuthViewController: UIViewController {
#IBOutlet weak var phoneTxtField: 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 submitPressed(_ sender: Any) {
let phoneNumber = phoneTxtField.text!
PhoneAuthProvider.provider().verifyPhoneNumber(phoneNumber, uiDelegate: nil, completion: { (verificationID, error) in
if let error = error {
debugPrint(error.localizedDescription)
return
}
guard let verificationID = verificationID else { return }
print("Verification ID")
print(verificationID)
let verifyScene = NEWVerifyCodeViewController()
verifyScene.verificationID = verificationID
self.performSegue(withIdentifier: "toCodefromPhoneAuth", sender: nil)
//self.navigationController?.pushViewController(verifyScene, animated: true)
})
}
}
and my NEWVerifyCodeViewController code is:
import UIKit
import Firebase
class NEWVerifyCodeViewController: UIViewController {
#IBOutlet weak var codeTxtField: UITextField!
var verificationID:String?
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 verifyPressed(_ sender: Any) {
if let verificationCode = codeTxtField.text {
let credential = PhoneAuthProvider.provider().credential(withVerificationID: verificationID!, verificationCode: verificationCode)
Auth.auth().signIn(with: credential) { (user, error) in
if let error = error {
debugPrint(error.localizedDescription)
}else {
debugPrint("Verified successfully")
print("Navigating to SignUp")
//self.performSegue(withIdentifier: "toSignUpfromCode", sender: nil)
//let newSignUp = NEWSignUp()
//self.navigationController?.pushViewController(newSignUp, animated: true)
//self.performSegue(withIdentifier: "toSignUpFromPhone", sender: nil)
//Once you have verified your phone number kill the firebase session.
//try? Auth.auth().signOut()
}
}
}
}
}
Now the problem is: when I tap on verify button in NEWVerifyCodeViewController the App crashes,
NOTES:
I printed Verification ID and its not NULL.
I printed code that the user receives and its not NULL.
So I'm not sure why that happens, and my console doesn't show any error after the tap except these:
So I made a small tweak that made my project work.
I changed this part in NEWPhoneAuthViewController :
let verifyScene = NEWVerifyCodeViewController()
verifyScene.verificationID = verificationID
to:
first created a global variable called: gVerificationID and set it to:
gVerificationID = verificationID
Thats it, not sure if thats the best practice and not sure why the first code didn't work but this is how I fixed it.
I am trying to upload an image in a UIImageView to Dropbox using SwiftyDropbox and Swift 3.0. When I press the button nothing happens after the first print statement. What am I doing wrong.
import UIKit
import SwiftyDropbox
class ViewController: UIViewController {
let client = DropboxClientsManager.authorizedClient
#IBOutlet weak var myPhotoView: UIImageView!
#IBAction func logInAction(_ sender: Any) {
myButtonPressed()
}
#IBAction func sendPhotoAction(_ sender: Any) {
print("Button Pressed")
let fileData = UIImageJPEGRepresentation(myPhotoView.image!, 1.0)
//let compressedJPGImage = UIImage(data: fileData!)
let path = "/"
client?.files.upload(path: path, mode: .overwrite, autorename: true, clientModified: nil, mute: false, input: fileData!).response{ response, error in
if let _ = response { // to enable use: if let metadata = response {
print("OK")
} else {
print("Error at end")
}
}
}
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.
}
func myButtonPressed(){
DropboxClientsManager.authorizeFromController(UIApplication.shared, controller: self, openURL: {(url:URL) -> Void in UIApplication.shared.openURL(url)
})
}
}
if your client is nil, then you aren't logged in. Try logging in and doing it again. Otherwise it should work fine.
https://dropbox.github.io/SwiftyDropbox/api-docs/latest/index.html#configure-your-project
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.
I've been following Udacity's Intro to iOS App Development with Swift tutorial, but got this error.
Value of type 'PlaySoundsViewController' has no member 'recordedAudio'
Line 84 has the error.
playSoundsVC.recordedAudio = recordedAudioURL
Here is the entire code:
import UIKit
import AVFoundation
class RecordSoundsViewController: UIViewController , AVAudioRecorderDelegate {
#IBOutlet weak var recordingInProgress: UILabel!
#IBOutlet weak var stopButton: UIButton!
#IBOutlet weak var recordButton: UIButton!
var audioRecorder:AVAudioRecorder!
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.
}
override func viewWillAppear(animated: Bool) {
//TODO: Hide stop button
stopButton.hidden = true
//TODO: Enable recordButton
recordButton.enabled = true
}
#IBAction func recordAudio(sender: AnyObject) {
//TODO: Show text "recording in progress"
recordingInProgress.hidden = false
//TODO: Show stopButton
stopButton.hidden = false
//TODO: Record the user's voice
print("in recordAudio")
//TODO: Disable recording button
recordButton.enabled = false
let dirPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory,.UserDomainMask, true)[0] as String
let recordingName = "recordedVoice.wav"
let pathArray = [dirPath, recordingName]
let filePath = NSURL.fileURLWithPathComponents(pathArray)
print(filePath)
let session = AVAudioSession.sharedInstance()
try! session.setCategory(AVAudioSessionCategoryPlayAndRecord)
try! audioRecorder = AVAudioRecorder(URL: filePath!, settings: [:])
audioRecorder.meteringEnabled = true
audioRecorder.prepareToRecord()
audioRecorder.record()
}
#IBAction func stopRecording(sender: AnyObject) {
//TODO: hide recordingInProgress label
recordingInProgress.hidden = true
recordButton.enabled = true
let audioSession = AVAudioSession.sharedInstance()
try! audioSession.setActive(false)
}
func audioRecorderDidFinishRecording(recorder: AVAudioRecorder, successfully flag: Bool) {
print("AVAudioRecorder finished saving recording")
if (flag) {
self.performSegueWithIdentifier("stopRecording", sender: audioRecorder.url)
} else {
print("Saving of recording failed")
}
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "stopRecording") {
let playSoundsVC = segue.destinationViewController as!
PlaySoundsViewController
let recordedAudioURL = sender as! NSURL
playSoundsVC.recordedAudio = recordedAudioURL
}
}
}
class PlaySoundsViewController: UIViewController {
var recordedURL: URL?
override func viewDidLoad() {
super.viewDidLoad()
}
}
Don't forget to add an identifier for segue:
add var recordedAudioURL:URL! to your PlaySoundsViewController file
it is a variable that holds the url in the next class which is been send from the current class.
happy coding :)
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "stopRecording") {
let playSoundsVC = segue.destinationViewController as! PlaySoundViewController
let recordedAudioURL = sender as! NSURL
playSoundsVC.recordedAudioURL = recordedAudioURL
}
}