Some tips below help me work faster and more efficiently. Let's check it out.
1. Don't depend on server API.
APIs are immensely important and we can't do anything without APIs. So can we watch Youtube or Facebook while backend teams are burying their noses in code?
You will get a red alert from your manager soon.
Or APIs are slow and hard for us to test while developing it. What should we do?
Don't depend on server API. Just depend on the schemas.
- Ask backend for API schemas, which they send to us when we call. Save it into a json file.
- Use tip #2 or #3 to create your data model.
- Setup your code as you're calling API. I usually seperate API calls to workers. You can do your way.
class GetUserDetailWorker {
// (1)
func run(completion: @escaping(User?, Error?) -> Void) {
Alamofire.request() {
handleResponse(response: AnyObject, completion: completion)
}
}
// (2)
private func handleResponse(response: AnyObject?, completion: @escaping(User?, Error?) -> Void) {
// parse json to your data model
// check logic
// ...
// call completion
}
}
(1): Your controllers don't know what is inside the GetUserDetailWorker
. They respond to success or failure from the worker. So, you are free to fake any data here and see how your controllers respond to.
(2): This is where you parse raw json to your data model, handle the logic and response.
Now do a trick.
Add function after your handleResponse
function.
func loadLocally(completion: @escaping(User?, Error?) -> Void) {
if let filepath = Bundle.main.path(forResource: "User", ofType: "json") {
do {
let contents = try String(contentsOfFile: filepath)
let data = contents.data(using: .utf8)!
if let json = try JSONSerialization.jsonObject(with: data, options : .allowFragments) as AnyObject? {
handleResponse(response: json, completion: completion)
} else {
print("bad json")
}
} catch {
completion(nil, error)
}
}
}
Add this at the begining of run
function.
loadLocally(completion: completion)
return
We load the user.json
and send it to controllers. It's on your computer, we can change any data as we want. When APIs are ready, just remove these 2 lines and work like a charm.
Some advantages
- Fast. You call it from your computer, no delay or depend on internet.
- Convenient. You can change any data you want, good cases, bad cases and change your UI approriately.
- Independent. You don't depend on server progress anymore.
2. Create init function
When you define struct
, Swift can give you an init
function, you don't have to write it yourself. But if you use class
, no free init
. What if you have a long class and long init
, like below.
class User {
var id: String
var tasks: [String]
var email: String?
var membershipExpirationDate: Date?
var startDate: Date?
var cancelAtPeriodEnd: Bool?
var balance: Int
let phoneNumber: String?
let currency: String
init(id: String, tasks: [String], email: String?, membershipExpirationDate: Date?, startDate: Date?, cancelAtPeriodEnd: Bool?, balance: Int, phoneNumber: String?, currency: String) {
self.id = id
self.tasks = tasks
self.email = email
self.membershipExpirationDate = membershipExpirationDate
self.startDate = startDate
self.cancelAtPeriodEnd = cancelAtPeriodEnd
self.balance = balance
self.phoneNumber = phoneNumber
self.currency = currency
}
}
Do you want to type it yourself? Try this way.
Notes
- Press
option
and drag to select multiline. - Delete unused words.
- Copy properties' name.
- Press
esc
to quit multi cursors.
3. Parse JSON result
I am not a fan of Codable
. It's really useful in simple responses, but complicated ones, no thanks. And it's hard to debug also.
Most of work, I parse JSON manually, don't use SwiftyJSON
or similar ones. One time, I joined a team with complicated responses. Example is below.
{
"Id": "b206bb24-03ab-4a25-a9c4-b26e2fd2e9f8",
"Name": "Hexagon 21",
"ScreenName": null,
"Picture": "https://scontent.xx.fbcdn.net/v/t1.0-9/20245457_303012200102286_1324449236613079430_n.jpg?_nc_cat=104&_nc_oc=AQmRtf3n0fmK36Z8Vnzz5QFECni4m52YHbm0GbzdSEI6slVpgf59oGBHZCeOBv3yzGc&_nc_ht=scontent.xx&oh=24ebc12ea4244757e584f7f438e06e44&oe=5E613D7C",
"ExternalId": "575475522634796",
"FacebookUserId": null,
"Account": null,
"Type": 1,
"Subtype": "FacebookGroup",
"IsDefault": false,
"Credential": null,
"AssociatedSource": null,
"PublishMessageProfiles": null,
"ProfileSubscribeNotifications": null,
"Selected": false,
"HasAppInstalled": null,
"IsWebHookSubscribed": false,
"IsTwitterWebHookSubscribed": null
}
Now, making a class from these is a boring work.
- Use this: https://app.quicktype.io/.
- Explore options on the right pane to see it changes. And here the result:
class User {
var id: String?
var name: String?
var screenName: NSNull?
var picture: String?
var externalID: String?
var facebookUserID: NSNull?
var account: NSNull?
var type: Int?
var subtype: String?
var isDefault: Bool?
var credential: NSNull?
var associatedSource: NSNull?
var publishMessageProfiles: NSNull?
var profileSubscribeNotifications: NSNull?
var selected: Bool?
var hasAppInstalled: NSNull?
var isWebHookSubscribed: Bool?
var isTwitterWebHookSubscribed: NSNull?
init(id: String?, name: String?, screenName: NSNull?, picture: String?, externalID: String?, facebookUserID: NSNull?, account: NSNull?, type: Int?, subtype: String?, isDefault: Bool?, credential: NSNull?, associatedSource: NSNull?, publishMessageProfiles: NSNull?, profileSubscribeNotifications: NSNull?, selected: Bool?, hasAppInstalled: NSNull?, isWebHookSubscribed: Bool?, isTwitterWebHookSubscribed: NSNull?) {
self.id = id
self.name = name
self.screenName = screenName
self.picture = picture
self.externalID = externalID
self.facebookUserID = facebookUserID
self.account = account
self.type = type
self.subtype = subtype
self.isDefault = isDefault
self.credential = credential
self.associatedSource = associatedSource
self.publishMessageProfiles = publishMessageProfiles
self.profileSubscribeNotifications = profileSubscribeNotifications
self.selected = selected
self.hasAppInstalled = hasAppInstalled
self.isWebHookSubscribed = isWebHookSubscribed
self.isTwitterWebHookSubscribed = isTwitterWebHookSubscribed
}
}
Pretty cool, right?
Conclusion
Some tips from my experience. Hope them help you work faster and more interesting your work.
Enjoy coding
Top comments (0)