13

条件がプログラムで指定されたときに、Objective Cの標準のNSAssert(condition_which_should_evaluate_true、@ "error message")ステートメントを使用し、ブレークポイントナビゲーターに「AllExceptions」ブレークポイントを追加して、デバッグビルドで実行を停止することに成功しました。

よくできましたが、ほとんどの場合、デバッグ中は、それ以降も通常のプログラム実行を継続したいと思います。多くの場合、アサーションが失敗した後にプログラムを続行すると、混乱/バグの原因を突き止めるのに役立ちます。少なくとも、私が別のプラットフォームでプログラミングしていたときのことを覚えています。

Objective Cの開発でそうするための標準的な方法はありますか?

4

7 に答える 7

15

方法があります。これはObjective-Cのものではなく、Unixのものです。

kill(getpid(), SIGSTOP);

または単に:

raise(SIGSTOP);

Swiftの場合:

raise(SIGSTOP)

__killこれにより、 or関数のデバッガーが機能しなくなり__pthread_killます。kill次に、またはを呼び出したフレームを確認するために、いくつかのスタックフレームを上に移動する必要がありますraise。デバッガのcontinueコマンドを使用して実行を再開できます。

デバッガーで実行しておらず、これを実行すると、アプリがハングすることに注意してください。[Technical Q&A QA1631:Detecting the Debugger](http://developer.apple.com/library/mac/#qa/qa1361/_index.htmlをご覧ください。この情報を使用して、ラッパー関数またはマクロを作成できます。SIGSTOPデバッガーで実行している場合にのみ送信します。この回答が役立つ場合があります。

また、Foundationフレームワークは、通常の関数で使用するための異なるアサートマクロを提供します。ですNSCAssert

于 2012-08-07T03:04:19.570 に答える
2

条件付きブレークポイントを使用したいようです。ソースコードの余白をクリックしてブレークポイントを設定し、小さな青いブレークポイントをCtrlキーを押しながらクリックすると、変数の値を条件としてブレークポイントを作成するなど、いくつかのオプションを編集できます。

これがいくつかのスクリーンショットと詳細情報を含むブログ投稿です。

このStackOverflowの質問にも、いくつかの良い指針があります。


プログラムでブレークポイントをトリガーすることを主張する場合は、関数を記述し、その中にブレークポイントを配置します。

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

次に、NSAssertと同様の方法でこの関数を呼び出すことができます。プロジェクトのプリコンパイル済みヘッダーファイル(Whatever.pch)で関数を宣言すると、明示的に#import何もしなくても、すべてのソースファイルで使用できるようになります。

于 2012-08-07T00:09:09.210 に答える
2

これが私がそれをする方法です:

まず、[ブレークポイント]タブで、例外が発生した場合にアプリを中断するように設定しました。 すべての例外

次に、コード内(私は通常、どこにでもインポートするこのような一般的な定義を含む一般的なヘッダーファイルを持っています):

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__]); }

これで、NSAssertのように使用できますが、アプリを強制終了する代わりに、ブレークポイントをトリガーするだけです。

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

// Or with arguments of course
MYAssert(bEverythingOkay, @"Something went wrong (TestValue=%zd; Reason=%@)", myTestValue, [this getLastError]);
于 2015-10-18T06:51:18.623 に答える
1

私はこの分野の専門家ではありませんが、キーボード入力を介してデバッガーに侵入できるコードを使用しています。

githubのdomesticcatsoftwareによるDCIntrospectがこれを行います。

メインファイルDCIntrospect.mの上部を見て、それがどのように行われるかを確認してください。

いくつかのソースを参照していますが、私の経験から、armv6/7のデバッガーとシミュレーターに侵入するために必要な現在のアセンブリについてはかなり最新です。

詳細な背景情報の外部参照

于 2012-08-07T01:14:09.370 に答える
1

なぜ誰も明確な答えを出さなかったのかわからない...5年経ちましたが、今までにないほど遅くなりました。


プリプロセッサ:

#ifdef DEBUG
#define manualBreakpoint() \
            NSLog(@"\n\n\
                    Breakpoint called on: \n\n\
                    File: %s \n\n\
                    Line number: %i", __FILE__, __LINE__);\
                                                          \
            raise(SIGSTOP)
#else
#define manualBreakpoint() ;
#endif

使用法:

使用するには、次のように入力するだけです。manualBreakpoint();

ノート:

これにより、そのコードが呼び出されたときにアプリが停止し、スタックトレースに現在のメソッドが表示されます(アプリが停止したファイル名と行番号もログに記録されます)。 appstore(別名リリース配布、またはアーカイブ)は何もしません。

于 2017-04-28T04:50:31.173 に答える
0

Robのコメント、「ios5プログラミング:限界を押し上げる」のアイデア、およびLumberjackフレームワークを使用して、DEBUGビルド中のアサーション中にデバッガーを停止して継続できるようにするマクロを次に示します。 RELEASE(または実際には非-DEBUG)ビルド。

#ifdef DEBUG

#define MyAssert(condition, desc, ...) \
if (!(condition)) { \
    NSLog((desc), ## __VA_ARGS__); \
    if (AmIBeingDebugged()) \
        kill (getpid(), SIGSTOP); \
    else { \
        NSLog(@"%@, %d: could not break into debugger.", THIS_FILE, __LINE__); \
    } \
}

#define MyCAssert(condition, desc, ...) \
if (!(condition)) { \
    NSLog((desc), ## __VA_ARGS__); \
    if (AmIBeingDebugged()) \
        kill (getpid(), SIGSTOP); \
    else \
        NSLog(@"%@, %d: could not break into debugger.", THIS_FILE, __LINE__)); \
    } \
}

#else  //NOT in DEBUG

#define MyAssert(condition, desc, ...) \
if (!(condition)) { \
    DDLogError((desc), ## __VA_ARGS__); \   //use NSLog if not using Lumberjack
    NSAssert((condition), (desc), ## __VA_ARGS__); \
}

#define MyCAssert(condition, desc, ...) \
if (!(condition)) { \
    DDLogError((desc), ## __VA_ARGS__); \   //use NSLog if not using Lumberjack
    NSCAssert((condition), (desc), ## __VA_ARGS__); \
}

#endif //end  DEBUG

#endif

これらのマクロには関数が必要です。この関数AmIBeingDebugged()は、Robが提供したリンクでAppleから入手できます。技術的なQ&A QA1631:デバッガーの検出。DEBUG(ビルド設定でも定義する必要があります。)

致命的なアサーションが発生したメソッド、ファイル、および行番号を吐き出すため、非ビルドでLumberjackを選択したことに注意してくださいDDLogError()NSLog()DEBUG

于 2012-08-24T02:55:24.163 に答える
0

コンソールを使用する場合の簡単なトリックは次のとおりです。

if (!condition_which_should_evaluate_true) {
   ; // Put breakpoint here
}

次に、その行の中にブレークポイントを置きます。条件がNOと評価された場合、ブレークポイントが呼び出されます。

于 2013-10-24T20:20:45.013 に答える