IOS 应用程序在 iTunes 版本上崩溃,但在本地模拟器和真实设备测试中运行良好
IOS App crashed on iTunes' version, but works fine on local simulator & real device testing
我有一个 IOS 应用已成功上传到 iTunes,
该应用程序也已在本地模拟器和真实设备上成功测试。
然而,当我从 App Store 下载应用程序时(使用相同的设备,相同的 OS 版本),应用程序将首先加载,并在特定视图上崩溃。
我从 NewRelic 崩溃分析中收到以下错误消息:
SIGSEGV
在 0x10024d050 0 + 4297379920
这似乎是一个非常不寻常的错误,因为本地副本应该与我上传到应用商店的副本完全相同。
如有任何建议,我们将不胜感激,
谢谢!
堆栈跟踪:
Exception Type: EXC_CRASH (SIGTRAP)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Triggered by Thread: 1
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0:
0 MyXcodeProject 0x00000001000fbfe4 0x100098000 + 409572
1 UIKit 0x0000000188e90954 0x188e80000 + 67924
2 UIKit 0x0000000188e90664 0x188e80000 + 67172
3 UIKit 0x00000001895841cc 0x188e80000 + 7356876
4 UIKit 0x000000018918b78c 0x188e80000 + 3192716
5 UIKit 0x00000001891a6b4c 0x188e80000 + 3304268
6 UIKit 0x00000001891a8f64 0x188e80000 + 3313508
7 UIKit 0x0000000188f85b38 0x188e80000 + 1071928
8 UIKit 0x0000000188fb3ac0 0x188e80000 + 1260224
9 UIKit 0x0000000188fb2998 0x188e80000 + 1255832
10 UIKit 0x0000000188ee54b4 0x188e80000 + 414900
11 Foundation 0x000000018556cba0 0x185484000 + 953248
12 CoreFoundation 0x000000018463ac1c 0x18455c000 + 912412
13 CoreFoundation 0x000000018463a8cc 0x18455c000 + 911564
14 CoreFoundation 0x0000000184638318 0x18455c000 + 901912
15 CoreFoundation 0x00000001845651f0 0x18455c000 + 37360
16 GraphicsServices 0x000000018d9876f8 0x18d97c000 + 46840
17 UIKit 0x0000000188ef6108 0x188e80000 + 483592
18 MyXcodeProject 0x00000001001ed04c 0x100098000 + 1396812
19 libdyld.dylib 0x0000000195cd6a04 0x195cd4000 + 10756
以下将是发生此错误的地方:
导入 UIKit
导入核心数据
class ContactListViewController:UIViewController、NSFetchedResultsControllerDelegate、UICollectionViewDataSource、UICollectionViewDelegate、UIAlertViewDelegate、WYPopoverControllerDelegate、CreateGroupVcDelegate、ContactListDetailVcDelegate、SelectAddContactsTableVcDelegate、SelectContactsVcDelegate {
@IBOutlet weak var collectionView: UICollectionView!
@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var btnEdit: UIButton!
var fetchedResultsController_Group: NSFetchedResultsController = NSFetchedResultsController()
var fetchedResultsController_Contact: NSFetchedResultsController = NSFetchedResultsController()
var fetchedResult_GroupAndContact = [GroupAndContact]()
// Select Group Index
var selectedGroupIndex = Int()
// Selected group ID
var selectedGroupId = Int()
var contactIndex = Int()
// BOOL indicator
var isEditMode : Bool = false
// Popover Controller
var popoverController_CreateGroupVc = WYPopoverController()
var popoverController_ContactListDetailVc = WYPopoverController()
var popoverController_SelectAddContactsTableVc = WYPopoverController()
override func viewDidLoad()
{
super.viewDidLoad()
MainMenuItem.setupMenuBtn(self)
self.navigationController?.navigationBar.topItem?.title = "Contact"
self.navigationController?.navigationBar.titleTextAttributes = [ NSFontAttributeName: UIFont(name: "Avenir Light", size: 18)!, NSForegroundColorAttributeName: UIColor.navigationBarTitle()]
// Do any additional setup after loading the view.
// Listeners
NSNotificationCenter.defaultCenter().addObserver(self, selector: "updateSavedDataContact_Success", name:"updateSavedDataContact_Success", object: nil)
// Default index 1 as the selected item for the colleciton view
selectedGroupIndex = 1
updateDataSource()
}
func updateDataSource ()
{
getFetchedResultController_Group()
let modIndexPath : NSIndexPath = NSIndexPath(forRow: selectedGroupIndex_data(), inSection: 0)
var result = self.fetchedResultsController_Group.objectAtIndexPath(modIndexPath) as? Group
selectedGroupId = result!.id as Int
getFetchedResultController_Contact(result!.id as Int)
self.collectionView.reloadData()
self.tableView.reloadData()
}
// #Listener Methods
func updateSavedDataContact_Success ()
{
updateDataSource()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func getFetchedResultController_Group ()
{
let appDel : AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
let moc: NSManagedObjectContext = appDel.managedObjectContext!
let fetchRequest = NSFetchRequest()
//3 - set the correct table
let entity = NSEntityDescription.entityForName("Group", inManagedObjectContext: moc)
fetchRequest.entity = entity
fetchRequest.fetchBatchSize = 20
/*
// Filter
let predicate1 : NSPredicate = NSPredicate(format: "is_incoming_all == \(mytaskValue)", argumentArray: nil)
let predicate12 : NSPredicate = NSPredicate(format: "name == \"Nice Group\"", argumentArray: nil)
let predicateArray : Array = [predicate1]
let compoundPredicate : NSPredicate = NSCompoundPredicate.andPredicateWithSubpredicates(predicateArray)
fetchRequest.predicate = compoundPredicate */
let sectionSortDescriptor = NSSortDescriptor(key: "sort_id", ascending: true)
let sortDescriptors = [sectionSortDescriptor] //, secondSortDescriptor]
fetchRequest.sortDescriptors = sortDescriptors
//4 - navigate in relationship to group by time
let aFetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: moc, sectionNameKeyPath: nil, cacheName: nil)
aFetchedResultsController.delegate = self
self.fetchedResultsController_Group = aFetchedResultsController
var error: NSError? = nil
if !self.fetchedResultsController_Group.performFetch(&error) {
abort()
}
}
func getFetchedResultController_Contact (groupId: Int)
{
getFetchedResultController_GroupAndContact(groupId)
let appDel : AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
let moc: NSManagedObjectContext = appDel.managedObjectContext!
let fetchRequest = NSFetchRequest()
//3 - set the correct table
let entity = NSEntityDescription.entityForName("Contact", inManagedObjectContext: moc)
fetchRequest.entity = entity
fetchRequest.fetchBatchSize = 20
// Filter
var strForPredicate = String()
strForPredicate = strForPredicate + "id == nil"
for (var i = 0; i < fetchedResult_GroupAndContact.count; i++)
{
strForPredicate = strForPredicate + " OR id == \(fetchedResult_GroupAndContact[i].contact_id)"
}
//"groupAndContact.group_id == \(groupId) AND groupAndContact.contact_id == id"
let predicate1 : NSPredicate = NSPredicate(format: strForPredicate, argumentArray: nil)
//let predicate1 : NSPredicate = NSPredicate(format: "id == SUBQUERY(groupAndContact, $gac, ANY $gac.group_id == \(groupId)).contact_id", argumentArray: nil)
//let predicate2 : NSPredicate = NSPredicate(format: "name == \"Nice Group\"", argumentArray: nil)
let predicateArray : Array = [predicate1]
let compoundPredicate : NSPredicate = NSCompoundPredicate.andPredicateWithSubpredicates(predicateArray)
fetchRequest.predicate = compoundPredicate
let sectionSortDescriptor = NSSortDescriptor(key: "name", ascending: true)
let sortDescriptors = [sectionSortDescriptor] //, secondSortDescriptor]
fetchRequest.sortDescriptors = sortDescriptors
//4 - navigate in relationship to group by time
let aFetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: moc, sectionNameKeyPath: nil, cacheName: nil)
aFetchedResultsController.delegate = self
self.fetchedResultsController_Contact = aFetchedResultsController
var error: NSError? = nil
if !self.fetchedResultsController_Contact.performFetch(&error) {
abort()
}
}
func getFetchedResultController_GroupAndContact (groupId: Int)
{
var managedObjectContext : NSManagedObjectContext? = {
let appDelegate = UIApplication.sharedApplication().delegate as AppDelegate
if let managedObjectContext = appDelegate.managedObjectContext {
return managedObjectContext
}
else {
return nil
}
}()
let fetchRequest1 = NSFetchRequest(entityName: "GroupAndContact")
// Filter
let predicate11 : NSPredicate = NSPredicate(format: "group_id == \(groupId)", argumentArray: nil)
//let predicate12 : NSPredicate = NSPredicate(format: "name == \"Nice Group\"", argumentArray: nil)
let predicateArray1 : Array = [predicate11]
let compoundPredicate1 : NSPredicate = NSCompoundPredicate.andPredicateWithSubpredicates(predicateArray1)
fetchRequest1.predicate = compoundPredicate1
if let fetchResults1 = managedObjectContext!.executeFetchRequest(fetchRequest1, error: nil) as? [GroupAndContact] {
fetchedResult_GroupAndContact = fetchResults1
}
}
// #Buttons
@IBAction func btnDeleteGroup(sender: AnyObject)
{
var indexPath = NSIndexPath()
indexPath = self.collectionView.indexPathForItemAtPoint(self.collectionView.convertPoint(sender.center, fromView: sender.superview))!
let modIndexPath : NSIndexPath = NSIndexPath(forRow: indexPath.row-1, inSection: indexPath.section)
var result = self.fetchedResultsController_Group.objectAtIndexPath(modIndexPath) as? Group
// Reset selectedItemIndex Logic : Delete
if (indexPath.row > selectedGroupIndex)
{
// selectedGroupIndex stays the same
}
else if (indexPath.row == selectedGroupIndex)
{
selectedGroupIndex = 1
}
else if (indexPath.row <= selectedGroupIndex)
{
selectedGroupIndex = selectedGroupIndex-1
}
/*
if(selectedGroupIndex == returnLastItemIndexInCollectionView())
{
selectedGroupIndex = 1
}
*/
AlertManager.instance.alertDeleteGroupConfirmation(result!.name, okBlock: {
// EXE
DataManager.instance.deleteSpecificGroup( Int(result!.id) )
}, cancelBlock: {})
btnEditSupport()
}
//temp
@IBAction func btnEdit(sender: AnyObject)
{
btnEditSupport()
}
func btnEditSupport()
{
isEditMode = !isEditMode
if(isEditMode)
{
btnEdit.setTitle("Done", forState: UIControlState.Normal)
}
else
{
btnEdit.setTitle("Edit", forState: UIControlState.Normal)
}
updateDataSource()
}
/*
// 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.
}
*/
// #CollectionView Delegate
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
let sectionInfo = self.fetchedResultsController_Group.sections![section] as NSFetchedResultsSectionInfo
return sectionInfo.numberOfObjects + 1
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
var cell: ContactListVcCollectionViewCell = collectionView.dequeueReusableCellWithReuseIdentifier("MyCell", forIndexPath: indexPath) as ContactListVcCollectionViewCell
/*
var isSelected = false
for (var i = 0; i < arySelectedItemsIndex.count; i++)
{
if(indexPath.row == arySelectedItemsIndex[i])
{
isSelected = true
}
}
*/
var isSelected = false
if(indexPath.row == selectedGroupIndex)
{
isSelected = true
}
// Display
var img = UIImage(named: "icon_delete.png")?.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate)
cell.imgDeleteGroup.image = img
cell.imgDeleteGroup.tintColor = UIColor.MBHred()
if ( indexPath.row == 0)
{
var img = UIImage(named: "icon_add.png")?.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate)
cell.imgGroupIcon.image = img
cell.imgGroupIcon.tintColor = UIColor.groupIconAddGroup()
cell.lbGroupName.text = "Add"
cell.lbGroupName.textColor = UIColor.groupIconAddGroup()
// hide delete button for [add group] & [All Contact]
cell.imgDeleteGroup.hidden = true
cell.btnDeleteGroup.hidden = true
}
else
{
let modIndexPath : NSIndexPath = NSIndexPath(forRow: indexPath.row-1, inSection: indexPath.section)
var result = self.fetchedResultsController_Group.objectAtIndexPath(modIndexPath) as? Group
cell.lbGroupName.text = result?.name
cell.lbGroupName.textColor = UIColor.groupIconNotSelected()
var img = UIImage(named: "group_\(result!.icon_id).png")?.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate)
// Display
cell.imgGroupIcon.image = img
cell.imgGroupIcon.tintColor = UIColor.groupIconNotSelected()
// Cell selected or not
if (isSelected)
{
cell.lbGroupName.textColor = UIColor.groupIconSelected()
cell.imgGroupIcon.tintColor = UIColor.groupIconSelected()
}
else
{
cell.lbGroupName.textColor = UIColor.groupIconNotSelected()
cell.imgGroupIcon.tintColor = UIColor.groupIconNotSelected()
}
// show delete button for [add group] & [All Contact]
// if the editmode is true
if (isEditMode && indexPath.row > 1)
{
cell.imgDeleteGroup.hidden = false
cell.btnDeleteGroup.hidden = false
}
else
{
cell.imgDeleteGroup.hidden = true
cell.btnDeleteGroup.hidden = true
}
}
return cell
}
// NOTE: Since the first item is always "Add", remeber to use Index.row-1 to fetch from Array
/*
let modIndexPath : NSIndexPath = NSIndexPath(forRow: indexPath.row-1, inSection: indexPath.section)
*/
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
if ( indexPath.row == 0 )
{
// Add Group
let vc = self.storyboard?.instantiateViewControllerWithIdentifier("CreateGroupViewController") as CreateGroupViewController
vc.preferredContentSize = CGSizeMake(self.view.bounds.width-25, self.view.bounds.height*4/5)
vc.loadView()
vc.delegateCreateGroupVcDelegate = self
vc.title = "Create a Group"
vc.btnCancel.addTarget(self, action: Selector("dismissCreateGroupVc"), forControlEvents: UIControlEvents.TouchUpInside)
/*
self.navigationController?.pushViewController(vc, animated: true)
*/
popoverController_CreateGroupVc = WYPopoverController(contentViewController: vc)
popoverController_CreateGroupVc.delegate = self
popoverController_CreateGroupVc.presentPopoverFromRect(CGRectMake(self.collectionView.bounds.origin.x, self.collectionView.bounds.origin.y, self.collectionView.bounds.width, 50) , inView: self.view, permittedArrowDirections: WYPopoverArrowDirection.Any, animated: true)
}
else
{
selectedGroupIndex = indexPath.row
// Choose from existing group
let modIndexPath : NSIndexPath = NSIndexPath(forRow: indexPath.row-1, inSection: indexPath.section)
var result = self.fetchedResultsController_Group.objectAtIndexPath(modIndexPath) as? Group
selectedGroupId = result!.id as Int
getFetchedResultController_Contact(result!.id as Int)
collectionView.reloadData()
tableView.reloadData()
println("result?.id = \(result?.id)")
}
}
// #alertView Delegate
func alertView(alert: UIAlertView!, clickedButtonAtIndex buttonIndex: Int)
{
if (buttonIndex == 1)
{
if ((alert.textFieldAtIndex(0)?.text) != nil)
{
DataManager.instance.addGroup(alert.textFieldAtIndex(0)!.text, iconId: 1)
}
}
}
// #TableView Delegate
func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int
{
let sectionInfo = self.fetchedResultsController_Contact.sections![section] as NSFetchedResultsSectionInfo
return sectionInfo.numberOfObjects + 1
}
func tableView(tableView: UITableView!,
cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell!
{
let sectionInfo = self.fetchedResultsController_Contact.sections![indexPath.section] as NSFetchedResultsSectionInfo
var cell = tableView.dequeueReusableCellWithIdentifier("MyCell", forIndexPath: indexPath) as ContactListVcTableViewCell
/*
var isSelected = false
for (var i = 0; i < arySelectedItemsIndex.count; i++)
{
if(indexPath.row == arySelectedItemsIndex[i])
{
isSelected = true
}
}
*/
var isSelected = false
if(indexPath.row == selectedGroupIndex)
{
isSelected = true
}
/*
// Display
var img = UIImage(named: "icon_delete.png")?.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate)
cell.imgDeleteGroup.image = img
cell.imgDeleteGroup.tintColor = UIColor.redColor()
*/
// Last Row of the TableView : Add Button
if (indexPath.row == sectionInfo.numberOfObjects)
{
var img = UIImage(named: "icon_add.png")?.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate)
cell.imgAddContact.image = img
cell.imgAddContact.tintColor = UIColor.groupIconAddGroup()
cell.lbName.hidden = true
cell.imgAddContact.hidden = false
//cell.lbAddContact.hidden = false
/*
// hide delete button for [add group] & [All Contact]
cell.imgDeleteGroup.hidden = true
cell.btnDeleteGroup.hidden = true */
}
// Other Rows of the TableView : Display
else
{
let modIndexPath : NSIndexPath = NSIndexPath(forRow: indexPath.row, inSection: indexPath.section)
var result = self.fetchedResultsController_Contact.objectAtIndexPath(modIndexPath) as? Contact
cell.lbName.text = result?.name
cell.lbName.textColor = UIColor.groupIconNotSelected()
cell.lbName.hidden = false
cell.imgAddContact.hidden = true
/*
//temp
var img = UIImage(named: "group_\(result!.icon_url).png")?.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate)
// Display
cell.imgGroupIcon.image = img
cell.imgGroupIcon.tintColor = UIColor.groupIconNotSelected()
*/
/*
// Cell selected or not
if (isSelected)
{
cell.lbGroupName.textColor = UIColor.groupIconSelected()
cell.imgGroupIcon.tintColor = UIColor.groupIconSelected()
}
else
{
cell.lbGroupName.textColor = UIColor.groupIconNotSelected()
cell.imgGroupIcon.tintColor = UIColor.groupIconNotSelected()
}
*/
/*
// show delete button for [add group] & [All Contact]
// if the editmode is true
if (isEditMode)
{
cell.imgDeleteGroup.hidden = false
cell.btnDeleteGroup.hidden = false
}
else
{
cell.imgDeleteGroup.hidden = true
cell.btnDeleteGroup.hidden = true
}
*/
}
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
let sectionInfo = self.fetchedResultsController_Contact.sections![indexPath.section] as NSFetchedResultsSectionInfo
// Last Row of the TableView : Add Button
if (indexPath.row == sectionInfo.numberOfObjects)
{
//tmp_0309
/*
let vc = self.storyboard?.instantiateViewControllerWithIdentifier("SelectAddContactsTableViewControllerNav") as UINavigationController
vc.preferredContentSize = CGSizeMake(self.view.bounds.width-20, self.view.bounds.height*1/2)
vc.loadView()
let vc2 = vc.viewControllers[0] as SelectAddContactsTableViewController
vc2.delegateSelectAddContactsTableVcDelegate = self
vc2.selectedGroupId = selectedGroupId
popoverController_SelectAddContactsTableVc = WYPopoverController(contentViewController: vc)
popoverController_SelectAddContactsTableVc.delegate = self
popoverController_SelectAddContactsTableVc.presentPopoverFromRect(CGRectMake(self.collectionView.bounds.origin.x, self.collectionView.bounds.origin.y, self.collectionView.bounds.width, 50) , inView: self.view, permittedArrowDirections: WYPopoverArrowDirection.Any, animated: true)
*/
self.performSegueWithIdentifier("toSelectContactsVc", sender: self)
}
else
{
let modIndexPath : NSIndexPath = NSIndexPath(forRow: indexPath.row, inSection: indexPath.section)
var result = self.fetchedResultsController_Contact.objectAtIndexPath(modIndexPath) as? Contact
contactIndex = indexPath.row
let myRect : CGRect = tableView.rectForRowAtIndexPath(indexPath)
var myRectMod : CGRect = CGRect(x: myRect.origin.x, y: myRect.origin.y, width: 20, height: myRect.height)
// Display ContactListDetailVc Popover
let vc = self.storyboard?.instantiateViewControllerWithIdentifier("ContactListDetailViewController") as ContactListDetailViewController
vc.loadView()
vc.delegateContactListDetailVcDelegate = self
vc.contactId = result!.id as Int
vc.title = "Contact Detail"
//vc.btnCancel.addTarget(self, action: Selector("dismissCreateGroupVc"), forControlEvents: UIControlEvents.TouchUpInside)
//vc.preferredContentSize = CGSizeMake( self.view.bounds.width-50, self.view.bounds.height-85)
vc.preferredContentSize = CGSizeMake( self.view.bounds.width-20, 270)
popoverController_ContactListDetailVc = WYPopoverController(contentViewController: vc)
popoverController_ContactListDetailVc.delegate = self
popoverController_ContactListDetailVc.presentPopoverFromRect(myRectMod, inView: self.tableView, permittedArrowDirections: WYPopoverArrowDirection.Up, animated: true)
//popoverController.presentPopoverAsDialogAnimated(true, options: WYPopoverAnimationOptions.FadeWithScale)
}
}
func tableView(tableView: UITableView!, canEditRowAtIndexPath indexPath: NSIndexPath!) -> Bool {
let sectionInfo = self.fetchedResultsController_Contact.sections![indexPath.section] as NSFetchedResultsSectionInfo
// Last Row of the TableView : Add Button
if (indexPath.row == sectionInfo.numberOfObjects)
{
return false
}
else
{
return true
}
}
func tableView(tableView: UITableView!, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath!) {
if (editingStyle == UITableViewCellEditingStyle.Delete) {
// handle delete (by removing the data from your array and updating the tableview)
let modIndexPath : NSIndexPath = NSIndexPath(forRow: indexPath.row, inSection: indexPath.section)
var result = self.fetchedResultsController_Contact.objectAtIndexPath(modIndexPath) as? Contact
DataManager.instance.deleteContactFromGroup(selectedGroupId, contactId: result?.id as Int)
/*
if (groupIndex != 0 )
{
DataManager.instance.deleteContactFromGroup(groupId, contactId: DataManager.instance.contact_id[indexPath.row])
}
else
{
DataManager.instance.deleteSpecificContact(DataManager.instance.contact_id[indexPath.row])
}
*/
//DataManager.instance.group_id.removeAtIndex(indexPath.row)
//DataManager.instance.group_name.removeAtIndex(indexPath.row)
//DataManager.instance.group_iconId.removeAtIndex(indexPath.row)
//tableView.reloadData()
}
}
...
这是我的构建设置...
转到“编辑方案”>“存档”>“构建配置”。
只需将"release"更改为"debug",存档版本将与本地调试版本完全相同。
iTunes 版本现在可用!!
我有一个 IOS 应用已成功上传到 iTunes, 该应用程序也已在本地模拟器和真实设备上成功测试。
然而,当我从 App Store 下载应用程序时(使用相同的设备,相同的 OS 版本),应用程序将首先加载,并在特定视图上崩溃。
我从 NewRelic 崩溃分析中收到以下错误消息:
SIGSEGV 在 0x10024d050 0 + 4297379920
这似乎是一个非常不寻常的错误,因为本地副本应该与我上传到应用商店的副本完全相同。
如有任何建议,我们将不胜感激,
谢谢!
堆栈跟踪:
Exception Type: EXC_CRASH (SIGTRAP)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Triggered by Thread: 1
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0:
0 MyXcodeProject 0x00000001000fbfe4 0x100098000 + 409572
1 UIKit 0x0000000188e90954 0x188e80000 + 67924
2 UIKit 0x0000000188e90664 0x188e80000 + 67172
3 UIKit 0x00000001895841cc 0x188e80000 + 7356876
4 UIKit 0x000000018918b78c 0x188e80000 + 3192716
5 UIKit 0x00000001891a6b4c 0x188e80000 + 3304268
6 UIKit 0x00000001891a8f64 0x188e80000 + 3313508
7 UIKit 0x0000000188f85b38 0x188e80000 + 1071928
8 UIKit 0x0000000188fb3ac0 0x188e80000 + 1260224
9 UIKit 0x0000000188fb2998 0x188e80000 + 1255832
10 UIKit 0x0000000188ee54b4 0x188e80000 + 414900
11 Foundation 0x000000018556cba0 0x185484000 + 953248
12 CoreFoundation 0x000000018463ac1c 0x18455c000 + 912412
13 CoreFoundation 0x000000018463a8cc 0x18455c000 + 911564
14 CoreFoundation 0x0000000184638318 0x18455c000 + 901912
15 CoreFoundation 0x00000001845651f0 0x18455c000 + 37360
16 GraphicsServices 0x000000018d9876f8 0x18d97c000 + 46840
17 UIKit 0x0000000188ef6108 0x188e80000 + 483592
18 MyXcodeProject 0x00000001001ed04c 0x100098000 + 1396812
19 libdyld.dylib 0x0000000195cd6a04 0x195cd4000 + 10756
以下将是发生此错误的地方:
导入 UIKit 导入核心数据
class ContactListViewController:UIViewController、NSFetchedResultsControllerDelegate、UICollectionViewDataSource、UICollectionViewDelegate、UIAlertViewDelegate、WYPopoverControllerDelegate、CreateGroupVcDelegate、ContactListDetailVcDelegate、SelectAddContactsTableVcDelegate、SelectContactsVcDelegate {
@IBOutlet weak var collectionView: UICollectionView!
@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var btnEdit: UIButton!
var fetchedResultsController_Group: NSFetchedResultsController = NSFetchedResultsController()
var fetchedResultsController_Contact: NSFetchedResultsController = NSFetchedResultsController()
var fetchedResult_GroupAndContact = [GroupAndContact]()
// Select Group Index
var selectedGroupIndex = Int()
// Selected group ID
var selectedGroupId = Int()
var contactIndex = Int()
// BOOL indicator
var isEditMode : Bool = false
// Popover Controller
var popoverController_CreateGroupVc = WYPopoverController()
var popoverController_ContactListDetailVc = WYPopoverController()
var popoverController_SelectAddContactsTableVc = WYPopoverController()
override func viewDidLoad()
{
super.viewDidLoad()
MainMenuItem.setupMenuBtn(self)
self.navigationController?.navigationBar.topItem?.title = "Contact"
self.navigationController?.navigationBar.titleTextAttributes = [ NSFontAttributeName: UIFont(name: "Avenir Light", size: 18)!, NSForegroundColorAttributeName: UIColor.navigationBarTitle()]
// Do any additional setup after loading the view.
// Listeners
NSNotificationCenter.defaultCenter().addObserver(self, selector: "updateSavedDataContact_Success", name:"updateSavedDataContact_Success", object: nil)
// Default index 1 as the selected item for the colleciton view
selectedGroupIndex = 1
updateDataSource()
}
func updateDataSource ()
{
getFetchedResultController_Group()
let modIndexPath : NSIndexPath = NSIndexPath(forRow: selectedGroupIndex_data(), inSection: 0)
var result = self.fetchedResultsController_Group.objectAtIndexPath(modIndexPath) as? Group
selectedGroupId = result!.id as Int
getFetchedResultController_Contact(result!.id as Int)
self.collectionView.reloadData()
self.tableView.reloadData()
}
// #Listener Methods
func updateSavedDataContact_Success ()
{
updateDataSource()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func getFetchedResultController_Group ()
{
let appDel : AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
let moc: NSManagedObjectContext = appDel.managedObjectContext!
let fetchRequest = NSFetchRequest()
//3 - set the correct table
let entity = NSEntityDescription.entityForName("Group", inManagedObjectContext: moc)
fetchRequest.entity = entity
fetchRequest.fetchBatchSize = 20
/*
// Filter
let predicate1 : NSPredicate = NSPredicate(format: "is_incoming_all == \(mytaskValue)", argumentArray: nil)
let predicate12 : NSPredicate = NSPredicate(format: "name == \"Nice Group\"", argumentArray: nil)
let predicateArray : Array = [predicate1]
let compoundPredicate : NSPredicate = NSCompoundPredicate.andPredicateWithSubpredicates(predicateArray)
fetchRequest.predicate = compoundPredicate */
let sectionSortDescriptor = NSSortDescriptor(key: "sort_id", ascending: true)
let sortDescriptors = [sectionSortDescriptor] //, secondSortDescriptor]
fetchRequest.sortDescriptors = sortDescriptors
//4 - navigate in relationship to group by time
let aFetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: moc, sectionNameKeyPath: nil, cacheName: nil)
aFetchedResultsController.delegate = self
self.fetchedResultsController_Group = aFetchedResultsController
var error: NSError? = nil
if !self.fetchedResultsController_Group.performFetch(&error) {
abort()
}
}
func getFetchedResultController_Contact (groupId: Int)
{
getFetchedResultController_GroupAndContact(groupId)
let appDel : AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
let moc: NSManagedObjectContext = appDel.managedObjectContext!
let fetchRequest = NSFetchRequest()
//3 - set the correct table
let entity = NSEntityDescription.entityForName("Contact", inManagedObjectContext: moc)
fetchRequest.entity = entity
fetchRequest.fetchBatchSize = 20
// Filter
var strForPredicate = String()
strForPredicate = strForPredicate + "id == nil"
for (var i = 0; i < fetchedResult_GroupAndContact.count; i++)
{
strForPredicate = strForPredicate + " OR id == \(fetchedResult_GroupAndContact[i].contact_id)"
}
//"groupAndContact.group_id == \(groupId) AND groupAndContact.contact_id == id"
let predicate1 : NSPredicate = NSPredicate(format: strForPredicate, argumentArray: nil)
//let predicate1 : NSPredicate = NSPredicate(format: "id == SUBQUERY(groupAndContact, $gac, ANY $gac.group_id == \(groupId)).contact_id", argumentArray: nil)
//let predicate2 : NSPredicate = NSPredicate(format: "name == \"Nice Group\"", argumentArray: nil)
let predicateArray : Array = [predicate1]
let compoundPredicate : NSPredicate = NSCompoundPredicate.andPredicateWithSubpredicates(predicateArray)
fetchRequest.predicate = compoundPredicate
let sectionSortDescriptor = NSSortDescriptor(key: "name", ascending: true)
let sortDescriptors = [sectionSortDescriptor] //, secondSortDescriptor]
fetchRequest.sortDescriptors = sortDescriptors
//4 - navigate in relationship to group by time
let aFetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: moc, sectionNameKeyPath: nil, cacheName: nil)
aFetchedResultsController.delegate = self
self.fetchedResultsController_Contact = aFetchedResultsController
var error: NSError? = nil
if !self.fetchedResultsController_Contact.performFetch(&error) {
abort()
}
}
func getFetchedResultController_GroupAndContact (groupId: Int)
{
var managedObjectContext : NSManagedObjectContext? = {
let appDelegate = UIApplication.sharedApplication().delegate as AppDelegate
if let managedObjectContext = appDelegate.managedObjectContext {
return managedObjectContext
}
else {
return nil
}
}()
let fetchRequest1 = NSFetchRequest(entityName: "GroupAndContact")
// Filter
let predicate11 : NSPredicate = NSPredicate(format: "group_id == \(groupId)", argumentArray: nil)
//let predicate12 : NSPredicate = NSPredicate(format: "name == \"Nice Group\"", argumentArray: nil)
let predicateArray1 : Array = [predicate11]
let compoundPredicate1 : NSPredicate = NSCompoundPredicate.andPredicateWithSubpredicates(predicateArray1)
fetchRequest1.predicate = compoundPredicate1
if let fetchResults1 = managedObjectContext!.executeFetchRequest(fetchRequest1, error: nil) as? [GroupAndContact] {
fetchedResult_GroupAndContact = fetchResults1
}
}
// #Buttons
@IBAction func btnDeleteGroup(sender: AnyObject)
{
var indexPath = NSIndexPath()
indexPath = self.collectionView.indexPathForItemAtPoint(self.collectionView.convertPoint(sender.center, fromView: sender.superview))!
let modIndexPath : NSIndexPath = NSIndexPath(forRow: indexPath.row-1, inSection: indexPath.section)
var result = self.fetchedResultsController_Group.objectAtIndexPath(modIndexPath) as? Group
// Reset selectedItemIndex Logic : Delete
if (indexPath.row > selectedGroupIndex)
{
// selectedGroupIndex stays the same
}
else if (indexPath.row == selectedGroupIndex)
{
selectedGroupIndex = 1
}
else if (indexPath.row <= selectedGroupIndex)
{
selectedGroupIndex = selectedGroupIndex-1
}
/*
if(selectedGroupIndex == returnLastItemIndexInCollectionView())
{
selectedGroupIndex = 1
}
*/
AlertManager.instance.alertDeleteGroupConfirmation(result!.name, okBlock: {
// EXE
DataManager.instance.deleteSpecificGroup( Int(result!.id) )
}, cancelBlock: {})
btnEditSupport()
}
//temp
@IBAction func btnEdit(sender: AnyObject)
{
btnEditSupport()
}
func btnEditSupport()
{
isEditMode = !isEditMode
if(isEditMode)
{
btnEdit.setTitle("Done", forState: UIControlState.Normal)
}
else
{
btnEdit.setTitle("Edit", forState: UIControlState.Normal)
}
updateDataSource()
}
/*
// 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.
}
*/
// #CollectionView Delegate
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
let sectionInfo = self.fetchedResultsController_Group.sections![section] as NSFetchedResultsSectionInfo
return sectionInfo.numberOfObjects + 1
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
var cell: ContactListVcCollectionViewCell = collectionView.dequeueReusableCellWithReuseIdentifier("MyCell", forIndexPath: indexPath) as ContactListVcCollectionViewCell
/*
var isSelected = false
for (var i = 0; i < arySelectedItemsIndex.count; i++)
{
if(indexPath.row == arySelectedItemsIndex[i])
{
isSelected = true
}
}
*/
var isSelected = false
if(indexPath.row == selectedGroupIndex)
{
isSelected = true
}
// Display
var img = UIImage(named: "icon_delete.png")?.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate)
cell.imgDeleteGroup.image = img
cell.imgDeleteGroup.tintColor = UIColor.MBHred()
if ( indexPath.row == 0)
{
var img = UIImage(named: "icon_add.png")?.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate)
cell.imgGroupIcon.image = img
cell.imgGroupIcon.tintColor = UIColor.groupIconAddGroup()
cell.lbGroupName.text = "Add"
cell.lbGroupName.textColor = UIColor.groupIconAddGroup()
// hide delete button for [add group] & [All Contact]
cell.imgDeleteGroup.hidden = true
cell.btnDeleteGroup.hidden = true
}
else
{
let modIndexPath : NSIndexPath = NSIndexPath(forRow: indexPath.row-1, inSection: indexPath.section)
var result = self.fetchedResultsController_Group.objectAtIndexPath(modIndexPath) as? Group
cell.lbGroupName.text = result?.name
cell.lbGroupName.textColor = UIColor.groupIconNotSelected()
var img = UIImage(named: "group_\(result!.icon_id).png")?.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate)
// Display
cell.imgGroupIcon.image = img
cell.imgGroupIcon.tintColor = UIColor.groupIconNotSelected()
// Cell selected or not
if (isSelected)
{
cell.lbGroupName.textColor = UIColor.groupIconSelected()
cell.imgGroupIcon.tintColor = UIColor.groupIconSelected()
}
else
{
cell.lbGroupName.textColor = UIColor.groupIconNotSelected()
cell.imgGroupIcon.tintColor = UIColor.groupIconNotSelected()
}
// show delete button for [add group] & [All Contact]
// if the editmode is true
if (isEditMode && indexPath.row > 1)
{
cell.imgDeleteGroup.hidden = false
cell.btnDeleteGroup.hidden = false
}
else
{
cell.imgDeleteGroup.hidden = true
cell.btnDeleteGroup.hidden = true
}
}
return cell
}
// NOTE: Since the first item is always "Add", remeber to use Index.row-1 to fetch from Array
/*
let modIndexPath : NSIndexPath = NSIndexPath(forRow: indexPath.row-1, inSection: indexPath.section)
*/
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
if ( indexPath.row == 0 )
{
// Add Group
let vc = self.storyboard?.instantiateViewControllerWithIdentifier("CreateGroupViewController") as CreateGroupViewController
vc.preferredContentSize = CGSizeMake(self.view.bounds.width-25, self.view.bounds.height*4/5)
vc.loadView()
vc.delegateCreateGroupVcDelegate = self
vc.title = "Create a Group"
vc.btnCancel.addTarget(self, action: Selector("dismissCreateGroupVc"), forControlEvents: UIControlEvents.TouchUpInside)
/*
self.navigationController?.pushViewController(vc, animated: true)
*/
popoverController_CreateGroupVc = WYPopoverController(contentViewController: vc)
popoverController_CreateGroupVc.delegate = self
popoverController_CreateGroupVc.presentPopoverFromRect(CGRectMake(self.collectionView.bounds.origin.x, self.collectionView.bounds.origin.y, self.collectionView.bounds.width, 50) , inView: self.view, permittedArrowDirections: WYPopoverArrowDirection.Any, animated: true)
}
else
{
selectedGroupIndex = indexPath.row
// Choose from existing group
let modIndexPath : NSIndexPath = NSIndexPath(forRow: indexPath.row-1, inSection: indexPath.section)
var result = self.fetchedResultsController_Group.objectAtIndexPath(modIndexPath) as? Group
selectedGroupId = result!.id as Int
getFetchedResultController_Contact(result!.id as Int)
collectionView.reloadData()
tableView.reloadData()
println("result?.id = \(result?.id)")
}
}
// #alertView Delegate
func alertView(alert: UIAlertView!, clickedButtonAtIndex buttonIndex: Int)
{
if (buttonIndex == 1)
{
if ((alert.textFieldAtIndex(0)?.text) != nil)
{
DataManager.instance.addGroup(alert.textFieldAtIndex(0)!.text, iconId: 1)
}
}
}
// #TableView Delegate
func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int
{
let sectionInfo = self.fetchedResultsController_Contact.sections![section] as NSFetchedResultsSectionInfo
return sectionInfo.numberOfObjects + 1
}
func tableView(tableView: UITableView!,
cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell!
{
let sectionInfo = self.fetchedResultsController_Contact.sections![indexPath.section] as NSFetchedResultsSectionInfo
var cell = tableView.dequeueReusableCellWithIdentifier("MyCell", forIndexPath: indexPath) as ContactListVcTableViewCell
/*
var isSelected = false
for (var i = 0; i < arySelectedItemsIndex.count; i++)
{
if(indexPath.row == arySelectedItemsIndex[i])
{
isSelected = true
}
}
*/
var isSelected = false
if(indexPath.row == selectedGroupIndex)
{
isSelected = true
}
/*
// Display
var img = UIImage(named: "icon_delete.png")?.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate)
cell.imgDeleteGroup.image = img
cell.imgDeleteGroup.tintColor = UIColor.redColor()
*/
// Last Row of the TableView : Add Button
if (indexPath.row == sectionInfo.numberOfObjects)
{
var img = UIImage(named: "icon_add.png")?.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate)
cell.imgAddContact.image = img
cell.imgAddContact.tintColor = UIColor.groupIconAddGroup()
cell.lbName.hidden = true
cell.imgAddContact.hidden = false
//cell.lbAddContact.hidden = false
/*
// hide delete button for [add group] & [All Contact]
cell.imgDeleteGroup.hidden = true
cell.btnDeleteGroup.hidden = true */
}
// Other Rows of the TableView : Display
else
{
let modIndexPath : NSIndexPath = NSIndexPath(forRow: indexPath.row, inSection: indexPath.section)
var result = self.fetchedResultsController_Contact.objectAtIndexPath(modIndexPath) as? Contact
cell.lbName.text = result?.name
cell.lbName.textColor = UIColor.groupIconNotSelected()
cell.lbName.hidden = false
cell.imgAddContact.hidden = true
/*
//temp
var img = UIImage(named: "group_\(result!.icon_url).png")?.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate)
// Display
cell.imgGroupIcon.image = img
cell.imgGroupIcon.tintColor = UIColor.groupIconNotSelected()
*/
/*
// Cell selected or not
if (isSelected)
{
cell.lbGroupName.textColor = UIColor.groupIconSelected()
cell.imgGroupIcon.tintColor = UIColor.groupIconSelected()
}
else
{
cell.lbGroupName.textColor = UIColor.groupIconNotSelected()
cell.imgGroupIcon.tintColor = UIColor.groupIconNotSelected()
}
*/
/*
// show delete button for [add group] & [All Contact]
// if the editmode is true
if (isEditMode)
{
cell.imgDeleteGroup.hidden = false
cell.btnDeleteGroup.hidden = false
}
else
{
cell.imgDeleteGroup.hidden = true
cell.btnDeleteGroup.hidden = true
}
*/
}
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
let sectionInfo = self.fetchedResultsController_Contact.sections![indexPath.section] as NSFetchedResultsSectionInfo
// Last Row of the TableView : Add Button
if (indexPath.row == sectionInfo.numberOfObjects)
{
//tmp_0309
/*
let vc = self.storyboard?.instantiateViewControllerWithIdentifier("SelectAddContactsTableViewControllerNav") as UINavigationController
vc.preferredContentSize = CGSizeMake(self.view.bounds.width-20, self.view.bounds.height*1/2)
vc.loadView()
let vc2 = vc.viewControllers[0] as SelectAddContactsTableViewController
vc2.delegateSelectAddContactsTableVcDelegate = self
vc2.selectedGroupId = selectedGroupId
popoverController_SelectAddContactsTableVc = WYPopoverController(contentViewController: vc)
popoverController_SelectAddContactsTableVc.delegate = self
popoverController_SelectAddContactsTableVc.presentPopoverFromRect(CGRectMake(self.collectionView.bounds.origin.x, self.collectionView.bounds.origin.y, self.collectionView.bounds.width, 50) , inView: self.view, permittedArrowDirections: WYPopoverArrowDirection.Any, animated: true)
*/
self.performSegueWithIdentifier("toSelectContactsVc", sender: self)
}
else
{
let modIndexPath : NSIndexPath = NSIndexPath(forRow: indexPath.row, inSection: indexPath.section)
var result = self.fetchedResultsController_Contact.objectAtIndexPath(modIndexPath) as? Contact
contactIndex = indexPath.row
let myRect : CGRect = tableView.rectForRowAtIndexPath(indexPath)
var myRectMod : CGRect = CGRect(x: myRect.origin.x, y: myRect.origin.y, width: 20, height: myRect.height)
// Display ContactListDetailVc Popover
let vc = self.storyboard?.instantiateViewControllerWithIdentifier("ContactListDetailViewController") as ContactListDetailViewController
vc.loadView()
vc.delegateContactListDetailVcDelegate = self
vc.contactId = result!.id as Int
vc.title = "Contact Detail"
//vc.btnCancel.addTarget(self, action: Selector("dismissCreateGroupVc"), forControlEvents: UIControlEvents.TouchUpInside)
//vc.preferredContentSize = CGSizeMake( self.view.bounds.width-50, self.view.bounds.height-85)
vc.preferredContentSize = CGSizeMake( self.view.bounds.width-20, 270)
popoverController_ContactListDetailVc = WYPopoverController(contentViewController: vc)
popoverController_ContactListDetailVc.delegate = self
popoverController_ContactListDetailVc.presentPopoverFromRect(myRectMod, inView: self.tableView, permittedArrowDirections: WYPopoverArrowDirection.Up, animated: true)
//popoverController.presentPopoverAsDialogAnimated(true, options: WYPopoverAnimationOptions.FadeWithScale)
}
}
func tableView(tableView: UITableView!, canEditRowAtIndexPath indexPath: NSIndexPath!) -> Bool {
let sectionInfo = self.fetchedResultsController_Contact.sections![indexPath.section] as NSFetchedResultsSectionInfo
// Last Row of the TableView : Add Button
if (indexPath.row == sectionInfo.numberOfObjects)
{
return false
}
else
{
return true
}
}
func tableView(tableView: UITableView!, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath!) {
if (editingStyle == UITableViewCellEditingStyle.Delete) {
// handle delete (by removing the data from your array and updating the tableview)
let modIndexPath : NSIndexPath = NSIndexPath(forRow: indexPath.row, inSection: indexPath.section)
var result = self.fetchedResultsController_Contact.objectAtIndexPath(modIndexPath) as? Contact
DataManager.instance.deleteContactFromGroup(selectedGroupId, contactId: result?.id as Int)
/*
if (groupIndex != 0 )
{
DataManager.instance.deleteContactFromGroup(groupId, contactId: DataManager.instance.contact_id[indexPath.row])
}
else
{
DataManager.instance.deleteSpecificContact(DataManager.instance.contact_id[indexPath.row])
}
*/
//DataManager.instance.group_id.removeAtIndex(indexPath.row)
//DataManager.instance.group_name.removeAtIndex(indexPath.row)
//DataManager.instance.group_iconId.removeAtIndex(indexPath.row)
//tableView.reloadData()
}
}
...
这是我的构建设置...
转到“编辑方案”>“存档”>“构建配置”。
只需将"release"更改为"debug",存档版本将与本地调试版本完全相同。
iTunes 版本现在可用!!