Firebase查询返回值类型多变致App解析崩溃问题求助
嘿,我来帮你搞定这个Firebase用户输入监听时数据类型不一致导致崩溃的问题!
解决Firebase用户输入监听数据类型混乱导致崩溃的方案
1. 核心问题:数据类型不可预测导致强转崩溃
Firebase返回的snapshot.value类型确实会随节点存储结构变化:如果节点下的key是连续数字,会返回数组;如果是自定义字符串key,会返回字典;若节点中存在null值,还会出现含空值的数组/字典。直接强转类型必然会触发崩溃,所以必须先做严格的类型校验和容错处理。
2. 修改后的容错代码示例
把你原来的监听方法改成下面这样,增加类型判断、空值过滤和异常处理:
- (void)listenUserTypingGate { __weak typeof(self)this = self; [[_userTypingRef queryOrderedByKey] observeEventType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot * _Nonnull snapshot) { if (!this) return; id value = snapshot.value; // 先处理空值情况 if (!value || [value isKindOfClass:[NSNull class]]) { [this handleNoUserTyping]; return; } // 分类型处理数据 if ([value isKindOfClass:[NSDictionary class]]) { // 处理字典类型:通常是自定义key的用户输入状态 NSDictionary *typingDict = (NSDictionary *)value; [this parseTypingDictionary:typingDict]; } else if ([value isKindOfClass:[NSArray class]]) { NSArray *typingArray = (NSArray *)value; // 过滤数组中的null值,避免后续解析崩溃 NSArray *filteredArray = [typingArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF != %@", [NSNull null]]]; if (filteredArray.count == 0) { [this handleNoUserTyping]; } else { [this parseTypingArray:filteredArray]; } } else { // 遇到未知类型,打印日志并做容错 NSLog(@"收到未知类型的输入状态数据:%@", [value class]); [this handleNoUserTyping]; } } withCancelBlock:^(NSError * _Nonnull error) { // 监听出错时也要做容错,避免崩溃 NSLog(@"用户输入状态监听失败:%@", error.localizedDescription); }]; } // 抽离字典解析逻辑,代码更清晰 - (void)parseTypingDictionary:(NSDictionary *)dict { for (NSString *userId in dict.allKeys) { id status = dict[userId]; // 再次校验value类型,避免空值或非布尔值 if ([status isKindOfClass:[NSNumber class]]) { BOOL isTyping = [status boolValue]; [self updateUserTypingStatus:userId isTyping:isTyping]; } } } // 抽离数组解析逻辑 - (void)parseTypingArray:(NSArray *)array { for (id item in array) { if ([item isKindOfClass:[NSString class]]) { // 假设数组存储的是正在输入的用户ID [self updateUserTypingStatus:item isTyping:YES]; } else if ([item isKindOfClass:[NSDictionary class]]) { // 数组嵌套字典的情况,复用字典解析逻辑 [self parseTypingDictionary:(NSDictionary *)item]; } } } // 无用户输入时的统一处理 - (void)handleNoUserTyping { [self clearAllTypingStatus]; }
3. 从根源避免问题:规范Firebase数据结构
其实最好的解决办法是统一数据存储格式,比如用字典而非数组存储用户输入状态:
userTyping: { "user_123": true, "user_456": false }
这样Firebase返回的永远是字典类型,你就不用处理各种类型分支,代码稳定性会大幅提升。另外,用户停止输入时记得及时更新对应节点为false或移除节点,避免数据冗余。
内容的提问来源于stack exchange,提问作者TienLe
相关产品推荐
相关产品推荐

