首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >将可编码结构编码为Alamofire POST参数- Swift

将可编码结构编码为Alamofire POST参数- Swift
EN

Stack Overflow用户
提问于 2021-09-10 22:22:36
回答 1查看 160关注 0票数 0

我正在尝试将我的前端iOS应用程序(Swift)连接到我的Django后端。

我尝试创建一个APIRouter类来处理任何请求。这个类需要符合URLRequestConvertible

我有这样的结构:

代码语言:javascript
运行
复制
struct APIAccountID: Codable {
    
    let username: String
    let password: String
}

这是可编码的。

我尝试在Alamofire POST请求中传递此结构的数据。

所以我尝试这样对对象进行编码:

代码语言:javascript
运行
复制
var parameters: [String: AnyObject]? {
    switch self {
    case .fetchAccessToken(let accountID):
        if let data = try? JSONEncoder().encode(accountID) {
            return data
        } else {
            print("Error: encoding post data")
            return nil
        }
    default: break
    }
}

这不起作用,因为在使用Alamofire URLEncodedFormParameterEncoderJSONParameterEncoder时,AnyAnyObject是不可编码的。

如果我使用这个参数开关:

代码语言:javascript
运行
复制
var parameters: Data? {
        switch self {
        case .fetchAccessToken(let accountID):
            if let data = try? JSONEncoder().encode(accountID) {
                return data
            } else {
                print("[fetchAccessToken] Error: encoding post data")
            }
        default:
            break
        }
        return nil
    }

当我发送请求时,我得到了这个错误:

代码语言:javascript
运行
复制
{
    "non_field_errors" =     (
        "Invalid data. Expected a dictionary, but got str."
    );
}

我的URLRequestConvertible函数:

代码语言:javascript
运行
复制
// MARK: - URLRequestConvertible
extension APIRouter: URLRequestConvertible {
    
    func asURLRequest() throws -> URLRequest {
        let url = try baseURL.asURL().appendingPathComponent(path)
        var request = URLRequest(url: url)
        request.method = method
        if method == .get {
            request = try URLEncodedFormParameterEncoder()
                .encode(parameters, into: request)
        } else if method == .post {
            request = try JSONParameterEncoder().encode(parameters, into: request)
            request.setValue("application/json", forHTTPHeaderField: "Accept")
        }
        return request
    }
}
EN

回答 1

Stack Overflow用户

发布于 2021-09-11 21:47:32

AlamoFire URLFormEncodedParameterEncoderJSONParameterEncoder可以接受任何符合Encodable的内容,所以您不需要首先使用JSONEncoder;它们会处理好这一点。

您的根本问题是,如果您将具有不同的参数类型,那么parameters的类型应该是什么,这取决于API调用。

你不能说

代码语言:javascript
运行
复制
var parameters: APIAccountID

因为这不适用于参数是updatePortfolio或其他值的情况。

您不能简单地说var parameters: Encodable?,因为您需要一个具体的类型。

您需要使用类型擦除。这是一种在Swift中使用的技术,允许将原本不相关的类型用作参数。有多种方法,但一种常见的方法是“装箱”,其中实际类型被存储为属性,当您引用类型擦除类型时,您将引用或函数调用重定向到已装箱或包装的类型。

因此,在这种情况下,您需要的是EncodableAnyEncodable -A类型擦除实现。幸运的是,可以从FlightSchool repos - https://github.com/Flight-School/AnyCodable中找到这样的东西

将该包添加到项目中后,可以将parameters修改为

代码语言:javascript
运行
复制
var parameters: AnyEncodable? {
    switch self {
        case .fetchAccessToken(let accountID):
            return AnyEncodable(accountID)
        case .updatePortfolio(let portfolio):
            return AnyEncodable(portfolio)
    }
}

现在,我们的parameters变量有一个固定的类型- AnyEncodable?,它符合Encodable,所以每个人都很高兴。该实现要求您用实际的Encodable实例化一个AnyEncodable实例

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69138527

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档