合成的NSNumber“超出范围”

时间:2012-06-28 14:40:38

标签: objective-c nsnumber synthesize

我正在做一个抓取我的YouTube订阅视频的iOS应用。 当我想要导航到第三次看下一个视频时,我遇到了问题。

对于这些,我需要收集start-index(NSNumber * youtubeStart)来添加它显示的视频数量(int const maxVideos)。

为此,我有我的VideosViewController.h

@interface VideosViewController : UIViewController {
    NSNumber *youtubeStart;
}

@property (nonatomic, retain) NSNumber *youtubeStart;

然后在VideosViewController.m

@synthesize youtubeStart;
static int const maxVideos = 6;

一个做

的方法
- (void) navigateVideos:(id)sender
{
    int navigate = 0;
    int start = [youtubeStart intValue];

    if(sender == bt_prev)
    {
        if(start >= maxVideos)
        {
            start -= maxVideos;
            navigate = 1;
        }
    }

    if(sender == bt_next)
    {
        start += maxVideos;
        navigate = 1;
    }

    if (navigate > 0)
    {   
        youtubeStart = [NSNumber numberWithInt:start];
        NSString *url = [NSString
             stringWithFormat:@"%@&start-index=%i&max-results=%i"
             , myUrl, [youtubeStart intValue], maxVideos];
        [self LoadOAuthUrl:url];
    }
}

当我“TouchUpInside”其中一个按钮“bt_prev”或“bt_next”时,它会调用“navigateVideos”。 我可以根据需要多次按bt_prev或bt_next,但是如果我连续3次按bt_next,youtubeStart就会超出范围。它似乎无法超越第三页。

你能帮我理解为什么以及如何处理它。

我的其他合成变量不在范围之外。

非常感谢你的帮助。

编辑:我在x-code上运行ipad模拟器上的应用程序。应用程序崩溃时出现EXC_BAD_ACCESS错误。 youtubeStart似乎在“int start = [youtubeStart intValue];”之前的调试器中“超出范围”这就是崩溃的原因。当它正常工作时,youtubeStart不会超出范围。

编辑2: 堆栈跟踪总是丢失。 我刚刚在调试器控制台中得到了这个:

Program received signal:  “EXC_BAD_ACCESS”.

这在调试器中有一个红色箭头:

0x0134d0b0  <+0036>  cmp    ecx,DWORD PTR [eax]

2 个答案:

答案 0 :(得分:0)

您未能遵守Cocoa内存管理规则。你的正确代码应该是

self.youtubeStart = [NSNumber numberWithInt:start];

答案 1 :(得分:0)

此问题是由于您未正确使用属性引起的。在为self.youtubeStart属性分配新值时,应始终使用youtubeStart。这样,您的财产就可以保留该对象。当您直接分配给iVar时,实际的NSNumber对象不会被保留,这意味着当您稍后访问它时(例如,当您调用start = [youtubeStart intValue]时)该对象可能已被自动释放。 / p>

我猜测'超出范围'错误确实意味着该对象已被释放。

这是我推荐的......

在VideosViewController.h中的@interface删除此代码:

{
    NSNumber *youtubeStart;
}

并将您的@synthesize更改为:

@synthesize youtubeStart = _youtubeStart;

然后,您将获得一些编译器错误/警告,您可以从代码中直接访问youtubeStart。通过更改self.youtubeStart

的访问权限来解决这些问题

这是使用属性的一个非常好的做法,因为它确保您不会意外地直接使用iVar。如果您确实想直接使用iVar,可以使用_youtubeStart(此{iVar由@synthesize行自动创建)。但是我建议不要使用它,除非你完全理解访问器和保留等的工作方式。

另外,如果您对这些内容感到困惑,我强烈建议您查看ARC:)