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;
}

它似乎从第二个参数(mappedViewFrame)中得到了错误的值。在查找错误时,我发现 mappedViewFrame 被破坏(在内存中被覆盖?)。这可以在调试器中轻松观察到:

flickr 上的调试器屏幕截图(我还不能发布图像)

副本仍然保留原始值,因此在这种情况下使用副本是一种解决方法。但我当然想了解为什么会发生这种情况。该类是 NSObject 的直接子类,整个项目是一个 OS X 原生应用程序。第一个论点从未被摧毁。问题与传入的值无关。我切换了它们,它总是第二个被破坏。

例如,我使用这些示例参数调用了初始化程序(与调试器屏幕截图中的不同),错误以相同的方式发生:

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,一切都按预期工作。所以以前不起作用的相同代码现在起作用了,我认为这可能有两个原因:

  1. 我的实现中还有另一个错误,导致计算结果错误。在引入“复制”变量时(在看到奇怪的调试器输出之后),我在没有注意到的情况下修复了另一个错误。之后,我将修复归功于我的新复制解决方案。

  2. 当我第一次遇到问题时,一个未知因素导致变量失真,现在不这样做了。好吧,为了保证我将副本留在那里,并检查该值是否保持不变。如果发生这种情况,我会在这里发布。在那之前,第一个理论更有可能。

这件事教会我不要信任调试器,而是在有疑问时使用日志记录,这很痛苦。如果有人知道是什么导致了奇怪的调试器输出或如何修复它,我将不胜感激。如果我有时间,我会进一步研究它何时出现,如果它只是在 xcode 中发生,或者是 gnu 调试器的一般问题。

于 2011-01-23T10:26:52.840 回答
0

我已经在几分钟内快速尝试过了。我从来没有真正尝试过创建 Mac OS X 项目,只是 Foundation 和 iPhone 项目,但想法似乎相同。我创建了一个 Cocoa 应用程序项目“Stack1”。我假设你也做了同样的事情,因为我认为 Foundation 项目不会在不手动导入 CGGeometry.h 或其他东西的情况下支持 CGRect 结构......无论如何,我设置了一个名为“Mapper”的新 Objective C 类并实现了您指定的 initWithSourceFrame:mappedFrame: 方法。

映射器.h

#import <Cocoa/Cocoa.h>

@interface Mapper : NSObject {

}

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

@end

映射器.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 回答