我有一个回忆写应用程序,在该应用程序中,您可以创建包含标题,正文,图片和日期(直到日期都有倒数)的回忆。直到我添加了这些与日期相关的代码行,它的工作状况都很好。现在,当我尝试保存新内存时,应用程序崩溃(“线程1:信号SIGABRT”)。你知道如何解决这个问题吗?
我在下面的代码中添加了内存类和AddMemoryViewController:
内存类别:
import Foundation
import Firebase
class Memory {
var title: String
var uid: String // user id
var body: String
var key:String
var imageRef:String!
var image:UIImage?
var date = Foundation.Date()
init( title:String , body:String , key:String = "", uid:String , imageRef:String , date:Foundation.Date ) {
self.title = title
self.key = key
self.body = body
self.uid = uid
self.imageRef = imageRef
self.key = ""
self.date = date
}
func toAnyObject()-> [String:AnyObject] {
return ["title" : self.title as AnyObject,"body":self.body as AnyObject,"uid":self.uid as AnyObject,"imageRef":self.imageRef as AnyObject, "date":self.date as AnyObject]
}
}
AddMemoryViewController:
import UIKit
导入Firebase 导入FirebaseAuth 进口FirebaseDatabase
AddMemoryViewController类:UIViewController,UIImagePickerControllerDelegate,UINavigationControllerDelegate {
var ref : DatabaseReference!
let sref = Storage.storage().reference()
var m : Memory!
var imgref : String?
var picker : UIImagePickerController? = nil
//vars for edit mode
var current : Memory!
var mode : String! // new Memory = newMemory , edit = edit
let currentTime = NSDate().timeIntervalSince1970 * 1000
var future = Date()
var dateToSet:两倍
// connections from storyboard to the code
@IBOutlet weak var countLabel: UILabel!
@IBAction func datePickerChanged(_ sender: UIDatePicker) {
future = sender.date
//Use midnight today as the starting date
guard let today = Calendar.current.date(bySettingHour: 0, minute: 0, second: 0, of: Date()) else { return }
//Calculate the number of days between today and the =user's chosen day.
let difference = Calendar.current.dateComponents([.day], from: today, to: future)
guard let days = difference.day else { return }
let ess = days > 1 ? "s" : ""
countLabel.text = "That date is \(days) day\(ess) away."
}
var datePicker = UIDatePicker()
// connections from storyboard to the code
@IBOutlet weak var txtTitle: UITextField!
@IBOutlet weak var tBody: UITextView!
@IBOutlet weak var ivImage: UIImageView!
@IBAction func addPicLibrary(_ sender: UIButton) {
picker?.allowsEditing = false
picker?.sourceType = UIImagePickerController.SourceType.photoLibrary
picker?.mediaTypes = UIImagePickerController.availableMediaTypes(for: .photoLibrary)!
picker?.modalPresentationStyle = .popover
present(picker!,animated: true, completion: nil)
}
@IBAction func addPicCamera(_ sender: UIButton) {
if UIImagePickerController.availableCaptureModes(for: .rear) != nil {
picker?.allowsEditing = false
picker?.sourceType = UIImagePickerController.SourceType.camera
picker?.cameraCaptureMode = .photo
picker?.modalPresentationStyle = .fullScreen
present(picker!,animated: true,completion: nil)
} else {
noCamera()
}
}
// alert when device has no camera
func noCamera() {
let alertVC = UIAlertController(title: "No Camera",message: "Sorry, this device has no camera",preferredStyle: .alert)
let okAction = UIAlertAction(title: "OK",style:.default,handler: nil)
alertVC.addAction(okAction)
present(alertVC,animated: true,completion: nil)
}
// Function to edit a Memory
func editNewMemory()
{
let currentKey = ref.child("MEmories/\(self.current.key)")
self.current.body = tBody.text!
self.current.title = txtTitle.text!
imgref = "\(txtTitle.text!).png"
self.current.imageRef = imgref
dateToSet = self.future.millisecondsSince1970
self.current.date = self.dateToSet
currentKey.setValue(current.toAnyObject())
self.saveImage()
self.saveToNSUserDefaualts(memory: self.current)
}
// Function to add a new Memory
func addNewMemory()
{
let refposts = ref.child("MEmories").childByAutoId()
imgref = "\(txtTitle.text!).png"
self.m = Memory(title: txtTitle.text!, body: tBody.text!, key: "", uid: (Auth.auth().currentUser!.uid), imageRef: imgref!, date: Foundation.NSNumber())
dateToSet = self.future.millisecondsSince1970
refposts.setValue(m.toAnyObject(), withCompletionBlock: {(error,data) in
self.m.key = data.key!
self.m.image = self.ivImage.image
self.m.date = self.dateToSet
self.saveImage()
self.saveToNSUserDefaualts(memory: self.m)
})
}
// When clicking on the 'save' button: save the Memorey in the tableView and the database
@IBAction func saveMemorey(_ sender: UIButton) {
let d = UserDefaults.standard
if( mode == "newMemory")
{
self.addNewMemory()
d.set(true, forKey: "userAdded")
}
else if mode == "edit"
{
self.editNewMemory()
d.set(true, forKey: "userEdited")
}
d.synchronize()
self.navigationController?.popViewController(animated: true) // Returns to the memories page after clicking 'save'
}
// Saving image in database function
func saveImage()
{
let metaData = StorageMetadata()
metaData.contentType = "image/png"
let tempImageRef = sref.child(imgref!)
let uploadData = ivImage.image!.pngData()
tempImageRef.putData(uploadData!, metadata: metaData, completion: {(data,error) in
if error == nil
{
print("upload success")
}
else
{
print("*upload not succeeded*")
}
})
}
// Saving to NSUserDefault (A class that provides simple storage of different data types solution.)
func saveToNSUserDefaualts(memory:Memory)
{
let d : UserDefaults = UserDefaults.standard
d.set(memory.title, forKey: "title")
d.set(memory.body, forKey: "body")
d.set(memory.key, forKey: "key")
d.set(memory.imageRef, forKey: "imageRef")
d.set(memory.uid, forKey: "uid")
d.set(memory.key, forKey: "key")
d.set(memory.date, forKey: "date")
let imageData = NSData(data:ivImage.image!.pngData()!)
d.set(imageData, forKey: "imageData")
d.synchronize()
}
override func viewDidLoad() {
super.viewDidLoad()
self.title = "Add MEmorey"
ref = Database.database().reference()
self.picker = UIImagePickerController()
self.picker!.delegate = self
//load data if its for edit
if current != nil
{
txtTitle.text = current.title
tBody.text = current.body
ivImage.image = current.image
func datePickerChanged(_ sender: UIDatePicker) {
future = Date(milliseconds: Int (truncating: current.date))
//Use midnight today as the starting date
guard let today = Calendar.current.date(bySettingHour: 0, minute: 0, second: 0, of: Date()) else { return }
//Calculate the number of days between today and the =user's chosen day.
let difference = Calendar.current.dateComponents([.day], from: today, to: future)
guard let days = difference.day else { return }
let ess = days > 1 ? "s" : ""
countLabel.text = "That date is \(days) day\(ess) away."
}
self.mode = "edit"
}
else
{
self.mode = "newMemory"
}
// Do any additional setup after loading the view.
//Set up the date picker to pick dates, not dates & times
datePicker.datePickerMode = .date
//Force the date picker to use midnight today as it's base date and
//to pick a date at least 1 day in the future
guard let today = Calendar.current.date(bySettingHour: 0, minute: 0, second: 0, of: Date()),
let tomorrow = Calendar.current.date(byAdding: .day, value: 1, to: today)
else {
return
}
datePicker.minimumDate = tomorrow
datePicker.date = tomorrow
}
// Tells the delegate that the user picked a still image or movie.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]){
if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage
{
ivImage.image = image
}
else
{
print("Something went wrong")
}
self.dismiss(animated: true, completion: nil)
}
答案 0 :(得分:0)
因此,您的应用程序失败,因为您试图将数据类型NSDate
存储在Firebase中,但它不支持它。 here的更多内容。
Firebase只能存储
NSNumber
,NSString
,NSDictionary
和NSArray
类型的对象。
在Set
Firebase中的数据之前,您需要将日期转换为其中一种数据类型。
我建议通过NSNumber
使用timeIntervalSince1970
格式。自epoch起,您的时间将增加一倍。
您甚至可以使自己成为很好的扩展方法,以帮助您在Date
和Double
两种类型之间进行转换。
extension Date {
var millisecondsSince1970: Int64 {
return Int64((self.timeIntervalSince1970 * 1000.0).rounded())
}
init(milliseconds:Int) {
self = Date(timeIntervalSince1970: TimeInterval(milliseconds / 1000))
}
}
因此要在Firebase中设置值,您要做的就是使用下面的代码块。但是,当从Firebase获取值时,您需要执行类似的操作以将其转换回NSDate
对象,以便在应用程序Date(milliseconds: data.date)
中轻松使用。
let dateToSet = self.future.millisecondsSince1970
refposts.setValue(m.toAnyObject(), withCompletionBlock: {(error,data) in
self.m.key = data.key!
self.m.image = self.ivImage.image
self.m.date = dateToSet
self.saveImage()
self.saveToNSUserDefaualts(memory: self.m)
})