Introducing LFRestTableController and LArrayClient
As I mentioned in a previous post and another blog of mine, it’s a common case for us to load table views
from URL calls. 2 classes have been created to help us deal with this kind of scenarios. Please note that although something brand new will be discussed, you can always use LRestClient
in the old way, with some bugs fixed.
Firstly a new class LArrayClient
is created based on LRestClient
. It’s generic, strong typed, and has an items:[T:LFModel]
property that holds all the objects stored. It confirms to protocol LTableClient
so that table view controllers can use it while the controllers being non-generic (due to the technical limitation we have). I’ll explain how to use it in detail.
In my current app, we have a “last ID” based pagination system, in which the app adds a “last ID” property to tell the URL it wants to load the next 20 items after “last ID”. The most common pagination system is skip/count based, and it will be implemented later. The following code creates a base class for the app with cache and toast support.
class ICArrayClient<T: ICModel>: LArrayClient<T> {
override init(api url: String, parameters param: LTDictStrObj? = nil) {
super.init(api: url, parameters: param)
root = IC.api.root
cache_policy = .CacheThenNetwork
pagination_method = .LastID
pagination_key = "last_loaded_id"
}
override func text_show() {
IC.show_text(self.text!, duration:nil)
}
override func text_hide() {
let window = UIApplication.sharedApplication().delegate!.window!
MBProgressHUD.hideAllHUDsForView(window!, animated:true)
}
}
In my previous post, I mentioned that I preferred to put all client calls together. While we can still do that, I’m trying a new practise like this:
class ICMessageListClient<T:LFModel>: ICArrayClient<T> {
init() {
let api = String(format:IC.api.message_list, IC.complaint!.id)
super.init(api: api)
}
}
Which, obviously, loads messages from an API. As the last step would be calling them in the UI code, here comes the LFRestTableController
:
class ICDetailController: LFRestTableController {
override func awakeFromNib() {
super.awakeFromNib()
pull_down = .Reload
pull_up = .More
reload_table = .Always
let c = ICMessageListClient<ICMessageModel>()
c.func_reload = {
(messages) -> Void in
self.reload_message_table(messages)
}
client = c
}
// ...
}
Here we tell the table view controller to always reload the contents while viewWillAppear
, and enable the “pull down to reload” / “pull up to load more” stuff. Then we create a client, set up the callback function func_reload
to do the table.reloadData()
things. I really hate the last client = c
line, which assign the client as LFTableClient
, but I explained why it has to be there and this is the least ugly approach I found. I wish I could just writing client = ICMessageListClient<ICMessageModel>()
but unfortunately I don’t know how to get that work.
Anyway, now all the reloading / pagination part has been done, and all you need to do is implement your reoad_message_table
function with a native object array, and hopefully you’ll be able to write elegant code in this way, which is the intention for me to make LRestClient
.
PS: To enable any pull-up related actions, I’m using a pod called CCBottomRefreshControl
. Without that installed the function does not work.
Tags: