My app runs fine on the local environment, When I publish it to the appStore, The problem happened:
Crashed: com.apple.main-thread
EXC_BAD_ACCESS KERN_INVALID_ADDRESS at 0x0000000130d0bec8
The crash infomation is coming from Crashlytics
TradeInputViewController.swift line 96 function signature specialization of ECExpert.TradeInputViewController.commitAddRecord (ECExpert.TradeInputViewController)() -> ()
My Code is:
**//
// TradeInputViewController.swift
// ECExpert
//
// Created by Fran on 15/6/26.
// Copyright (c) 2015年 Fran. All rights reserved.
//
import UIKit
class TradeInputViewController: BasicViewController, UITableViewDelegate, UITableViewDataSource {
static let CellIdentifier = "cellIdentifier"
static let DeleteButtonTag = 101
private var tableView: UITableView!
private var manager = AFNetworkingFactory.networkingManager()
private var customerArray = NSMutableArray()
private var productArray = NSMutableArray()
private var giftArray = NSMutableArray()
private var dateTypeString = "yyyy-MM-dd"
private var dateFormatter = NSDateFormatter()
override func viewDidLoad() {
super.viewDidLoad()
self.needLogin = true
dateFormatter.dateFormat = dateTypeString
self.title = i18n("Input transactions")
setUpView()
self.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Save, target: self, action: "saveRecord:")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func saveRecord(sender: AnyObject!){
if productArray.count > 0 && customerArray.count > 0{
let alertView = UIAlertView(title: "", message: i18n("Determine the input information?"), delegate: nil, cancelButtonTitle: i18n("Cancel"), otherButtonTitles: i18n("Sure"))
alertView.showAlertViewWithCompleteBlock({[unowned self] (buttonIndex) -> Void in
if buttonIndex == 1{
self.commitAddRecord()
}
})
}else{
let alertView = UIAlertView(title: nil, message: i18n("The input information is insufficient, unable to complete the transaction."), delegate: nil, cancelButtonTitle: i18n("Cancel"))
alertView.show()
}
}
func commitAddRecord(){
let params = NSMutableDictionary()
params.setObject((customerArray.firstObject as! NSDictionary).objectForKey("customer_id")!, forKey: "customer_id")
params.setObject(currentAppDelegate().loginUserInfo!["dealer_id"]!, forKey: "dealer_id")
let tradeProducts = NSMutableArray()
for item in productArray{
let product = item as! ProductModel
let dic = NSMutableDictionary()
dic["scanCode"] = product.scanCode
dic["totalCount"] = product.totalCount
tradeProducts.addObject(dic)
}
let productJsonData = NSJSONSerialization.dataWithJSONObject(tradeProducts, options: NSJSONWritingOptions.PrettyPrinted, error: nil)
if productJsonData != nil{
let productJson = NSString(data: productJsonData!, encoding: NSUTF8StringEncoding)
params["main_products"] = productJson
}
let tradeGifts = NSMutableArray()
for item in giftArray{
let gift = item as! ProductModel
let dic = NSMutableDictionary()
dic["scanCode"] = gift.scanCode
dic["totalCount"] = gift.totalCount
tradeGifts.addObject(dic)
}
let giftJsonData = NSJSONSerialization.dataWithJSONObject(tradeGifts, options: NSJSONWritingOptions.PrettyPrinted, error: nil)
if giftJsonData != nil{
let giftJson = NSString(data: giftJsonData!, encoding: NSUTF8StringEncoding)
params["gift_products"] = giftJson
}
self.progressHUD?.mode = MBProgressHUDMode.Indeterminate
self.progressHUD?.labelText = ""
self.progressHUD?.detailsLabelText = ""
self.progressHUD?.show(true)
manager.POST(APP_URL_TRADE_INPUT, parameters: params, success: {[unowned self] (operation: AFHTTPRequestOperation!, responseObj: AnyObject!) -> Void in
let dic = responseObj as? NSDictionary
let code = dic?["code"] as? NSInteger
if code != nil && code == 1{
self.progressHUD?.mode = MBProgressHUDMode.Text
self.progressHUD?.detailsLabelText = dic!["data"] as! String
self.progressHUD?.minShowTime = 2
self.progressHUD?.showAnimated(true, whileExecutingBlock: { () -> Void in
}, completionBlock: { () -> Void in
self.navigationController?.popViewControllerAnimated(true)
})
}else if code != nil && code == 0{
self.progressHUD?.mode = MBProgressHUDMode.Text
self.progressHUD?.detailsLabelText = dic!["data"] as! String
self.hideProgressHUD(2)
}else{
KMLog("\(dic)")
self.hideProgressHUD()
}
}) {[unowned self] (operation: AFHTTPRequestOperation!, error: NSError!) -> Void in
self.progressHUD?.mode = MBProgressHUDMode.Text
self.progressHUD?.labelText = i18n("Failed to connect link to server!")
self.progressHUD?.detailsLabelText = error.localizedDescription
self.hideProgressHUD(2)
}
}
func setUpView(){
tableView = UITableView(frame: getVisibleFrame())
tableView.delegate = self
tableView.dataSource = self
tableView.backgroundColor = RGBA(0, 0, 0, 0.3)
tableView.tableFooterView = UIView(frame: CGRectZero)
self.view.addSubview(tableView)
}
override func goback() {
let alertView = UIAlertView(title: i18n("Give up the change?"), message: i18n("Give up modifying data?"), delegate: nil, cancelButtonTitle: i18n("Sure"), otherButtonTitles: i18n("Cancel"))
alertView.showAlertViewWithCompleteBlock {(buttonIndex) -> Void in
if buttonIndex == 0{
super.goback()
}
}
}
// MARK: - UITableViewDelegate
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let section = indexPath.section
let row = indexPath.row
if section == 1{
let detailVC = ProductDetailViewController(product: productArray.objectAtIndex(row) as! ProductModel, productArray: productArray, fromTableView: tableView, pageDataType: ProductDetailPageDataType.Main, pageEditType: ProductDetailPageEditType.All)
self.navigationController?.pushViewController(detailVC, animated: true)
}else if section == 2{
let detailVC = ProductDetailViewController(product: giftArray.objectAtIndex(row) as! ProductModel, productArray: giftArray, fromTableView: tableView, pageDataType: ProductDetailPageDataType.Gift, pageEditType: ProductDetailPageEditType.All)
self.navigationController?.pushViewController(detailVC, animated: true)
}
}
func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let view = UIView(frame: CGRectZero)
view.backgroundColor = UIColor.lightGrayColor()
let height = self.tableView(tableView, heightForHeaderInSection: section)
let padding: CGFloat = 10
let labelH: CGFloat = 20
let titleLabel = UILabel(frame: CGRectZero)
titleLabel.numberOfLines = 1
titleLabel.textColor = UIColor.whiteColor()
let buttonW: CGFloat = 30
let buttonH: CGFloat = 30
let buttonFrame = CGRectMake( KM_FRAME_SCREEN_WIDTH - buttonW - padding , (height - buttonH) / 2.0 , buttonW, buttonH)
let addButton = UIButton.buttonWithType(UIButtonType.ContactAdd) as! UIButton
addButton.frame = buttonFrame
addButton.tintColor = UIColor.whiteColor()
view.addSubview(titleLabel)
view.addSubview(addButton)
if section == 0{
titleLabel.text = i18n("Buyer")
addButton.addTarget(self, action: "addBuyerAction", forControlEvents: UIControlEvents.TouchUpInside)
}else if section == 1{
titleLabel.text = i18n("Goods List")
addButton.addTarget(self, action: "addProductAction", forControlEvents: UIControlEvents.TouchUpInside)
}else{
titleLabel.text = i18n("Gift List")
addButton.addTarget(self, action: "addGiftAction", forControlEvents: UIControlEvents.TouchUpInside)
}
let labelSize = titleLabel.sizeThatFits(CGSizeZero)
let labelFrame = CGRectMake(padding, (height - labelH) / 2.0, labelSize.width, labelH)
titleLabel.frame = labelFrame
return view
}
func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let view = UIView(frame: CGRectZero)
view.backgroundColor = UIColor.clearColor()
return view
}
func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 40
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 44
}
// MARK: - section header view button action
func addBuyerAction(){
let scanVC = ScanViewController(scanType: ScanType.QRCode) {[unowned self] (scanViewControlelr: ScanViewController, scanResult: String) -> Void in
scanViewControlelr.goback()
let jsonData = scanResult.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)
var error: NSError?
let jsonDic = NSJSONSerialization.JSONObjectWithData(jsonData!, options: NSJSONReadingOptions.MutableLeaves, error: &error) as? NSDictionary
self.progressHUD?.mode = MBProgressHUDMode.Indeterminate
self.progressHUD?.labelText = ""
self.progressHUD?.detailsLabelText = ""
self.progressHUD?.show(true)
if error == nil{
self.manager.POST(APP_URL_CHECKVIP, parameters: jsonDic, success: {[unowned self] (operation: AFHTTPRequestOperation!, responseObj: AnyObject!) -> Void in
let dic = responseObj as? NSDictionary
let code = dic?["code"] as? NSInteger
if code != nil && code == 1{
let customerDic = dic!["data"] as! NSDictionary
self.customerArray.removeAllObjects()
self.customerArray.addObject(customerDic)
self.tableView.reloadData()
self.hideProgressHUD()
}else if code != nil && code == 0{
self.progressHUD?.mode = MBProgressHUDMode.Text
self.progressHUD?.detailsLabelText = dic!["data"] as! String
self.hideProgressHUD(2)
}else{
KMLog("\(dic)")
self.hideProgressHUD()
}
}, failure: { (operation: AFHTTPRequestOperation!, error: NSError!) -> Void in
self.progressHUD?.mode = MBProgressHUDMode.Text
self.progressHUD?.labelText = i18n("Failed to connect link to server!")
self.progressHUD?.detailsLabelText = error.localizedDescription
self.hideProgressHUD(2)
})
}else{
self.progressHUD?.mode = MBProgressHUDMode.Text
self.progressHUD?.detailsLabelText = i18n("Invalid two-dimensional code")
self.hideProgressHUD(2)
}
}
scanVC.title = i18n("Scan customer VIP card")
self.navigationController?.pushViewController(scanVC, animated: true)
}
func addProductAction(){
let scanVC = ScanViewController(scanType: ScanType.BarCode) {[unowned self] (scanViewControlelr: ScanViewController, scanResult: String) -> Void in
scanViewControlelr.goback()
var product: ProductModel?
for item in self.productArray{
let p = item as! ProductModel
if p.scanCode == scanResult{
product = p
break
}
}
if product != nil{
product?.totalCount++
self.productArray.removeObject(product!)
self.productArray.insertObject(product!, atIndex: 0)
self.tableView.reloadData()
}else{
let params = ["scancode": scanResult]
self.progressHUD?.mode = MBProgressHUDMode.Indeterminate
self.progressHUD?.labelText = ""
self.progressHUD?.detailsLabelText = ""
self.progressHUD?.show(true)
self.manager.POST(APP_URL_SCAN_BAR_CODE, parameters: params, success: { (operation: AFHTTPRequestOperation!, responseObj: AnyObject!) -> Void in
let dic = responseObj as? NSDictionary
let code = dic?["code"] as? NSInteger
if code != nil && code == 1{
let product = ProductModel.productWithKeyValues(dic!["data"] as! [NSObject : AnyObject]!)
product.scanCode = scanResult
product.totalCount = 1
self.productArray.insertObject(product, atIndex: 0)
self.tableView.reloadData()
self.hideProgressHUD()
}else if code != nil && code == 0{
self.progressHUD?.mode = MBProgressHUDMode.Text
self.progressHUD?.detailsLabelText = dic!["data"] as! String
self.hideProgressHUD(2)
}else{
KMLog("\(dic)")
self.hideProgressHUD()
}
}, failure: { (operation: AFHTTPRequestOperation!, error: NSError!) -> Void in
self.progressHUD?.mode = MBProgressHUDMode.Text
self.progressHUD?.labelText = i18n("Failed to connect link to server!")
self.progressHUD?.detailsLabelText = error.localizedDescription
self.hideProgressHUD(2)
})
}
}
scanVC.title = i18n("Scan product bar code")
self.navigationController?.pushViewController(scanVC, animated: true)
}
func addGiftAction(){
let scanVC = ScanViewController(scanType: ScanType.BarCode) {[unowned self] (scanViewControlelr: ScanViewController, scanResult: String) -> Void in
scanViewControlelr.goback()
var product: ProductModel?
for item in self.giftArray{
let p = item as! ProductModel
if p.scanCode == scanResult{
product = p
break
}
}
if product != nil{
product?.totalCount++
self.giftArray.removeObject(product!)
self.giftArray.insertObject(product!, atIndex: 0)
self.tableView.reloadData()
}else{
let params = ["scancode": scanResult]
self.progressHUD?.mode = MBProgressHUDMode.Indeterminate
self.progressHUD?.labelText = ""
self.progressHUD?.detailsLabelText = ""
self.progressHUD?.show(true)
self.manager.POST(APP_URL_SCAN_BAR_CODE, parameters: params, success: {[unowned self] (operation: AFHTTPRequestOperation!, responseObj: AnyObject!) -> Void in
let dic = responseObj as? NSDictionary
let code = dic?["code"] as? NSInteger
if code != nil && code == 1{
let product = ProductModel.productWithKeyValues(dic!["data"] as! [NSObject : AnyObject]!)
product.scanCode = scanResult
product.totalCount = 1
self.giftArray.insertObject(product, atIndex: 0)
self.tableView.reloadData()
self.hideProgressHUD()
}else if code != nil && code == 0{
self.progressHUD?.mode = MBProgressHUDMode.Text
self.progressHUD?.detailsLabelText = dic!["data"] as! String
self.hideProgressHUD(2)
}else{
KMLog("\(dic)")
self.hideProgressHUD()
}
}, failure: {[unowned self] (operation: AFHTTPRequestOperation!, error: NSError!) -> Void in
self.progressHUD?.mode = MBProgressHUDMode.Text
self.progressHUD?.labelText = i18n("Failed to connect link to server!")
self.progressHUD?.detailsLabelText = error.localizedDescription
self.hideProgressHUD(2)
})
}
}
scanVC.title = i18n("Scan gift bar code")
self.navigationController?.pushViewController(scanVC, animated: true)
}
// MARK: - UITableViewDataSource
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 3
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0{
return 1
}else if section == 1 {
if productArray.count > 0{
return productArray.count
}else{
return 1
}
}else{
if giftArray.count > 0 {
return giftArray.count
}else{
return 1
}
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = UIFactory.tableViewCellForTableView(tableView, cellIdentifier: TradeInputViewController.CellIdentifier, cellType: UITableViewCellStyle.Subtitle, cleanCellContentView: false) {[unowned self] (tableViewCell: UITableViewCell!) -> Void in
tableViewCell?.backgroundColor = UIColor.clearColor()
tableViewCell?.textLabel?.textColor = UIColor.whiteColor()
tableViewCell?.detailTextLabel?.textColor = UIColor.whiteColor()
let buttonW: CGFloat = 22
let buttonH: CGFloat = 22
let cellHeight = self.tableView(tableView, heightForRowAtIndexPath: indexPath)
let deleteButton = UIButton.buttonWithType(UIButtonType.Custom) as? UIButton
deleteButton!.frame = CGRectMake(KM_FRAME_SCREEN_WIDTH - 10 - buttonW - 30, (cellHeight - buttonH) / 2.0, buttonW, buttonH)
deleteButton!.tag = TradeInputViewController.DeleteButtonTag
deleteButton!.backgroundColor = UIColor.clearColor()
deleteButton!.setImage(UIImage(named: "button_minus"), forState: UIControlState.Normal)
deleteButton!.addTarget(self, action: "deleteSelectCellDataAction:", forControlEvents: UIControlEvents.TouchUpInside)
tableViewCell?.contentView.addSubview(deleteButton!)
tableViewCell?.selectionStyle = UITableViewCellSelectionStyle.None
}
var deleteButton = cell?.contentView.viewWithTag(TradeInputViewController.DeleteButtonTag) as? UIButton
deleteButton?.hidden = false
cell?.accessoryType = UITableViewCellAccessoryType.DisclosureIndicator
let section = indexPath.section
let row = indexPath.row
if section == 0{
if customerArray.count > 0{
cell!.accessoryType = UITableViewCellAccessoryType.None
let customer = customerArray.firstObject as! NSDictionary
var customerName = customer["customer_nickname"] as? String
if customerName == nil || customerName!.isEmpty{
customerName = customer["customer_name"] as? String
}
let customerVip = customer["customer_vip"] as? String
var contact = customer["customer_phone"] as? String
let connect = i18n("Connection way")
cell?.textLabel?.text = "\(customerName!)(\(connect):\(contact!))"
let vip = i18n("VIP")
cell?.detailTextLabel?.text = "\(vip):\(customerVip!)"
}else{
emptyCell(cell!, text: i18n("Please select the buyer"), deleteButton: deleteButton!)
}
}else if section == 1{
if productArray.count > 0{
let product: ProductModel! = productArray.objectAtIndex(row) as! ProductModel
let productName = product.productNameZH.isEmpty ? product.productNameEN : product.productNameZH
let totalCount = product.totalCount
let tc = i18n("Total count")
cell?.textLabel?.text = productName
cell?.detailTextLabel?.text = "\(tc):\(totalCount)"
}else{
emptyCell(cell!, text: i18n("Please select the goods"), deleteButton: deleteButton!)
}
}else{
if giftArray.count > 0 {
let product: ProductModel! = giftArray.objectAtIndex(row) as! ProductModel
let productName = product.productNameZH.isEmpty ? product.productNameEN : product.productNameZH
let totalCount = product.totalCount
let tc = i18n("Total count")
cell?.textLabel?.text = productName
cell?.detailTextLabel?.text = "\(tc):\(totalCount)"
}else{
emptyCell(cell!, text: i18n("Please select the gift"), deleteButton: deleteButton!)
}
}
return cell!
}
func emptyCell(cell: UITableViewCell,text: String, deleteButton: UIButton){
cell.accessoryType = UITableViewCellAccessoryType.None
cell.textLabel?.text = text
cell.detailTextLabel?.text = ""
cell.imageView?.image = nil
deleteButton.hidden = true
}
func deleteSelectCellDataAction(sender: AnyObject!){
let cell = (sender as! UIButton).superview?.superview as! UITableViewCell
let indexPath = tableView.indexPathForCell(cell)
let alertView = UIAlertView(title: i18n("Hint"), message: i18n("Remove the selected data?"), delegate: nil, cancelButtonTitle: i18n("Cancel"), otherButtonTitles: i18n("Sure"))
alertView.showAlertViewWithCompleteBlock {[unowned self, indexPath] (buttonIndex) -> Void in
if buttonIndex == 1{
let section = indexPath?.section
let row = indexPath?.row
if section == 0{
self.customerArray.removeObjectAtIndex(row!)
}else if section == 1{
self.productArray.removeObjectAtIndex(row!)
}else{
self.giftArray.removeObjectAtIndex(row!)
}
self.tableView.reloadData()
}
}
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}**