Shared WebView in UIActivityViewController - swift

I get a PDF in Json, retrieve it and have it displayed in a webview, but I also need it to be shared with the UIActivityViewController, but when I pass the webview it does not show options available for sharing
I am doing the following:
//I get the json
if let url = URL(string: "http://10.1.80.106:9000/api/recibo/imprimir?vigencia=2015-06-30") {
var urlRequest = URLRequest(url: url)
urlRequest.setValue("application/pdf", forHTTPHeaderField: "Content-Type")
urlRequest.setValue("aaaabbbccc", forHTTPHeaderField: "Authorization")
//i create the webview
let webView = UIWebView(frame: self.view.frame)
webView.loadRequest(urlRequest as URLRequest)
webView.scalesPageToFit = true
let pdfVC = UIViewController()
pdfVC.view.addSubview(webView)
pdfVC.title = "Recibo de Pagamento"
self.navigationController?.pushViewController(pdfVC, animated: true)
//instantiate the UIActivityViewController for the share, and step the WebView as parameter
let vc = UIActivityViewController(activityItems: [(webView.request?.url?.absoluteString) as Any], applicationActivities: [])
if let popoverController = vc.popoverPresentationController {
popoverController.sourceView = self.view
popoverController.sourceRect = self.view.bounds
}
self.present(vc, animated: true, completion: nil)
}

Actually, instead of WebView you could also use the QuickLook Framework, which is designed for this specific purpose. You just pass
the location of the file and conform to the protocols. It will present
a view controller with the document inside. You can also have the native options to share the file.
Check out this answer about it's implementation and example.

Related

Why does my app crashes when I tap "Save Image" option on UIActivityViewController?

So, in the 3D Touch peek controller, I have this computed var where I setup the UIPreviewAction:
override lazy var previewActionItems: [UIPreviewActionItem] = {
let save = UIPreviewAction.init(title: "Share Image", style: UIPreviewAction.Style.default, handler: { (action, controller) in
let renderer = UIGraphicsImageRenderer(size: self.view.bounds.size)
let imageAux = renderer.image { ctx in
self.view.drawHierarchy(in: self.view.bounds, afterScreenUpdates: true)
}
self.delegate!.shareImage(image: imageAux, url: self.data.url)
})
return [save]
}()
and in the delegate controller I have this method to present the UIActivityViewController:
func shareImage(image: UIImage, url: String) {
if let data = image.pngData() {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let filename = paths[0].appendingPathComponent(url)
try? data.write(to: filename)
}
let activityViewController = UIActivityViewController(activityItems: [image] , applicationActivities: nil)
activityViewController.popoverPresentationController?.sourceView = self.view
self.present(activityViewController, animated: true, completion: nil)
}
everything works fine, i can share with any apps, and can store using the File Explore, but if I press "Save Image", the app crashes. Looks like I need gallery permission, but I don't know how to implement it in the UIPreviewAction to check if I have the permission or not, so that if I do it saves, and if I do not it asks for permission.
Add new records in your new InfoPlist.strings file.
<key>NSPhotoLibraryAddUsageDescription</key>
<string>$(PRODUCT_NAME)</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>$(PRODUCT_NAME)</string>
delete your app from simulator and run again.

how to use web url image in activity controller to share image in swift

I'm using 'AlamofireImage' pod and show images in collection View cell but client want to share Image I'm using this but not working :
var shareImages = [UIImage]()
shareImages = [UIImage(named: "http://idea-factory.in/images/25-021.jpg")] as! [UIImage];
let activityViewController:UIActivityViewController = UIActivityViewController(activityItems: shareImages, applicationActivities: nil)
let excludedTypes: [UIActivity.ActivityType] = [.postToVimeo, .postToTwitter, .assignToContact, .saveToCameraRoll]
activityViewController.excludedActivityTypes = excludedTypes
self.present(activityViewController, animated: true, completion: nil)
error comes : Thread 1: signal SIGABRT
I'm not sure if this is helpful but I normally get that error if I either haven't linked up my view controllers properly or needed to force unwrap a value and haven't.
You must use the image once it is received completely.
One of the methods you can use is
let downloader = ImageDownloader()
let urlRequest = URLRequest(url: URL(string: "http://idea-factory.in/images/25-021.jpg")!)
downloader.download(urlRequest) { response in
print(response.request)
print(response.response)
debugPrint(response.result)
if let image = response.result.value {
//use your activity controller here
}
}

