为什么将这些图像保存到核心数据需要 17 秒?在iPhone上?
我一直在使用 Apple 的 iPhone CoreDateRecipes 示例代码来了解有关表视图和核心数据的更多信息。我已经根据该示例编写了自己的测试应用程序,除了一件事之外,它运行良好。当我为“菜谱”选择一张照片时,无论它是来自相机还是图库,当我点击“完成”离开编辑模式时,大约需要 15 秒才能将控制权返回给用户。在设备上测试时会发生这种情况 - 在模拟器中,仍然存在延迟,但只有 2-4 秒。
我测试了“编辑/完成”按钮,没有选择照片并编辑其他数据,它会立即保存,所以我很确定图像是罪魁祸首。下面是离开编辑模式的代码,以及图像处理代码 - 我可以添加/更改/删除什么来加快速度?我知道这些示例代码片段只是概念证明,但我不敢相信他们发布了一个用户体验如此糟糕的示例!
一如既往,感谢您的任何指导...如果您需要查看任何其他代码,请告诉我,或者 您可以在此处查看整个示例项目
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
[super setEditing:editing animated:animated];
[self updatePhotoButton];
nameTextField.enabled = editing;
overviewTextField.enabled = editing;
[self.navigationItem setHidesBackButton:editing animated:YES];
if (!editing) {
NSManagedObjectContext *context = recipe.managedObjectContext;
NSError *error = nil;
if (![context save:&error]) {
NSLog(@"Error in RecipeDetailViewController:setEditing -- %@, %@",error, [error userInfo]);
abort();
}
}
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)selectedImage editingInfo:(NSDictionary *)editingInfo {
NSManagedObject *oldImage = recipe.image;
if (oldImage != nil) {
[recipe.managedObjectContext deleteObject:oldImage];
}
NSManagedObject *image = [NSEntityDescription insertNewObjectForEntityForName:@"Image" inManagedObjectContext:recipe.managedObjectContext];
recipe.image = image;
[image setValue:selectedImage forKey:@"image"];
CGSize size = selectedImage.size;
CGFloat ratio = 0;
if (size.width > size.height) {
ratio = 70.0 / size.width;
} else {
ratio = 70.0 / size.height;
}
CGRect rect = CGRectMake(0.0, 0.0, ratio * size.width, ratio * size.height);
UIGraphicsBeginImageContext(rect.size);
[selectedImage drawInRect:rect];
recipe.thumbnailImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[self dismissModalViewControllerAnimated:YES];
}
I have been working with Apple's iPhone CoreDateRecipes sample code to learn more about tableviews and core data. I have coded my own test app based off of that sample, and it works well except for one thing. When I choose a photo for the 'recipe', no matter if it is from the camera or the library, when I hit "Done" to leave editing mode, it takes about 15 seconds before returning control to the user. This happens when testing on the device - in simulator, there is still a delay, but it is only 2-4 seconds.
I tested the "edit/done" button without choosing a photo and editing other data, and it saves instantaneously, so I'm pretty sure the image is to blame. Below is the code where it leaves editing mode, and the image processing code - what can I add/change/remove to speed this up? I know these sample code pieces are just proofs of concept, but I can't believe they published an example with such a crappy user experience!
Thanks, as always, for any guidance...let me know if there is any other code you need to see, or you can see the whole sample project here
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
[super setEditing:editing animated:animated];
[self updatePhotoButton];
nameTextField.enabled = editing;
overviewTextField.enabled = editing;
[self.navigationItem setHidesBackButton:editing animated:YES];
if (!editing) {
NSManagedObjectContext *context = recipe.managedObjectContext;
NSError *error = nil;
if (![context save:&error]) {
NSLog(@"Error in RecipeDetailViewController:setEditing -- %@, %@",error, [error userInfo]);
abort();
}
}
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)selectedImage editingInfo:(NSDictionary *)editingInfo {
NSManagedObject *oldImage = recipe.image;
if (oldImage != nil) {
[recipe.managedObjectContext deleteObject:oldImage];
}
NSManagedObject *image = [NSEntityDescription insertNewObjectForEntityForName:@"Image" inManagedObjectContext:recipe.managedObjectContext];
recipe.image = image;
[image setValue:selectedImage forKey:@"image"];
CGSize size = selectedImage.size;
CGFloat ratio = 0;
if (size.width > size.height) {
ratio = 70.0 / size.width;
} else {
ratio = 70.0 / size.height;
}
CGRect rect = CGRectMake(0.0, 0.0, ratio * size.width, ratio * size.height);
UIGraphicsBeginImageContext(rect.size);
[selectedImage drawInRect:rect];
recipe.thumbnailImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[self dismissModalViewControllerAnimated:YES];
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
首先,正如吉尔伯特指出的,示例代码并不适合生产使用,而且速度会很慢。
其次,您不应该将图像存储在 Core Data 中。该示例可能展示了如何做到这一点,但这通常是一个非常糟糕的主意。您应该将图像存储在磁盘上,然后在 Core Data 中保留指向该图像的指针(文件路径)。 此规则有一些例外(非常小的图像),但您应该重新考虑您的设计。
最后,您看到的许多缓慢可能与核心数据无关。图像选择器代码本身非常慢。我建议将代码更改为仅写入磁盘,并查看与写入核心数据相比有多慢。 如果速度快得多,我会感到惊讶。
更新
您可以在 Core Data 中存储小图像,我从其他帖子中得到的建议是,桌面版比 iOS 版更适合。 造成这种情况的原因是缓存。在 iOS 上,Core Data 使用的缓存非常小。如果您在数据库中存储的图像很大,则可以轻松地耗尽该缓存,并导致将来应该在缓存中的调用转而访问磁盘。 这不是“不存储二进制数据”的硬性规则,而是更多的观察性能的规则,如果您对磁盘的访问超出了应有的范围,则二进制数据很容易成为原因。
联系人
对于联系人,您可能会变慢,因为他们的操作方式与您不同,并且他们可以轻松使用私有 API 来访问相机。 因为是苹果,所以他们不一定遵循与我们相同的规则。
First, as Gilbert pointed out, example code is not meant for production use and will be slow.
Second, you should not store images in Core Data. The example may show how to do it but it is generally a very bad idea. You should be storing images on disk and then keeping a pointer (file path) to the image in Core Data. There are some exceptions to this rule (very small images) but you should rethink your design.
Lastly, A lot of the slowness you are seeing may not be Core Data related. The image picker code is very slow on its own. I would recommend changing the code to just write to disk and see how slow that is compared to the writing to Core Data. I would be surprised if it was much faster.
Update
You can store small images inside of Core Data and my advice from other posts stands, mores for the desktop than iOS. The reason for this is the cache. On iOS, the cache that Core Data uses is very small. If you store images in the database that are large, you can blow out that cache easily and cause future calls that should be in the cache to hit the disk instead. This is not a hard and fast rule of "don't store binary data" but more of a rule of watch your performance and if you are hitting the disk more than you should, binary data could easily be the cause.
Contacts
With regard to contacts, you can be slower because they are doing things differently than you are and they could easily be using private APIs to access the camera. Because it is Apple, they don't necessarily play by the same rules as us.
我不是 iPhone 开发人员,但一般情况下,示例代码不会考虑用户体验。示例代码显示了示例。
一般来说,您需要在额外的线程中执行昂贵的(长时间运行的)操作。
也许这篇博文会有所帮助:尊重主线程
I'm not an iPhone developer, but generally, example code does not take into account the user experience. Example code shows examples.
In general, you need to perform expensive (long running) operations in additional threads.
Maybe this blog post will help: Respect the Main Thread
我下载了该项目,构建了它并在模拟器中运行它。我无法重现你的问题。我发现保存图像所花费的时间在视觉上是瞬时的,即不长于视图转换。
如果您在原始的、未经修改的项目上看到同样的问题,那么您可能还有其他问题。确保您拥有该项目的最新版本,该版本应该是您链接中的版本。我知道至少有一个非常古老的东西漂浮在周围,因为我最近打到了它。
I downloaded the project, built it and ran it in the simulator. I couldn't reproduce your problem. I found that the time it took to save an image was visually instantaneous i.e. no longer than the view transition.
If you see the same issue on the original, unmodified project, then you have something else going on. Make sure you have the latest version of the project which should be the one at your link. I know there is at least one really old one floating around because I hit it recently.