2

2 つの引数を持つ初期化子があります。

-(id) initWithSourceFrame:(CGRect)sourceViewFrame  mappedFrame:(CGRect)mappedViewFrame {
  CGRect copy = mappedViewFrame;
  self = [super init];
  if (self) {
    // not able to access mappedViewFrame here..
    // copy is ok
    // doing initialization here...
  }
  return self;
}

2 番目の引数 (mappedViewFrame) から間違った値を取得しているようです。エラーを探していると、mappedViewFrame が破棄される (メモリ内でオーバーライドされる) ことがわかりました。これは、デバッガーで簡単に確認できます。

flickrのデバッガーのスクリーンショット(まだ画像を投稿できません)

コピーはまだ元の値を保持しているため、この場合はコピーを使用することで回避できました。しかし、もちろん、なぜこれが起こるのかを理解したいと思っています。クラスは NSObject の直接のサブクラスであり、プロジェクト全体が OS X ネイティブ アプリです。最初の引数は破棄されませんでした。問題は、渡された値とは関係ありません。それらを切り替えましたが、常に破損したのは2番目でした。

たとえば、これらの例の引数 (デバッガーのスクリーンショットのものとは異なります) を使用して初期化子を呼び出したところ、同じようにエラーが発生しました。

Mapper *mapper = [[Mapper alloc] initWithSourceFrame:CGRectMake(0, 0, 100, 100) mappedFrame:CGRectMake(0,0, 200,200)];

メソッド宣言:

-(id) initWithSourceFrame:(CGRect) sourceViewFrame mappedFrame:(CGRect) mappedViewFrame;

私はObjective-Cに少し慣れていないので、何か明らかなことを見逃していたら申し訳ありません。ただし、メソッドの呼び出し中に引数が有効にならないのは奇妙に見えます。

4

2 に答える 2

1

デバッガーの代わりに NSLog を使用してエラーを再現しようとしたときに、考えられる解決策を見つけました。

面白いことに、ログに記録された値は正しかったのです。NSLog への呼び出しの直前に、デバッガーはスクリーンショットのようにガベージ出力を表示します。ただし、(NSLog または別のプログラムによるアクセスによって) 値にアクセスした後、デバッガーは正しい値を表示します。

したがって、デバッガーの問題のように見えます。一部のオブジェクトが割り当てられている場合、値の誤った表示が表示される可能性が高くなります。

疑問が残ります: なぜ私のプログラムは動かなかったのですか? 「コピー」変数を (2 行目から) 削除し、mappedViewFrame に直接アクセスすると、すべてが期待どおりに機能します。したがって、以前は機能しなかった同じコードが機能するようになりました。これには次の 2 つの理由が考えられます。

  1. 実装に別のエラーがあり、間違った計算結果が発生しました。'copy' 変数を導入したとき (奇妙なデバッガ出力を見た後)、気づかずに他のエラーを修正しました。その後、修正を新しいコピー ソリューションに反映させました。

  2. 最初に問題に遭遇したとき、未知の要因により変数が歪んでいましたが、今はそうではありません。念のため、コピーをそこに残して、値が変更されていないかどうかを確認します。これが発生する場合は、ここに投稿します。それまでは、最初の理論の可能性がはるかに高くなります。

このことは、デバッガーを信頼するのではなく、疑わしい場合はログを使用することを教えてくれました。これは苦痛です。奇妙なデバッガ出力の原因や修正方法を誰かが知っていれば、私はそれを大いに感謝します. 時間があれば、これがいつ表示されるのか、xcode だけで発生するのか、gnu デバッガー全般の問題なのかをさらに調べます。

于 2011-01-23T10:26:52.840 に答える
0

私はこれを数分ですぐに試しました。私は実際にMacOSXプロジェクトを作成しようとしたことはなく、FoundationプロジェクトとiPhoneプロジェクトだけを作成しようとしましたが、考え方は同じようです。Cocoaアプリケーションプロジェクト「Stack1」を作成しました。FoundationプロジェクトがCGGeometry.hなどを手動でインポートせずにCGRect構造体をサポートするとは思わないので、あなたも同じことをしたと思います...とにかく、「Mapper」と呼ばれる新しいObjectiveCクラスを設定して実装しました指定したinitWithSourceFrame:mappedFrame:メソッド。

Mapper.h

#import <Cocoa/Cocoa.h>

@interface Mapper : NSObject {

}

-(id) initWithSourceFrame:(CGRect) sourceViewFrame mappedFrame:(CGRect) mappedViewFrame;

@end

Mapper.m

#import "Mapper.h"

@implementation Mapper

-(id) initWithSourceFrame:(CGRect)sourceViewFrame  mappedFrame:(CGRect)mappedViewFrame {
    NSLog(@"height: %f, width: %f", mappedViewFrame.size.height, mappedViewFrame.size.width);
    self = [super init];
    NSLog(@"height: %f, width: %f", mappedViewFrame.size.height, mappedViewFrame.size.width);
    if (self) {
        NSLog(@"height: %f, width: %f", mappedViewFrame.size.height, mappedViewFrame.size.width);
    }
    return self;
}

@end

Stack1AppDelegate.hは変更しませんでした。

Stack1AppDelegate.m

#import "Stack1AppDelegate.h"
#import "Mapper.h"

@implementation Stack1AppDelegate

@synthesize window;

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    // Insert code here to initialize your application 
    Mapper *mapper = [[Mapper alloc] initWithSourceFrame:CGRectMake(0, 0, 100, 100) mappedFrame:CGRectMake(0,0, 200,200)];

}

@end

私のコードは、あなたと同じようにMapperインスタンスを割り当て、NSLogを使用して、[super init]の前、[super init]の後、およびif(self)ブロック内に幅と高さを出力するだけでした。

ログは次のとおりです。

2011-01-23 16:09:07.167 Stack1[935:a0f] height: 200.000000, width: 200.000000
2011-01-23 16:09:07.170 Stack1[935:a0f] height: 200.000000, width: 200.000000
2011-01-23 16:09:07.170 Stack1[935:a0f] height: 200.000000, width: 200.000000

プロジェクト全体もここにアップロードしました:

http://ak.net84.net/files/temp/Stack1.zip

于 2011-01-22T22:50:23.290 に答える