Xử lý response trong swift
swift
57
White

VietHQ viết ngày 20/03/2019

Bài toán

Khi nhận response từ server, chúng ta thường thấy json có điểm chung như sau

struct Response {
    let timestamp: String
    let id: Int
    let payload: Any
}

timestampid là những trường mặc định luôn được trả về, chúng có type cố định. Còn type của payload lại phụ thuộc vào api bạn call, thế nên mình đang để dưới dạng Any.

Tuy nhiên sử dụng type Any có nhiều hạn chế: chúng ta phải biết chính xác nó-là-gì để ép kiểu trước khi sử dụng.

Vì vậy chúng ta cần nghĩ ra các phương án khác thay thế Any.

Sử dụng Generic và protocol

Trước hết tách những trường mặc định ra 1 struct riêng

struct ResponseInfo {
    let timestamp: String
    let error: Error?
}

Định nghĩa thêm protocol ResponseType để tiện mở rộng cho payload về sau.
Tùy chỉnh lại code cũ một chút, ta có được hình hài mới cho Response:

protocol ResponseType {}

struct Response<T: ResponseType> {
    let info: ResponseInfo
    let payload: T
}

Như vậy ứng với dữ liệu trả về khác nhau, ta có thể viết như sau

let bookResponse = Response(info: info, payload: book)
let userResponse = Response(info: info, payload: user)
//...

Dùng generic khi gọi đến property payload ta không phải ép kiểu nữa.

bookResponse.payload // Book
userResponse.payload // User

Gán thêm phương thức vào Response

Bây giờ mình muốn thêm phương thức vào trong response để tiện debug, ứng với mỗi response ta có thêm description.

VD:

Với payload là User tương ứng với description "response" + User.description
với payload là Book tương ứng với description "response" + Book.description

Muốn như vậy ta phải implement như sau

protocol ResponseType: CustomDebugStringConvertible {}

struct User: ResponseType {
    var debugDescription: String {
        return "{username: \(username), age: \(age)}"
    }

    // ...
}

extension Response: CustomDebugStringConvertible {
    var debugDescription: String {
        return "response: \(self.payload.debugDescription)"
    }
}

// ...

Đoạn code trên cũng khá đơn giản, mình tận dụng lại CustomDebugStringConvertible có sẵn để thêm description cho Response và cả payload.

Việc gán protocol ResponseType cho payload đảm bảo tất cả đối tượng implement lại protocol này đều phải thêm thuộc tính debugDescription.

Nếu ta muốn thêm phương thức khác vào trong payload, đơn giản chỉ cần tạo protocol mới và cho ResponseType kế thừa

protocol ResponseType: CustomDebugStringConvertible, Jsonable,... {}

Tuy nhiên giờ mình muốn quản lý tất cả payload ở một chỗ. Lúc này Enum phát huy tác dụng.

Sử dụng Enum

Ta tạo enum chứa tất cả các type của payload. Lúc này Response cũng sẽ chỉnh sửa lại chút, gán enum type cho payload thay vì generic

enum ResponsePayload {
    case userDetail(User)
    case bookDetail(Book)
    // ...
}

struct Response {
    let info: ResponseInfo
    let payload : ResponsePayload
}

let newUser = Response(info: info, payload: .userDetail(user))

Lúc này muốn sử dụng payload, ta cần thêm một công đoạn nữa, chứ không gọi trực tiếp như sử dụng generic.

if case .userDetail(_) = newUser.payload {
    // use payload
} else {
    fatalError()
}

Muốn gán thêm phương thức mới cho payload cũng làm tương tự như đối với sử dụng generic

Tổng kết

  • Sử dụng generic code gọn hơn sử dụng enum, tuy nhiên nhược điểm là phân tán, khó tập trung vào 1 chỗ để quản lý.

  • Sử dụng enum code dài hơn chút, nhưng ta gom được tất cả vào 1 chỗ, dễ quản lý hơn.

Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

VietHQ

17 bài viết.
8 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
White
7 1
Giới thiệu Callback là kĩ thuật được ưa chuộng trong lập trình hiện nay. Ngặt nỗi, nếu sử dụng không khéo rất dễ xảy ra callback hell. Dưới con mắ...
VietHQ viết 2 năm trước
7 1
White
5 1
Thời gian đầu làm việc với objc mình khá băn khoăn trong việc sử dụng các thuộc tính trong property như strong, weak, copy, assign. Nhân lúc rảnh r...
VietHQ viết hơn 5 năm trước
5 1
White
5 0
1. Giới thiệu Từ hồi mới bắt đầu làm IOS, thằng nào cũng hỏi mình có biết sử dụng AFNetworking không? Khổ nỗi lúc đó, mình mới chuyển từ làm game ...
VietHQ viết hơn 3 năm trước
5 0
Bài viết liên quan
White
14 4
(Link) (Link) (Link) Ở 2 phần tut trước, mình đã hướng dẫn khá chi tiết cách viết một ứng dụng camera có tích hợp chức năng nhận diện khuôn mặ...
HoangPH viết hơn 5 năm trước
14 4
White
2 0
Có nhiều cách viết blog công nghệ hơn là làm bánh hay làm tình. Những ngày này Hà Nội mưa liên miên, được cái mát giời, mình lại tức cảnh sinh tìn...
VietHQ viết 3 năm trước
2 0
White
0 0
Swift là ngôn ngữ do Apple tạo ra và nhận được sử ủng hộ lớn từ cộng đồng. Nhất là từ khi nó opensource. Bản thân ngôn ngữ vẫn đang ngày một hoàn t...
VietHQ viết gần 2 năm trước
0 0
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
17 bài viết.
8 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!