![](/img/trans.png)
[英]iOS & Stackmob - [NSNull length]: unrecognized selector sent to instance
[英]iOS 8 works but iOS 7 crashes with -[NSNull length]: unrecognized selector sent to instance
我一直在寻找答案,但是仍然无法解决问题。 此-[NSNull长度]:无法识别的选择器发送到实例,而此[NSNull长度]:无法识别的选择器发送到实例0x43fe068没有帮助。
我正在使用一个具有Parse后端的聊天应用程序,并且我遇到了一个时间戳问题,聊天消息显示为乱序,因此我使用Databrowser从我的Parse数据库中删除了乱序的行。 当我测试该应用程序时,这似乎可以解决同时运行iOS 8的iPhone 6 Plus和iPhone 6模拟器上的问题。但是,当在运行iOS 7的iPhone 5s上打开同一聊天室时,该应用程序会崩溃,并与以下错误。
-[NSNull length]: unrecognized selector sent to instance
我不知道为什么删除一行会导致这种情况发生,为什么只在iOS 7上? 我设置了“所有异常”断点,这是违规行以及屏幕截图。
self.lastMessageLabel.textColor = [UIColor redColor];
即使我注释掉上面的行,我仍然会收到NSNull length
崩溃的NSNull length
,但是它在通用main.m处中断了。
关于如何解决这个问题的任何建议将不胜感激。 谢谢。
编辑1:这是我的ChatView.m中由我的PrivateInbox加载的代码。
- (void)loadMessages {
if (isLoading == NO)
{
isLoading = YES;
JSQMessage *message_last = [messages lastObject];
PFQuery *query = [PFQuery queryWithClassName:PF_CHAT_CLASS_NAME];
[query whereKey:PF_CHAT_ROOM equalTo:chatroomId];
if (message_last != nil) {
[query whereKey:PF_CHAT_SENTDATE greaterThan:[self.dateFormatter stringFromDate:message_last.date]];
}
[query includeKey:PF_CHAT_USER];
[query orderByAscending:PF_CHAT_SENTDATE];
[query addAscendingOrder:PF_CHAT_CREATEDAT];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error)
{
if (error == nil)
{
for (PFObject *object in objects)
{
PFUser *user = object[PF_CHAT_USER];
[users addObject:user];
if(![object[PF_CHAT_TEXT] isKindOfClass:[NSNull class]]) {
NSDate* sentDate;
if(object[PF_CHAT_SENTDATE] != nil)
sentDate = [self.dateFormatter dateFromString:object[PF_CHAT_SENTDATE]];
else
sentDate = object.createdAt;
JSQTextMessage *message = [[JSQTextMessage alloc] initWithSenderId:user.objectId senderDisplayName:user.objectId date:sentDate text:object[PF_CHAT_TEXT]];
[messages addObject:message];
} else if(object[PF_CHAT_PHOTO] != nil) {
NSDate* sentDate;
if(object[PF_CHAT_SENTDATE] != nil)
sentDate = [self.dateFormatter dateFromString:object[PF_CHAT_SENTDATE]];
else
sentDate = object.createdAt;
PFFile* photoFile = object[PF_CHAT_PHOTO];
JSQPhotoMediaItem *photoItem = [[JSQPhotoMediaItem alloc] init];
JSQMediaMessage *photoMessage = [[JSQMediaMessage alloc] initWithSenderId:user.objectId
senderDisplayName:user.objectId
date:sentDate
media:photoItem];
[messages addObject:photoMessage];
{
[photoFile getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
photoItem.image = [UIImage imageWithData:data];
[self.collectionView reloadItemsAtIndexPaths:[NSArray arrayWithObjects:[NSIndexPath indexPathForItem:[messages indexOfObject:photoMessage] inSection:0], nil]];
}];
}
} else if(object[PF_CHAT_VIDEO] != nil) {
NSDate* sentDate;
if(object[PF_CHAT_SENTDATE] != nil)
sentDate = [self.dateFormatter dateFromString:object[PF_CHAT_SENTDATE]];
else
sentDate = object.createdAt;
PFFile* videoFile = object[PF_CHAT_VIDEO];
JSQVideoMediaitem *videoItem = [[JSQVideoMediaitem alloc] initWithFileURL:[NSURL URLWithString:[videoFile url]] isReadyToPlay:YES];
JSQMediaMessage *videoMessage = [[JSQMediaMessage alloc] initWithSenderId:user.objectId
senderDisplayName:user.objectId
date:sentDate
media:videoItem];
[messages addObject:videoMessage];
}
}
if ([objects count] != 0) {
[JSQSystemSoundPlayer jsq_playMessageReceivedSound];
[self resetUnreadCount];
[self finishReceivingMessage];
}
}
else [ProgressHUD showError:@"Network error."];
isLoading = NO;
}];
}
}
编辑2:我尝试了尼克洛克伍德(Nick Lockwood)的NSNullSafe https://github.com/nicklockwood/NullSafe ,它允许打开私人收件箱而不会崩溃,并且使我摆脱了NSNull Length错误,但我认为这只是掩盖了问题,我仍然不愿意不知道为什么它在iOS 8上没有崩溃,但在iOS 7上却崩溃了。
我认为这可能与两种手术系统之间的差异无关。
崩溃很明显,您正在向无法处理该消息的NSNUll
类的对象发送消息。
通常,您使用解析或Web服务的事实使我认为该对象由后端作为JSON中的null
生成,并通过JSON解析转换为NSNull
对象。
您应该找到一种可能在解析级别处理NSNull对象的方法。
@Andrea是正确的,如果您不能从API(服务器)端弄清楚它,那么这是NSDictionary
和NSArray
的类别,它删除了所有NSNull
对象,并且您的应用程序不会崩溃。
@interface NSDictionary (NullReplacement)
- (NSDictionary *)dictionaryByReplacingNullsWithBlanks;
@end
@interface NSArray (NullReplacement)
- (NSArray *)arrayByReplacingNullsWithBlanks;
@end
@implementation NSDictionary (NullReplacement)
- (NSDictionary *)dictionaryByReplacingNullsWithBlanks {
const NSMutableDictionary *replaced = [self mutableCopy];
const id nul = [NSNull null];
const NSString *blank = @"";
for (NSString *key in self) {
id object = [self objectForKey:key];
if (object == nul) [replaced setObject:blank forKey:key];
else if ([object isKindOfClass:[NSDictionary class]]) [replaced setObject:[object dictionaryByReplacingNullsWithBlanks] forKey:key];
else if ([object isKindOfClass:[NSArray class]]) [replaced setObject:[object arrayByReplacingNullsWithBlanks] forKey:key];
}
return [NSMutableDictionary dictionaryWithDictionary:[replaced copy]];
}
@end
@implementation NSArray (NullReplacement)
- (NSArray *)arrayByReplacingNullsWithBlanks {
NSMutableArray *replaced = [self mutableCopy];
const id nul = [NSNull null];
const NSString *blank = @"";
for (int idx = 0; idx < [replaced count]; idx++) {
id object = [replaced objectAtIndex:idx];
if (object == nul) [replaced replaceObjectAtIndex:idx withObject:blank];
else if ([object isKindOfClass:[NSDictionary class]]) [replaced replaceObjectAtIndex:idx withObject:[object dictionaryByReplacingNullsWithBlanks]];
else if ([object isKindOfClass:[NSArray class]]) [replaced replaceObjectAtIndex:idx withObject:[object arrayByReplacingNullsWithBlanks]];
}
return [replaced copy];
}
@end
警告:仅在分析少量数据时才适用。
其他两个答案是正确的-这不是OS版本的问题,而是您正在传递NULL值并且没有捕获该值。
您在异常中捕获的行:
self.lastMessageLabel.textColor = [UIColor redColor];
表示症状,而不是原因。 我不确定100%_setTextColor的实际工作原理,但是我敢打赌,它可以通过使用NSString / NSAttributedString的length属性制作一个NSRange使其起作用,以便它知道从哪里开始应用颜色并结束应用颜色。 如果数据为NULL,则正如其他用户所述,您正在尝试访问错误类的length属性,从而导致崩溃。
从堆栈跟踪判断,第5行(setMessage:forUser)和第6行(cellForRow ...)是您应尝试捕获NULL值的位置。 或者,或者应该修改数据控制器,以便在JSON中传回NULL值时,可以将其替换为占位符,例如“ No Message”。
无论哪种情况,在cellForRow ...中构建tableView单元格时,将值分配给self.lastMessageLabel.text时,都可能发生崩溃。 检查在那里使用的NSString作为类类型(isKindOfClass [NSNULL class]),看看是否有帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.