UIActivityViewController share a video on WhatsApp

I have look around a lot but didn't find a solution to my problem.
I am displaying videos in a tableviewcell like this
if let videoUrlString = post?.videoUrl, let videoUrl = URL(string: videoUrlString) {
self.volumenView.isHidden = false
player = AVPlayer(url: videoUrl)
playerLayer = AVPlayerLayer(player: player)
playerLayer?.frame = postImageView.frame
playerLayer?.frame.size.width = UIScreen.main.bounds.width
playerLayer?.frame.size.height = UIScreen.main.bounds.width / post!.ratio!
self.contentView.layer.addSublayer(playerLayer!)
self.volumenView.layer.zPosition = 1
player?.play()
player?.isMuted = isMuted
NotificationCenter.default.addObserver(self, selector:#selector(self.playerDidFinishPlaying(note:)),name: NSNotification.Name.AVPlayerItemDidPlayToEndTime, object: player?.currentItem)
}
this works perfectly fine.
Now I want the user to be able to share the video on WhatsApp.
I ve made it work text post and image post which work fine but wasn't able to make it run with videos.
this is how I currently send the notification
let videoURL = NSURL(fileURLWithPath: (post?.videoUrl)!)
let data:[String: NSURL] = ["video": videoURL]
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "shareCalled"), object: nil, userInfo: data)
this works so far that the chat partner receives a link to where the video is stored in firebase and by clicking that link he can see the video.
This works but its not elegant, I would like to send the video as one and not as a link where the user has to suspiciously click on.
Any idea?
Edit: code where I share the post (notice: text and image work fine, video just sends the url but not a video as one
#objc func shareCalled(_ notification: NSNotification) {
if let data = notification.userInfo?["image"] as? UIImage {
let activityVC = UIActivityViewController(activityItems: [data], applicationActivities: nil)
activityVC.popoverPresentationController?.sourceView = self.view
activityVC.excludedActivityTypes = [UIActivityType.airDrop, UIActivityType.addToReadingList,UIActivityType.openInIBooks, UIActivityType.openInIBooks]
self.present(activityVC, animated: true, completion: nil)
}
if let data = notification.userInfo?["caption"] as? String {
let activityVC = UIActivityViewController(activityItems: [data], applicationActivities: nil)
activityVC.popoverPresentationController?.sourceView = self.view
activityVC.excludedActivityTypes = [UIActivityType.airDrop, UIActivityType.addToReadingList,UIActivityType.openInIBooks, UIActivityType.openInIBooks]
self.present(activityVC, animated: true, completion: nil)
}
if let data = notification.userInfo?["video"] as? URL {
let activityVC = UIActivityViewController(activityItems: [data], applicationActivities: nil)
activityVC.popoverPresentationController?.sourceView = self.view
activityVC.excludedActivityTypes = [UIActivityType.airDrop, UIActivityType.addToReadingList,UIActivityType.openInIBooks, UIActivityType.openInIBooks]
self.present(activityVC, animated: true, completion: nil)
}
}

How should you disable a button from being ran over and over upon every click?

