I have an existing iPhone app that I'm adding a UISplitViewController to. The iPad part works like a charm, but I'm having a guaranteed crash with the iPhone 6(S) Plus.
Setup - Master is a UITabBarController. Initial detail is a view with a placeholder logo view. Once an object is selected, detail is replaced with a UITabBarController.
Whenever I select an item and open up Detail in the iPhone 6 Plus and rotate it from portrait (detail only visible) to landscape (where the master would be visible), it crashes. This does not occur on rotation with the placeholder detail view.
Before the crash, it does call the delegate methods primaryViewControllerForExpandingSplitViewController and splitViewController(splitViewController: UISplitViewController, separateSecondaryViewControllerFromPrimaryViewController. However, everything works fine on the iPad.
I've done a ton of searching already and only seen a couple twitter mentions of this type of crash. Things like setting or not setting the displayModeButtonItem don't help.
I recreated this crash in a fresh project - it can be downloaded here:
https://github.com/sschale/SplitViewCrash/
Crash log:
Crashed Thread: 0 Dispatch queue: com.apple.main-thread
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_PROTECTION_FAILURE at 0x00007fff53609ff8
Exception Note: EXC_CORPSE_NOTIFY
VM Regions Near 0x7fff53609ff8:
MALLOC_TINY 00007f8405000000-00007f8405300000 [ 3072K] rw-/rwx SM=PRV
--> STACK GUARD 00007fff4fe0a000-00007fff5360a000 [ 56.0M] ---/rwx SM=NUL stack guard for thread 0
Stack 00007fff5360a000-00007fff53dff000 [ 8148K] rw-/rwx SM=COW thread 0
Thread 0 Crashed:: Dispatch queue: com.apple.main-thread 0 liboainject.dylib 0x000000010e5e59b2
0 liboainject.dylib 0x000000010e5e59b2
_writeEventToSharedMemory + 27
1 liboainject.dylib 0x000000010e5e55d7 _OARecordFinalEvent + 1161
2 liboainject.dylib 0x000000010e5e79f1 ___swapMethods_block_invoke_6 + 338
3 libobjc.A.dylib 0x000000010f4f9b6b weak_read_no_lock + 89
4 libobjc.A.dylib 0x000000010f4fa4c6 objc_loadWeakRetained + 104
5 com.apple.UIKit 0x00000001110510b6 -[UIViewController presentedViewController] + 58
6 com.apple.UIKit 0x0000000111033fc6 -[UIViewController _canBecomeDeepestUnambiguousResponder] + 31
7 com.apple.UIKit 0x0000000111033fde -[UIViewController _canBecomeDeepestUnambiguousResponder] + 55
8 com.apple.UIKit 0x0000000111033fde -[UIViewController _canBecomeDeepestUnambiguousResponder] + 55
9 com.apple.UIKit 0x0000000111033fde -[UIViewController _canBecomeDeepestUnambiguousResponder] + 55
10 com.apple.UIKit 0x0000000111033fde -[UIViewController _canBecomeDeepestUnambiguousResponder] + 55
//(500 more of those)
....
Thread 1:: Dispatch queue: com.apple.libdispatch-manager
0 libsystem_kernel.dylib 0x0000000116e49ee2 kevent64 + 10
1 libdispatch.dylib 0x0000000116ac57f0 _dispatch_mgr_invoke + 260
2 libdispatch.dylib 0x0000000116ac558a _dispatch_mgr_thread + 54
Thread 2:
0 libsystem_kernel.dylib 0x0000000116e495e2 __workq_kernreturn + 10
1 libsystem_pthread.dylib 0x0000000116e0d578 _pthread_wqthread + 1283
2 libsystem_pthread.dylib 0x0000000116e0b341 start_wqthread + 13
Thread 3:
0 libsystem_kernel.dylib 0x0000000116e495e2 __workq_kernreturn + 10
1 libsystem_pthread.dylib 0x0000000116e0d578 _pthread_wqthread + 1283
2 libsystem_pthread.dylib 0x0000000116e0b341 start_wqthread + 13
Thread 4:
0 libsystem_kernel.dylib 0x0000000116e495e2 __workq_kernreturn + 10
1 libsystem_pthread.dylib 0x0000000116e0d578 _pthread_wqthread + 1283
2 libsystem_pthread.dylib 0x0000000116e0b341 start_wqthread + 13
Thread 5:
0 libsystem_kernel.dylib 0x0000000116e495e2 __workq_kernreturn + 10
1 libsystem_pthread.dylib 0x0000000116e0d578 _pthread_wqthread + 1283
2 libsystem_pthread.dylib 0x0000000116e0b341 start_wqthread + 13
This crashes on iPad too. Use Multitasking to resize the app to Compact width (e.g. 1/3rd screen), press the Launch Detail button, then resize it to Regular width.
When you're in Compact width, the split view controller is "collapsed". That means that it no longer shows separate primary and secondary view controllers at the same time -- instead, it "collapses" them into a single view controller hierarchy. When it's in that environment, it often needs your help in order to act sensibly. The default behavior works well when both your primary and secondary view controllers are UINavigationControllers, but not in other cases.
(In your app, your primary is a UITabBarController, and after you "Launch Detail" once, the secondary is also a UITabBarController. You may want to reconsider that design, because it makes things more difficult. Keep reading.)
Your app's "Launch Detail" button performs a "Show Detail" segue, which effectively calls this method on UISplitViewController:
public func showDetailViewController(vc: UIViewController, sender: AnyObject?)
Note the comment in the header:
// In a horizontally-compact environment the master view controller
// or detail view controller is sent the showViewController:sender:
// message. If neither one of them provide an implementation for this
// method then it will fall back to a full screen presentation.
By "master view controller or detail view controller", it means the view controller that is currently shown, which in your case is a UITabBarController. But UITabBarController does not implement anything for showViewController() because it doesn't have enough information -- where would it show a view controller? Would it add a new tab, or replace an old one, or what?
So, as a result, you get that fallback, full-screen presentation. I doubt you actually want that user experience.
Later on, when the size changes back to Regular and the split view controller expands, it gets confused by the presentation and eventually crashes. (See what I mean about the defaults not being very good?)
One way to fix this is to implement the delegate method to handle the showDetail. When the width is Compact, explicitly find the view controller you want to put the new view controller onto, and do it. I think you probably want to push onto the nav controller in the first tab:
func splitViewController(splitViewController: UISplitViewController, showDetailViewController vc: UIViewController, sender: AnyObject?) -> Bool
{
if splitViewController.traitCollection.horizontalSizeClass == .Compact {
// The default implementation will not handle this properly.
// Find the appropriate navigation controller and push onto it.
// It would be better to have a direct outlet to the appropriate navigation controller,
// but this will work for an example...
if let tabBarController = splitViewController.viewControllers.first as? UITabBarController {
if let navController = tabBarController.viewControllers?.first as? UINavigationController {
navController.pushViewController(vc, animated: true)
// we handled the "show detail", so split view controller,
// please don't do anything else
return true
}
}
}
// we did not handle the "show detail", so split view controller,
// please do your default behavior
return false
}
If you do that, you will also want to implement this delegate method. When the size is changed back to Regular, you will want to handle the "expand" by popping that view controller off of the same nav controller, then returning it:
optional public func splitViewController(
splitViewController: UISplitViewController
separateSecondaryViewControllerFromPrimaryViewController
primaryViewController: UIViewController) -> UIViewController?
Related
I can't figure out what's the reason of this crash?
Incident Identifier: BF4459C1-B97D-448E-AAE0-4DA6A1E4731C
CrashReporter Key: E725A626-A25C-4923-8383-0BC7ECA7DADE
Hardware Model: iPhone6,1
Process: SampleProject [480]
Path: /var/containers/Bundle/Application/458F9694-4BDA-4207-8C90-C2192520F8E2/SampleProject.app/SampleProject
Identifier: com.mydomain.SampleProject
Version: 1.3.0 (1.3.0.36)
Code Type: ARM-64
Parent Process: ??? [1]
Date/Time: 2017-05-17T04:11:03Z
Launch Time: 2017-05-17T04:06:51Z
OS Version: iPhone OS 10.3.1 (14E304)
Report Version: 104
Exception Type: SIGSEGV
Exception Codes: SEGV_ACCERR at 0xfffffffffffffff8
Crashed Thread: 0
Application Specific Information:
Selector name found in current argument registers: _setLayoutAttributes:atGlobalItemIndex:
Thread 0 Crashed:
0 UIKit 0x000000018de7d38c -[UICollectionViewData _setLayoutAttributes:atGlobalItemIndex:] + 80
1 UIKit 0x000000018de7ac94 __45-[UICollectionViewData validateLayoutInRect:]_block_invoke + 1892
2 UIKit 0x000000018de79f68 -[UICollectionViewData validateLayoutInRect:] + 1492
3 UIKit 0x000000018de8023c -[UICollectionViewData layoutAttributesForElementsInRect:] + 264
4 UIKit 0x000000018de7dbc0 -[UICollectionView _updateVisibleCellsNow:] + 548
5 UIKit 0x000000018dfea058 -[UICollectionView _setupCellAnimations] + 28
6 UIKit 0x000000018dff459c -[UICollectionView _beginUpdates] + 44
7 UIKit 0x000000018e72c8c0 -[UICollectionView _performBatchUpdates:completion:invalidationContext:tentativelyForReordering:animator:] + 256
8 UIKit 0x000000018e72c79c -[UICollectionView _performBatchUpdates:completion:invalidationContext:tentativelyForReordering:] + 92
9 UIKit 0x000000018e72c720 -[UICollectionView _performBatchUpdates:completion:invalidationContext:] + 80
10 UIKit 0x000000018dff4558 -[UICollectionView performBatchUpdates:completion:] + 60
11 SampleProject 0x000000010002a4b8 -[InvitesDataSource didDeleteDataAtIndexes:loadDataAtIndexes:] (InvitesDataSource.m:50)
12 SampleProject 0x0000000100092f58 -[DialogsController _didReceiveOldestInvites:] (DialogsController.m:311)
13 SampleProject 0x0000000100092500 -[DialogsController _didReceiveOldestDialogs:ofType:] (DialogsController.m:248)
14 SampleProject 0x000000010004aad8 -[DialogsController(Notifications) dialogListDidReceived:] (DialogsController+Notifications.m:94)
Piece of code mentioned in crashlog is quite peaceful:
- (void)didDeleteDataAtIndexes:(NSIndexSet *)deleted loadDataAtIndexes:(NSIndexSet *)loaded {
[self.collectionView performBatchUpdates:^{
[deleted enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
[self.collectionView deleteItemsAtIndexPaths:[self _indexPathsForIndex:idx]];
}];
[loaded enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
[self.collectionView insertItemsAtIndexPaths:[self _indexPathsForIndex:idx]];
}];
} completion:^(BOOL finished) {
[self.collectionView reloadData];
}];
}
This may be happening because you do need to also make sure with collectionViews to delete and insert sections. when you try to insert an item in a section that doesn't exist you will get this crash.
Preform Batch updates doesn't know that you meant to add section X+1 when you insert an item at X+1, X. without you already having added that section in.
make sure to use insert and delete section:
https://developer.apple.com/documentation/uikit/uicollectionview/1618090-insertsections
https://developer.apple.com/documentation/uikit/uicollectionview/1618102-deletesections
To insert, delete, or move a single section or item, you must follow these steps:
Update the data in your data source object.
Call the appropriate method of the collection view to insert or delete the section or item.
It is critical that you update your data source before notifying the collection view of any changes. The collection view methods assume that your data source contains the currently correct data. If it does not, the collection view might receive the wrong set of items from your data source or ask for items that are not there and crash your app.
I want my App to show IncomingCall ViewController, when App Receives Some Incoming Call.
This is my Code that I uses to show Incoming Call.. From my ContactsViewController, which is Active View when Incoming Call take places.
- (void)showIncomigCallVC{
[self performSegueWithIdentifier:#"segueToIncomingCallVC" sender:nil];
}
This is my Code, that is called by Library.
/* Callback called by the library upon receiving incoming call */
static void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id,
pjsip_rx_data *rdata)
{
pjsua_call_info ci;
PJ_UNUSED_ARG(acc_id);
PJ_UNUSED_ARG(rdata);
pjsua_call_get_info(call_id, &ci);
PJ_LOG(3,(THIS_FILE, "....\n\n\n Incoming call from %.*s!! \n\n\n",
(int)ci.remote_info.slen,
ci.remote_info.ptr));
ContactsViewController *incomingCallVC = [[ContactsViewController alloc]init];
[incomingCallVC showIncomigCallVC];
/* Automatically answer incoming calls with 200/OK */
pjsua_call_answer(call_id, 200, NULL, NULL);
}
And This is my Console Output:
20:39:37.482 XCPjsua.c ......
Incoming call from <sip:eeshaMiss12#ekiga.net>!!
2017-01-16 20:39:37.494 simpleVoIP[922:19652] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Receiver (<ContactsViewController: 0x7bea3d00>) has no segue with identifier 'segueToIncomingCallVC''
*** First throw call stack:
(
0 CoreFoundation 0x03a14212 __exceptionPreprocess + 194
1 libobjc.A.dylib 0x034d3e66 objc_exception_throw + 52
2 UIKit 0x01a69893 -[UIViewController shouldPerformSegueWithIdentifier:sender:] + 0
3 simpleVoIP 0x00089ba6 -[ContactsViewController showIncomigCallVC] + 70
4 simpleVoIP 0x00086caf on_incoming_call + 255
5 simpleVoIP 0x000fc273 pjsua_call_on_incoming + 3811
6 simpleVoIP 0x00103294 mod_pjsua_on_rx_request + 84
7 simpleVoIP 0x0012938f pjsip_endpt_process_rx_data + 351
8 simpleVoIP 0x00128bf2 endpt_on_rx_msg + 546
9 simpleVoIP 0x0012fba1 pjsip_tpmgr_receive_packet + 849
10 simpleVoIP 0x001315ec udp_on_read_complete + 316
11 simpleVoIP 0x0014b8e0 ioqueue_dispatch_read_event + 704
12 simpleVoIP 0x0014d5b2 pj_ioqueue_poll + 946
13 simpleVoIP 0x001290c3 pjsip_endpt_handle_events2 + 163
14 simpleVoIP 0x00102023 worker_thread + 99
15 simpleVoIP 0x0014eb96 thread_main + 86
16 libsystem_pthread.dylib 0x04c8a11b _pthread_body + 184
17 libsystem_pthread.dylib 0x04c8a063 _pthread_body + 0
18 libsystem_pthread.dylib 0x04c8993e thread_start + 34
)
libc++abi.dylib: terminating with uncaught exception of type NSException
I am Beginner, any Recommendation will be appreciated.. Thanks in Advance
You are experiencing the crash, because you are programatically allocating your ContactsViewController, instead of using from the storyboard.
When you do this:
ContactsViewController *incomingCallVC = [[ContactsViewController alloc]init];
[incomingCallVC showIncomigCallVC];
You are creating an instance of ContactsViewController, what has nothing to do with the one created in our storyboard.
It would be possible to overcome on this, however, you are trying to make a segue call on a viewController, what has only been loaded to the memory, but is not visible at all. That will never work, it will always crash.
I would recommend to show your viewController, whatever is behind the segue, straight away, instead of creating a viewController and show it with a segue.
EDIT:
Using the code below, you should be able to present your desired UIViewController subclass from the end of your callback function.
// Lets get keywindow
UIWindow* keyWindow = [[[UIApplication sharedApplication] delegate] window];
keyWindow.frame = [UIScreen mainScreen].bounds;
// Lets get `IncomingCallViewController` from storyboard
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"TheNameOfYourStoryboard" bundle:nil];
// do not forget to set the identifier of your viewController on the storyboard as "IncomingCallViewController"
UIViewController *vc = [sb instantiateViewControllerWithIdentifier:#"IncomingCallViewController"];
// Lets present the keyWindow from the main thread
dispatch_async(dispatch_get_main_queue(), ^{
keyWindow.rootViewController = vc;
[keyWindow makeKeyAndVisible];
});
I am running unit tests against my view controllers. There are two view controllers in this suite, one of them has a segue to the other in the storyboard file.
In tests for both controllers, I create my test subject in same way: i get a storyboard with storyboardWithName:factory:bundle: (Typhoon for dependency injection uses the factory thing). Then, I use storyboard.instantiateViewControllerWithIdentifier: to get the VC.
In tests for my first view controller, all tests pass. Importantly, the view controller's deinit method is called ONLY when the vc itself goes out of scope in the test cases, or a new instance becomes the subject and the old one has its retain count reduced to 0.
however, in tests for the second VC, the tests fail in either of these cases (the VC goes out of scope or a new one becomes the subject) because for some reason there is a call being made to [UIStoryboardScene dealloc] which in turn calls deinit on the controller, even though its retain count should still be 1 (retained by the test case). ARC sends another release message to the VC when I set a new instance as the subject, and I get EXC_BAD_ACCESS (CODE=i386, GPFLT).
The [UIStoryboardScene dealloc] happens in a bunch of compiled code in XCTest framework (copied here), but I believe it's happening because the test case is ending, even though it shouldn't.
* thread #1: tid = 0x57cf91, 0x00000001089953a3 sbprod`Mode2ViewController.__deallocating_deinit(self=0x00007fd2bbdde5d0) + 19 at Mode2ViewController.swift:68, queue = 'com.apple.main-thread', stop reason = breakpoint 3.1
* frame #0: 0x00000001089953a3 sbprod`Mode2ViewController.__deallocating_deinit(self=0x00007fd2bbdde5d0) + 19 at Mode2ViewController.swift:68
frame #1: 0x0000000108995492 sbprod`#objc Mode2ViewController.__deallocating_deinit + 34 at Mode2ViewController.swift:0
frame #2: 0x000000010a1ff702 UIKit`-[UIStoryboardScene dealloc] + 36
frame #3: 0x000000010b04dafe libobjc.A.dylib`objc_object::sidetable_release(bool) + 232
frame #4: 0x000000010b04e0b8 libobjc.A.dylib`(anonymous namespace)::AutoreleasePoolPage::pop(void*) + 488
frame #5: 0x0000000115841f37 XCTest`__24-[XCTestCase invokeTest]_block_invoke_2 + 430
frame #6: 0x0000000115876613 XCTest`-[XCTestContext performInScope:] + 190
frame #7: 0x0000000115841d78 XCTest`-[XCTestCase invokeTest] + 169
frame #8: 0x00000001158423a2 XCTest`-[XCTestCase performTest:] + 459
frame #9: 0x000000011583fcf7 XCTest`-[XCTestSuite performTest:] + 396
frame #10: 0x000000011583fcf7 XCTest`-[XCTestSuite performTest:] + 396
frame #11: 0x000000011583fcf7 XCTest`-[XCTestSuite performTest:] + 396
frame #12: 0x000000011582cb10 XCTest`__25-[XCTestDriver _runSuite]_block_invoke + 51
frame #13: 0x000000011584db4c XCTest`-[XCTestObservationCenter _observeTestExecutionForBlock:] + 640
frame #14: 0x000000011582ca55 XCTest`-[XCTestDriver _runSuite] + 453
frame #15: 0x000000011582d7d1 XCTest`-[XCTestDriver _checkForTestManager] + 259
frame #16: 0x0000000115877a9a XCTest`_XCTestMain + 628
So:
Why is the UIStoryboardScene being created at all? I don't want a scene, just a VC, for my tests. It doesn't appear to happen in the previous test case. I think the only differences as far as the storyboard cares between the two VCs is that one of them has a segue into it, and the other out of it.
If the UIStoryboardScene is in fact existing in both cases, why is it deiniting my VC before it ought to?
My test cases are also not very different from one another in scope, however this test case passes some closures to places and I'm not 100% on how closures affect ARC.
EDIT: relevant code shown here.
In my test case, which is made using Quick:
override func spec() {
var subject: Mode2ViewController!
let presentDisplayString = "DesiredString"
describe("Mode2ViewController") {
describe("loading") {
describe("date and location") {
context("when location is available") {
beforeEach {
let system = MockSystemComponents.CreateWith(location: true, groups: nil)
let assembly = ApplicationAssembly().activateWithCollaboratingAssemblies([
system
])
//crash occurs on next line, before the 2nd test case, because the
//old subject has already been deallocated (by UIStoryboardScene)
//but reassigning this var, which had retains it, triggers a release
subject = assembly.mode2ViewController() as! Mode2ViewController
let _ = subject.view
}
it("records the location") {
expect(subject).notTo(beNil())
}
it("displays the location as a meaningful string") {
expect(subject.locationLabel.text).to(equal(presentDisplayString))
}
}
}
}
}
}
Note: the stack trace given above (first edit) is from a breakpoint I inserted in Mode2ViewController.deinit().
Turns out that the problem was that objective c treats things which begin with the keyword new differently with regards to their retain count. Typhoon can't handle methods that begin with new for this reason (see issue).
Solution: rename my typhoon method and the object being generated has the correct retain count.
I'm implementing an iOS app. and found that sometimes the screen became black little by little.
for example, in a view controller, there are a collection view, a button, a page controller, and sometimes I found the collection view became black(or invisible), only black background is shown, after 1-2 seconds, the button is gone, then the whole screen is black. but if I put the app into background, then bring it back, everything is ok.
here is the code:
- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
NSTimeInterval timeLeft = [UIApplication sharedApplication].backgroundTimeRemaining - 1.0;
if(timeLeft < 0)
{
completionHandler(UIBackgroundFetchResultNoData);
}
//create new thread to do something, and sleep at current thread
...create new threads
[NSThread sleep:timeLeft];
completionHandler(UIBackgroundFetchResultNewData);
});
}
the issue could be reproduced if I repeat the following actions several times:
Do some thing
Put app to background(press home button)
Bring app back to foreground
repeat 1 - 3
we found following error in organizer for our app:
: CoreAnimation: warning, deleted thread with uncommitted CATransaction; set CA_DEBUG_TRANSACTIONS=1 in environment to log backtraces.
after added , I got the following log:
Myapp[11496] : CoreAnimation: warning, deleted thread with uncommitted CATransaction; created by:
0 QuartzCore 0x31ca6a75 + 268
1 QuartzCore 0x31ca6929 + 224
2 QuartzCore 0x31cabddb + 86
3 QuartzCore 0x31cab9f7 + 150
4 UIKit 0x3203f919 + 344
5 UIKit 0x320bb11b + 138
6 UIKit 0x322b0ebf + 218
7 UIKit 0x322b1169 + 104
8 UIKit 0x322b1735 + 36
9 Myapp 0x002e538d __61-[AppDelegate application:performFetchWithCompletionHandler:]_block_invoke + 632
10 libdispatch.dylib 0x3a487d53 + 10
11 libdispatch.dylib 0x3a48d689 + 228
12 libdispatch.dylib 0x3a48d8dd + 56
13 libsystem_pthread.dylib 0x3a5b8c17 _pthread_wqthread + 298
14 libsystem_pthread.dylib 0x3a5b8adc start_wqthread + 8
my questions is:
how could application:performFetchWithCompletionHandler cause animation issue?
to answer questions:
1. I'm sure that phone is not going to sleep
2. source code. sorry the project is too big
Check that you are working with UI on main thread only, this should be the case.
Edit: - I've seen this one, although never used it(written by Peter Steinberger).
Also this answer can help avoiding several more problems.
The thread created to perform your fetch invokes a call to update your ui, when it finishes performing whatever task it is doing, and its no longer needed it is deallocated. UIUpdates MUST be performed on the main thread or they might not be performed right away.
Have you tried dispatching to the main thread whatever ui update you are performing there?
It's hard to know what you your completion handler is doing, but if it's updating UI try to dispatch them on the main thread
- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
NSTimeInterval timeLeft = [UIApplication sharedApplication].backgroundTimeRemaining - 1.0;
if(timeLeft < 0)
{
dispatch_async(dispatch_get_main_queue(), ^{
completionHandler(UIBackgroundFetchResultNoData);
});
}
//create new thread to do something, and sleep at current thread
...create new threads
[NSThread sleep:timeLeft];
dispatch_async(dispatch_get_main_queue(), ^{
completionHandler(UIBackgroundFetchResultNewData);
});
});
}
On sporadic occasions I'm getting an EXC_BAD_ACCESS (SIGSEV) in one of Apple's Accelerator framework methods, vDSP_fft2d_zip. The crash report gave the following for Thread 10. Again, most of the time this works like a champ. Any ideas on how to find the cause and fix it?
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0x412f2740
Triggered by Thread: 10
. . .
Thread 10 Crashed:
0 libvDSP.dylib 0x2ddfcdb4 ___lldb_unnamed_function431$$libvDSP.dylib + 68
1 libvDSP.dylib 0x2ddfab66 ___lldb_unnamed_function427$$libvDSP.dylib + 562
2 libvDSP.dylib 0x2ddfa8ee vDSP_fft2d_zop + 434
3 libvDSP.dylib 0x2ddfa732 vDSP_fft2d_zip + 18
4 ASSIST for iPad 0x000ac32e -[Processor setupFilterForBubbleSizeMM:rectWidth:rectImageWidth:dataFilled:dataUnfilled:] (Processor.mm:813)
5 ASSIST for iPad 0x000af4d2 -[Processor runConvolutionProcessOnImage:aveImage:] (Processor.mm:1835)
6 ASSIST for iPad 0x000ac5f6 -[Processor processAnswers] (Processor.mm:869)
7 ASSIST for iPad 0x000ae9cc -[Processor process] (Processor.mm:1644)
8 ASSIST for iPad 0x000d7744 -[ReallTimeScanner processImage:] (ReallTimeScanner.mm:1046)
9 Foundation 0x2f296c82 __NSThread__main__ + 1058
10 libsystem_pthread.dylib 0x396b6c1a _pthread_body + 138
11 libsystem_pthread.dylib 0x396b6b8a _pthread_start + 98
12 libsystem_pthread.dylib 0x396b4c8c thread_start + 4
The relevant code looks like this:
#define FFT_SIZE 512
#define FFT_POWER 9
dataFilledIn->imagp=(float *) malloc(sizeof(float)*FFT_SIZE*FFT_SIZE);
dataFilledIn->realp=(float *) malloc(sizeof(float)*FFT_SIZE*FFT_SIZE);
dataUnfilledIn->imagp=(float *) malloc(sizeof(float)*FFT_SIZE*FFT_SIZE);
dataUnfilledIn->realp=(float *) malloc(sizeof(float)*FFT_SIZE*FFT_SIZE);
memset(dataFilledIn->imagp, 0, sizeof(float)*FFT_SIZE*FFT_SIZE);
memset(dataFilledIn->realp, 0, sizeof(float)*FFT_SIZE*FFT_SIZE);
memset(dataUnfilledIn->imagp, 0, sizeof(float)*FFT_SIZE*FFT_SIZE);
memset(dataUnfilledIn->realp, 0, sizeof(float)*FFT_SIZE*FFT_SIZE);
for(float y=0; y<FFT_SIZE; y+=0.25)
{
for(float x=0; x<FFT_SIZE; x+=0.25)
{
dataFilledIn->realp[(int)y*FFT_SIZE+(int)x] += 0.0625;
dataUnfilledIn->realp[(int)y*FFT_SIZE+(int)x] -= 0.0625;
}
}
vDSP_fft2d_zip(setup, dataFilledIn, 1, 0, FFT_POWER, FFT_POWER, kFFTDirection_Forward);
Answering my own question here: Be sure that the very first parameter sent in (type FFTSetup) to vDSP_fft2d_zip() is initialized correctly, and you should use this call
vDSP_destroy_fftsetup(setup);
to clean it up. I was initializing the setup var properly, like this
setup = vDSP_create_fftsetup(FFT_POWER, kFFTRadix2);
and then cleaning it up, but then was not initializing it again before subsequent calls to vDSP_fft2d_zip(). Unfortunately it only rarely caused a crash, which made it seem like the frequent calls to vDSP_fft2d_zip(setup, . . .) were working when they weren't. The crashes were sporadic making the real cause hard to trace.
There are some articles in Raywenderlich may help you:
Objectively Speaking: A Crash Course in Objective C for iOS 6
Objectively Speaking 2: A Crash Course in Objective C for iOS 6