我有一个应用程序使用Firebase在用户之间发送和接收消息。在将我的代码更新到新的Swift 3的过程中,我可以将iOS 10的酷炫新功能添加到我的应用程序中,但遇到了一些错误。我能够修复其中的大多数,除了这一个在运行时:使用Swift 3时'InvalidPathValidation'
Terminating app due to uncaught exception 'InvalidPathValidation', reason: '(child:) Must be a non-empty string and not contain '.' '#' '$' '[' or ']''
我不知道可能导致这一点。用户的用户ID在登录时被打印到控制台,但是一旦登录按钮被按下,我的应用就会崩溃。在我更新到Swift 3之前,这个错误并不存在,实际上只有在我修复了我的应用程序的另一部分中的错误后才出现。
无论如何,我的应用程序中只有两个主类:LoginViewController
和ChatViewController
。
这里是LoginViewController
代码:
import UIKit
import Firebase
class LoginViewController: UIViewController {
// MARK: Properties
var ref: FIRDatabaseReference! // 1
var userID: String = ""
override func viewDidLoad() {
super.viewDidLoad()
ref = FIRDatabase.database().reference() // 2
}
@IBAction func loginDidTouch(_ sender: AnyObject) {
FIRAuth.auth()?.signInAnonymously() { (user, error) in
if let user = user {
print("User is signed in with uid: ", user.uid)
self.userID = user.uid
} else {
print("No user is signed in.")
}
self.performSegue(withIdentifier: "LoginToChat", sender: nil)
}
}
override func prepare(for segue: UIStoryboardSegue, sender: AnyObject?) {
super.prepare(for: segue, sender: sender)
let navVc = segue.destinationViewController as! UINavigationController // 1
let chatVc = navVc.viewControllers.first as! ChatViewController // 2
chatVc.senderId = userID // 3
chatVc.senderDisplayName = "" // 4
}
}
这里是我的ChatViewController
代码:
import UIKit
import Firebase
import JSQMessagesViewController
class ChatViewController: JSQMessagesViewController {
// MARK: Properties
var rootRef = FIRDatabase.database().reference()
var messageRef: FIRDatabaseReference!
var messages = [JSQMessage]()
var outgoingBubbleImageView: JSQMessagesBubbleImage!
var incomingBubbleImageView: JSQMessagesBubbleImage!
var userIsTypingRef: FIRDatabaseReference! // 1
private var localTyping = false // 2
var isTyping: Bool {
get {
return localTyping
}
set {
// 3
localTyping = newValue
userIsTypingRef.setValue(newValue)
}
}
var usersTypingQuery: FIRDatabaseQuery!
override func viewDidLoad() {
super.viewDidLoad()
title = "ChatChat"
setupBubbles()
// No avatars
collectionView!.collectionViewLayout.incomingAvatarViewSize = CGSize.zero
collectionView!.collectionViewLayout.outgoingAvatarViewSize = CGSize.zero
messageRef = rootRef.child("messages")
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
observeMessages()
observeTyping()
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
}
func collectionView(collectionView: JSQMessagesCollectionView!,
messageDataForItemAtIndexPath indexPath: NSIndexPath!) -> JSQMessageData! {
return messages[indexPath.item]
}
func collectionView(collectionView: JSQMessagesCollectionView!,
messageBubbleImageDataForItemAtIndexPath indexPath: NSIndexPath!) -> JSQMessageBubbleImageDataSource! {
let message = messages[indexPath.item] // 1
if message.senderId == senderId { // 2
return outgoingBubbleImageView
} else { // 3
return incomingBubbleImageView
}
}
override func collectionView(_ collectionView: UICollectionView,
numberOfItemsInSection section: Int) -> Int {
return messages.count
}
func collectionView(collectionView: JSQMessagesCollectionView!,
avatarImageDataForItemAtIndexPath indexPath: NSIndexPath!) -> JSQMessageAvatarImageDataSource! {
return nil
}
private func setupBubbles() {
let factory = JSQMessagesBubbleImageFactory()
outgoingBubbleImageView = factory?.outgoingMessagesBubbleImage(
with: UIColor.jsq_messageBubbleBlue())
incomingBubbleImageView = factory?.incomingMessagesBubbleImage(
with: UIColor.jsq_messageBubbleLightGray())
}
func addMessage(id: String, text: String) {
let message = JSQMessage(senderId: id, displayName: "", text: text)
messages.append(message!)
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell{
let cell = super.collectionView(collectionView, cellForItemAt: indexPath) as! JSQMessagesCollectionViewCell
let message = messages[indexPath.item]
if message.senderId == senderId {
cell.textView!.textColor = UIColor.white()
} else {
cell.textView!.textColor = UIColor.black()
}
return cell
}
func didPressSendButton(button: UIButton!, withMessageText text: String!, senderId: String!,
senderDisplayName: String!, date: NSDate!) {
let itemRef = messageRef.childByAutoId() // 1
let messageItem = [ // 2
"text": text,
"senderId": senderId
]
itemRef.setValue(messageItem as? AnyObject) // 3
// 4
JSQSystemSoundPlayer.jsq_playMessageSentSound()
// 5
finishSendingMessage()
isTyping = false
}
private func observeMessages() {
// 1
let messagesQuery = messageRef.queryLimited(toLast: 25)
// 2
messagesQuery.observe(.childAdded) { (snapshot: FIRDataSnapshot!) in
// 3
let id = snapshot.value!["senderId"] as! String
let text = snapshot.value!["text"] as! String
// 4
self.addMessage(id: id, text: text)
// 5
self.finishReceivingMessage()
}
}
private func observeTyping() {
let typingIndicatorRef = rootRef.child("typingIndicator")
userIsTypingRef = typingIndicatorRef.child(senderId)
userIsTypingRef.onDisconnectRemoveValue()
// 1
usersTypingQuery = typingIndicatorRef.queryOrderedByValue().queryEqual(toValue: true)
// 2
usersTypingQuery.observe(.value) { (data: FIRDataSnapshot!) in
// 3 You're the only typing, don't show the indicator
if data.childrenCount == 1 && self.isTyping {
return
}
// 4 Are there others typing?
self.showTypingIndicator = data.childrenCount > 0
self.scrollToBottom(animated: true)
}
}
override func textViewDidChange(_ textView: UITextView) {
super.textViewDidChange(textView)
// If the text is not empty, the user is typing
isTyping = textView.text != ""
}
func collectionView(collectionView: JSQMessagesCollectionView!, attributedTextForCellBottomLabelAtIndexPath indexPath: NSIndexPath!) -> AttributedString! {
return AttributedString(string:"test")
}
}
精神,所有这些代码是写在斯威夫特3.
如果您可以找到任何能够帮助我解决问题的东西,并最终让我的应用程序工作,我将成为您最好的朋友。
在此先感谢!
谢谢,是的,我认为这是一个失败的实验哈哈我最好的选择是回到什么可行,等待一个稳定的版本 –
请[不要发布相同的答案多个问题](https://meta.stackexchange.com/q/104227)。发布一个很好的答案,然后投票/标记以重复关闭其他问题。如果问题不重复,*定制您对问题*的答案。 –