Swift iOS向Firebase Realtime Database存数据时键无效错误如何解决
错误产生原因
- Firebase Realtime Database 对节点键名有强制校验规则:键名不能是空字符串,也不能包含
/、.、#、$、[、]这几个特殊字符。你触发报错大概率是传入的genre或者fileName变量值包含了上述禁用字符,最常见的场景是 fileName 带有文件扩展名的点(比如video.mp4里的.)、或者携带文件路径的斜杠。 - 补充:你当前的代码逻辑也不符合预期,
setValue会直接覆盖整个genre节点的所有内容,每次写入新的 fileName 都会把之前存的其他 fileName 数据全部删除,达不到你要的多 fileName 共存的存储结构。
解决方法
- 首先对所有用作键名的字符串做特殊字符转义,把禁用字符替换为允许的字符(例如下划线),可以先加一个字符串扩展工具方法:
extension String { /// 转换为Firebase允许的安全键名 func toFirebaseSafeKey() -> String { let invalidCharSet = CharacterSet(charactersIn: "/.#$[]") return self.components(separatedBy: invalidCharSet).joined(separator: "_") } }
- 把覆盖写入的
setValue改为增量更新的updateChildValues方法,只会新增/修改对应fileName的子节点,不会影响其他已有数据,修改后的业务代码如下:
public func insertPostsToDB(with fileName: String, user: String, genre: String, completion: @escaping (Bool) -> Void) { guard let username = UserDefaults.standard.string(forKey: "username") else { completion(false) return } // 处理键名的非法字符 let safeGenre = genre.toFirebaseSafeKey() let safeFileName = fileName.toFirebaseSafeKey() // 校验处理后的键名非空 guard !safeGenre.isEmpty, !safeFileName.isEmpty else { completion(false) return } // 增量写入数据 database.child(safeGenre).updateChildValues([safeFileName : username]) { error, _ in completion(error == nil) } }
- 如果业务需要保留原始的fileName信息,可以调整存储结构,在子节点里额外存储原始文件名,避免转义后丢失原始信息,示例结构:
Genre safe_fileName_1: user: "user1" originalFileName: "fileName.1.mp3"
内容的提问来源于stack exchange,提问作者Artun
相关产品推荐
相关产品推荐

