使用Swift 3时'InvalidPathValidation'
我有一个应用程序使用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.
如果您可以找到任何能够帮助我解决问题的东西,并最终让我的应用程序工作,我将成为您最好的朋友。
在此先感谢!
雨燕3.0是一个开发者版本是测试版目前,预计后期2016年
释放一些图书馆可能无法使用作为然而,也可能包含错误,所以你应该立即重新安装最新的公共稳定版本的Swift(目前截至撰写v2.2)。
你自己说你已经更新到Xcode的测试版。因此,我建议您通过重新下载Xcode from the Mac App Store并删除Xcode的测试版来重新安装Swift 2.2。
对于Swift 3,请等到Apple在2016年秋季发布公开版本。然后,查看您的代码是否有效。
Firebase可能尚未更新其Swift 3.0的库。
直到它,我建议你继续使用Swift 2.2。由于兼容性错误,您不希望您的应用程序突然停止工作。
你说你下载了一个测试版的Xcode。至少我会等待苹果在2016年秋季发布Xcode的公共版本,然后再次尝试您的代码。
但是,我们不知道Firebase何时会更新其库。保留代码的备份,并在备用机器中下载更新版本的Xcode。如果您的代码在备用机器上正常工作,请将其下载到主机中。或者,安装虚拟机(如VirtualBox),然后在那里尝试您的应用程序。
斯威夫特3
Firebase:如果您创建自己的密钥,它们必须是UTF-8编码,可以最多768个字节,并不能包含$,#,[, ],/或ASCII控制字符0-31或127.
要处理它们,您需要用其他名称替换非firebase字符。
以下String extension
用空格替换那些字符,你可以选择你自己的。 (出埃及记“ - ”)。
地址:
extension String {
func makeFirebaseString()->String{
let arrCharacterToReplace = [".","#","$","[","]"]
var finalString = self
for character in arrCharacterToReplace{
finalString = finalString.replacingOccurrences(of: character, with: " ")
}
return finalString
}
}
用途:
let searchString = "Super.Hero"
let firebaseSearchString = searchString.makeFirebaseString()
// firebaseSearchString is "Super Hero" now
谢谢,是的,我认为这是一个失败的实验哈哈我最好的选择是回到什么可行,等待一个稳定的版本 –
请[不要发布相同的答案多个问题](https://meta.stackexchange.com/q/104227)。发布一个很好的答案,然后投票/标记以重复关闭其他问题。如果问题不重复,*定制您对问题*的答案。 –