Swift firebase timestamp cant show - ios

I am able to retrieve and convert my timestamp that I got from firebase(i did a breakpoint at that line and my time shows 5/3/18,3:05 PM, so it's fine), below is my code:
func loadMsg() {
let toId = user!.id!
let fromId = Auth.auth().currentUser!.uid
let chatRoomId = (fromId < toId) ? fromId + "_" + toId : toId + "_" + fromId
let ref = Database.database().reference().child("privateMessages").child(chatRoomId)
ref.observe(.value) { (snapshot) in
ref.observeSingleEvent(of: .childAdded, with: { (datasnap) in
let lastMsgTime = (datasnap.value as! [String: AnyObject])["timestamp"] as? Double
// to get timestamp and convert to date and time
let x = lastMsgTime!
let date = NSDate(timeIntervalSince1970: x)
let formatter = DateFormatter()
formatter.dateStyle = .short
formatter.timeStyle = .short
let time = formatter.string(from: date as Date)
self.message.timestamp = time //HERE IT CRASHES!!!!!
if let snapshot = snapshot.children.allObjects as? [DataSnapshot] {
self.messages.removeAll()
for data in snapshot {
let newMsg = Message(dictionary: data.value as! [String: AnyObject])
self.messages.append(newMsg)
}
}
})
DispatchQueue.main.async {self.tableView.reloadData()}
}
}
However it crashes at the line which i commented above, i was supposed to show it on my tableviewCell in my message cell. My tableView cell was done by xib which looks like :
and the code of my tableviewCell would be:
{
self.message = message
if message.fromId == currentUser {
sentView.isHidden = false
sentMsgLabel.text = message.textMessages
receivedMsgLabel.text = ""
receivedView.isHidden = true
timeReceived.text = message.timestamp
timeSent.text = message.timestamp
} else {
sentView.isHidden = true
sentMsgLabel.text = ""
receivedMsgLabel.text = message.textMessages
receivedMsgLabel.isHidden = false
timeReceived.text = message.timestamp
timeSent.text = message.timestamp
}
}
So, why would it crash and says
"Thread 1: Fatal error: Unexpectedly found nil while unwrapping an
Optional value"
my message class code:
class Message: NSObject {
var fromId: String?
var textMessages: String?
var timestamp: String?
var toId: String?
var message: Message!
var _messageKey: String!
init(dictionary: [String: Any]) {
self.fromId = dictionary["fromId"] as? String
self.textMessages = dictionary["textMessages"] as? String
self.toId = dictionary["toId"] as? String
self.timestamp = dictionary["timestamp"] as? String
}
init(messageKey: String, postData: Dictionary<String, AnyObject>) {
_messageKey = messageKey
if let message = postData["textMessages"] as? String {
textMessages = message
}
if let sender = postData["fromId"] as? String {
fromId = sender
}
}
}
I believe there isnt any issue with my firebase, main problem is at the tableview cell, why wouldnt it show?

Try to get timestamp from server like this:
ServerValue.timestamp()

Related

Efficient way to Insert and Update a core data object [2020]

Currently I am checking whether the object already exists in core data based on id and then updating and inserting. Is there any better way to do it? Have added "id" as a unique constraint, Which prevents inserting of objects with same "id". Does inserting just update the existing object with same id?
#nonobjc public class func saveUserMovies(movieJSON: [[String: Any]], user: UserProfile, isFavorites: Bool = false, isWatchlisted: Bool = false) {
let context = MMPersistentStore.sharedInstance.privateManagedObjectContext
for movie in movieJSON {
let movieID = movie["id"] as! Int
let fetchMovieWithIDRequest = fetchMovieRequest()
let moviePredicate = NSPredicate(format: "id == %d", movieID)
let sortDiscriptor = NSSortDescriptor(key: "id", ascending: false)
fetchMovieWithIDRequest.sortDescriptors = [sortDiscriptor]
fetchMovieWithIDRequest.predicate = moviePredicate
var userMovie: UserMovie?
context.performAndWait {
do {
userMovie = try fetchMovieWithIDRequest.execute().first
} catch {
print(MMErrorStrings.coreDataFetchError)
}
}
if let fetchedMovie = userMovie {
fetchedMovie.genreIds = movie["genre_ids"] as? [Int64]
fetchedMovie.adult = movie["adult"] as? Bool ?? false
if isFavorites {
fetchedMovie.isFavorite = isFavorites
} else {
fetchedMovie.isWatchlisted = isWatchlisted
}
fetchedMovie.video = movie["video"] as? Bool ?? false
fetchedMovie.backdropPath = movie["backdrop_path"] as? String
fetchedMovie.originalLanguage = movie["original_language"] as? String
fetchedMovie.originalTitle = movie["original_title"] as? String
fetchedMovie.overview = movie["overview"] as? String
fetchedMovie.posterPath = movie["poster_path"] as? String
fetchedMovie.releaseDate = movie["release_date"] as? String
fetchedMovie.releaseYear = String(fetchedMovie.releaseDate?.prefix(4) ?? "")
fetchedMovie.title = movie["title"] as? String
fetchedMovie.popularity = movie["popularity"] as? Double ?? 0.0
fetchedMovie.voteCount = movie["voteCount"] as? Int64 ?? 0
fetchedMovie.voteAverage = movie["voteAverage"] as? Double ?? 0.0
MMPersistentStore.sharedInstance.save(context: context)
} else {
let fetchedMovie = UserMovie(context: context)
fetchedMovie.id = movie["id"] as? Int64 ?? 0
fetchedMovie.user = user
fetchedMovie.genreIds = movie["genre_ids"] as? [Int64]
fetchedMovie.adult = movie["adult"] as? Bool ?? false
if isFavorites {
fetchedMovie.isFavorite = isFavorites
} else {
fetchedMovie.isWatchlisted = isWatchlisted
}
fetchedMovie.video = movie["video"] as? Bool ?? false
fetchedMovie.backdropPath = movie["backdrop_path"] as? String
fetchedMovie.originalLanguage = movie["original_language"] as? String
fetchedMovie.originalTitle = movie["original_title"] as? String
fetchedMovie.overview = movie["overview"] as? String
fetchedMovie.posterPath = movie["poster_path"] as? String
fetchedMovie.releaseDate = movie["release_date"] as? String
fetchedMovie.releaseYear = String(fetchedMovie.releaseDate?.prefix(4) ?? "")
fetchedMovie.title = movie["title"] as? String
fetchedMovie.popularity = movie["popularity"] as? Double ?? 0.0
fetchedMovie.voteCount = movie["voteCount"] as? Int64 ?? 0
fetchedMovie.voteAverage = movie["voteAverage"] as? Double ?? 0.0
MMPersistentStore.sharedInstance.save(context: context)
}
}
}
}
Have added "id" as a unique constraint, Which prevents inserting of objects with same "id".
I didn't use it before yet
Does inserting just update the existing object with same id?
No, it'll insert the new object.
For your case, you could make a refactoring, please refer the findOrCreate function in https://github.com/objcio/core-data/blob/master/SharedCode/Managed.swift
It'll help you avoid duplicated code.
One more thing, your request doesn't need the sortDescriptor, and it should have the limit = 1, and returnObjectAsFaults = false for optimisation.
After that, you just need to make sure your function is called in the same context to avoid duplications.

