Xamarin.iOS如何将嵌套模型数据上传至Firestore
Xamarin.iOS Firebase Firestore 嵌套模型上传方案
核心疑问解答
不要使用Dictionary<object, object>,Xamarin.Firebase.iOS.Firestore 要求提交的键值数据为NSDictionary<NSString, NSObject>类型,其中键必须是字符串,值为Firestore兼容的NSObject派生类型(NSString、NSNumber、NSArray、NSDictionary等)。
你猜想的「每个模型单独处理为Dictionary再组装」是正确的,嵌套结构需要从最内层子模型开始转换,逐层向外组装。你之前写的仅定义键结构的实现确实不符合要求,Firestore需要完整的键值对应关系。
具体实现代码
第一步:编写模型转Firestore字典的扩展方法
using Foundation; using System.Collections.Generic; using System.Linq; public static class FirestoreModelExtensions { // 最内层Nutrient模型转Firestore字典 public static NSDictionary<NSString, NSObject> ToFirestoreDict(this Nutrient nutrient) { return NSDictionary<NSString, NSObject>.FromObjectsAndKeys( objects: new NSObject[] { new NSString(nutrient.Id), new NSString(nutrient.DayId), new NSString(nutrient.NutrientName), NSNumber.FromDouble(nutrient.NutrientAmount) }, keys: new NSString[] { new NSString("id"), new NSString("dayId"), new NSString("nutrientName"), new NSString("nutrientAmount") } ); } // 中层Day模型转Firestore字典 public static NSDictionary<NSString, NSObject> ToFirestoreDict(this Day day) { // 先把Nutrients列表转成NSArray,每个元素是Nutrient的Firestore字典 var nutrientsArray = NSArray.FromNSObjects(day.Nutrients?.Select(n => n.ToFirestoreDict()).ToArray() ?? new NSObject[0]); return NSDictionary<NSString, NSObject>.FromObjectsAndKeys( objects: new NSObject[] { new NSString(day.Id), new NSString(day.GrowId), new NSString(day.LightsOn), new NSString(day.LightsOff), nutrientsArray }, keys: new NSString[] { new NSString("id"), new NSString("growId"), new NSString("lightsOn"), new NSString("lightsOff"), new NSString("nutrients") } ); } // 外层Grow模型转Firestore字典 public static NSDictionary<NSString, NSObject> ToFirestoreDict(this Grow grow) { // 先把Days列表转成NSArray,每个元素是Day的Firestore字典 var daysArray = NSArray.FromNSObjects(grow.Days?.Select(d => d.ToFirestoreDict()).ToArray() ?? new NSObject[0]); return NSDictionary<NSString, NSObject>.FromObjectsAndKeys( objects: new NSObject[] { new NSString(grow.Id), new NSString(grow.PlantName), daysArray }, keys: new NSString[] { new NSString("id"), new NSString("plantName"), new NSString("days") } ); } }
第二步:改写InsertGrow上传方法
using Firebase.Firestore; using System.Threading.Tasks; public async Task<bool> InsertGrow(Grow grow) { try { // 直接调用扩展方法转换模型为Firestore要求的字典格式 var growFirestoreDict = grow.ToFirestoreDict(); // 获取Firestore实例 var firestore = Firestore.SharedInstance; // 上传到Grows集合二选一: // 方式1:自动生成文档Id var documentRef = await firestore.GetCollection("grows").AddDocumentAsync(growFirestoreDict); // 方式2:用Grow的Id作为自定义文档Id // await firestore.GetCollection("grows").GetDocument(grow.Id).SetDataAsync(growFirestoreDict); return true; } catch { // 可自行添加错误日志逻辑 return false; } }
补充说明
- 字段名的大小写可根据需求调整,示例用了小驼峰命名,和Firestore常规命名规范对齐
- 代码已对空列表做了兼容处理,你可以根据业务需要补充其他字段的空值判断
- 上述代码用到的NSDictionary、NSArray等类型已经是Firestore iOS SDK要求的原生兼容类型,不需要额外做平台转换
内容的提问来源于stack exchange,提问作者Jimmy Purnell
相关产品推荐
相关产品推荐

