本地Supabase环境下Swift客户端无法查询数据问题求助
我来帮你排查这个问题,结合你使用的Supabase CLI 2.28.1、Swift客户端2.29.3,以及你描述的情况——本地环境能正常认证用户、Studio里能查到sample表的4条记录,但Swift客户端执行查询后只输出(),我整理了几个最可能的解决方向,你可以一步步试试:
1. 仔细排查Row Level Security(RLS)的配置
你提到试过开关RLS,但可能没抓准关键点:
- 先彻底关闭RLS做测试:在Supabase Studio的SQL编辑器里执行
ALTER TABLE sample DISABLE ROW LEVEL SECURITY;,然后重新运行Swift客户端的查询代码。如果能查到数据,说明之前的RLS规则没有正确允许当前用户访问。 - 如果要保留RLS,得给当前认证的用户配置明确的查询权限,比如执行这条SQL:
CREATE POLICY "允许认证用户查看sample数据" ON sample FOR SELECT TO authenticated USING (true);
执行完后记得启用RLS:ALTER TABLE sample ENABLE ROW LEVEL SECURITY;
2. 修正Swift客户端的查询代码解析逻辑
你当前的代码直接取execute().value,可能因为没有正确解析数据类型导致输出空元组()。Supabase Swift客户端的execute()返回的是PostgrestResponse,需要把数据解析成对应类型才能正确输出:
- 首先定义和表结构匹配的模型(处理字段名的驼峰/下划线映射):
struct Sample: Codable { let id: Int64 let createdAt: Date enum CodingKeys: String, CodingKey { case id case createdAt = "created_at" } }
- 然后修改查询代码,用
decode方法解析成模型数组:
do { let samples = try await SupabaseService.shared.client.database .from("sample") .select() .execute() .decode(type: [Sample].self) print("查询到的数据: \(samples)") } catch { print("查询错误: \(error.localizedDescription)") }
如果不想用模型,也可以转成字典数组查看:
let sampleData = try await SupabaseService.shared.client.database .from("sample") .select() .execute() .value as? [[String: Any]] print(sampleData ?? "未查询到数据")
3. 查看本地Supabase服务的实时日志
这是定位问题的关键步骤,打开终端执行:
supabase logs -f
这个命令会实时输出Supabase本地服务的日志,然后你运行Swift客户端的查询代码,看日志里有没有权限报错、查询语法错误之类的信息,能帮你精准定位问题。
4. 确认查询时的用户认证状态
虽然你说能拿到用户的id/email,但建议在查询前确认当前会话是否有效:
if let currentUser = SupabaseService.shared.client.auth.currentUser { print("当前已认证用户ID: \(currentUser.id)") // 在这里执行你的查询代码 } else { print("当前用户未认证,请检查认证流程") }
有时候可能认证会话没有正确持久化,导致查询时用的是匿名角色(anon),而该角色没有访问sample表的权限。
5. 确认数据库表的基础权限
除了RLS,还要确保对应的数据库角色有SELECT权限,在Supabase Studio的SQL编辑器里执行:
GRANT SELECT ON sample TO authenticated; GRANT SELECT ON sample TO anon;
这条命令会给认证用户和匿名用户都开放sample表的查询权限,排除基础权限问题。
你可以按照这个顺序一步步排查,先从关闭RLS测试开始,快速定位是不是权限问题,再逐步深入代码和配置细节。
内容来源于stack exchange

