【问题标题】:How do I set up a success/failure block so that I can pass a string into it using Swift?如何设置成功/失败块,以便可以使用 Swift 将字符串传递给它?
【发布时间】:2017-12-12 23:22:50
【问题描述】:

我有一个 API 方法可以返回特定联赛的球队。我需要做的就是传入一些参数。

例如,API URL 如下所示:http://api.website.com/api/teams?season=last&league=0Xc334xUK4

这是我的代码:

@objc class APITeam: NSObject {

    var leagueObjectID: NSString!

    let baseUrl = "http://api.website.com/api"

    static let sharedInstance = APITeam()

    static let getTeamsEndpoint = "/teams"

    static let params = "?season=last&league="

    private override init() {}

    func getTeams (_ onSuccess: @escaping(Any) -> Void, onFailure: @escaping(Error) -> Void) {

        var request = URLRequest(url: URL(string: baseUrl + APITeam.getTeamsEndpoint + APITeam.params)!)

        let session = URLSession.shared

        request.httpMethod = "GET"

        let task = session.dataTask(with: request) { (data : Data?, response : URLResponse?, error : Error?) in

            if(error != nil){
                onFailure(error!)
            } else{

                do {

                    let result  = try JSONSerialization.jsonObject(with: data!)
                    onSuccess(result)

                } catch {

                    print(error)

                }

            }

        }
        task.resume()

    }

}

为了让这个 API 方法返回数据,我需要在发出请求时传入我想要球队的联赛的 objectID。

我尝试将参数添加到:

func getTeams (_ onSuccess: @escaping(Any) -> Void, onFailure: @escaping(Error) -> Void, leagueObjectID: String) {

 var request = URLRequest(url: URL(string: baseUrl + APITeam.getTeamsEndpoint + APITeam.params + leagueObjectID)!)

这没有按预期工作。当我在另一个类中使用该方法时,“leagueObjectID”充当成功的附加部分,如果有意义的话,错误块。我需要能够将leagueObjectID 传递到方法中,以便在发出请求的URL 末尾使用它。

这就是我在 Objective-c 类中调用 APITeam 的方式:

[[APITeam sharedInstance] getTeams:^(id result) {

} onFailure:^(NSError * error) {

}];

如您所见,我添加到 getTeams 函数中的额外参数没有显示出来,当我尝试手动添加时,出现错误。

你会如何处理这个问题? 一个例子将不胜感激。

感谢您的宝贵时间

【问题讨论】:

  • “当我在另一个类中使用该方法时” - 编辑您的问题以显示此代码;工作的原始版本和带有附加 leagueObjectID 参数的失败版本。这将帮助人们“理解”您所描述的内容并为您提供帮助。
  • 惯用风格是将单个闭包作为最后一个参数。任何其他参数都将出现在闭包参数之前。单个闭包将被声明为 (SomeType?,Error?);那么如果Error 不是nil 你就知道有一个错误。这种风格允许您在函数调用上使用尾随闭包。
  • @CRD 我的问题的底部显示了我试图做的事情。我觉得最好不要再次粘贴整个代码块。
  • @Paulw11 我现在要试试这个。
  • @LondonGuy - 除非我误解或不清楚,否则“问题的底部”显示您如何更改 getTeams 的定义,而不是您如何创建 APITeam实例并调用getTeams“在另一个班级”,这就是你说你遇到问题的时候。

标签: ios swift nsurlrequest


【解决方案1】:

改成

func getTeams (leagueObjectID: String, onSuccess: @escaping(Any) -> Void, onFailure: @escaping(Error) -> Void)

【讨论】:

    【解决方案2】:

    static 在其他语言中可能无法正常工作。 static var 的行为类似于 class var

    如果我理解正确,这将满足您的需求

    @objc class APITeam: NSObject {
        private static let baseUrl = "http://api.website.com/api"
    
        private static let getTeamsEndpoint = "/teams"
    
        let params = "?season=last&league="
    
        private override init() {}
    
        func getTeam(id: String, _ onSuccess: @escaping(Any) -> Void, onFailure: @escaping(Error) -> Void) {
            var request = URLRequest(url: URL(string: APITeam.baseUrl + APITeam.getTeamsEndpoint + APITeam.params + id)!)
            request.httpMethod = "GET"
    
            URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in
                if let error = error {
                    onFailure(error)
                } else if let responseData = data {
                    do {
                        let result = try JSONSerialization.jsonObject(with: responseData)
                        onSuccess(result)
                    } catch {
                        print(error)
    
                    }
    
                }
    
            }.resume()
    
        }
    
    }
    

    用法: APITeam().getTeam(id: "0Xc334xUK4", ..your completion handlers here..)

    【讨论】:

    • 至于你应该怎么做,看看Alamofire。这是 Swift 最常见的 HTTP 包装器。
    • 将使用 APITeam 的类是用 Objective C 编写的。自动完成似乎没有显示任何关于 APITeam getTeams 函数中声明的 ID 参数的信息:dropbox.com/s/ejq60e7gbn834m4/…
    • 将该函数也标记为@objc,然后在尝试访问之前构建一次应用程序。似乎让 Xcode 生成桥接头。
    • 我无法调用 APITeam getTeams 方法,所以我将原始代码与“sharedInstance”一起使用。构建应用程序解决了这个问题。我没有意识到我必须构建才能使其工作。我以为 XCode 会自动处理它。
    • 如果我的回答帮助您解决了问题,请将其标记为已接受。是的,我已经被卡住了几次。永远不要低估 Xcode 的无用性;P 如果构建一次不能完成工作,它还有助于删除派生数据、清理项目、清理构建文件夹并重新启动 Xcode。如果这也不起作用,请尝试牺牲几只羔羊,然后删除派生数据并重新构建。
    【解决方案3】:

    这对我有用:

    @objc class APITeam: NSObject {
    
        var leagueObjectID: NSString!
    
        let baseUrl = "http://api.website.com/api"
    
        static let sharedInstance = APITeam()
    
        static let getTeamsEndpoint = "/teams"
    
        static let params = "?season=last&league="
    
        private override init() {}
    
        func getTeams (leagueObjectID: String, _ onSuccess: @escaping(Any) -> Void, onFailure: @escaping(Error) -> Void) {
    
            var request = URLRequest(url: URL(string: baseUrl + APITeam.getTeamsEndpoint + APITeam.params + leagueObjectID)!)
    
            let session = URLSession.shared
    
            request.httpMethod = "GET"
    
            let task = session.dataTask(with: request) { (data : Data?, response : URLResponse?, error : Error?) in
    
                if(error != nil){
                    onFailure(error!)
                } else{
    
                    do {
    
                        let result  = try JSONSerialization.jsonObject(with: data!)
                        onSuccess(result)
    
                    } catch {
    
                        print(error)
    
                    }
    
                }
    
            }
            task.resume()
    
        }
    
    }
    

    然后在我的 Objective-C 类中:

    [[APITeam sharedInstance] getTeamsWithLeagueObjectID:@"93PwHe5e4S" :^(id league) {
        NSLog(@"THE LEAGUE: %@", league);
    } onFailure:^(NSError * error) {
    
    }];
    

    在尝试访问原始类之前构建应用程序也很重要。这对我来说是至关重要的一步。有时我不需要这样做,但这一次,在我构建应用程序之前,我无法访问新更改的 APITeam getTeams 函数。

    【讨论】:

      猜你喜欢
      • 2018-08-31
      • 2012-11-01
      • 2021-12-29
      • 1970-01-01
      • 1970-01-01
      • 2015-06-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多