应用程序崩溃 - 从应用程序商店安装但不是在本地安装时
App crash - when installed from App store but not locally
当我以 DEBUG 测试我的应用程序时,它就可以工作了。但是当我发布到 App store 并从 App Store 安装应用程序时,它 crash。
因此我将DEBUG运行方法改成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);
}
您的 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
!
-[__NSArrayM length]: unrecognized selector sent to instance 0x1740457c0
self.server class 是 NSArray .must string length
当我以 DEBUG 测试我的应用程序时,它就可以工作了。但是当我发布到 App store 并从 App Store 安装应用程序时,它 crash。
因此我将DEBUG运行方法改成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);
}
您的 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
!
-[__NSArrayM length]: unrecognized selector sent to instance 0x1740457c0
self.server class 是 NSArray .must string length