Skip to content

Instantly share code, notes, and snippets.

@wangdu1005
Created November 4, 2016 07:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wangdu1005/b8eb9c20378e2457eba40751776cef0b to your computer and use it in GitHub Desktop.
Save wangdu1005/b8eb9c20378e2457eba40751776cef0b to your computer and use it in GitHub Desktop.
the error of "failed to obtain a cell from its dataSource "
import UIKit
import Alamofire
class OrderListTableViewController: UITableViewController {
var orderNameList = ["jack", "ken", "howard"]
var orderLandlordNameList = ["ord1", "ord2", "ord3"]
var orderDurationList = ["1~2", "3~4", "5~6"]
var orderStatusList = ["new", "old", "change"]
var result = " "
var orderListHeaderView: OrderListHeaderView!
var orderUnconfirmHeaderView: OrderUnconfirmHeaderView!
// var orderResult: AnyObject!
var orderResult: [[String:AnyObject]]?
var orderType: String!
var hostId : String? = nil
var hostSecret : String? = nil
var hostEmail : String = ""
var LID : String? = nil
var orderToken = " "
var orderAmount : Int = 0
override func viewDidLoad() {
super.viewDidLoad()
// Config the table view style
tableView.allowsSelection = false
tableView.separatorStyle = .none
// Start spinner
ActivityIndicatorHelper.shared.showActivityIndicator(view: self.view)
print("type: \(self.orderType)")
// Display Dynamic Navigation Title
// self.navigationItem.title = self.orderType
if (UserDefaults.standard.value(forKey: "hostId") as! String?) != nil{
self.hostId = UserDefaults.standard.value(forKey: "hostId") as? String
}
if (UserDefaults.standard.value(forKey: "hostSecret") as! String?) != nil{
self.hostSecret = UserDefaults.standard.value(forKey: "hostSecret") as? String
}
if (UserDefaults.standard.value(forKey: "hostEmail") as! String?) != nil{
self.hostEmail = (UserDefaults.standard.value(forKey: "hostEmail") as? String)!
}
if (UserDefaults.standard.value(forKey: "genericAccessToken") as! String?) != nil{
self.orderToken = (UserDefaults.standard.value(forKey: "genericAccessToken") as! String?)!
} else {
self.orderToken = " "
}
print("test orderToken: \(self.orderToken)")
print("test!! host id id id mode: \(self.hostId)")
var appRefreshToken : String? = nil
if (UserDefaults.standard.value(forKey:"appRefreshToken") as! String?) != nil{
appRefreshToken = UserDefaults.standard.value(forKey:"appRefreshToken") as? String
}
/* NOTE:
1.If the genericAccessToken in the userDefault, and it is not expired, then there is no
need to request a new access token by refresh token, because refresh token is One Time Token
it will be delete after request new access token
2.If genericAccessToken is expired then request a new access token if login clientSecret token is alive.
Token check result:
1 == Token expired
2 == Token still alive
3 == No data in access_token table
4 == Check fail, type is null
*/
let tokenCheck = TokenManager(hostID: self.hostId!)
tokenCheck.isTokenExpried(token: self.orderToken, type: "access") { result, error in
switch result! {
case 1: // token expired, if clientSecret token is alive, then request new genericAccessToken and it's new refresh token
print(" access token expired checkresult = \(result); error = \(error)")
tokenCheck.isTokenExpried(token: self.hostSecret!, type: "refresh") { result, error in
if(result == 2){ // hostSecret token is alive
tokenCheck.isTokenExpried(token: appRefreshToken!, type: "refresh") { result, error in
switch result! {
case 2: // refresh token alive
print("STAGE3-1 appRefreshToken checkresult = \(result); error = \(error)")
let tokenManager = TokenManager(hostID: self.hostId!)
// Get the genericAccessToken to save to userDefault
tokenManager.getAccessToken(byRefreshToken: (appRefreshToken! as AnyObject) as! String, hostSecret: (self.hostSecret! as AnyObject) as! String, scope: "scope_get"){ responseObject, error in
print("responseObject genericAccessToken!!!!! = \(responseObject); error = \(error)")
self.orderToken = responseObject!
self.getOrderListByAccessToken(token: self.orderToken, startVal: "", endVal: "", bnbSelect: 0, sortTypeVal: "", orderNum: "")
}
default:
// IMPORTANT NOTE!!!:
// result 1 (expired) and 3 (token not on DB) are not possiable, because every time access token expired, app will
// request a new access token and new refresh token if login clientSecret token is alive
print("result 1 (expired) and 3 (token not on DB) are not possiable")
print("appRefreshToken checkresult!!!! = \(result); error = \(error)")
}
}
} else {
// hostSecret is belong to refresh token, user will be log out if hostSecret is not alive, regardless of other status
// Logout action request to API remove data on DB
let tokenWorks = TokenManager(hostEmail: self.hostEmail)
tokenWorks.removeAllKeyDataTokens()
// Display alert message with confirmation
let myAlert = UIAlertController(title: "貼心提醒", message: "主人您的自動登入權限已到期,請重新登入,謝謝!", preferredStyle: UIAlertControllerStyle.alert);
print("print view stacks \(self.navigationController?.viewControllers)")
// Go to login view
let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.default){ action in
let sb = UIStoryboard(name: "Main", bundle:nil)
let initView = sb.instantiateViewController(withIdentifier: "ViewController") as! ViewController
let loginView = sb.instantiateViewController(withIdentifier: "LoginViewController") as! LoginViewController
let newVC : [UIViewController] = [initView, loginView]
self.navigationController?.viewControllers = newVC
print("new print view stacks \(self.navigationController?.viewControllers)")
_ = self.navigationController?.popToViewController(self.navigationController!.viewControllers[1], animated: true)
}
myAlert.addAction(okAction);
self.present(myAlert, animated: true, completion: nil);
}
}
case 2: // token still alive
print(" access token still alive checkresult = \(result); error = \(error)")
self.getOrderListByAccessToken(token: self.orderToken, startVal: "", endVal: "", bnbSelect: 0, sortTypeVal: "", orderNum: "")
default:
print(" access token checkresult = \(result); error = \(error)")
}
}
print("test!! appRefreshToken mode: \(appRefreshToken)")
if(self.orderType != "unconfirm"){
self.orderListHeaderView = Bundle.main.loadNibNamed("OrderListHeaderView", owner: self, options: nil)![0] as! OrderListHeaderView
tableView.tableHeaderView = orderListHeaderView
} else {
self.orderUnconfirmHeaderView = Bundle.main.loadNibNamed("OrderUnconfirmHeaderView", owner: self, options: nil)![0] as! OrderUnconfirmHeaderView
tableView.tableHeaderView = orderUnconfirmHeaderView
}
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
// print("view contriller stacks:::: \(self.navigationController!.viewControllers)")
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
// TODO: orderToken must check is expired or not, if it is expired and login token is not expired, then renew a new order token to it.
self.getOrderListByAccessToken(token: self.orderToken, startVal: "", endVal: "", bnbSelect: 0, sortTypeVal: "", orderNum: "")
}
@IBAction func searchBarTapped(sender: AnyObject) {
print("Click the search tap")
self.performSegue(withIdentifier: "searchView", sender: nil)
}
// NOTE: Passing data by button in the cell is a very important skill
@IBAction func orderDetailButtonTapped(sender: AnyObject) {
// For a button press
let button = sender as! UIButton
let indexPath = self.tableView.indexPathForView(view: button)!
let ordNumber = self.orderResult![indexPath.row]["ordID"] as? String
let ordArr : [String] = [ordNumber!, self.orderType]
print("Click the order detail view indexPath: \(ordArr)")
if(self.orderType == "unconfirm"){
self.performSegue(withIdentifier: "unconfirmDetailView", sender: ordArr)
} else {
self.performSegue(withIdentifier: "orderDetailView", sender: ordArr)
}
}
func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let identifier = segue.identifier {
switch identifier {
case "searchView":
if let vc = segue.destination as? OrderSearchViewController {
vc.orderListTableViewController = self
print(" order type!!!!!!!: \(self.orderType) ")
vc.orderTitle = self.orderType!
}
case "orderDetailView":
if let vc = segue.destination as? OrderDetailTableViewController {
vc.ordArr = sender as? Array
}
case "unconfirmDetailView":
if let vc = segue.destination as? OrderUnconfirmDetailViewController{
vc.ordArr = sender as? Array
}
default: break
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
guard var orderCount = self.orderResult?.count else {
return 0
}
if(orderCount == 0){
orderCount = 1
}
print("orderResult count! : \(self.orderResult?.count)")
print("orderCount! : \(orderCount)")
return orderCount
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
print("test indexPath::: \(indexPath)")
if self.orderResult?.count == 0 {
let cellIdentifier = "Cell2"
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath as IndexPath) as! OrderListTableViewCell
cell.noOrderRemind?.text = "無任何訂單可查看\n建議設定其他篩選條件以利查詢"
return cell
} else {
let cellIdentifier = "Cell"
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath as IndexPath) as! OrderListTableViewCell
print("i need to bebug::: \(orderResult?[indexPath.row])")
let orderResultRow = orderResult?[indexPath.row]
if let checkInStartDate = orderResultRow?["ordSDate"] as? String, let checkInEndDate = orderResultRow?["ordEDate"] as? String{
let checkDuration = "入住期間: " + "\(checkInStartDate) ~ \(checkInEndDate)"
// Configure the cell...
cell.nameLabel?.text = orderResultRow?["ordUName"] as? String
cell.landlordName?.text = orderResultRow?["ordRoomType"] as? String
cell.checkInDuration?.text = checkDuration
cell.orderStatus?.text = ""
}
return cell
}
}
func completeSearchView(data: [String: AnyObject?]) {
print(data["orderTypeBack"] as Any)
print(data["startVal"] as Any)
print(data["endVal"] as Any)
print(data["bnbSelectVal"] as Any)
print(data["sortTypeVal"] as Any)
print(data["orderNumber"] as Any)
// var orderTypeBack = data["orderTypeBack"] as? String
let startVal = data["startVal"] as? String
let endVal = data["endVal"] as? String
let bnbSelectVal = data["bnbSelectVal"] as? Int
let sortTypeVal = data["sortTypeVal"] as? String
let orderNumber = data["orderNumber"] as? String
self.orderType = data["orderTypeBack"] as? String
self.getOrderListByAccessToken(token: self.orderToken, startVal: startVal!, endVal: endVal!, bnbSelect: bnbSelectVal!, sortTypeVal: sortTypeVal!, orderNum: orderNumber!)
}
func getOrderListByAccessToken(token: String, startVal: String, endVal: String, bnbSelect: Int, sortTypeVal: String, orderNum: String){
let orderToken = token
let urlComponents = NSURLComponents(string: "\(Constants.API.URL)/oauth2/orders_list")!
let searchType : Int
let ordStatus : Int
let startVal : String = startVal
let endVal : String = endVal
let bnbSelect : Int = bnbSelect
let sortTypeVal : String = sortTypeVal
let orderNum : String = orderNum
var lang : String
switch self.orderType {
case "paid" :
// Checked No problem
searchType = 2
ordStatus = 1
lang = "cn"
case "unpay" :
// Checked No problem
searchType = 2
ordStatus = 3
lang = "cn"
case "cancel" :
// Checked No problem
searchType = 2
ordStatus = 2
lang = "cn"
case "reject" :
// Checked No problem, but when start and end has value still need to check the sql is right or not
searchType = 2
ordStatus = 4
lang = "cn"
case "unconfirm" :
//
searchType = 2
ordStatus = 5
lang = "cn"
default:
searchType = 2
ordStatus = 0
lang = "cn"
}
print("searchType: \(searchType)")
print("ordStatus: \(ordStatus)")
print("startVal: \(startVal)")
print("endVal: \(endVal)")
urlComponents.queryItems = [
NSURLQueryItem(name: "searchType", value: String(searchType)) as URLQueryItem,
NSURLQueryItem(name: "ordStatus", value: String(ordStatus)) as URLQueryItem,
NSURLQueryItem(name: "startVal", value: String(startVal)) as URLQueryItem,
NSURLQueryItem(name: "endVal", value: String(endVal)) as URLQueryItem,
NSURLQueryItem(name: "bnbSelect", value: String(bnbSelect)) as URLQueryItem,
NSURLQueryItem(name: "sortTypeVal", value: String(sortTypeVal)) as URLQueryItem,
NSURLQueryItem(name: "orderNum", value: String(orderNum)) as URLQueryItem,
NSURLQueryItem(name: "lang", value: String(lang)) as URLQueryItem
]
let URL = urlComponents.url
var mutableURLRequest = URLRequest(url: URL!)
mutableURLRequest.httpMethod = "GET"
mutableURLRequest.setValue("Bearer \(orderToken)", forHTTPHeaderField: "Authorization")
Alamofire.request(mutableURLRequest).responseJSON{ response in
switch response.result {
case .success(let data):
let json = data
print("debug json!!!!! \(json)")
DispatchQueue.main.async(execute: {
let orderInfoJSON = (json as AnyObject).object(forKey: "ordInfo")
print(" json info order count: \((orderInfoJSON! as AnyObject).count)")
self.orderAmount = (orderInfoJSON! as AnyObject).count
if(self.orderType != "unconfirm"){
self.orderListHeaderView.orderAmount.text = "訂單數量: \(self.orderAmount)"
} else {
self.orderUnconfirmHeaderView.orderAmount.text = "訂單數量: \(self.orderAmount)"
}
// print("debug!!!!! \(orderInfoJSON)")
self.orderResult = orderInfoJSON as? [[String:AnyObject]]
// stop spinner when download is done
ActivityIndicatorHelper.shared.hideActivityIndicatorView()
self.tableView.reloadData()
})
case .failure(let error):
print("wangdu test faile alert message: \(error)")
Helper.displayAlertMessage(hostMessage: "無法獲得訂單資料,\n請檢查是否網路連線正常!", targetClass: self)
}
}
}
}
// MARK: - UITableView
extension UITableView {
func indexPathForView (view : UIView) -> NSIndexPath? {
let location = view.convert(CGPoint.zero, to:self)
return indexPathForRow(at: location) as NSIndexPath?
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment