通过MFMailComposeController传输后,NSKeyedUnarchiver会产生nil值

时间:2017-12-29 01:46:56

标签: ios arrays mfmailcomposer nskeyedunarchiver

我使用MFMailComposeController发送密钥存档作为电子邮件的附件。我的应用程序读取电子邮件附件获取密钥存档,但取消存档它会提供 nil 值。详情如下:

发送视图控制器:

    - (IBAction)saveAndSend:(id)sender {

    // Email Subject
    NSString *emailTitle = @"Test Email";
    // Email Content
    NSString *messageBody = @"TimeChime Trace Data";
    // To address
    NSArray *toRecipents = [NSArray arrayWithObject:@"summitpointsoftware@gmail.com"];

    if (![MFMailComposeViewController canSendMail]) {
        NSLog(@"Mail services are not available.");
        return;
    }
    MFMailComposeViewController *mc = [[MFMailComposeViewController alloc] init];
    mc.mailComposeDelegate = self;
    [mc setSubject:emailTitle];
    [mc setMessageBody:messageBody isHTML:NO];
    [mc setToRecipients:toRecipents];
    // attach NSData to message. Note: file name extension will be used by the mail client to launch
    // the handler with this extension in its info.plist.

    NSData *data = [[NSData alloc]init];
    data = [NSKeyedArchiver archivedDataWithRootObject:self.items];

    [mc addAttachmentData:data mimeType:@"application/CustomUTIHandler" fileName:@"traceData.nrc"];

    // Present mail view controller on screen
    [self presentViewController:mc animated:YES completion:NULL];

}

在发送之前存档的数组(NRCEventItem数组):

    Printing description of self->_items:
<__NSArrayM 0x1c045e390>(
Event Date/time: 2017-12-29 00:08:17 +0000, Event Sender: <AppDelegate: 0x1c40523c0>, Event Description: appl did become active,
Event Date/time: 2017-12-29 00:15:32 +0000, Event Sender: <HourlyChimeTableViewController: 0x10282fa00>, Event Description: triggerNotification,
Event Date/time: 2017-12-29 00:30:32 +0000, Event Sender: <HourlyChimeTableViewController: 0x10282fa00>, Event Description: triggerNotification,
Event Date/time: 2017-12-29 00:45:32 +0000, Event Sender: <HourlyChimeTableViewController: 0x10282fa00>, Event Description: triggerNotification,
Event Date/time: 2018-01-05 00:00:32 +0000, Event Sender: <HourlyChimeTableViewController: 0x10282fa00>, Event Description: triggerNotification,
Event Date/time: 2018-01-05 00:15:32 +0000, Event Sender: <HourlyChimeTableViewController: 0x10282fa00>, Event Description: triggerNotification,
Event Date/time: 2018-01-05 00:30:32 +0000, Event Sender: <HourlyChimeTableViewController: 0x10282fa00>, Event Description: triggerNotification,
Event Date/time: 2018-01-05 00:45:32 +0000, Event Sender: <HourlyChimeTableViewController: 0x10282fa00>, Event Description: triggerNotification
)

EventItem类符合NSCoding:

    //
//  NRCEventItem.h
//  Hourly Chime2
//
//  Created by Nelson Capes on 12/12/17.
//  Copyright © 2017 Nelson Capes. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface NRCEventItem : NSObject <NSCoding>
@property (nonatomic) NSDate *eventDateTime;
@property (nonatomic) NSString *eventSender;
@property (nonatomic) NSString *eventDescription;
@end

接收应用的info.plist:

enter image description here

获取电子邮件附件并取消归档数据的接收应用的代码:

- (void) receiveNotificationFromAppDelegate:(NSNotification *) notification {
NSLog(@"userInfo trace %@",notification.userInfo[KTraceKey]);

self.items = (NSMutableArray*)[NSKeyedUnarchiver unarchiveObjectWithData:notification.userInfo[KTraceKey]];
[self.tableView reloadData];

}

取消归档后的数据:

    Printing description of path:
/private/var/mobile/Containers/Data/Application/CCDA0B96-8DD6-496E-B0A0-08B3C072E76A/Documents/Inbox/traceData-40.nrc
Printing description of items:
<__NSArrayM 0x1c4240720>(
Event Date/time: (null), Event Sender: (null), Event Description: (null),
Event Date/time: (null), Event Sender: (null), Event Description: (null),
Event Date/time: (null), Event Sender: (null), Event Description: (null),
Event Date/time: (null), Event Sender: (null), Event Description: (null),
Event Date/time: (null), Event Sender: (null), Event Description: (null),
Event Date/time: (null), Event Sender: (null), Event Description: (null),
Event Date/time: (null), Event Sender: (null), Event Description: (null),
Event Date/time: (null), Event Sender: (null), Event Description: (null)
)

显然,NSKeyedUnarchiver将数据识别为数组,并且数组中的元素是NRCEventItem。但是,数组的每个元素中的属性现在都是 nil 。我还通过立即取消归档归档来测试归档步骤,并且阵列的属性与归档之前一样。

结论:不知何故,使用MFMailComposeViewController在传输过程中改变了数据。

如果有人能说清楚这一点,我会非常感激。

1 个答案:

答案 0 :(得分:0)

我发现了问题(并且不是MFMailComposeViewController)。我的自定义类NRCEventItem没有实现NSCoding协议,因此包含它们的可变数组已正确存档和取消存档,但项目没有。以下是该项目的正确代码:

    //
//  NRCEventItem.m
//  Hourly Chime2
//
//  Created by Nelson Capes on 12/12/17.
//  Copyright © 2017 Nelson Capes. All rights reserved.
//

#import "NRCEventItem.h"
#import "constants.h"
@implementation NRCEventItem
-(void)encodeWithCoder:(NSCoder *)aCoder{

    [aCoder encodeObject:_eventSender forKey:kEventLoggerSender];
    [aCoder encodeObject:_eventDateTime forKey:KEventLoggerDateTime];
    [aCoder encodeObject:_eventDescription forKey:KEventLoggerEventDescription];

}
-(instancetype) initWithCoder:(NSCoder *)aDecoder{
    self = [super init];
    if (self){

        self.eventSender = [aDecoder decodeObjectForKey:kEventLoggerSender];
        self.eventDateTime = [aDecoder decodeObjectForKey:KEventLoggerDateTime];
        self.eventDescription = [aDecoder decodeObjectForKey:KEventLoggerEventDescription];

    }
    return self;
}
-(NSString *)description{
    return [NSString stringWithFormat:@"Event Date/time: %@, Event Sender: %@, Event Description: %@", self.eventDateTime, self.eventSender, self.eventDescription];
}
@end

我最后也改变了存档和解压缩的代码。以下是有效的代码:

NSMutableData *data = [[NSMutableData alloc]init];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc]initForWritingWithMutableData:data];
[archiver encodeObject:self.items forKey:@"items"];
[archiver finishEncoding];

NSMutableData *data = [[NSMutableData alloc]init];
data = notification.userInfo[KTraceKey];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc]initForReadingWithData:data];
self.items = [unarchiver decodeObjectForKey:@"items"];
[unarchiver finishDecoding];

我发现使用NSKeyedArchiver和NSKeyedUnarchiver与encodeObject和decodeObject而不是archivedDataWithRootObject有一个好处:如果你没有调用 finishEncoding ,unarchiver会通知你档案中是否没有数据。使用根对象存档和取消存档时,您不会收到此通知。

我建议使用MFMailComposeViewController是在不同设备上运行的应用程序之间传输数据的简洁方法。关键是实现info.plist,它显示在我的OP。

感谢Dave提出编码可能存在的问题!