应用程序崩溃 - 从 App Store 但不是本地安装时

Posted

技术标签:

【中文标题】应用程序崩溃 - 从 App Store 但不是本地安装时【英文标题】:App crash - when installed from App store but not locally 【发布时间】:2017-04-08 07:57:06 【问题描述】:

当我将我的应用程序测试为 DEBUG 时,它就可以工作了。但是当我发布到 App Store 并从 App Store 安装应用程序时,它会崩溃

因此我将DEBUG RUN 方法改为RELEASE 运行方法进行测试。

当我现在以 RELEASE 运行方法运行时,应用程序也会崩溃(与应用商店崩溃相同)。应用程序崩溃指向第 19 行。

我该如何解决?在这里,我告诉我通过将一个字符串与我从第 18 行获得的字符串连接来制作 DNS(A 或 AAAA 记录)self.server = [self.server stringByAppendingString:@".example.com"];

- (void)myMethodHere:(NSString *)a   
  //where a = @"splitme://test1/test2/test3";

  NSArray *work_array = [a componentsSeparatedByString:@"splitme://"];
  self.use_url =[work_array objectAtIndex:1];

  if ([self.use_url length] > 0)     
    NSArray *work_array = [self.use_url componentsSeparatedByString:@"/"];
    self.server    = [work_array objectAtIndex:0];

    // -------------------
    // CRASH HERE // CRASH HERE 
    // -------------------
    if([self.server length] > 0) 
      NSLog(@"!!!!!!!!!!!!!!!!!!!!!! 4 - part 1: %@", self.server); // WORKS 

      // Here we go CRASHing...
      self.server = [self.server stringByAppendingString:@".example.com"];
      NSLog(@"!!!!!!!!!!!!!!!!!!!!!! 4 - part 2: %@", self.server); // CRASH CRASH

    
    else 
      self.server = @"test.example.com";      
    

  
  else 
    NSLog(@"!!!!!!!!!!!!!!!!!!!!!! 9: %@", self.use_url);
    

  [self load_later];


编辑 1: 以下做法让我通过,但如果我在此范围之外再次拥有 self.server,则应用程序再次崩溃。

  NSString *part1 = self.server;
  NSString *part2 = @".example.com";
  NSString *result =[part1 stringByAppendingString:part2];
  self.server = result;
  NSLog(@"!!!!!!!!!!!!!!!!!!!!!! 4 - part 2: %@", self.server);

编辑 2:在注释掉 NSLog 行后,在 AppDelegate.m 上崩溃。

2017-04-08 10:32:01.773648+0200 app[344:18271] [MC] System group container for systemgroup.com.apple.configurationprofiles path is /private/var/containers/Shared/SystemGroup/systemgroup.com.apple.configurationprofiles
2017-04-08 10:32:01.774146+0200 app[344:18271] [MC] Reading from public effective user settings.
2017-04-08 10:32:01.778647+0200 app[344:18271] -[__NSArrayM length]: unrecognized selector sent to instance 0x1740457c0
2017-04-08 10:32:01.778888+0200 app[344:18271] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayM length]: unrecognized selector sent to instance 0x1740457c0'
*** First throw call stack:
(0x18a956fd8 0x1893b8538 0x18a95def4 0x18a95af4c 0x18a856d2c 0x100006f78 0x1000076e8 0x1000066cc 0x190a85f9c 0x190a85b78 0x190a8c3f8 0x190a89894 0x190afb2fc 0x190d038b4 0x190d092a8 0x190d1dde0 0x190d0653c 0x18c4ff884 0x18c4ff6f0 0x18c4ffaa0 0x18a905424 0x18a904d94 0x18a9029a0 0x18a832d94 0x190af045c 0x190aeb130 0x100007d78 0x18984159c)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb) 

编辑 3: 即使使用显式强制转换,也会导致 NSString 崩溃而不是 NSString

- (void)setServer:(NSString *)value

  if (value != nil && ![value isKindOfClass:[NSString class]]) 
    NSLog(@"!!!!!!!!!!!lol!!!!!!!!!!!!! Bug! Set breakpoint here!");
  
  self.server = value;


NSArray *work_array = [self.use_url componentsSeparatedByString:@"/"];
NSString *setServerURL =(NSString *) [work_array objectAtIndex:0];
[self setServer:setServerURL];

编辑 4: 崩溃

- (void)myMethodHere:(NSString *)a   
  NSArray *work_array = [a componentsSeparatedByString:@"test://"];
  id objectOne = [work_array objectAtIndex:1];
  if ([objectOne isKindOfClass:[NSString class] ] ) 
    NSString *objectOneIntoString = objectOne;
    self.use_url = (NSString *) objectOneIntoString;
  

  if ([self.use_url length] > 0) 
    NSLog(@"3: %@", self.use_url);
    NSArray *work_array = [self.use_url componentsSeparatedByString:@"/"];
    id objectTwo = [work_array objectAtIndex:0];
    if ([objectTwo isKindOfClass:[NSString class] ]) 
      NSString *objectTwoIntoString = objectTwo;
      self.server = objectTwoIntoString;
    

    if([self.server length] > 0) 
      NSLog(@"4 - part 1: %@", self.server);
      NSString *part1 = self.server;
      NSString *part2 = @".example.com";
      NSString *result = (NSString *) [part1 stringByAppendingString:part2];
      self.server = result;
      NSLog(@"4 - part 2: %@", self.server);
    
    else 
      self.server = @"dns.example.com";
      NSLog(@"5:%@", self.server);

    

    NSLog(@"8: %@", self.server);

  
  else 
    NSLog(@"9: %@", self.use_url);
    

  NSLog(@"10: %@", self.use_url);

【问题讨论】:

崩溃日志或调试器中的错误消息是什么? 先生,当我删除 NSLog 的那一行时,当我将它作为 RELEASE 方法运行时它也会崩溃,但当我作为 DEBUG 方法运行它时它可以工作。请在此处查看 Xcode 中的崩溃输出:paste.ubuntu.com/24339339 在注释掉 NSLog 的行后,我在 AppDelegate.m 中有崩溃指示,请参阅我上面的编辑。 先生,当我使用删除 NSString *part1 = self.server; NSString *part2 = @".example.com"; NSString *result =[part1 stringByAppendingString:part2]; self.server = result; NSLog(@"!!!!!!!!!!!!!!!!!!!!!! 4 - part 2: %@", self.server); 的所有代码时,我的构建工作。先生,这是ios本身的BUG吗? 我想这可能对你有帮助#define excitedLog(string) NSLog(@"!!!!!!!!!!!!! %@", string) 【参考方案1】:

您的 pastebin 中的错误消息是:

2017-04-08 10:32:01.778647+0200 app[344:18271] -[__NSArrayM length]: unrecognized selector sent to instance 0x1740457c0
2017-04-08 10:32:01.778888+0200 app[344:18271] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayM length]: unrecognized selector sent to instance 0x1740457c0'

这告诉您有一个 数组,您在其上调用了length。因此,如果它真的与您的 server 属性相关,那么您会不小心将 NSArray 存储在某处。

这里有一个关于如何捕捉它的想法:实现setServer: 方法并检查类型是否正确。

- (void)setServer:(NSString *)value

    if (value != nil && ![value isKindOfClass:[NSString class]]) 
        NSLog(@"Bug! Set breakpoint here!");
    
    _server = value;

编辑:您错误地实现了 setter,通常会产生无限递归。所以让我们从头开始:

我假设你有一个这样定义的属性:

@property (strong) NSString * server; // Or maybe "copy"

如果您的房产不是看起来像这样,您需要告诉我们!

然后你完全像这样实现setter:

- (void)setServer:(NSString *)value

    if (value != nil && ![value isKindOfClass:[NSString class]]) 
        NSLog(@"Bug! Set breakpoint here!");
    
    _server = value;
   // DO NOT DO self.server = value HERE!

然后您可以在其余代码中执行self.server = blabla;,如果您的代码设置的不是字符串,NSLog 将被命中。 所以在那里设置一个断点

编辑 2:

现在我在您的另一条评论中看到了问题所在……

@property (assign, nonatomic) NSString *server;

assign 不保留对象!您需要使用strong 或(如果是NSString *copy。事实上,会发生以下情况:

您将一个对象分配给server。 由于没有保留,所以很快就会释放对象。 但server 仍有指向该内存位置的指针。

现在可能发生两件事:

在您访问该属性之前,会在内存位置创建一个新的不同对象。你现在得到了一个意想不到的对象。调用此对象的方法可能会起作用,也可能会因为对象不知道方法而崩溃。 或者内存位置被视为无效,您会立即崩溃。

切勿将assign 用于对象!

【讨论】:

强制转换没有用,它不会神奇地改变对象的类型。它只是告诉编译器“我知道类型将是 this 而不是你推断的”。实现设置器,设置断点并运行程序以查看确切您意外存储数组而不是字符串的位置。 正如我所写,cast 不会神奇地将您的对象转换为另一种类型。它只是向编译器提示您认为 应该是对象的类型。你设置断点了吗?您是否检查过堆栈,实际上是谁在传递数组?您是否检查过调试器中的相关对象?你真的需要使用调试器!从您提供的稀疏信息中很难找出发生了什么,尤其是因为我们不知道您的程序的其余部分。 先生,您能看看我的编辑 4。我已经使用了您的方法。但是崩溃仍然发生在这里NSLog(@"8: %@", self.server);所有其他都是PASS。在第 8 步之前,没有其他调用 self.server 可能会被 NSArray 覆盖,第 4 步 NSLog(@"4 - part 2: %@", self.server); 成功。感谢您的帮助。 我已经更新了我的答案。您错误地实现了设置器。而且您仍然没有使用调试器。为什么? 我第二次更新了我的答案。实际的问题是您没有正确声明您的财产。我应该早点要求看那个声明……【参考方案2】:

-[__NSArrayM 长度]:无法识别的选择器发送到实例 0x1740457c0

self.server 类是 NSArray .must 字符串长度

【讨论】:

***.com/a/7290346/285594 - 我已将 NSArray 显式转换为 NSString 但没有帮助,它仍然崩溃。 self.server = (NSString *) [work_array objectAtIndex:0]; 在哪里@property (assign, nonatomic) NSString *server; @YumYumYum 显式强制转换绝对没有任何作用。这只是对编译器说“我知道我在做什么”。 Obj-C 是一种动态语言。您可以执行NSString *string = (id) [NSArray array] 之类的操作。这就是为什么你必须确保你做的事情是正确的,否则会出现类型错误。

以上是关于应用程序崩溃 - 从 App Store 但不是本地安装时的主要内容,如果未能解决你的问题,请参考以下文章

从 App Store 安装后应用程序崩溃。 Google Analytics 向我发送实例崩溃报告<已编辑>

我的应用在 iOS 4.3 上崩溃,但仅在从 App Store 下载时

如何在 App Store Connect 中批准新版本

屏幕截图出现在 iTunes Connect 而不是 App Store

如何调试 iPhone 应用程序崩溃日志。仅在 App Store 购买的版本中崩溃,而不是在开发中

iOS App Store 应用程序在登录期间崩溃(不在开发中)