代码之家  ›  专栏  ›  技术社区  ›  ahmet emrah

iPhone:调用[nsbundle mainbundle]会在设备上崩溃,但不会在模拟器上崩溃。

  •  1
  • ahmet emrah  · 技术社区  · 16 年前

    基本上,问题就在于标题所说的。

    我的应用程序在模拟器上运行平稳,没有任何崩溃。 事实上,以前的版本在应用商店中。我在这里和那里做了一些小改动,突然它开始在一个非常奇怪的地方崩溃。

    我用 [NSBundle mainBundle] resourcepath] 在代码的各个地方访问plist文件、图像等,前几次调用 NSBundle mainBundle] 是完全正常的-但是,在某一点上,它返回…

    -[NSBundle < null selector>]: unrecognized selector sent to instance 0x10a0e0
    

    …并在设备上崩溃。下面是准确的代码段:

    -(void) setImageName:(NSString *)s
    {
     [imageName release];
     imageName = [s copy];
     NSLog(@"last line before crash"); 
     NSString *imagePath =[[NSBundle mainBundle] resourcePath];
     NSLog(@"Why would it crash before here???"); 
    
        imagePath = [imagePath stringByAppendingString:imageName];
        imageUI = [[UIImage alloc] initWithContentsOfFile:imagePath];
        [self setNeedsDisplay];
    }
    

    为了检查那个电话是否真的是问题所在,我保存了 resourcePath 在第一次调用 [NSBundle mainbundle] 在项目中(如我上面所述,前几个电话完全正常),并使用 资源库 我需要的任何地方都要串起来,瞧!没有碰撞/泄漏,没有…

    我完全困惑了……为什么那个呼叫会使我的应用程序在设备上崩溃,而不是模拟器?

    编辑: 使用。。。

    NSArray *array = [NSBundle allBundles];
    NSBundle *bundle = [array objectAtIndex:0];
    NSString *imagePath = [bundle bundlePath];
    

    …而不是 [[NSBundle mainBundle] resourcePath] 也工作。我想我只是在做一些影响这个电话的事情。

    编辑2 :这里是我在-[nsObject doesNotTrecognizeSelector]中设置断点时的回溯:

    #0  0x30e27b98 in -[NSObject doesNotRecognizeSelector:]
    #1  0x30dacb18 in ___forwarding___
    #2  0x30da3840 in __forwarding_prep_0___
    #3  0x0000bcfe in -[CustomTableViewCell setImageName:] at CustomTableViewCell.m:93
    #4  0x0000499e in -[RootTableViewController tableView:willDisplayCell:forRowAtIndexPath:] at RootTableViewController.m:469
    #5  0x3364d5d0 in -[UITableView(UITableViewInternal) _createPreparedCellForGlobalRow:withIndexPath:]
    #6  0x3364cde0 in -[UITableView(UITableViewInternal) _createPreparedCellForGlobalRow:]
    #7  0x335f832c in -[UITableView(_UITableViewPrivate) _updateVisibleCellsNow]
    #8  0x335f6514 in -[UITableView layoutSubviews]
    #9  0x335f22d8 in -[UIView(CALayerDelegate) _layoutSublayersOfLayer:]
    #10 0x32bac1c0 in -[CALayer layoutSublayers]
    #11 0x32babedc in CALayerLayoutIfNeeded
    #12 0x32bab844 in CA::Context::commit_transaction
    #13 0x32bab474 in CA::Transaction::commit
    #14 0x32bb35dc in CA::Transaction::observer_callback
    #15 0x30da1830 in __CFRunLoopDoObservers
    #16 0x30de9346 in CFRunLoopRunSpecific
    #17 0x30de8c1e in CFRunLoopRunInMode
    #18 0x332e7374 in GSEventRunModal
    #19 0x335adc30 in -[UIApplication _run]
    #20 0x335ac230 in UIApplicationMain
    

    …其中3-customtableviewscell.m:93是nsstring*imagepath=[[nsbundle mainbundle]resourcepath];在我上面发布的代码部分。

    6 回复  |  直到 16 年前
        1
  •  1
  •   TechZen    16 年前

    设备(而不是模拟器)上的崩溃(反之亦然)通常是由编译的库/框架引起的,该库/框架是为一个硬件平台而不是另一个硬件平台编译的。由于模拟器运行在Intel和ARM上的设备上,这会导致奇怪的崩溃。检查您可能添加的任何内容,尤其是最近未编译的任何内容。

    误差 -[NSBundle < null selector>]: unrecognized selector sent to instance 0x10a0e0 无论出于什么原因, NSBundle 班级已经“忘记”了,它有一个 mainBundle 方法。注意,它是一个空的选择器,而不是我们在与内存相关的错误中所期望的对象。这意味着某个地方的高层腐败。

    我会把下面的日志放在任何呼叫之前 [NSBundle mainBundle];

    NSLog(@"responds to selector mainBundle=%@",[NSBundle respondsToSelector:@selector(mainBundle)]?@"YES":@"NO");
    

    如果它真的突然失去了 主束 选择器。

    编辑01:

    谢谢你的回答。似乎 nsbundle声明它可以响应 mainbundle:“响应选择器 mainbundle=yes”,就在 紧急呼叫[nsbundle mainbundle]

    嗯,碰撞一定很严重,导致错误代码返回。这表明问题可能出现在调用mainbundle之前或之后的行中。

    考虑到崩溃发生在CustomTableViewCell中,我想这是NIB中的一个问题。您是否在NIB中定义了UITableViewCell的子类?你有笔尖上定义的图像吗?它是什么文件类型?同一错误是由不同的图像还是不同的笔尖引起的?

    我认为关键的线索是它在模拟器上工作,而不是在设备上。您需要根据硬件寻找行为不同的东西。

    你在这里肯定遇到了困难。

        2
  •  4
  •   Kendall Helmstetter Gelner    16 年前

    打开nszombieEnabled,您将看到问题的真正位置。

        3
  •  1
  •   Stefan Arentz    16 年前

    基本上,问题就在于标题所说的。 -不,不是。我可以向你保证 [NSBundle mainBundle] 车祸的原因。崩溃是代码的另一部分出错的症状。比如坏的内存管理。

        4
  •  1
  •   Daddy    16 年前

    请注意,在文档中硬编码路径字符串不是一个好主意。你的路径改变了(通常是每一个构建)。就崩溃而言,如果没有看到更多的代码,就很难知道了。但是看看这个建议:

    而不是

     [imagePath stringByAppendingString:imageName]; 
    

    你应该用

     [imagePath stringByAppendingPathComponent:imageName];
    

    StringByAppendingPathComponent特别适合处理路径和文件名。

        5
  •  1
  •   epatel    16 年前

    你应该能做到 [NSBundle mainBundle] 几乎任何时候。如果把它分散在代码上,以便在第一次中断时捕获它,那么最好是接近中断内存管理(即发生内存损坏)的情况,因为st3fan状态可能是问题所在。

        6
  •  0
  •   Ben Gottlieb    16 年前

    一个可能的问题是,如果出于某种原因,您碰巧传递了同一个imagename两次,那么在保留它之前,您将释放它。您可能希望将前两行更改为:

    if (imageName != s) {
        [imageName release];
        imageName = [s retain]; 
    }