iOS 11 added a markup option after taking a screenshot, how can I programmatically apply this option after programmatically taking a screenshot? it directly gets saved to photos without providing the markup/share option.
I use the code below to take and save the screenshot
#IBAction func takeScreenshot(_ sender: Any) {
let layer = UIApplication.shared.keyWindow!.layer
let scale = UIScreen.main.scale
UIGraphicsBeginImageContextWithOptions(layer.frame.size, false, scale);
layer.render(in: UIGraphicsGetCurrentContext()!)
let screenshot = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
UIImageWriteToSavedPhotosAlbum(screenshot!, nil, nil, nil)
}
Instant Markup is not documented anywhere in Apple's Reference Docs, so I think its safe to assume this isn't made public through their SDK.
Instead you would have to create your own markup editor.
Note: You may not change the way actual device screenshots are handled (when the user presses Home and Lock together) as per Apple's guidelines.
Related
Found here:
How do I take a full screen Screenshot in Swift?
func getScreenshot() -> UIImage {
var window: UIWindow? = UIApplication.shared.keyWindow
window = UIApplication.shared.windows[0] as? UIWindow
UIGraphicsBeginImageContextWithOptions(window!.frame.size, window!.isOpaque, 0.0)
window!.layer.render(in: UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image!
}
I want to use this code to get an image from my viewcontroller. Thereafter I wanna save the image to my photo library for printing and sending by mail.
Only when I add this code in the penultimate line over return image!:
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
,I get the "signal SIGABRT" error.
In my info.plist I tried to add: Privacy - Photo Library Usage Description without any value.
Can anybody help me to find what's going wrong?
Another option would be to save the screenshot as pdf in any folder, to find it later for sending and printing.
Thank you for any hint.
Use NSPhotoLibraryAddUsageDescription (Privacy - Photo Library Additions Usage Description)
NSPhotoLibraryAddUsageDescription
A message that tells the user why the app is requesting write-only access to the user’s photo library.
Important
This key is required if your app uses APIs that have write access to the user’s photo library.
Good afternoon,
I am trying to take a snapshot of a PDF but I am facing some difficulties to access view's content on iOS 12.
In order to display the PDF's content, I've already used two different approaches:
UIDocumentInteractorController
Webview
On iOS 11, I couldn't already take a snapshot of a UIDocumentInteractorController view and the best answer that I could find was this one https://stackoverflow.com/a/13332623/2568889. In short, it says that the document viewer runs in an external process and on its own windows that the main app process doesn't have access to.
The WebView was the solution at that time, until iOS 12 came. While testing on real devices running iOS 12, I had the same issue of not being able to access the viewer's content while taking the snapshot. While inspecting the view hierarchy, it looks like we have a childviewcontroller (PDFHostViewController) that is the one rendering the actual view.
Please take into account that this issue is just happening for PDFs, on regular webpages is working fine!
Code used to take snapshot:
private extension UIView {
func takeSnapshot() -> UIImage {
let format = UIGraphicsImageRendererFormat()
format.opaque = self.isOpaque
let renderer = UIGraphicsImageRenderer(size: self.frame.size, format: format)
return renderer.image { context in
self.drawHierarchy(in: self.frame, afterScreenUpdates: true)
}
}
}
Note: I have also tried to use the native Webview.takeSnapshot(with:,completionHandler) of the web view but it just works for regular webpages, not PDFs
Maybe it works with Apple's PDFKit. As far as i know the PDFView is a subclass of UIView.
import PDFKit
#IBOutlet var pdfView: PDFView!
let pdfDocument = PDFDocument(url: url)
pdfView.document = pdfDocument
And then your extension as PDFView extension
I need to record the screen to make a ten-seconds video when someone is broadcasting like the record function of "live.me" app. I can't use replaykit because I need to support iOS8.
when user click the record button,I start to screen shot twenty-four times in a second.
public func screenShot() -> UIImage? {
UIGraphicsBeginImageContextWithOptions(self.bounds.size, true, 0)
self.drawViewHierarchyInRect(self.bounds, afterScreenUpdates: true)
let img = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return img
}
then I use AVasset to put all pictures to video
This way, there are too many disadvantages,such as high cpu low performance of mobile phones can't use it。
Is this way wrong or the way works I need to optimize?
I need to have a Facebook share button on one of my app's view controllers so that when the user pushes it, it will share a screenshot of the user's current screen to Facebook.
I have been watching a few tutorials such as this one on how to implement a Facebook share button: https://www.youtube.com/watch?v=774_-cTjnVM
But these only show how I can share a message on Facebook, and I'm still a little bit confused how to share the whole screen that user is currently interacting with.
Sharing directly to Facebook isn't hard to do. First, import the Social framework:
import Social
Now add this as the action for your button:
let screen = UIScreen.mainScreen()
if let window = UIApplication.sharedApplication().keyWindow {
UIGraphicsBeginImageContextWithOptions(screen.bounds.size, false, 0);
window.drawViewHierarchyInRect(window.bounds, afterScreenUpdates: false)
let image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
let composeSheet = SLComposeViewController(forServiceType: SLServiceTypeFacebook)
composeSheet.setInitialText("Hello, Facebook!")
composeSheet.addImage(image)
presentViewController(composeSheet, animated: true, completion: nil)
}
You might be interested to know that UIActivityViewController lets users share to Facebook but also other services. The code above is for your exact question: sharing to Facebook. This code renders the entire visible screen; you can also have individual views render themselves if you want.
Note: As Duncan C points out in a comment below, this rendering code won't include anything outside your app, such as other apps or system controls.
In iOS 8 and earlier there used to be a private framework that you could use to capture the entire screen. Using that framework would cause your app to be rejected for the app store, but at least it worked.
Starting in iOS 9 that API no longer works
The best you can do is to capture your app's views. That won't include the status bar or other things drawn by the system or other apps.
One way is to create an off-screen context, render the parent view you want to capture into the off-screen context (probably using drawViewHierarchyInRect:afterScreenUpdates:, load the data from the context into a UIImage, and then close the context.
Another way is a new API that will capture a snapshot of a view hierarchy. One of the new methods to capture a snapshot is snapshotViewAfterScreenUpdates. That creates specialized snapshot view.
swift 3
let screen = UIScreen.main
if let window = UIApplication.shared.keyWindow {
UIGraphicsBeginImageContextWithOptions(screen.bounds.size, false, 0);
window.drawHierarchy(in: window.bounds, afterScreenUpdates: false)
let image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
let composeSheet = SLComposeViewController(forServiceType: SLServiceTypeFacebook)
composeSheet?.setInitialText("Hello, Facebook!")
composeSheet?.add(image)
present(composeSheet!, animated: true, completion: nil)
}
I'm using Core Image in Swift for editing photos and I have a problem when I save the photo. I'm not saving it with correct orientation.
When I get the picture from the Photo Library I'm saving the orientation in a variable as UIImageOrientation but I don't know how to set it back before saving the edited photo to the Photo Library. Any ideas how?
Saving the orientation:
var orientation: UIImageOrientation = .Up
orientation = gotImage.imageOrientation
Saving the edited photo to the Photo Library:
#IBAction func savePhoto(sender: UIBarButtonItem) {
let originalImageSize = CIImage(image:gotImage)
filter.setValue(originalImageSize, forKey: kCIInputImageKey)
// 1
let imageToSave = filter.outputImage
// 2
let softwareContext = CIContext(options:[kCIContextUseSoftwareRenderer: true])
// 3
let cgimg = softwareContext.createCGImage(imageToSave, fromRect:imageToSave.extent())
// 4
let library = ALAssetsLibrary()
library.writeImageToSavedPhotosAlbum(cgimg,
metadata:imageToSave.properties(),
completionBlock:nil)
}
Instead of using the metadata version of writeImageToSavedPhotosAlbum, you can use :
library.writeImageToSavedPhotosAlbum(
cgimg,
orientation: orientation,
completionBlock:nil)
then you can pass in the orientation directly.
To satisfy Swift, you may need to typecast it first:
var orientation : ALAssetOrientation = ALAssetOrientation(rawValue:
gotImage.imageOrientation.rawValue)!
As per my somewhat inconclusive answer here.
(As you have confirmed, this solution does indeed work in Swift - I derived it, untested, from working Objective-C code)
If you are interested in manipulating other information from image metadata, here are a few related answers I provided to other questions...
Updating UIImage orientation metaData?
Force UIImagePickerController to take photo in portrait orientation/dimensions iOS
How to get author of image in cocoa
Getting a URL from (to) a "picked" image, iOS
And a small test project on github that digs out image metadata from various sources (it's objective-C, but the principles are the same).
You are calling writeImageToSavedPhotosAlbum:metadata:completionBlock:... The docs on that method say:
You must specify the orientation key in the metadata dictionary to preserve the orientation of the image.