결국 Alamofire
다음에Result를 설명한 후에 두 가지 일반적인 예를 제시할 것이다. 첫 번째 예는 기본적인 네트워크 봉인 사상을 표현하고 두 번째 예는 기본적인viewModel 사상을 표현한다.
Result
/// Used to represent whether a request was successful or encountered an error.
///
/// - success: The request and all post processing operations were successful resulting in the serialization of the
/// provided associated value.
///
/// - failure: The request encountered an error resulting in a failure. The associated values are the original data
/// provided by the server as well as the error that caused the failure.
public enum Result {
case success(Value)
case failure(Error)
}
결과를 어떻게 묘사하는지에 관해서는 두 가지 가능성이 있는데, 성공하지 않으면 실패할 수 있기 때문에 매거진을 고려하는 것이다.위의 코드에서 매거된 모든 하위 옵션에 대해 값을 연결했다.여러분, 범용적인 문법은 이와 유사합니다. 중간에 하나의 유형을 성명하는데 이 T지식은 상징적이며 값을 부여할 때 어떠한 유형도 할 수 있습니다.다음 코드를 보는 방법도 있습니다.
struct CellConfigurator where Cell: Updatable, Cell: UITableViewCell {
}
|
위 코드의 Cell은 뒤에 제시된 두 가지 조건에 부합되어야 한다. 이런 용법은 범형에 조건 제한을 증가시키는 것이다. 이런 용법은 또 다른 방식이 있다. 다음 코드를 보자.
func send(_ r: T, handler: @escaping (T.Response?, String?) -> Void);
사실 이치의 차이는 많지 않고 모두 범형에 대한 유연한 운용에 속한다.
Alamofire에서 Result를 어떻게 사용하는지 살펴보겠습니다.
@discardableResult
public func responseJSON(
queue: DispatchQueue? = nil,
options: JSONSerialization.ReadingOptions = .allowFragments,
completionHandler: @escaping (DataResponse) -> Void)
-> Self
{
return response(
queue: queue,
responseSerializer: DataRequest.jsonResponseSerializer(options: options),
completionHandler: completionHandler
)
}
사전:
{
"people":[
{"firstName":"Brett","lastName":"McLaughlin","email":"aaaa"},
{"firstName":"Jason","lastName":"Hunter","email":"bbbb"},
{"firstName":"Elliotte","lastName":"Harold","email":"cccc"}
]
}
배열:
[
"a",
"b",
"c"
]
물론 이 두 가지 형식의 데이터가 아니라면 JSONserialization을 사용하십시오.jsonObject 해석에서 예외가 발생합니다.
여기서 우리는 대략 이 Result에 대해 어느 정도 알고 있다. 다음 코드는 Result에 속성을 추가했는데 주요 목적은 사용하기에 더욱 편리하다는 것이다.
/// Returns `true` if the result is a success, `false` otherwise.
public var isSuccess: Bool {
switch self {
case .success:
return true
case .failure:
return false
}
}
/// Returns `true` if the result is a failure, `false` otherwise.
public var isFailure: Bool {
return !isSuccess
}
/// Returns the associated value if the result is a success, `nil` otherwise.
public var value: Value? {
switch self {
case .success(let value):
return value
case .failure:
return nil
}
}
/// Returns the associated error value if the result is a failure, `nil` otherwise.
public var error: Error? {
switch self {
case .success:
return nil
case .failure(let error):
return error
}
}
물론 더 자세한 정보를 인쇄하기 위해 Result는 CustomStringConvertible와 CustomDebugStringConvertible 프로토콜을 실현했습니다.
// MARK: - CustomStringConvertible
extension Result: CustomStringConvertible {
/// The textual representation used when written to an output stream, which includes whether the result was a
/// success or failure.
public var description: String {
switch self {
case .success:
return "SUCCESS"
case .failure:
return "FAILURE"
}
}
}
// MARK: - CustomDebugStringConvertible
extension Result: CustomDebugStringConvertible {
/// The debug textual representation used when written to an output stream, which includes whether the result was a
/// success or failure in addition to the value or error.
public var debugDescription: String {
switch self {
case .success(let value):
return "SUCCESS: \(value)"
case .failure(let error):
return "FAILURE: \(error)"
}
}
}
전체적으로 말하자면, Result는 비교적 간단한 포장이다.
범용 기반 네트워크 봉인
실제 개발 과정에서 우리는 Alamofire를 사용하여 요청을 보내고 서버의 데이터를 얻으며 이를 2차 봉인한다. 여기서 봉인된 예를 설명하는데 내용은 프로토콜 프로그래밍과 코코아의 만남에서 나온다.
1. 우리는 하나의 협의가 필요하다. 이 협의는 함수를 제공하는데 그 목적은 Data를 이 협의를 실현하는 대상 자체로 바꾸는 것이다.우리가 이럴 때 이 대상의 유형을 모르므로 주의해야 한다. 더 많은 유형을 맞추기 위해 이 대상은 일시적으로 범형으로 설계되었기 때문에 프로토콜의 함수는 정적 함수이어야 한다.
protocol Decodable {
static func parse(data: Data) -> Self?
}
2. 봉인 요청은 협의의 방식으로 한다
public enum JZGHTTPMethod: String {
case options = "OPTIONS"
case get = "GET"
case head = "HEAD"
case post = "POST"
case put = "PUT"
case patch = "PATCH"
case delete = "DELETE"
case trace = "TRACE"
case connect = "CONNECT"
}
protocol Request {
var path: String { get }
var privateHost: String? { get }
var HTTPMethod: JZGHTTPMethod { get }
var timeoutInterval: TimeInterval { get }
var parameter: [String: Any]? { get }
associatedtype Response: Decodable
}
3. 송신단을 봉인하고 협의하는 방식으로
protocol Client {
var host: String { get }
func send(_ r: T, handler: @escaping (T.Response?, String?) -> Void);
}
4. 클라이언트 프로토콜의 대상이라면 요청을 보낼 수 있는 능력이 있습니다. 여기서 Alamofire는 중간 계층으로 존재하며 요청 능력만 제공하여 다른 중간 능력으로 임의로 바꿀 수 있습니다.
struct AlamofireClient: Client {
public static let `default` = { AlamofireClient() }()
public enum HostType: String {
case sandbox = "https://httpbin.org/post"
}
/// Base host URL
var host: String = HostType.sandbox.rawValue
func send(_ r: T, handler: @escaping (T.Response?, String?) -> Void) {
let url = URL(string: r.privateHost ?? host.appending(r.path))!
let sessionManager = Alamofire.SessionManager.default
sessionManager.session.configuration.timeoutIntervalForRequest = r.timeoutInterval
Alamofire.request(url, method: HTTPMethod(rawValue: r.HTTPMethod.rawValue)!,
parameters: r.parameter,
encoding: URLEncoding.default,
headers: nil)
.response { (response) in
if let data = response.data, let res = T.Response.parse(data: data) {
handler(res, nil)
}else {
handler(nil, response.error?.localizedDescription)
}
}
}
}
포장이 완료되면 위쪽 포장 기능을 사용해 보겠습니다.
1. TestRequest를 만듭니다.swift 파일, 내부 코드:
struct TestRequest: Request {
let name: String
let userId: String
var path: String {
return ""
}
var privateHost: String? {
return nil
}
var timeoutInterval: TimeInterval {
return 20.0
}
var HTTPMethod: JZGHTTPMethod {
return .post
}
var parameter: [String : Any]? {
return ["name" : name,
"userId" : userId]
}
typealias Response = TestResult
}
2. TestResult를 생성합니다.swift 파일, 내부 코드:
struct TestResult {
var origin: String
}
extension TestResult: Decodable {
static func parse(data: Data) -> TestResult? {
do {
let dic = try JSONSerialization.jsonObject(with: data, options: .allowFragments)
guard let dict = dic as? Dictionary else {
return nil
}
return TestResult(origin: dict["origin"] as! String)
}catch {
return nil
}
}
}
3. 요청 보내기
let request = TestRequest(name: "mama", userId: "12345");
AlamofireClient.default.send(request) { (response, error) in
print(response)
}
네트워크에 대한 기본적인 봉인은 여기까지입니다. 여기의Result는 모든 종류의 대상이 될 수 있습니다. 예를 들어 User는 위의 방법을 통해 User 대상으로 직접 해석할 수 있습니다.
일반 기반 셀링 봉인
이러한 설계는 일반적으로 MVVM에 적용됩니다. 다음 코드를 살펴보겠습니다. 1.프로토콜을 정의합니다. 이 프로토콜은 함수를 제공합니다. 함수는 파라미터를 제공합니다. 이 파라미터가viewModel입니다.cell은 이 프로토콜을 실현하기만 하면 이 매개 변수를 통해viewModel을 가져와viewModel에 따라 자신의 컨트롤 속성을 설정할 수 있습니다.
protocol Updatable: class {
associatedtype ViewData
func update(viewData: ViewData)
}
2. 프로토콜을 다시 정의한다. 이 프로토콜은cell의 일부 정보를 표시해야 한다. 예를 들어reuseIdentifier,cellClass이다. 이 프로토콜은cell 어댑터가cell을 업데이트하는 능력을 부여하는 방법을 제공해야 한다.
protocol CellConfiguratorType {
var reuseIdentifier: String { get }
var cellClass: AnyClass { get }
func update(cell: UITableViewCell)
}
3. Cell Configurator를 만듭니다. 이 Cell Configurator는view Data를 연결해야 합니다. 이view Data는 Updatable 프로토콜의 방법으로cell에 전달됩니다.
struct CellConfigurator where Cell: Updatable, Cell: UITableViewCell {
let viewData: Cell.ViewData
let reuseIdentifier: String = NSStringFromClass(Cell.self)
let cellClass: AnyClass = Cell.self
func update(cell: UITableViewCell) {
if let cell = cell as? Cell {
cell.update(viewData: viewData)
}
}
}
|
절대로 그 근본을 벗어나지 않는다. 우리가 데이터를 요청한 후에 데이터를Cell Configurator로 바꿔야 한다. 즉, 그룹에 저장된 것이Cell Configurator 형식의 데이터이다.
사용 예를 보십시오.
(1) 배열 만들기
let viewController = ConfigurableTableViewController(items: [
CellConfigurator(viewData: TextCellViewData(title: "Foo")),
CellConfigurator(viewData: ImageCellViewData(image: UIImage(named: "og")!)),
CellConfigurator(viewData: ImageCellViewData(image: UIImage(named: "GoogleLogo")!)),
CellConfigurator(viewData: TextCellViewData(title: "Bar")),
])
2.cell 등록
func registerCells() {
for cellConfigurator in items {
tableView.register(cellConfigurator.cellClass, forCellReuseIdentifier: cellConfigurator.reuseIdentifier)
}
}
3. cell 구성
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellConfigurator = items[(indexPath as NSIndexPath).row]
let cell = tableView.dequeueReusableCell(withIdentifier: cellConfigurator.reuseIdentifier, for: indexPath)
cellConfigurator.update(cell: cell)
return cell
}
이cell 포장 사상은 여기서 나온 거예요.https://github.com/fastred/ConfigurableTableViewController
총결산
지식 수준에 한계가 있기 때문에, 잘못이 있으면 지적해 주시기 바랍니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.