I don't know why but I was under the assumption that a button shouldn't be clickable over and over again to redo itself....
I have a fairly simple code.
When my button is clicked, it downloads an image using urlSession into the backgroundview of another viewController and segues into it.
My problem is that if click on button 3 times while I wait for the image to load, my viewController segues 3 layers down into a navigationController and to get back to the original viewController I have to click the back button 3 times. Shouldn't I not be able to segue 3 layers down!?
#IBAction func showImage(_: UIButton) {
loadImage()
}
func loadImage () {
let url = URL(string: "https://upload.wikimedia.org/wikipedia/en/thumb/a/a4/Flag_of_the_United_States.svg/1280px-Flag_of_the_United_States.svg.png")
var request = NSMutableURLRequest(url: url!, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0)
request.httpMethod = "GET"
let session = URLSession.shared.dataTask(with: request as URLRequest) { (data, response, error) in
guard let data = data else {
print("You got an error:\(error)")
return
}
let img = UIImage(data: data )
let imgview = UIImageView(image: img)
let sb = UIStoryboard(name: "Main", bundle: nil)
let ivc = sb.instantiateViewController(withIdentifier: "showImage")
ivc.view = imgview
self.navigationController?.pushViewController(ivc, animated: true)
}
session.resume()
}
Thanks to Phillip Mills comment, this is what I have done:
I added a
#IBOutlet weak var showImage: UIButton!
and then upon clicking, I disabled the button with:
showImage.isEnabled = false
And after doing the segue I enabled it again with:
showImage.isEnabled = true
My full code is:
#IBOutlet weak var showImage: UIButton! // Added
#IBAction func showImage(_: UIButton) {
showImage.isEnabled = false // Added
loadImage()
}
func loadImage () {
let url = URL(string: "https://upload.wikimedia.org/wikipedia/en/thumb/a/a4/Flag_of_the_United_States.svg/1280px-Flag_of_the_United_States.svg.png")
var request = NSMutableURLRequest(url: url!, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0)
request.httpMethod = "GET"
let session = URLSession.shared.dataTask(with: request as URLRequest) { (data, response, error) in
guard let data = data else {
print("You got an error:\(error)")
return
}
let img = UIImage(data: data )
let imgview = UIImageView(image: img)
let sb = UIStoryboard(name: "Main", bundle: nil)
let ivc = sb.instantiateViewController(withIdentifier: "showImage")
ivc.view = imgview
self.navigationController?.pushViewController(ivc, animated: true)
self.showImage.isEnabled = true // Added
}
session.resume()
}

open PDF URL in iOS 8?

I have write this code to show pdf using UIDocumentInteractionController.But,I don't know how to search pdf at local directory and open in iOS 8 and below..Any help?
let filename = history.invoiceLongDate // 01223642
if !filename.isEmpty{
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
let docs = paths[0]
let pathURL = NSURL(fileURLWithPath: docs, isDirectory: true)
if #available(iOS 9.0, *) {
let fileURL = NSURL(fileURLWithPath: "\(filename)_my_invoice.pdf", isDirectory: false, relativeToURL: pathURL)
self.docController = UIDocumentInteractionController(URL: fileURL)
self.docController?.delegate = self
self.docController?.presentOptionsMenuFromRect(sender.frame, inView: self.view, animated: true)
} else {
// Fallback on earlier versions
// Any Help with that?
}
}
You can view PDF in iOS 8 by using webview. Try below code,
if let pdf = NSBundle.mainBundle().URLForResource("myPDF", withExtension: "pdf", subdirectory: nil, localization: nil) {
let req = NSURLRequest(URL: pdf)
let webView = UIWebView(frame: CGRectMake(0,0,self.view.frame.size.width,self.view.frame.size.height))
webView.loadRequest(req)
self.view.addSubview(webView)
}
OR
if let baseUrl = NSURL.fileURLWithPath(pathURL) {
let fileURL = baseUrl.URLByAppendingPathComponent(NFConstants.NFCoreDataStringIdentifiers.CoreDataStoresPathComponent.rawValue)
}
Hope this will be helpful to you.
UIDocumentInteractionController is available with (iOS 3.2, *).
For Viewing PDF file:
var documentInteractionController: UIDocumentInteractionController!
#IBAction func openDocument(sender: UIButton) {
let URL: NSURL = NSBundle.mainBundle().URLForResource("pdf-sample", withExtension: "pdf")!
if (URL != "") {
// Initialize Document Interaction Controller
self.documentInteractionController = UIDocumentInteractionController(URL: URL)
// Configure Document Interaction Controller
self.documentInteractionController.delegate = self
// Present Open In Menu
self.documentInteractionController.presentOptionsMenuFromRect(sender.frame, inView: self.view, animated: true)
//presentOpenInMenuFromRect(button.frame, inView: self.view, animated: true)
}
}
// MARK: UIDocumentInteractionControllerDelegate
func documentInteractionControllerViewControllerForPreview(controller: UIDocumentInteractionController) -> UIViewController {
return self
}