草庐IT

ios - 在 Swift 中创建灵活的 API 类

coder 2023-09-15 原文

我正在尝试为应用程序设计一个 API 辅助函数。我的想法是我将能够从 viewController 调用该函数,使用如下代码:

let api = APIController();
api.request("get_product_list")
api.delegate = self

这是目前的类(class):

import Foundation

protocol APIControllerProtocol {
 func didReceiveAPIResults(originalRequest: String, status: Bool, data: String, message: String)
}


class APIController { 

 var delegate: APIControllerProtocol?

 let url = "https://example.co.uk/api.php"
 let session = NSURLSession.sharedSession()
 let appID = "EXAMPLEAPPID";
 let deviceID = "EXAMPLEDEVICE"

 func request(req:String)-> Void {
    let urlString = "\(url)?request=\(req)"
    let combinedUrl = NSURL(string: urlString)
    let request = NSMutableURLRequest(URL: combinedUrl!)
    request.HTTPMethod = "POST"
    let stringPost="app_id=\(appID)&device_id=\(deviceID)"
    let data = stringPost.dataUsingEncoding(NSUTF8StringEncoding)

    request.timeoutInterval = 60
    request.HTTPBody=data
    request.HTTPShouldHandleCookies=false

    let task = session.dataTaskWithRequest(request) {
        (data, response, error) -> Void in
        do {
            let jsonData = try NSJSONSerialization.JSONObjectWithData(data!, options:NSJSONReadingOptions.MutableContainers ) as! NSDictionary
            let statusInt = jsonData["status"]! as! Int
            let status = (statusInt == 1)
            let data = String(jsonData["data"])
            let message = String(jsonData["message"])
            self.delegate?.didReceiveAPIResults(req,status: status,data: data,message: message)
        } catch _ {
            print("ERROR")
        }
    }
    task.resume()
 }
}

我遇到的困难是“数据”参数可能是以下之一:

  1. 字符串/数字,例如客户的购买次数
  2. 一组项目,例如产品列表
  3. 字典,例如客户的详细信息

我已将数据参数设置为 String,因为这允许我进行一些测试,但随后将其转换回可用于 tableView 的东西变得非常困惑。

这里有专家可以建议我最好的方法吗?也许向我展示如何在 cellForRowAtIndexPath 方法中使用结果?以下是来自 API 的示例响应,如果有用的话:

{
"status":1,
"message":"",
"cached":0,
"generated":1447789113,
"data":[
    {"product":"Pear","price":0.6},
    {"product":"Apple","price":0.7},
    {"product":"Raspberry","price":1.1}
]
}

最佳答案

一个函数一次做太多事情会产生非常困惑的代码。此外,您不需要太多的 if 语句或 enums - 您的 View Controller 会增长得非常快。

我建议拆分请求和解析逻辑。然后,您的 API 类将负责请求。它会将数据返回给另一个负责解析的类。然后在 Parser 类中,您可以添加 toDictionary()toArray()toArrayOfClasses() 等方法。这将是基本的 API 结构。

如果你想稍微扩展它,你可以添加另一个类层来处理所有这些逻辑,这样你的 View Controller 就不知道它是使用 API 还是其他数据源 - 这样你就可以轻松实现新事物将来,像 Core Data 或从您的 API 类迁移到某个框架,也许是 Parse.com - 这一层为您提供了灵 active 。

示例结构:

  1. API - 请求
  2. 解析器 - 解析 API 响应
  3. DataManager - 向 API 发送请求并返回解析后的响应。

或者如果您不想要这第三点,您可以只在 View Controller 中请求和解析。

关于ios - 在 Swift 中创建灵活的 API 类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33765685/

有关ios - 在 Swift 中创建灵活的 API 类的更多相关文章

  1. ruby-on-rails - Rails - 从另一个模型中创建一个模型的实例 - 2

    我有一个正在构建的应用程序,我需要一个模型来创建另一个模型的实例。我希望每辆车都有4个轮胎。汽车模型classCar轮胎模型classTire但是,在make_tires内部有一个错误,如果我为Tire尝试它,则没有用于创建或新建的activerecord方法。当我检查轮胎时,它没有这些方法。我该如何补救?错误是这样的:未定义的方法'create'forActiveRecord::AttributeMethods::Serialization::Tire::Module我测试了两个环境:测试和开发,它们都因相同的错误而失败。 最佳答案

  2. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  3. ruby-on-rails - ActionController::RoutingError: 未初始化常量 Api::V1::ApiController - 2

    我有用于控制用户任务的Rails5API项目,我有以下错误,但并非总是针对相同的Controller和路由。ActionController::RoutingError:uninitializedconstantApi::V1::ApiController我向您描述了一些我的项目,以更详细地解释错误。应用结构路线scopemodule:'api'donamespace:v1do#=>Loginroutesscopemodule:'login'domatch'login',to:'sessions#login',as:'login',via::postend#=>Teamroutessc

  4. Ruby 文件 IO 定界符? - 2

    我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的

  5. ruby - 如何在 Ruby 中创建无类 DSL? - 2

    我正在尝试找出如何为我的Ruby项目创建一种“无类DSL”,类似于在Cucumber步骤定义文件中定义步骤定义或在Sinatra应用程序中定义路由。例如,我想要一个文件,其中调用了我的所有DSL函数:#sample.rbwhen_string_matches/hello(.+)/do|name|call_another_method(name)end我认为用我的项目特有的一堆方法污染全局(内核)命名空间是一种不好的做法。因此方法when_string_matches和call_another_method将在我的库中定义,并且sample.rb文件将以某种方式在我的DSL方法的上下文中

  6. ruby-on-rails - 如何在 Rails 3 中创建自定义脚手架生成器? - 2

    有这些railscast。http://railscasts.com/episodes/218-making-generators-in-rails-3有了这个,你就会知道如何创建样式表和脚手架生成器。http://railscasts.com/episodes/216-generators-in-rails-3通过这个,您可以了解如何添加一些文件来修改脚手架View。我想把两者结合起来。我想创建一个生成器,它也可以创建脚手架View。有点像RyanBates漂亮的生成器或web_app_themegem(https://github.com/pilu/web-app-theme)。我

  7. ruby - 为什么在 ruby​​ 中创建 Rational 不需要新方法 - 2

    这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Rubysyntaxquestion:Rational(a,b)andRational.new!(a,b)我正在阅读ruby镐书,我对创建有理数的语法感到困惑。Rational(3,4)*Rational(1,2)产生=>3/8为什么Rational不需要new方法(我还注意到例如我可以在没有new方法的情况下创建字符串)?

  8. 【鸿蒙应用开发系列】- 获取系统设备信息以及版本API兼容调用方式 - 2

    在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList​()Obt

  9. Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting - 2

    1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里

  10. ruby-on-rails - Mandrill API 模板 - 2

    我正在使用Mandrill的RubyAPIGem并使用以下简单的测试模板:testastic按照Heroku指南中的示例,我有以下Ruby代码:require'mandrill'm=Mandrill::API.newrendered=m.templates.render'test-template',[{:header=>'someheadertext',:main_section=>'Themaincontentblock',:footer=>'asdf'}]mail(:to=>"JaysonLane",:subject=>"TestEmail")do|format|format.h

随机推荐