How can I display all applications that can read pdf file (adobe pdf reader for example) when a button is clicked? I searched but I found that the majority use UIWebView to display pdf file. How can I do it with the way that I described?
Edit:
I have only the pdf link that I get from the server
Try this
var docController:UIDocumentInteractionController!
let pdfUrl = NSURL(string: "ENTER_URL_OF_PDF")
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
downloadDoc(pdfUrl: pdfUrl!)
}
#IBAction func buttonAction(_ sender: AnyObject) {
docController.presentOptionsMenu(from: self.view.frame, in: self.view, animated: true)
}
func downloadDoc(pdfUrl : NSURL) {
let urlTest = self.pdfUrl!.absoluteString
let pdfUrl = NSURL(string: urlTest!)
if(pdfUrl != nil){
let pdfRequest: NSURLRequest = NSURLRequest(url: pdfUrl! as URL)
NSURLConnection.sendAsynchronousRequest(pdfRequest as URLRequest, queue: OperationQueue.main) {(response, data, error) in
let httpResponse = response as? HTTPURLResponse
if(httpResponse?.statusCode == 200 && error == nil){
let documentsUrl = FileManager.default.urls(for: FileManager.SearchPathDirectory.documentDirectory, in: FileManager.SearchPathDomainMask.userDomainMask).first as! NSURL
if let fileName = self.pdfUrl!.lastPathComponent {
let destinationUrl = documentsUrl.appendingPathComponent(fileName)
if let data = data {
do {
try data.write(to: destinationUrl!, options: .atomic)
} catch {
print(error)
}
self.docController = UIDocumentInteractionController(url: destinationUrl!)
}
}
}
}
}
}
You can go with UIDocumentInteractionController, it will handle all for you like zooming pdf, scrolling, showing suitable app to handle the pdf.
SWIFT 2.3:
import UIKit
class ViewController:UIViewController, UIDocumentInteractionControllerDelegate {
var documentController: UIDocumentInteractionController = UIDocumentInteractionController()
override func viewDidLoad() {
super.viewDidLoad()
downloadFileForfileObject("https://d0.awsstatic.com/whitepapers/KMS-Cryptographic-Details.pdf")
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
}
func downloadFileForfileObject(url: String) { //Download pdf File asynchronosly
let documentURL = NSURL(string: url)
let documentsURLPath = NSFileManager.defaultManager().URLsForDirectory(.CachesDirectory, inDomains: .UserDomainMask).first! as NSURL
let fileExtension = ((documentURL!.pathComponents)?.last)! as String
let request: NSURLRequest = NSURLRequest(URL: documentURL!, cachePolicy: NSURLRequestCachePolicy.ReturnCacheDataElseLoad, timeoutInterval: 60)
let fileURLPath = documentsURLPath.URLByAppendingPathComponent("\(fileExtension)")
let sessionCobfig = NSURLSessionConfiguration()
let session = NSURLSession(configuration: sessionCobfig, delegate: nil, delegateQueue: nil)
let task = session.dataTaskWithRequest(request) { (data, response, error) in
if error == nil {
self.openSelectedDocumentFromURL((fileURLPath?.path!)!)
} else {
print(error?.localizedDescription)
}
}
task.resume()
}
func openSelectedDocumentFromURL(documentURLString: String) {
let documentURL: NSURL = NSURL(fileURLWithPath: documentURLString)
documentController = UIDocumentInteractionController(URL: documentURL)
documentController.delegate = self
documentController.presentPreviewAnimated(true)
}
// MARK: - UIDocumentInteractionViewController delegate methods
func documentInteractionControllerViewControllerForPreview(controller: UIDocumentInteractionController) -> UIViewController {
return self
}
}
Call downloadFileForfileObject() in viewDidLoad method with your pdf url as a parameter. The pdf will be automatically shown by UIDocumentInteractionController delegate method.
SWIFT 3:
import UIKit
class MOViewController:UIViewController, UIDocumentInteractionControllerDelegate {
var documentController: UIDocumentInteractionController = UIDocumentInteractionController()
override func viewDidLoad() {
super.viewDidLoad()
downloadFileForfileObject(url: "https://d0.awsstatic.com/whitepapers/KMS-Cryptographic-Details.pdf")
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
}
func downloadFileForfileObject(url: String) { //Download pdf File asynchronosly
let documentURL = NSURL(string: url)
let documentsURLPath = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first! as NSURL
let fileExtension = ((documentURL!.pathComponents)?.last)! as String
let request: URLRequest = URLRequest(url: documentURL! as URL, cachePolicy: NSURLRequest.CachePolicy.returnCacheDataElseLoad, timeoutInterval: 60)
let fileURLPath = documentsURLPath.appendingPathComponent("\(fileExtension)")
let sessionConfig = URLSessionConfiguration.default
let session = URLSession(configuration: sessionConfig, delegate: nil, delegateQueue: nil)
let teask = session.dataTask(with: request) { (data, response, error) in
if (error == nil) {
// Success
self.openSelectedDocumentFromURL(documentURLString: fileURLPath!.path)
} else {
print(error?.localizedDescription)
}
}
teask.resume()
}
func openSelectedDocumentFromURL(documentURLString: String) {
let documentURL: NSURL = NSURL(fileURLWithPath: documentURLString)
documentController = UIDocumentInteractionController(url: documentURL as URL)
documentController.delegate = self
documentController.presentPreview(animated: true)
}
// MARK: - UIDocumentInteractionViewController delegate methods
func documentInteractionControllerViewControllerForPreview(_ controller: UIDocumentInteractionController) -> UIViewController {
return self
}
Document download verification:
You check whether document is downloading or not by follows, see image.
Output:
Thanks:)
Related
I would like to add a couple of images that are stored in variables to a QLPreviewController. The QuickLook datasource requires a fileURL which I'm not sure how to get for an image that is stored in a variable and not in disk or in the project.
Any pointers as to how I can solve this issue?
Below code can be used to to display image file from local and from URL in QLPreviewController.
import UIKit
import QuickLook
class ViewController: UIViewController {
lazy var previewItem = NSURL()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
#IBAction func displayLocalFile(_ sender: UIButton){
let previewController = QLPreviewController()
// Set the preview item to display
self.previewItem = self.getPreviewItem(withName: "bull.png")
previewController.dataSource = self
self.present(previewController, animated: true, completion: nil)
}
#IBAction func displayFileFromUrl(_ sender: UIButton){
// Download file
self.downloadfile(completion: {(success, fileLocationURL) in
if success {
// Set the preview item to display======
self.previewItem = fileLocationURL! as NSURL
// Display file
DispatchQueue.main.async {
let previewController = QLPreviewController()
previewController.dataSource = self
self.present(previewController, animated: true, completion: nil)
}
}else{
debugPrint("File can't be downloaded")
}
})
}
func getPreviewItem(withName name: String) -> NSURL{
// Code to diplay file from the app bundle
let file = name.components(separatedBy: ".")
let path = Bundle.main.path(forResource: file.first!, ofType: file.last!)
let url = NSURL(fileURLWithPath: path!)
return url
}
func downloadfile(completion: #escaping (_ success: Bool,_ fileLocation: URL?) -> Void){
let itemUrl = URL(string: "https://developer.apple.com/wwdc20/images/hero/memoji/large/L7_2x.jpg")
// then lets create your document folder url
let documentsDirectoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
// lets create your destination file url
let destinationUrl = documentsDirectoryURL.appendingPathComponent("filename.jpg")
// to check if it exists before downloading it
if FileManager.default.fileExists(atPath: destinationUrl.path) {
debugPrint("The file already exists at path")
completion(true, destinationUrl)
// if the file doesn't exist
} else {
// you can use NSURLSession.sharedSession to download the data asynchronously
URLSession.shared.downloadTask(with: itemUrl!, completionHandler: { (location, response, error) -> Void in
guard let tempLocation = location, error == nil else { return }
do {
// after downloading your file you need to move it to your destination url
try FileManager.default.moveItem(at: tempLocation, to: destinationUrl)
print("File moved to documents folder")
completion(true, destinationUrl)
} catch let error as NSError {
print(error.localizedDescription)
completion(false, nil)
}
}).resume()
}
}
}
//MARK:- QLPreviewController Datasource
extension ViewController: QLPreviewControllerDataSource {
func numberOfPreviewItems(in controller: QLPreviewController) -> Int {
return 1
}
func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem {
return self.previewItem as QLPreviewItem
}
}
I just wanna make an iOS app with Instagram API then I can see the user profile.
I just wrote this Code on my Xcode project to make iOS app.
here is the code :--
#IBOutlet weak var webView: UIWebView!
override func viewDidLoad() {
super.viewDidLoad()
webView.delegate = self
signInRequest()
}
func signInRequest() {
let getURL = String(format: "%#?client_id=%#&redirect_uri=%#&response_type=token&scope=%#&DEBUG=True", arguments: [API.INSTAGRAM_AUTHURL,API.INSTAGRAM_CLIENT_ID,API.INSTAGRAM_REDIRECT_URI,API.INSTAGRAM_SCOPE])
let request = URLRequest.init(url: URL.init(string: getURL)!)
webView.loadRequest(request)
}
func checkRequestForCallbackURL(request: URLRequest) -> Bool {
let requestURLString = (request.url?.absoluteString)! as String
if requestURLString.hasPrefix(API.INSTAGRAM_REDIRECT_URI) {
let range: Range<String.Index> = requestURLString.range(of: "#access_token=")!
handleAuth(authToken: requestURLString.substring(from: range.upperBound))
return false
}
return true
}
func handleAuth(authToken: String) {
let url = String(format: "https://api.instagram.com/v1/users/self/?access_token=%#", authToken)
let request: NSMutableURLRequest = NSMutableURLRequest(url: URL(string: url)!)
request.httpMethod = "GET"
request.cachePolicy = NSURLRequest.CachePolicy.reloadIgnoringCacheData
let session = URLSession(configuration: .default)
session.dataTask(with: request as URLRequest) { (data, response, error) -> Void in
if let data = data {
let json = try? JSONSerialization.jsonObject(with: data, options: []) as? NSDictionary
let strFullName = (json?.value(forKey: "data") as AnyObject).value(forKey: "full_name") as! String
let secondVC: SecondViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "secondSeg") as! SecondViewController
secondVC.text = strFullName
self.present(secondVC
, animated: true, completion: nil)
}
}.resume()
}
func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebView.NavigationType) -> Bool {
return checkRequestForCallbackURL(request: request)
}
}
my question is when I run my app and want to see the instagram user username I can't see on my label.
I can't see the user (full_name, username, followers, etc...)
here is secondVC Code.
var text: String = ""
#IBOutlet weak var userNameLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
userNameLabel?.text = text
}
I believe your viewdidload function is being called before the update of your text variable
Try replacing:
var text: String = ""
With:
var text: String = "" {
didSet {
userNameLabel?.text = text
}
}
import UIKit
class MOViewController:UIViewController, UIDocumentInteractionControllerDelegate {
//my variable
var documentController: UIDocumentInteractionController = UIDocumentInteractionController()
override func viewDidLoad() {
super.viewDidLoad()
//my pdf file
downloadFileForfileObject(url: "https://d0.awsstatic.com/whitepapers/KMS-Cryptographic-Details.pdf")
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
}
//download file function
func downloadFileForfileObject(url: String) { //Download pdf File asynchronosly
let documentURL = NSURL(string: url)
let documentsURLPath = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first! as NSURL
let fileExtension = ((documentURL!.pathComponents)?.last)! as String
let request: URLRequest = URLRequest(url: documentURL! as URL, cachePolicy: NSURLRequest.CachePolicy.returnCacheDataElseLoad, timeoutInterval: 60)
let fileURLPath = documentsURLPath.appendingPathComponent("\(fileExtension)")
let sessionConfig = URLSessionConfiguration.default
let session = URLSession(configuration: sessionConfig, delegate: nil, delegateQueue: nil)
let task = session.dataTask(with: request) { (data, response, error) in
if (error == nil) {
// Success go to open url
self.openSelectedDocumentFromURL(documentURLString: fileURLPath!.path)
} else {
print(error?.localizedDescription)
}
}
task.resume()
}
func openSelectedDocumentFromURL(documentURLString: String) {
let documentURL: NSURL = NSURL(fileURLWithPath: documentURLString)
documentController = UIDocumentInteractionController(url: documentURL as URL)
documentController.delegate = self
documentController.presentPreview(animated: true)
}
// MARK: - UIDocumentInteractionViewController delegate methods
//documentInteraction method
func documentInteractionControllerViewControllerForPreview(_ controller: UIDocumentInteractionController) -> UIViewController {
return self
}
Hi all, above code does not work , the cache directory does not have my file that download.
I have an app which records sound from microphone and then sends it to my website through NSUrlRequest. To test it, I added that audio is played from website so I can hear if it worked.
When I test it on simulator, everything works fine: audio is recorded and uploaded and I can hear it, but when I install it on my iPhone, I cannot hear anything and at my website, there is a corrupted audio file.
My TestNahravani.swift Code:
import UIKit
import AVFoundation
class TestNahravani: UIViewController, AVAudioRecorderDelegate, AVAudioPlayerDelegate {
#IBOutlet weak var recordButton: UIButton!
#IBOutlet weak var playButton: UIButton!
var soundRecorder: AVAudioRecorder!
var soundPlayer:AVAudioPlayer?
let fileName = "demo.m4a"
override func viewDidLoad() {
super.viewDidLoad()
setupRecorder()
}
#IBAction func recordSound(sender: UIButton) {
if (sender.titleLabel?.text == "Record"){
soundRecorder.record()
sender.setTitle("Stop", for: .normal)
playButton.isEnabled = false
} else {
soundRecorder.stop()
sender.setTitle("Record", for: .normal)
}
}
#IBAction func playSound(sender: UIButton) {
if (sender.titleLabel?.text == "Play"){
recordButton.isEnabled = false
sender.setTitle("Stop", for: .normal)
preparePlayer()
} else {
soundPlayer?.stop()
sender.setTitle("Play", for: .normal)
}
}
// MARK:- AVRecorder Setup
func setupRecorder() {
//set the settings for recorder
let recordSettings = [AVSampleRateKey : NSNumber(value: Float(44100.0)),
AVNumberOfChannelsKey : NSNumber(value: 2),
AVEncoderAudioQualityKey : NSNumber(value: Int32(AVAudioQuality.max.rawValue)),
AVFormatIDKey : NSNumber(value: kAudioFormatMPEG4AAC)]
var error: NSError?
do {
soundRecorder = try AVAudioRecorder(url: getFileURL() as URL, settings: recordSettings)
} catch let error1 as NSError {
error = error1
soundRecorder = nil
}
if let err = error {
print("AVAudioRecorder error: \(err.localizedDescription)")
} else {
soundRecorder.delegate = self
soundRecorder.prepareToRecord()
}
}
// MARK:- Prepare AVPlayer
func preparePlayer() {
var errorX: NSError?
let dirPaths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let docsDir: AnyObject=dirPaths[0] as AnyObject
var recordedFilePath : String = docsDir.appendingPathComponent(fileName)
let recordedFileURL = getFileURL()
// "currentFilename", "recordedFilePath" and "recordedFileURL" are all global variables
// This recording stored at "recordedFileURL" can be played back fine.
let sendToPath = "http://www.kvetinac97.cz/jt.php"
let sendToURL = NSURL(string: sendToPath)
let recording: NSData! = NSData(contentsOf: recordedFileURL as URL)
if recording == nil {
recordedFilePath = "FailedUpload"
}
let boundary = "--------14737809831466499882746641449----"
let contentType = "multipart/form-data;boundary=\(boundary)"
let beginningBoundary = "--\(boundary)"
let endingBoundary = "--\(boundary)--"
let header = "Content-Disposition: form-data; name=\"\(fileName)\"; filename=\"\(recordedFilePath)\"\r\n"
let body = NSMutableData()
body.append(("\(beginningBoundary)\r\n" as NSString).data(using: String.Encoding.utf8.rawValue)!)
body.append((header as NSString).data(using: String.Encoding.utf8.rawValue)!)
body.append(("Content-Type: application/octet-stream\r\n\r\n" as NSString).data(using: String.Encoding.utf8.rawValue)!)
body.append(recording! as Data) // adding the recording here
body.append(("\r\n\(endingBoundary)\r\n" as NSString).data(using: String.Encoding.utf8.rawValue)!)
let request = NSMutableURLRequest()
request.url = sendToURL! as URL
request.httpMethod = "POST"
request.addValue(contentType, forHTTPHeaderField: "Content-Type")
request.addValue("multipart/form-data", forHTTPHeaderField: "Accept")
request.httpBody = body as Data
let session = URLSession.shared
let task = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
if let data = NSData(contentsOf: NSURL(string: "http://www.kvetinac97.cz/uploads/demo.m4a")! as URL) {
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
try AVAudioSession.sharedInstance().setActive(true)
self.soundPlayer = try AVAudioPlayer(data: data as Data, fileTypeHint: AVFileType.m4a.rawValue)
self.soundPlayer!.delegate = self
self.soundPlayer!.prepareToPlay()
self.soundPlayer!.volume = 1.0
self.soundPlayer!.play()
} catch let error1 as NSError {
errorX = error1
self.soundPlayer = nil
print ("Chyba nejaka \(error1)")
}
}
else {
print ("Smulicka")
}
})
task.resume()
}
func generateBoundaryString() -> String {
return "Boundary-\(NSUUID().uuidString)"
}
// MARK:- File URL
func getCacheDirectory() -> String {
let paths = NSSearchPathForDirectoriesInDomains(.cachesDirectory,.userDomainMask, true)
return paths[0]
}
func getFileURL() -> NSURL {
let path = getCacheDirectory().appending(fileName)
let filePath = NSURL(fileURLWithPath: path)
return filePath
}
// MARK:- AVAudioPlayer delegate methods
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
recordButton.isEnabled = true
playButton.setTitle("Play", for: .normal)
}
// MARK:- AVAudioRecorder delegate methods
func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) {
playButton.isEnabled = true
recordButton.setTitle("Record", for: .normal)
}
// MARK:- didReceiveMemoryWarning
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
I figured out where my problem was
As it appears, iPhone simulator does not require AVAudioSession to be activated whilst real iPhone does.
So it can be fixed easily with adding
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryRecord)
try AVAudioSession.sharedInstance().setActive(true)
before audioRecorder initialization.
I am trying to save a audio file from a server to the users phone so they dont have to download it again its always there. I have almost everything but i am trying to test and see if the audio file actually plays after it is saved. How do i do this?
Code i have:
var urlWebView = NSURL(string: "http://domain.com//////audios////Nightmares.wav")
var requestWebView = NSURLRequest(URL: urlWebView)
NSURLConnection.sendAsynchronousRequest(requestWebView, queue: NSOperationQueue.mainQueue(), completionHandler: {
response, data, error in
if error != nil {
println("There was an error")
} else {
let musicFile = (data: data)
var documentsDirectory:String?
var paths:[AnyObject] = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)
if paths.count > 0 {
documentsDirectory = paths[0] as? String
var savePath = documentsDirectory! + "/audio.wav"
NSFileManager.defaultManager().createFileAtPath(savePath, contents: data, attributes: nil)
self.audioPlayer = AVAudioPlayer(contentsOfURL: savePath, error: nil)
//tried to play it here but i cant since savePath is a string and not actually audio file
}
}
})
import UIKit
import Foundation
import AVFoundation
class ViewController: UIViewController {
#IBOutlet weak var strFiles: UITextView!
var myPlayer = AVAudioPlayer()
var yourSound:NSURL?
func prepareYourSound(myData:NSData) {
myPlayer = AVAudioPlayer(data: myData, error: nil)
myPlayer.prepareToPlay()
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
var urlWebView = NSURL(string: "http://freewavesamples.com/files/Korg-DS-8-Rotary-Organ-C6.wav")!
var requestWebView = NSURLRequest(URL: urlWebView)
NSURLConnection.sendAsynchronousRequest(requestWebView, queue: NSOperationQueue.mainQueue(), completionHandler: {
response, data, error in
if error != nil {
println("There was an error")
} else {
let musicFile = (data: data)
var documentsDirectory:String?
var paths:[AnyObject] = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)
if paths.count > 0 {
documentsDirectory = paths[0] as? String
var savePath = documentsDirectory! + "/audio.wav"
NSFileManager.defaultManager().createFileAtPath(savePath, contents: data, attributes: nil)
self.prepareYourSound(musicFile)
self.myPlayer.play()
//tried to play it here but i cant since savePath is a string and not actually audio file
// list your files from disk (documents)
let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
let files = NSFileManager().enumeratorAtPath(documentsPath)
var myFiles:[String] = []
while let file: AnyObject = files?.nextObject() {
myFiles.append(file as String)
self.strFiles.text = "\(self.strFiles.text)\n\(file as String)"
}
}
}
})
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}