1

NSData用于发送和接收文本、图片和语音等消息。为了区分消息的类型,我附加了一个标题。当消息到达时,我为NSString对象分配标头并用于[header isEqualToString:@"txt"]确定不同的操作。

这是我处理到达消息的方法:

int msgarrvd (void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
    void *payloadptr = message->payload;
    int payLoadLen = message->payloadlen;
    NSLog(@"%d", payLoadLen);

    NSMutableArray *msgArray = [NSMutableArray array];
    NSData *dataHeader = [NSData dataWithBytes:payloadptr length:3];
    NSStringEncoding strEncode = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingUTF8);
    NSString *header = [[NSString alloc] initWithData:dataHeader encoding:strEncode];
    NSLog(@"header:%@", header);

        if ([header isEqualToString:@"txt"]) {
            // text message
            NSData *content = [NSData dataWithBytes:payloadptr length:payLoadLen];
            NSString *msgContent = [[NSString alloc] initWithData:content encoding:strEncode];
            NSString *subStr = [msgContent substringFromIndex:3];
            [msgArray addObject:subStr];
        }
        if ([header isEqualToString:@"pic"]) {
          // pic message
        }
        if ([header isEqualToString:@"voc"]) {
            // voice message
            NSMutableData *voiceData = [NSMutableData data];
            [voiceData appendData:[NSData dataWithBytes:payloadptr length:payLoadLen]];
            [voiceData replaceBytesInRange:NSMakeRange(3, payLoadLen) withBytes:payloadptr];
            NSFileManager *fm = [NSFileManager defaultManager];
            NSString *voicePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingString:@"sound.wav"];
            [fm createFileAtPath:voicePath contents:voiceData attributes:nil];
            NSURL *voiceURL = [NSURL fileURLWithPath:voicePath];
            [msgArray addObject:voiceURL];

        NSMutableDictionary *myDictionary = [NSMutableDictionary dictionary];
        if ([header isEqualToString:@"txt"]) {
            [myDictionary setObject:header forKey:@"header"];
        }
        if ([header isEqualToString:@"pic"]) {
            [myDictionary setObject:header forKey:
             @"header"];
        }
        if ([header isEqualToString:@"voc"]) {
            [myDictionary setObject:header forKey:@"header"];
        }

        [myDictionary setObject:msgArray forKey:@"content"];
        [[NSNotificationCenter defaultCenter] postNotificationName:@"MessageCome" object:nil userInfo:myDictionary];

        MQTTClient_freeMessage(&message);
        MQTTClient_free(payloadptr);

        return 1;
    }

Xcode 抛出-[__NSArrayM length]: unrecognized selector sent to instance 0x17dc7bb0Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayM length]: unrecognized selector sent to instance 0x17dc7bb0'

到底是什么问题?

任何帮助都应该不胜感激!

更多的

 - (void)handle:(NSNotification *)notification
    {
        NSDictionary *message = [NSDictionary dictionaryWithDictionary:[notification userInfo]];
        NSString *msgType = [message objectForKey:@"header"];
        if ([msgType isEqualToString:@"txt"]) {
            NSArray *array = [message objectForKey:@"content"];
            NSString *msg = [[array valueForKey:@"description"] componentsJoinedByString:@""];
            [self.messages addObject:msg];
            NSLog(@"%@&%lu", msg, (unsigned long)[self.messages count]);
            dispatch_async(dispatch_get_main_queue(), ^{
                [self.tableView reloadData];
            });

        }
        if ([msgType isEqualToString:@"pic"]) {
            // process pic
        }
        if ([msgType isEqualToString:@"voc"]) {
            [self.messages addObject:[message objectForKey:@"content"]];
            dispatch_async(dispatch_get_main_queue(), ^{
                [self.tableView reloadData];
            });
        }
    }

这是我的观察者

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handle:) name:@"MessageCome" object:nil];



    context void *  NULL    0x00000000
topicName   char *  "/test" 0x16dcbe24
*topicName  char    '/' '/'
topicLen    int 0   0
message MQTTClient_message *    0x16dcc064  0x16dcc064
struct_id   char [4]    ""  
struct_version  int 4   4
payloadlen  int 28675   28675
payload void *  0x4409004   0x04409004
qos int 1   1
retained    int 0   0
dup int 0   0
msgid   int 25864   25864
payloadptr  void *  0x4409004   0x04409004
payLoadLen  int 28675   28675
msgArray    __NSArrayM *    @"1 object" 0x16dcc280
[0] NSURL * @"file:///var/mobile/Applications/417171BD-60C5-4DF6-989D-2983426B9CAD/Library/Documentationsound.wav"  0x16dd0760
dataHeader  _NSInlineData * 3 bytes 0x16d48420
strEncode   NSStringEncoding    4   4
header  __NSCFString *  @"voc"  0x16dca530
myDictionary    __NSDictionaryM *   2 key/value pairs   0x16dd0830
[0] (null)  @"content" : @"1 object"    
[1] (null)  @"header" : @"voc"  
content NSData *    nil 
msgContent  NSString *  nil 
subStr  NSString *  nil 
voiceData   NSMutableData * nil 
fm  NSFileManager * nil 
voicePath   NSString *  nil 
voiceURL    NSURL * nil 

这是我的 tableView 数据源

    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{

    return [self.messages count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
        cell.selectionStyle = UITableViewCellSelectionStyleGray;
        cell.textLabel.text = [self.messages objectAtIndex:indexPath.row];
    }


    // Configure the cell...
    cell.textLabel.text = [self.messages objectAtIndex:indexPath.row];
    return cell;
}
4

3 回答 3

1

此行(在msgarrvd

[myDictionary setObject:msgArray forKey:@"content"];

将字典的内容键设置为数组(实际上是可变的)。

这一行(在通知处理程序中)

[self.messages addObject:[message objectForKey:@"content"]]

获取内容键的对象(记住数组)并将其添加到messages数组中。

此行(在tableView:cellForRowAtIndexPath:

cell.textLabel.text = [self.messages objectAtIndex:indexPath.row];

messages数组中获取一个对象(记住它本身就是一个数组)并尝试将它分配给一个名为的属性,该属性text应该是一个字符串。然后在 Cocoa 库中的某个地方,想要找出字符串有多长,但它不是字符串,它是一个数组,并且数组不响应-length.

于 2013-11-08T11:46:19.943 回答
1

这是错误:

if ([msgType isEqualToString:@"voc"]) {
    [self.messages addObject:[message objectForKey:@"content"]];   // HERE
    dispatch_async(dispatch_get_main_queue(), ^{
        [self.tableView reloadData];
    });
}

正如您已经展示的那样,这@"content"是一个数组:

myDictionary    __NSDictionaryM *   2 key/value pairs   0x16dd0830
[0] (null)  @"content" : @"1 object"    // HERE
[1] (null)  @"header" : @"voc"  

并且您的表格代码期望它是一个字符串:

cell.textLabel.text = [self.messages objectAtIndex:indexPath.row];

因此出现无法识别的选择器错误,因为标签的文本应该是NSString对象而不是NSArray对象。

请注意填充数据源@"voc"@"txt"键入消息的方式的不同。

于 2013-11-08T11:39:11.050 回答
1

要获取 NSMutableArray 的大小,您需要调用:

 [array count]

不是长度

该错误告诉您在 NSMutableArray 类上调用“长度” - 这就是它崩溃的原因。它不在您粘贴的代码中 - 所以最好放置一个异常断点并检查它来自哪一行。

于 2013-11-08T10:11:40.990 回答