Objective C - how to programmatically stop execution for debugging, while allowing continuation?

There's a way. It's not an Objective-C thing, it's a Unix thing.

kill(getpid(), SIGSTOP);

or simply:

raise(SIGSTOP);

In Swift:

raise(SIGSTOP)

This will break in the debugger in the __kill or __pthread_kill function. You will need to then go up a few stack frames to look at the frame that called kill or raise. You can use the debugger`s continue command to resume execution.

Note that if you're not running under the debugger and you execute this, your app will just hang. Take a look at [Technical Q&A QA1631: Detecting the Debugger](http://developer.apple.com/library/mac/#qa/qa1361/_index.html. You can use that information to write a wrapper function or macro that only sends SIGSTOP when running under the debugger. This answer may help.

Also, the Foundation framework provides a different assert macro for use in regular functions. It's NSCAssert.


Sounds like you want to use Conditional Breakpoints. If you set a breakpoint by clicking in the margin of your source code, then ctrl-click the little blue breakpoint thing, you can edit some options, including making the breakpoint conditional on the value of a variable.

Here's a blog post with some screenshots and more info.

This Stack Overflow question has some good pointers, too.


If you insist on triggering the breakpoint programmatically, then write a function and put a breakpoint inside it:

void MyConditionalBreak(BOOL condition, NSString *comment)
{
    if (condition) {
        NSLog(@"Stopped because %@", comment); // SET BREAKPOINT ON THIS LINE
    }
}

Then you can call this function in a similar manner to NSAssert. If you declare the function in your project's precompiled header file (Whatever.pch) it will be available in all of your source files, without having to explicitly #import anything.


Here is how I do it:

First, in breakpoints tab I set my apps to break if any exception is raised: All Exceptions

Then In code (I usually have common header file containing common definitions like this that I import everywhere):

static void ThrowException(NSString* reason)
{
   @try 
   {
      @throw [NSException
               exceptionWithName:@"DebugAssertionException"
               reason:reason
               userInfo:nil];
   }  
   @catch (NSException * e) 
   {
      NSLog(@"%@", e);
   }
}

#define MYAssert(test, fmt, ...) if (!(test)) { ThrowException([NSString stringWithFormat:@"%s !!! ASSERT !!! " fmt, __PRETTY_FUNCTION__, ##__VA_ARGS__]); }

Now, You can use it like NSAssert, but instead of killing your app, you merely trigger a breakpoint:

MYAssert(bEverythingOkay, @"Something went wrong!");

// Or with arguments of course
MYAssert(bEverythingOkay, @"Something went wrong (TestValue=%zd; Reason=%@)", myTestValue, [this getLastError]);