Created
November 4, 2016 07:28
-
-
Save wangdu1005/b8eb9c20378e2457eba40751776cef0b to your computer and use it in GitHub Desktop.
the error of "failed to obtain a cell from its dataSource "
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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