My weather data is not showing up in my view controller

I can't figure out why my view controller is not showing the data, even though I can see it in the output window.
Output:
Muḩāfaz̧at Al Jīzah
Clear
88.0
my code:
override func viewDidLoad() {
super.viewDidLoad()
loadCurrentWeather = currentWeatherData()
loadCurrentWeather.downloadWeatherData {
//setting uo UI to download data
self.updateTodayUI()
}
}
func updateTodayUI() {
locationLabel.text = loadCurrentWeather.cityName
weatherTypeLabel.text = loadCurrentWeather.weatherType
currentTempLabel.text = "\(loadCurrentWeather.currentTemp)"
weatherTypeImage.image = UIImage(named: loadCurrentWeather.weatherType)
}
My view controller in Xcode:
My view controller on iphone:
currentweatherData the code where I'm downloading the data form.
import UIKit
import Alamofire
class currentWeatherData {
var cityNameone: String!
var dateone: String!
var weatherTypeone: String!
var currentTempone: Double!
var cityName: String {
if cityNameone == nil {
cityNameone = ""
}
return cityNameone
}
var date: String {
if dateone == nil {
dateone = ""
}
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .short
dateFormatter.timeStyle = .none
let currentDate = dateFormatter.string(from: Date())
self.dateone = "Today, \(currentDate)"
return dateone
}
var weatherType: String{
if weatherTypeone == nil{
weatherTypeone = ""
}
return weatherTypeone
}
var currentTemp: Double {
if currentTempone == nil {
currentTempone = 0.0
}
return currentTempone
}
func downloadWeatherData(completed: DownloadComplete){
// to tell alamofire where to download the data
let weatherURL = URL (string: currentWeatherURL)!
Alamofire.request(weatherURL).responseJSON{ response in
let result = response.result
if let dictionary = result.value as? Dictionary<String, AnyObject>{
if let name = dictionary["name"] as? String {
self.cityNameone = name.capitalized
print(self.cityNameone ?? "No city name")
}
if let weather = dictionary["weather"] as? [Dictionary<String, AnyObject>]{
if let main = weather[0]["main"] as? String {
self.weatherTypeone = main.capitalized
print(self.weatherTypeone ?? "No weather type")
}
}
if let main = dictionary["main"] as? Dictionary<String, AnyObject> {
if let currentTemperature = main["temp"] as? Double {
let kelvintoFarenheit = (currentTemperature * (9/5) - 459.67)
let totalKelvinToFarenheit = Double(round(10 * kelvintoFarenheit/10))
self.currentTempone = totalKelvinToFarenheit
print(self.currentTempone ?? .nan)
}
}
}
}
completed()
}
}
Is problem with my code or my view controller? Is it something wrong with my constraints?
I can't seem to figure it out.
You are calling completed too early - before the JSON response arrives. You have to call it inside the closure of the responseJSON call instead:
Alamofire.request(weatherURL).responseJSON { response in
let result = response.result
// ...
completed()
}
I cannot see all of your code to troubleshoot, but you may have a concurrency issue. Try putting the call to updateTodayUI inside of viewDidLoad(_:) inside of an async block like this:
DispatchQueue.main.async {
updateTodayUI()
}
You can find more information on dispatch queues and concurrency in the documentation.

