【发布时间】:2022-01-01 14:04:22
【问题描述】:
我是 Xcode 的新手(使用 4.3),不知道如何将图像保存到设备的相机胶卷。到目前为止,我所做的只是为按钮设置一个 IBAction 来保存图像。我可以使用什么库方法或函数将图像保存到用户的相机胶卷?
【问题讨论】:
标签: iphone ios objective-c ipad camera
我是 Xcode 的新手(使用 4.3),不知道如何将图像保存到设备的相机胶卷。到目前为止,我所做的只是为按钮设置一个 IBAction 来保存图像。我可以使用什么库方法或函数将图像保存到用户的相机胶卷?
【问题讨论】:
标签: iphone ios objective-c ipad camera
您使用UIImageWriteToSavedPhotosAlbum() 函数。
//Let's say the image you want to save is in a UIImage called "imageToBeSaved"
UIImageWriteToSavedPhotosAlbum(imageToBeSaved, nil, nil, nil);
编辑:
//ViewController.m
- (IBAction)onClickSavePhoto:(id)sender{
UIImageWriteToSavedPhotosAlbum(imageToBeSaved, nil, nil, nil);
}
【讨论】:
UIImageView *imageToBeSaved;。我以为我必须在我的 .m 中添加 @synthesize imageToBeSaved,但我收到一条错误消息,提示“缺少属性实现声明的上下文”
作为参考,你可以用类似的方式保存视频:
UISaveVideoAtPathToSavedPhotosAlbum(videoPath, nil, nil, nil);
您可能想要保存视频以上传到 Instagram,例如:
// Save video to camera roll; we can share to Instagram from there.
-(void)didTapShareToInstagram:(id)sender {
UISaveVideoAtPathToSavedPhotosAlbum(self.videoPath, self, @selector(video:didFinishSavingWithError:contextInfo:), (void*)CFBridgingRetain(@{@"caption" : caption}));
}
- (void) video: (NSString *) videoPath
didFinishSavingWithError: (NSError *) error
contextInfo: (void *) contextInfoPtr {
NSDictionary *contextInfo = CFBridgingRelease(contextInfoPtr);
NSString *caption = contextInfo[@"caption"];
NSString *escapedString = [videoPath stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]]; // urlencodedString
NSString *escapedCaption = [caption stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]]; // urlencodedString
NSURL *instagramURL = [NSURL URLWithString:[NSString stringWithFormat:@"instagram://library?AssetPath=%@&InstagramCaption=%@", escapedString, escapedCaption]];
[[UIApplication sharedApplication] openURL:instagramURL];
}
【讨论】:
这是使用 Photos 框架的 iOS8+ 的答案。
目标-C:
#import <Photos/Photos.h>
UIImage *snapshot = self.myImageView.image;
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetChangeRequest *changeRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:snapshot];
changeRequest.creationDate = [NSDate date];
} completionHandler:^(BOOL success, NSError *error) {
if (success) {
NSLog(@"successfully saved");
}
else {
NSLog(@"error saving to photos: %@", error);
}
}];
斯威夫特:
// Swift 4.0
import Photos
let snapshot: UIImage = someImage
PHPhotoLibrary.shared().performChanges({
PHAssetChangeRequest.creationRequestForAsset(from: snapshot)
}, completionHandler: { success, error in
if success {
// Saved successfully!
}
else if let error = error {
// Save photo failed with error
}
else {
// Save photo failed with no error
}
})
这是 Apple 文档的 link。
不要忘记将适当的键/值添加到您的 info.plist 以请求访问照片库的权限:
<key>NSCameraUsageDescription</key>
<string>Enable camera access to take photos.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Enable photo library access to select a photo from your library.</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>Enable photo library access to save images to your photo library directly from the app.</string>
【讨论】:
然后使用以下代码保存图像
UIImageWriteToSavedPhotosAlbum(imageView.image!, nil, nil, nil)
【讨论】:
使用 asImage() 获取要保存到相机胶卷的独特内容。
如果您使用 asImage(),您只需几行代码就可以将各种有趣的东西保存到相机胶卷中!如果对象已经合并了一些透明度,这将非常强大。
asImage() 与 UITextView、WKWebView、UIImageView、UIButton、UISlider、UITableView 一起使用来命名一些对象(但是当您获取图像时它们可能需要可见(具有非零 alpha))。我什至用它来捕获平铺,但在我的设计中已经加载到 UIImageView 中。我怀疑 asImage() 也可能适用于更多对象类型,但我只尝试了我提到的那些。
如果它是 UITextView,并且您将背景颜色设置为 .clear,那么文本会以透明背景保存。如果您的文本包含表情符号或拟我表情,您现在可以将这些图像放入相机胶卷或应用程序内部的 UIImageViews。在您的相机胶卷中拥有具有透明背景的拟我表情/表情符号,它们可以用于各种应用程序,这是非常强大的。
如果您将照片图像裁剪为圆形,或设置角半径以剪掉角,其他对象可能会有一些透明度。
注意在我的代码中,pointerToTextObjectSelected 是一个 UITextView
var pointerToTextObjectSelected = UITextView()
// above populated elsewhere
let thisObject = pointerToTextObjectSelected.asImage()
let imageData = thisObject.pngData()
let imageToSave = UIImage(data: imageData!)
UIImageWriteToSavedPhotosAlbum(imageToSave!, nil, nil, nil)
// You will need this extension :
extension UIView {
// Using a function since `var image` might conflict with an existing variable
// (like on `UIImageView`)
func asImage() -> UIImage {
if #available(iOS 10.0, *) {
let renderer = UIGraphicsImageRenderer(bounds: bounds)
return renderer.image { rendererContext in
layer.render(in: rendererContext.cgContext)
}
} else {
UIGraphicsBeginImageContext(self.frame.size)
self.layer.render(in:UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return UIImage(cgImage: image!.cgImage!)
}
}
}
【讨论】: