因此,我将用户输入数据保存在文档目录中的 plist 中。数据由几个字符串组成。比如文字和图片。用户通过文本字段在添加 View 中输入数据,通过相机或相册输入图像。
我使用以下方法将数据保存在添加 View Controller 中:
// Name for the image
NSString *imageName;
if (self.image) {
// Create a unique name for the image by generating a UUID, converting it to
// a string, and appending the .jpg extension.
CFUUIDRef imageUUID = CFUUIDCreate(kCFAllocatorDefault);
imageName = (NSString*)CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, imageUUID));
CFRelease(imageUUID);
imageName = [imageName stringByAppendingString".jpg"];
// Lookup the URL for the Documents folder
NSURL *imageFileURL = [[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask][0];
// Append the file name to create the complete URL for saving the image.
imageFileURL = [imageFileURL URLByAppendingPathComponent:imageName isDirectory:NO];
// Convert the image to JPG format and write the data to disk at the above URL.
[UIImageJPEGRepresentation(self.image, 1.0f) writeToURL:imageFileURL atomically:YES];
} else {
// If there is no image, we must make sure imageName is not nil.
imageName = @"";
}
#define PLIST_NAME @"Data.plist"
[self createPlistCopyInDocumentsLIST_NAME];
NSString *filePath = [self plistFileDocumentPathLIST_NAME];
NSMutableArray *dataArray = [[NSMutableArray alloc] initWithContentsOfFile:filePath];
NSDictionary *data = @{@"city":self.name,@"state":self.stateTextField.text,@"cityPrice":self.priceTextField.text,@"cityText":self.cityDescription.text, @"cityImage": imageName};
[dataArray addObject:data];
[dataArray writeToFile:filePath atomically:YES];
然后我为文档路径添加以下方法:
- (NSString *)plistFileDocumentPathNSString *)plistName
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writablePath = [documentsDirectory stringByAppendingPathComponent:plistName];
return writablePath;
}
- (void)createPlistCopyInDocumentsNSString *)plistName
{
// First, test for existence.
BOOL success;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSString *plistFilePath = [self plistFileDocumentPath:plistName];
success = [fileManager fileExistsAtPath:plistFilePath];
if (success) {
return;
}
// The writable file does not exist, so copy from the bundle to the appropriate location.
NSString *defaultPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:plistName];
success = [fileManager copyItemAtPath:defaultPath toPath:plistFilePath error:&error];
if (!success) {
NSAssert1(0, @"Failed to create writable file with message '%@'.", [error localizedDescription]);
}
}
然后在我的 tableview Controller 中读取数据并显示如下:
- (void)viewWillAppearBOOL)animated
{
[super viewWillAppear:animated];
NSString *filePath = [self plistFileDocumentPath"Data.plist"];
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL exist = [fileManager fileExistsAtPath:filePath];
if (!exist) {
return;
}
NSMutableArray *dataArray = [[NSMutableArray alloc] initWithContentsOfFile:filePath];
content = dataArray;
[self.tableView reloadData];
}
- (NSString *)plistFileDocumentPathNSString *)plistName
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writablePath = [documentsDirectory stringByAppendingPathComponent:plistName];
return writablePath;
}
我确实看到了 plist 确实加载如下:
content = [[NSMutableArray alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource"Data" ofType"plist"]];
我还可以在我的详细 View 中正确显示所有信息。我创建了一个新 View ,以便将 plist 中保存的数据显示为 pdf 文件。我能够从我目录中的现有 plist 中检索数据,但我无法转换该代码以从我保存的 plist 中读取数据。
这就是我从该 plist 创建 pdf 的方式。
- (IBAction)pdfPressedid)sender {
// create some sample data. In a real application, this would come from the database or an API.
NSString* path = [[NSBundle mainBundle] pathForResource"sampleData" ofType"plist"];
NSDictionary* data = [NSDictionary dictionaryWithContentsOfFile:path];
NSArray* students = [data objectForKey"Students"];
// get a temprorary filename for this PDF
path = NSTemporaryDirectory();
self.pdfFilePath = [path stringByAppendingPathComponent:[NSString stringWithFormat"%f.pdf", [[NSDate date] timeIntervalSince1970] ]];
// Create the PDF context using the default page size of 612 x 792.
// This default is spelled out in the iOS documentation for UIGraphicsBeginPDFContextToFile
UIGraphicsBeginPDFContextToFile(self.pdfFilePath, CGRectZero, nil);
// get the context reference so we can render to it.
CGContextRef context = UIGraphicsGetCurrentContext();
int currentPage = 0;
// maximum height and width of the content on the page, byt taking margins into account.
CGFloat maxWidth = kDefaultPageWidth - kMargin * 2;
CGFloat maxHeight = kDefaultPageHeight - kMargin * 2;
// we're going to cap the name of the class to using half of the horizontal page, which is why we're dividing by 2
CGFloat classNameMaxWidth = maxWidth / 2;
// the max width of the grade is also half, minus the margin
CGFloat gradeMaxWidth = (maxWidth / 2) - kColumnMargin;
// only create the fonts once since it is a somewhat expensive operation
UIFont* studentNameFont = [UIFont boldSystemFontOfSize:17];
UIFont* classFont = [UIFont systemFontOfSize:15];
CGFloat currentPageY = 0;
// iterate through out students, adding to the pdf each time.
for (NSDictionary* student in students)
{
// every student gets their own page
// Mark the beginning of a new page.
UIGraphicsBeginPDFPageWithInfo(CGRectMake(0, 0, kDefaultPageWidth, kDefaultPageHeight), nil);
currentPageY = kMargin;
// draw the student's name at the top of the page.
NSString* name = [NSString stringWithFormat"%@ %@",
[student objectForKey"FirstName"],
[student objectForKey:@"LastName"]];
CGSize size = [name sizeWithFont:studentNameFont forWidth:maxWidth lineBreakMode:NSLineBreakByWordWrapping];
[name drawAtPoint:CGPointMake(kMargin, currentPageY) forWidth:maxWidth withFont:studentNameFont lineBreakMode:NSLineBreakByWordWrapping];
currentPageY += size.height;
// draw a one pixel line under the student's name
CGContextSetStrokeColorWithColor(context, [[UIColor blueColor] CGColor]);
CGContextMoveToPoint(context, kMargin, currentPageY);
CGContextAddLineToPoint(context, kDefaultPageWidth - kMargin, currentPageY);
CGContextStrokePath(context);
// iterate through the list of classes and add these to the PDF.
NSArray* classes = [student objectForKey:@"Classes"];
for(NSDictionary* class in classes)
{
NSString* className = [class objectForKey:@"Name"];
NSString* grade = [class objectForKey:@"Grade"];
// before we render any text to the PDF, we need to measure it, so we'll know where to render the
// next line.
size = [className sizeWithFont:classFont constrainedToSize:CGSizeMake(classNameMaxWidth, MAXFLOAT) lineBreakMode:NSLineBreakByWordWrapping];
// if the current text would render beyond the bounds of the page,
// start a new page and render it there instead
if (size.height + currentPageY > maxHeight) {
// create a new page and reset the current page's Y value
UIGraphicsBeginPDFPageWithInfo(CGRectMake(0, 0, kDefaultPageWidth, kDefaultPageHeight), nil);
currentPageY = kMargin;
}
// render the text
[className drawInRect:CGRectMake(kMargin, currentPageY, classNameMaxWidth, maxHeight) withFont:classFont lineBreakMode:NSLineBreakByWordWrapping alignment:NSTextAlignmentLeft];
// print the grade to the right of the class name
[grade drawInRect:CGRectMake(kMargin + classNameMaxWidth + kColumnMargin, currentPageY, gradeMaxWidth, maxHeight) withFont:classFont lineBreakMode:NSLineBreakByWordWrapping alignment:NSTextAlignmentLeft];
currentPageY += size.height;
}
// increment the page number.
currentPage++;
}
// end and save the PDF.
UIGraphicsEndPDFContext();
// Ask the user if they'd like to see the file or email it.
UIActionSheet* actionSheet = [[UIActionSheet alloc] initWithTitle:@"Would you like to preview or email this PDF?"
delegate:self
cancelButtonTitle:@"Cancel"
destructiveButtonTitle:nil
otherButtonTitles:@"review", @"Email", nil];
[actionSheet showInView:self.view];
}
有人可以查看上面给出的信息并帮助我更改此创建 pdf 代码以读取我保存到文档目录中 plist 的数据。这是 github 中演示项目的链接,供任何想要伸出援助之手的人使用。
附加信息:
我将用户输入数据保存在 plist 中,根是一个数组。我用来呈现 PDF 文件的代码来自根是字典的 plist 。我需要帮助更改 pdfpressed 中的代码以读取 plist 根将是一个数组而不是字典。
编辑:
我使用了发布的修复程序,整个方法现在看起来像这样:
- (IBAction)pdfPressedid)sender {
NSArray *sysPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory ,NSUserDomainMask, YES);
NSString *documentsDirectory = [sysPaths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:@"Data1.plist"];
NSLog(@"File Path: %@", filePath);
NSArray *students = [NSArray arrayWithContentsOfFile:filePath];
// get a temprorary filename for this PDF
filePath = NSTemporaryDirectory();
self.pdfFilePath = [filePath stringByAppendingPathComponent:[NSString stringWithFormat:@"%f.pdf", [[NSDate date] timeIntervalSince1970] ]];
// Create the PDF context using the default page size of 612 x 792.
// This default is spelled out in the iOS documentation for UIGraphicsBeginPDFContextToFile
UIGraphicsBeginPDFContextToFile(self.pdfFilePath, CGRectZero, nil);
// get the context reference so we can render to it.
CGContextRef context = UIGraphicsGetCurrentContext();
int currentPage = 0;
// maximum height and width of the content on the page, byt taking margins into account.
CGFloat maxWidth = kDefaultPageWidth - kMargin * 2;
CGFloat maxHeight = kDefaultPageHeight - kMargin * 2;
// we're going to cap the name of the class to using half of the horizontal page, which is why we're dividing by 2
CGFloat classNameMaxWidth = maxWidth / 2;
// the max width of the grade is also half, minus the margin
CGFloat gradeMaxWidth = (maxWidth / 2) - kColumnMargin;
// only create the fonts once since it is a somewhat expensive operation
UIFont* studentNameFont = [UIFont boldSystemFontOfSize:17];
UIFont* classFont = [UIFont systemFontOfSize:15];
CGFloat currentPageY = 0;
// iterate through out students, adding to the pdf each time.
for (NSDictionary* student in students)
{
// every student gets their own page
// Mark the beginning of a new page.
UIGraphicsBeginPDFPageWithInfo(CGRectMake(0, 0, kDefaultPageWidth, kDefaultPageHeight), nil);
currentPageY = kMargin;
// draw the student's name at the top of the page.
NSString* name = [NSString stringWithFormat:@"%@ %@ %@ %@", [student valueForKey:@"city"], [student valueForKey:@"state"],[student valueForKey:@"cityPrice"],[student valueForKey:@"cityText"]];
CGSize size = [name sizeWithFont:studentNameFont forWidth:maxWidth lineBreakMode:NSLineBreakByWordWrapping];
[name drawAtPoint:CGPointMake(kMargin, currentPageY) forWidth:maxWidth withFont:studentNameFont lineBreakMode:NSLineBreakByWordWrapping];
currentPageY += size.height;
// draw a one pixel line under the student's name
CGContextSetStrokeColorWithColor(context, [[UIColor blueColor] CGColor]);
CGContextMoveToPoint(context, kMargin, currentPageY);
CGContextAddLineToPoint(context, kDefaultPageWidth - kMargin, currentPageY);
CGContextStrokePath(context);
// iterate through the list of classes and add these to the PDF.
NSArray* classes = [student objectForKey:@"Classes"];
for(NSDictionary* class in classes)
{
NSString* className = [class objectForKey:@"Name"];
NSString* grade = [class objectForKey:@"Grade"];
// before we render any text to the PDF, we need to measure it, so we'll know where to render the
// next line.
size = [className sizeWithFont:classFont constrainedToSize:CGSizeMake(classNameMaxWidth, MAXFLOAT) lineBreakMode:NSLineBreakByWordWrapping];
// if the current text would render beyond the bounds of the page,
// start a new page and render it there instead
if (size.height + currentPageY > maxHeight) {
// create a new page and reset the current page's Y value
UIGraphicsBeginPDFPageWithInfo(CGRectMake(0, 0, kDefaultPageWidth, kDefaultPageHeight), nil);
currentPageY = kMargin;
}
// render the text
[className drawInRect:CGRectMake(kMargin, currentPageY, classNameMaxWidth, maxHeight) withFont:classFont lineBreakMode:NSLineBreakByWordWrapping alignment:NSTextAlignmentLeft];
// print the grade to the right of the class name
[grade drawInRect:CGRectMake(kMargin + classNameMaxWidth + kColumnMargin, currentPageY, gradeMaxWidth, maxHeight) withFont:classFont lineBreakMode:NSLineBreakByWordWrapping alignment:NSTextAlignmentLeft];
currentPageY += size.height;
}
// increment the page number.
currentPage++;
}
// end and save the PDF.
UIGraphicsEndPDFContext();
// Ask the user if they'd like to see the file or email it.
UIActionSheet* actionSheet = [[UIActionSheet alloc] initWithTitle:@"Would you like to preview or email this PDF?"
delegate:self
cancelButtonTitle:@"Cancel"
destructiveButtonTitle:nil
otherButtonTitles:@"review", @"Email", nil];
[actionSheet showInView:self.view];
}
它确实渲染了数据,但它都是作为标题绘制的,并为每个项目创建一个页面。这是屏幕截图
您能帮忙分离信息并让它们出现在一页中吗?
编辑 1:
这是我想要做的:
这是 plist 结构:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
<dict>
<key>city</key>
<string>asd</string>
<key>state</key>
<string>10</string>
<key>cituPrice</key>
<string>11</string>
<key>cityQuantity</key>
<string>12</string>
<key>cityVintage</key>
<string>13</string>
</dict>
<dict>
<key>city</key>
<string>te2</string>
<key>state</key>
<string>1</string>
<key>cityPrice</key>
<string>2</string>
<key>cityQuantity</key>
<string>3</string>
<key>cityVintage</key>
<string>4</string>
</dict>
<dict>
<key>city</key>
<string>3434</string>
<key>state</key>
<string>6</string>
<key>cityPrice</key>
<string>7</string>
<key>cityQuantity</key>
<string>8</string>
<key>cityVintage</key>
<string>9</string>
</dict>
<dict>
<key>city</key>
<string>test 1</string>
<key>state</key>
<string>20</string>
<key>cityPrice</key>
<string>30</string>
<key>cityQuantity</key>
<string>44</string>
<key>cityVintage</key>
<string>55</string>
</dict>
</array>
</plist>
这就是 plist 保存在文档中时的结构。
Best Answer-推荐答案 strong>
更新的解决方案
替换pdfgenerate中的方法
- (IBAction)pdfPressedid)sender {
NSArray *sysPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory ,NSUserDomainMask, YES);
NSString *documentsDirectory = [sysPaths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:@"Data.plist"];
NSLog(@"File Path: %@", filePath);
NSArray *students = [NSArray arrayWithContentsOfFile:filePath];
// get a temprorary filename for this PDF
filePath = NSTemporaryDirectory();
self.pdfFilePath = [filePath stringByAppendingPathComponent:[NSString stringWithFormat:@"%f.pdf", [[NSDate date] timeIntervalSince1970] ]];
// Create the PDF context using the default page size of 612 x 792.
// This default is spelled out in the iOS documentation for UIGraphicsBeginPDFContextToFile
UIGraphicsBeginPDFContextToFile(self.pdfFilePath, CGRectZero, nil);
// get the context reference so we can render to it.
CGContextRef context = UIGraphicsGetCurrentContext();
int currentPage = 0;
// maximum height and width of the content on the page, byt taking margins into account.
CGFloat maxWidth = kDefaultPageWidth - kMargin * 2;
CGFloat maxHeight = kDefaultPageHeight - kMargin * 2;
// we're going to cap the name of the class to using half of the horizontal page, which is why we're dividing by 2
CGFloat classNameMaxWidth = maxWidth / 2;
// the max width of the grade is also half, minus the margin
CGFloat gradeMaxWidth = (maxWidth / 2) - kColumnMargin;
CGFloat grade1MaxWidth = (maxWidth / 2) - kColumnMargin;
CGFloat grade2MaxWidth = (maxWidth / 2) - kColumnMargin;
// only create the fonts once since it is a somewhat expensive operation
UIFont* studentNameFont = [UIFont boldSystemFontOfSize:17];
UIFont* classFont = [UIFont systemFontOfSize:15];
CGFloat currentPageY = 0;
UIGraphicsBeginPDFPageWithInfo(CGRectMake(0, 0, kDefaultPageWidth, kDefaultPageHeight), nil);
currentPageY = kMargin;
// iterate through out students, adding to the pdf each time.
for (NSDictionary* student in students)
{
// every student gets their own page
// Mark the beginning of a new page.
// draw the student's name at the top of the page.
NSString* name = [NSString stringWithFormat:@"%@",
[student valueForKey:@"city"]];
CGSize HeaderSize = [name sizeWithFont:studentNameFont forWidth:maxWidth lineBreakMode:NSLineBreakByWordWrapping];
// iterate through the list of classes and add these to the PDF.
//NSArray* classes = [student objectForKey:@"Classes"];
NSString* className = [student valueForKey:@"state"];
NSString* grade = [student valueForKey:@"cityPrice"];
NSString* grade1 = [student valueForKey:@"cityText"];
NSString* grade2 = [student valueForKey:@"cityQuantity"];
// before we render any text to the PDF, we need to measure it, so we'll know where to render the
// next line.
CGSize DetailSize = [className sizeWithFont:classFont constrainedToSize:CGSizeMake(classNameMaxWidth, MAXFLOAT) lineBreakMode:NSLineBreakByWordWrapping];
// if the current text would render beyond the bounds of the page,
// start a new page and render it there instead
if (HeaderSize.height + DetailSize.height+currentPageY > maxHeight) {
// create a new page and reset the current page's Y value
UIGraphicsBeginPDFPageWithInfo(CGRectMake(0, 0, kDefaultPageWidth, kDefaultPageHeight), nil);
currentPageY = kMargin;
currentPage++;
}
[name drawAtPoint:CGPointMake(kMargin, currentPageY) forWidth:maxWidth withFont:studentNameFont lineBreakMode:NSLineBreakByWordWrapping];
// draw a one pixel line under the student's name
CGContextSetStrokeColorWithColor(context, [[UIColor blueColor] CGColor]);
CGContextMoveToPoint(context, kMargin, currentPageY+HeaderSize.height);
CGContextAddLineToPoint(context, kDefaultPageWidth - kMargin, currentPageY+HeaderSize.height);
CGContextStrokePath(context);
// render the text
[className drawInRect:CGRectMake(kMargin, currentPageY+HeaderSize.height, classNameMaxWidth, maxHeight) withFont:classFont lineBreakMode:NSLineBreakByWordWrapping alignment:NSTextAlignmentLeft];
// print the grade to the center of the class name
[grade drawInRect:CGRectMake (kMargin , currentPageY+HeaderSize.height, gradeMaxWidth, maxHeight) withFont:classFont lineBreakMode:NSLineBreakByWordWrapping alignment:NSTextAlignmentCenter];
// print the grade1 to the right of the class name
[grade1 drawInRect:CGRectMake(kMargin , currentPageY+HeaderSize.height, grade1MaxWidth, maxHeight) withFont:classFont lineBreakMode:NSLineBreakByWordWrapping alignment:NSTextAlignmentRight];
[grade2 drawInRect:CGRectMake(kMargin , currentPageY+HeaderSize.height, grade2MaxWidth, maxHeight) withFont:classFont lineBreakMode:NSLineBreakByWordWrapping alignment:NSTextAlignmentRight];
// increment the page number.
currentPageY = currentPageY+DetailSize.height+HeaderSize.height+30;
}
// end and save the PDF.
UIGraphicsEndPDFContext();
// Ask the user if they'd like to see the file or email it.
UIActionSheet* actionSheet = [[UIActionSheet alloc] initWithTitle:@"Would you like to preview or email this PDF?"
delegate:self
cancelButtonTitle:@"Cancel"
destructiveButtonTitle:nil
otherButtonTitles:@"review", @"Email", nil];
[actionSheet showInView:self.view];
}
旧解决方案
NSArray *sysPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory ,NSUserDomainMask, YES);
NSString *documentsDirectory = [sysPaths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:@"Data1.plist"];
NSLog(@"File Path: %@", filePath);
NSArray *students = [NSArray arrayWithContentsOfFile:filePath];
您必须获取特定键的值而不是该键的对象
[student objectForKey:@"city"];
像这样使用它而不是上面的行
[student valueForKey:@"city"];
您将数据存储为数组,以便您可以获取内容数组,上面的代码将帮助您像在 pdfpressed 中一样获取学生变量中的对象数组,您可以继续在其中绘制内容pdf文件。
关于ios - 如何从保存在文档目录中的 plist 中读取数据并在新 View 中将其显示为 pdf?,我们在Stack Overflow上找到一个类似的问题:
https://stackoverflow.com/questions/22053169/
|