Getting Value From FirebaseDB

I am trying to get values from my firebasedb, on run, ref.observeSingleEvent(of: .value, with: { snapshot in causes fatal error unexpectedly found nil while unwrapping an Optional value. As im sure you can tell... I have no idea what im doing... Thank you in advance...
func geths() -> Int{
var sch:Int = 0
var nam:String = ""
print("start geths")
ref.observeSingleEvent(of: .value, with: { snapshot in
if (snapshot.exists()){
print("snapexist")
if let snapval = snapshot.value as? [String:AnyObject]{
let hs = snapval["hs"] as? String
let name = snapval["name"] as? String
self.hso = hs!
self.nameo = name!
nam = self.nameo
if let myNumber = NumberFormatter().number(from: self.hso) {
let i = myNumber.intValue
sch = i
}else{
sch = 0
}
}else{
print("error")
}
}else{
print("error")
}
})
return sch
}
EDIT************
still dont work :( same errors
func geths() -> Int{
var sch:Int = 0
var nam:String = ""
print("start geths")
ref.observeSingleEvent(of: .value, with: { (snapshot) in
if (snapshot.exists()){
print("snapexist")
let snapval = snapshot.value as? NSDictionary
let hs = snapval?["hs"] as? String ?? ""
let name = snapval?["name"] as? String ?? ""
if (hs != nil){
self.hso = hs
}else{
self.hso = "0"
}
if (name != nil){
self.nameo = name
}else{
self.nameo = "bob"
}
nam = self.nameo
if let myNumber = NumberFormatter().number(from: self.hso) {
let i = myNumber.intValue
sch = i
}else{
sch = 0
}
}else{
print("error")
}
})
return sch
}
create firebase reference like this :
var ref: FIRDatabaseReference!
ref = FIRDatabase.database().reference()
for more details go though this link :
https://firebase.google.com/docs/database/ios/read-and-write
You must initialize the ref variable, you was only declare it by
var ref: FIRDatabaseReference!
For example
var ref: FIRDatabaseReference! = FIRDatabase.database().reference(withPath: "hs")
You may read example about using Firebase here:
https://www.raywenderlich.com/139322/firebase-tutorial-getting-started-2

Can not retrieve data correctly from Firebase

This is my second version me trying to retrieve code from Firebase and do stuff with it. This is how I done it the second way:
channelRef?.observe(.childChanged, with: { (snapshot) -> Void in
let update = snapshot.value as! Dictionary<String, AnyObject>
var readyToGoValue: Bool?
var userID: String?
var amountOfPlayers: Int?
var changedCreator: String?
if let updatedReadyToGo = update["readyToGo"] as! Bool!{
if updatedReadyToGo == true
{
readyToGoValue = true
}
else
{
readyToGoValue = false
}
}
if let updateduserID = update["userID"] as! String!{
userID = updateduserID
}
if let updatedAmountOfPlayers = update["currentPlayers"] as! Int!{
amountOfPlayers = updatedAmountOfPlayers
}
if let updateduserID = update["userID"] as! String!{
userID = updateduserID
}
if let updatedCreator = update["creator"] as! String!{
changedCreator = updatedCreator
}
let currentUser = FIRAuth.auth()?.currentUser?.uid
if changedCreator != nil
{
print("changed creator")
self.creator = changedCreator!
}
This crashed with an error code:
Could not cast value of type '__NSCFString' (0x10a77f4a0) to 'NSDictionary' (0x10a780288). at the line " update". This was my first attempt:
channelRef?.observe(.childChanged, with: { (snapshot) -> Void in
let value = snapshot.value as? NSDictionary
let readyToGoValue = value?["readyToGo"] as? Bool ?? false
let userID = value?["userID"] as? String ?? ""
var amountOfPlayers = value?["currentPlayers"] as? Int ?? 0
let changedCreator = value?["creator"] as? String ?? ""
print(snapshot)
let currentUser = FIRAuth.auth()?.currentUser?.uid
print(changedCreator)
print(amountOfPlayers)
if changedCreator != ""
{
print("changed creator")
self.creator = changedCreator
}
This doesn't work swell. When changing the creator (just a string) in Firebase, I get this as a print when adding print(snapshot):
Snap (creator) hi
However the print("changed creator") never is executed. Why is this?
edit: This is how I got channelRef?:
super.prepare(for: segue, sender: sender)
if let channel = sender as? Channel {
let chatVc = segue.destination as! channelMultiplayerViewController
chatVc.channel = channel
chatVc.channelRef = channelRef.child(channel.id)
chatVc.usersKey = userKey
}
Printing more data:
print("path channel ref: " + "\(self.channelRef)")
print("snapshot: " + "\(snapshot)")
print("value: " + "\(value)")
-path channel ref: Optional(https://X.com/channels/-KeGKaJavH6uPYaSa7k4)
-snapshot: Snap (creator) new Creator
-value: nil
Update:
data structure:
This will work for now, but isn't there a better approach?:
if snapshot.key == "creator"
{
changedCreator = snapshot.value as! String
}
Another problem, exactly the same as above but with the solution for the first problem, this problem won't get solved. When I try to get the first child node, so the first user, and trying to get their userID, nothing works. I use this code:
let firstChild = UInt(1)
self.channelRef?.queryLimited(toFirst: firstChild).observeSingleEvent(of: .value, with: { (snapshot) in
let value = snapshot.value as? NSDictionary
print(snapshot)
print(value)
let newCreator = value?.value(forKey: "userID") as? String
if newCreator != nil{
print("Got the userID")
}
if snapshot.key == "userID"
{
print("Got the userID")
}
})
Snap (-KeJWMiXaL-FGp0J7b3u) {
"-KeJWO0V9kxgGnrACAtP" = {
PictureVersion = 2;
readyToGo = 0;
userID = SZlQ76RLCJQpFa0CDhrgFJoYzrs2;
username = pietje;
};
}
Optional({
"-KeJWO0V9kxgGnrACAtP" = {
PictureVersion = 2;
readyToGo = 0;
userID = SZlQ76RLCJQpFa0CDhrgFJoYzrs2;
username = pietje;
};
})
And this prints out, so no userID is given. Why is this? The userID is right there! I read the docs but it should work...
Try replacing chatVc.channelRef = channelRef.child(channel.id) with chatVc.channelRef = channelRef

Firebase function freezes app in xcode7, but works in xcode6.4

For some reason this code works perfectly in xcode6.4, but when switching to xcode7 it freezes the app.
What I am trying to do is pull the post information on a user's feed and display it on a tableview. I am able to pull the information from Firebase, but the app freezes before it displays on the tableview.
EDIT: The tableview works when I do not have any constraints or autolayout. It seems to not work when I try to have dynamic cell heights.
func getRadarData() {
let url = "https://(insert appname).firebaseio.com/users/" + currentUser + "/postsReceived/"
let targetRef = Firebase(url: url)
targetRef.observeEventType(.ChildAdded, withBlock: {
snapshot in
print("child")
if let found = self.posts.map({ $0.key }).indexOf(snapshot.key) {
let obj = self.posts[found]
print(obj)
print(found)
self.posts.removeAtIndex(found)
}
let postsUrl = "https://(insert appname).firebaseio.com/posts/" + snapshot.key
let postsRef = Firebase(url: postsUrl)
var updatedAt = snapshot.value["updatedAt"] as? NSTimeInterval
var endAt = snapshot.value["endAt"] as? NSTimeInterval
if updatedAt == nil {
updatedAt = 0
}
if endAt == nil {
endAt = 0
}
postsRef.observeSingleEventOfType(.Value, withBlock: { snapshot in
if let key = snapshot.key
{if let content = snapshot.value["content"] as? String {
if let creator = snapshot.value["creator"] as? String {
if let createdAt = snapshot.value["createdAt"] as? NSTimeInterval {
let userurl = "https://(insert appname).firebaseio.com/users/" + (creator)
let userRef = Firebase(url: userurl)
userRef.observeSingleEventOfType(.Value, withBlock: { snapshot in
if let username = snapshot.value["username"] as? String {
let updatedDate = NSDate(timeIntervalSince1970: (updatedAt!/1000))
let createdDate = NSDate(timeIntervalSince1970: (createdAt/1000))
let endedDate = NSDate(timeIntervalSince1970: (endAt!))
let post = Post(content: content, creator: creator, key: key, createdAt: updatedDate, name: username, joined: true, messageCount: 0, endAt: endedDate)
self.posts.append(post)
// Sort posts in descending order
self.posts.sortInPlace({ $0.createdAt.compare($1.createdAt) == .OrderedDescending })
self.tableView.reloadData()
}
})
}
}
}
}
})
})
}
Here is my code for my tableview where I used autolayout on the textView and nameLabel
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: RadarTableViewCell = tableView.dequeueReusableCellWithIdentifier("radarCell", forIndexPath: indexPath) as! RadarTableViewCell
let creator: (String) = posts[indexPath.row].creator
let key = posts[indexPath.row].key
let radarContent: (AnyObject) = posts[indexPath.row].content
cell.textView.selectable = false
cell.textView.text = radarContent as? String
cell.textView.userInteractionEnabled = false
cell.textView.selectable = true
let radarCreator: (AnyObject) = posts[indexPath.row].name
cell.nameLabel.text = radarCreator as? String
return cell
The issue was that I had initial text in my textView. I deleted it on my Storyboard and my app works now.
Found the solution here: Why does a previously working Xcode project hang up in Xcode 7 when presenting a new UITableviewController Subclass?

Resources