You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 14:54:05