我使用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:
获取电子邮件附件并取消归档数据的接收应用的代码:
- (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在传输过程中改变了数据。
如果有人能说清楚这一点,我会非常感激。
答案 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提出编码可能存在的问题!