I have a problem in modifying the video format after downloading from videoplayback to mp4 and save to camera.
This is my download code, but I downloaded some video with a different format example : "videoplayback". I can't save to camera because I want to change format video to mp4.
func SessionDownload(URLSession : String) {
MBProgressHUD.hideAllHUDs(for: view, animated: true)
let hud = MBProgressHUD.showAdded(to: self.view, animated: true)
// Set the bar determinate mode to show task progress.
progress = 0.0
hud?.mode = MBProgressHUDMode.determinateHorizontalBar
hud?.isUserInteractionEnabled = true;
hud?.labelText = NSLocalizedString("Downloading...", comment: "HUD loading title")
DispatchQueue.global(qos: .default).async(execute: {() -> Void in
// Do something useful in the background and update the HUD periodically.
self.doSomeWorkWithProgress()
DispatchQueue.main.async(execute: {() -> Void in
//hud?.hide(true)
hud?.labelText = NSLocalizedString("Just Wait...", comment: "HUD loading title")
})
})
let videoPath = URLSession
print(videoPath)
let s = videoPath
let url = NSURL(string:s)!
let req = NSMutableURLRequest(url:url as URL)
let config = URLSessionConfiguration.default
let task = self.session.downloadTask(with: req as URLRequest)
self.task = task
task.resume()
}
//MARK:- share video
func doSomeWorkWithProgress() {
// This just increases the progress indicator in a loop.
while progress < 1.0 {
DispatchQueue.main.async(execute: {() -> Void in
print(self.progress)
MBProgressHUD(for: self.view).progress = self.progress
})
usleep(50000)
}
}
//MARK:- URL Session delegat
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
print("downloaded \(100*totalBytesWritten/totalBytesExpectedToWrite)")
taskTotalBytesWritten = Int(totalBytesWritten)
taskTotalBytesExpectedToWrite = Int(totalBytesExpectedToWrite)
percentageWritten = Float(taskTotalBytesWritten) / Float(taskTotalBytesExpectedToWrite)
print(percentageWritten)
let x = String(format:"%.2f", percentageWritten)
print(x)
self.progress = Float(x)!
print(progress)
}
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didResumeAtOffset fileOffset: Int64, expectedTotalBytes: Int64) {
// unused in this example
}
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
print("completed: error: \(error)")
}
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
print("Finished downloading!")
let fileManager = FileManager()
// this can be a class variable
let directoryURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]
print(directoryURL)
let docDirectoryURL = NSURL(fileURLWithPath: "\(directoryURL)")
print(docDirectoryURL)
//Save To Photos
PHPhotoLibrary.shared().performChanges({
PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL:directoryURL)
}) { saved, error in
if saved {
let alertController = UIAlertController(title: "Your video was successfully saved", message: nil, preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .default, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
}
}
let destinationFilename = downloadTask.originalRequest?.url?.lastPathComponent
print(destinationFilename!)
// append that to your base directory
let destinationURL = docDirectoryURL.appendingPathComponent("\(destinationFilename!)")
print(destinationURL!)
/* check if the file exists, if so remove it. */
if let path = destinationURL?.path {
if fileManager.fileExists(atPath: path) {
do {
try fileManager.removeItem(at: destinationURL!)
} catch let error as NSError {
print(error.debugDescription)
}
}
}
do
{
try fileManager.copyItem(at: location, to: destinationURL!)
}
catch {
print("Error while copy file")
}
DispatchQueue.main.async(execute: {() -> Void in
MBProgressHUD.hide(for: self.view, animated: true)
})
// let videoLink = NSURL(fileURLWithPath: filePath)
let objectsToShare = [destinationURL!] //comment!, imageData!, myWebsite!]
let activityVC = UIActivityViewController(activityItems: objectsToShare , applicationActivities: nil)
activityVC.setValue("Video", forKey: "subject")
//New Excluded Activities Code
if #available(iOS 9.0, *) {
activityVC.excludedActivityTypes = [UIActivity.ActivityType.airDrop, UIActivity.ActivityType.addToReadingList, UIActivity.ActivityType.assignToContact, UIActivity.ActivityType.copyToPasteboard, UIActivity.ActivityType.mail, UIActivity.ActivityType.message, UIActivity.ActivityType.openInIBooks, UIActivity.ActivityType.postToTencentWeibo, UIActivity.ActivityType.postToVimeo, UIActivity.ActivityType.postToWeibo, UIActivity.ActivityType.print]
} else {
// Fallback on earlier versions
activityVC.excludedActivityTypes = [UIActivity.ActivityType.airDrop, UIActivity.ActivityType.addToReadingList, UIActivity.ActivityType.assignToContact, UIActivity.ActivityType.copyToPasteboard, UIActivity.ActivityType.mail, UIActivity.ActivityType.message, UIActivity.ActivityType.postToTencentWeibo, UIActivity.ActivityType.postToVimeo, UIActivity.ActivityType.postToWeibo, UIActivity.ActivityType.print ]
}
if let popoverController = activityVC.popoverPresentationController {
popoverController.sourceView = self.BtnDownloadVideo
popoverController.sourceRect = self.BtnDownloadVideo.bounds
}
self.present(activityVC, animated: true, completion: nil)
}
I'm assuming when you download a file from the internet, you are sure you are downloading a video in this circumstance? And what you are really wanting is just to change the format, i.e. PathExtension such as .mp4, .png, jpeg, etc.
Iff (if and only if) this is the case, then you can add a file extension on to the path component.
let destinationURL = docDirectoryURL.appendingPathComponent("\(destinationFilename!)").appendingPathExtension("mp4")
Now, when you check your saved files, it will include the ".mp4"
Again, I'm assuming you are 110% confident you are downloading a ".mp4" from the interwebs.
Related
I am making app with swift and getting data from my Wordpress Website and using Rest Api to display data in CollectionView, all works fine but the problem is when i add new posts in website it doesn’t automatically shows in app , and when i refresh data then also can’t see the newest post . this is my code on refresh
#objc
private func didPullToRefresh(_ sender: Any) {
sortBy = "&orderby=date"
page = 1
self.fetchPostData { (posts) in
self.newsData = posts }
SVProgressHUD.show()
self.collectionView.setContentOffset(CGPoint(x:0,y:0), animated: true)
refreshControl.endRefreshing()
}
and this is the code to fetch data
func fetchPostData(completionHandler: #escaping ([Post]) -> Void ) {
DispatchQueue.main.asyncAfter(deadline: .now()) {
SVProgressHUD.show()
}
let url = URL(string: "https://www.pbkalam.com/wp-json/wp/v2/posts/?page=\(page)\(sortBy)" )!
print(url)
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
guard let data = data else {return}
do {
let postsData = try JSONDecoder().decode([Post].self, from: data)
completionHandler(postsData)
DispatchQueue.main.async {
self.collectionView.isUserInteractionEnabled = true
self.collectionView.reloadData()
SVProgressHUD.dismiss()
}
}
catch {
let error = error
print(String(describing: error))
SVProgressHUD.dismiss()
}
}
task.resume()
}
Here is my cell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "postcell", for: indexPath) as! ViewCell
cell.setup(with: newsData[indexPath.row-(indexPath.row/4)])
when i use
sortBy = "&orderby=rand"
then it loads the random posts but not the newest.. please help
i have tried this code
#objc
private func didPullToRefresh(_ sender: Any) {
sortBy = "&orderby=date&order=desc"
page = 1
self.fetchPostData { (posts) in
self.newsData = posts }
self.collectionView.reloadData()
SVProgressHUD.show()
self.collectionView.setContentOffset(CGPoint(x:0,y:0), animated: true)
refreshControl.endRefreshing()
}
So I am trying to create a temp JSON depending on whether a listener is tuned into a podcast or a radio station.
Because we already have all the podcast info we don't need to ask a remote JSON for it. But we still need to have the ability that when the MusicPlayer is playing that in the View it shows the cover, artist and title.
So my thinking was create a simple JSON Struct inside the MusicPlayer class and when the media player sends the data to the following
func getArtBoard(artist: String, song: String, cover: String) {
guard let url = URL(string: cover) else { return }
getData(from: url) { [weak self] image in
guard let self = self,
let downloadedImage = image else {
return
}
let artwork = MPMediaItemArtwork.init(boundsSize: downloadedImage.size, requestHandler: { _ -> UIImage in
return downloadedImage
})
self.nowplaying(with: artwork, artist: artist, song: song)
}
}
It would also save it temp to - which is inside the
class MusicPlayer {
struct NowPlaying: Codable, Identifiable {
var id: ObjectIdentifier
var artist : String
var song : String
var cover : String
}
//more code here
}
However I am getting two errors
Type 'MusicPlayer.NowPlaying' does not conform to protocol 'Decodable'
Type 'MusicPlayer.NowPlaying' does not conform to protocol 'Encodable'
Questions:
How do I make it to conform. - But we able to call it via Music.NowPlaying.
Is this the best way to do it, or can I access the MPMediaItemPropertyTitle in View?
The complete code.
import Foundation
import AVFoundation
import MediaPlayer
import AVKit
class MusicPlayer {
static let shared = MusicPlayer()
static var mediatype = ""
struct NowPlaying: Codable, Identifiable {
var id: ObjectIdentifier
var artist : String
var song : String
var cover : String
}
var player: AVPlayer?
let playerViewController = AVPlayerViewController()
func gettype(completion: #escaping (String) -> Void){
completion(MusicPlayer.mediatype)
}
func getNowPlayingView(completion: #escaping (String) -> Void){
completion(MusicPlayer.mediatype)
}
func startBackgroundMusic(url: String, type:String) {
MusicPlayer.mediatype = String(type)
//let urlString = "http://stream.radiomedia.com.au:8003/stream"
let urlString = url
guard let url = URL.init(string: urlString) else { return }
let playerItem = AVPlayerItem.init(url: url)
player = AVPlayer.init(playerItem: playerItem)
do {
try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default, options: [.duckOthers, .defaultToSpeaker, .mixWithOthers, .allowAirPlay])
print("Playback OK")
// let defaults = UserDefaults.standard
// defaults.set("1", forKey: defaultsKeys.musicplayer_connected)
try AVAudioSession.sharedInstance().setActive(true)
print("Session is Active")
} catch {
// let defaults = UserDefaults.standard
// defaults.set("0", forKey: defaultsKeys.musicplayer_connected)
print(error)
}
#if targetEnvironment(simulator)
self.playerViewController.player = player
self.playerViewController.player?.play()
print("SIMULATOR")
#else
self.setupRemoteTransportControls()
player?.play()
#endif
}
func startBackgroundMusicTwo() {
let urlString = "http://stream.radiomedia.com.au:8003/stream"
//let urlString = url
guard let url = URL.init(string: urlString) else { return }
let playerItem = AVPlayerItem.init(url: url)
player = AVPlayer.init(playerItem: playerItem)
do {
try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default, options: [.duckOthers, .defaultToSpeaker, .mixWithOthers, .allowAirPlay])
print("Playback OK")
// let defaults = UserDefaults.standard
// defaults.set("1", forKey: defaultsKeys.musicplayer_connected)
try AVAudioSession.sharedInstance().setActive(true)
print("Session is Active")
} catch {
// let defaults = UserDefaults.standard
// defaults.set("0", forKey: defaultsKeys.musicplayer_connected)
print(error)
}
#if targetEnvironment(simulator)
self.playerViewController.player = player
self.playerViewController.player?.play()
print("SIMULATOR")
#else
self.setupRemoteTransportControls()
player?.play()
#endif
}
func setupRemoteTransportControls() {
// Get the shared MPRemoteCommandCenter
let commandCenter = MPRemoteCommandCenter.shared()
// Add handler for Play Command
commandCenter.playCommand.addTarget { [unowned self] event in
if self.player?.rate == 0.0 {
self.player?.play()
return .success
}
return .commandFailed
}
// Add handler for Pause Command
commandCenter.pauseCommand.addTarget { [unowned self] event in
if self.player?.rate == 1.0 {
self.player?.pause()
return .success
}
return .commandFailed
}
// self.nowplaying(artist: "Anna", song: "test")
}
func nowplaying(with artwork: MPMediaItemArtwork, artist: String, song: String){
MPNowPlayingInfoCenter.default().nowPlayingInfo = [
MPMediaItemPropertyTitle:song,
MPMediaItemPropertyArtist:artist,
MPMediaItemPropertyArtwork: artwork,
MPNowPlayingInfoPropertyIsLiveStream: true
]
// self.getArtBoard();
}
func setupNowPlayingInfo(with artwork: MPMediaItemArtwork) {
MPNowPlayingInfoCenter.default().nowPlayingInfo = [
// MPMediaItemPropertyTitle: "Some name",
// MPMediaItemPropertyArtist: "Some name",
MPMediaItemPropertyArtwork: artwork,
//MPMediaItemPropertyPlaybackDuration: CMTimeGetSeconds(currentItem.duration),
//MPNowPlayingInfoPropertyPlaybackRate: 1,
//MPNowPlayingInfoPropertyElapsedPlaybackTime: CMTimeGetSeconds(currentItem.currentTime())
]
}
func getData(from url: URL, completion: #escaping (UIImage?) -> Void) {
URLSession.shared.dataTask(with: url, completionHandler: {(data, response, error) in
if let data = data {
completion(UIImage(data:data))
}
})
.resume()
}
func getArtBoard(artist: String, song: String, cover: String) {
guard let url = URL(string: cover) else { return }
getData(from: url) { [weak self] image in
guard let self = self,
let downloadedImage = image else {
return
}
let artwork = MPMediaItemArtwork.init(boundsSize: downloadedImage.size, requestHandler: { _ -> UIImage in
return downloadedImage
})
self.nowplaying(with: artwork, artist: artist, song: song)
}
}
func stopBackgroundMusic() {
guard let player = player else { return }
player.pause()
}
}
UPDATE
Got the above error solved thanks to the comment below.
However am having issues fetching the data.
Type 'MusicPlayer.NowPlayingData.Type' cannot conform to 'Encodable'; only struct/enum/class types can conform to protocols
The code I used. - https://developer.apple.com/documentation/foundation/jsonencoder
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
let data = try encoder.encode(NowPlayingData)
print(String(data: data, encoding: .utf8)!)
To write it I placed
func getArtBoard(artist: String, song: String, cover: String) {
MusicPlayer.NowPlayingData(artist: artist, song: song, cover: cover)
}
DATA trying to encode
func getArtBoard(artist: String, song: String, cover: String) {
//MusicPlayer.NowPlayingData(artist: artist, song: song, cover: cover)
let pear = "{'artist':\(artist), 'song': \(song), 'cover':\(cover)}"
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
MusicPlayer.JN = try encoder.encode(pear)
I have loaded iframe form into wkwebview and its working fine. When the tap scanner button inside an iframe and it opens the camera to scan the document, after document uploaded to the server it will return to wkweb view but here wkweb view is not refreshed and showing a blank white screen.
Here is my code for wkweb view:
private func loadWebView(){
webView.uiDelegate = self
webView.allowsBackForwardNavigationGestures = true
do {
guard let filePath = Bundle.main.path(forResource: "index", ofType: "html")
else {
// File Error
print ("File reading error")
return
}
let contents = try String(contentsOfFile: filePath, encoding: .utf8)
let baseUrl = URL(fileURLWithPath: "https://url")
DispatchQueue.main.async {
self.webView.loadHTMLString(contents as String, baseURL: baseUrl)
}
}
catch {
print ("File HTML error")
}
webView.configuration.preferences.javaScriptEnabled = true
webView.configuration.userContentController.add(self, name: "jsHandler")
webView.configuration.userContentController.add(self, name: "saveHandler")
webView.configuration.userContentController.add(self, name: "openCamera")
}
func makeSaveForm(ProcessInstanceId: String, FullFormKey: String, TaskIdValue: String, FormValues: String) -> saveFormModel {
let newForm = saveFormModel()
newForm.ProcessInstanceId = ProcessInstanceId
newForm.FullFormKey = FullFormKey
newForm.TaskIdValue = TaskIdValue
newForm.FormValues = FormValues
return newForm
}
func ProcessInstanceIDApiCall(ProcessInstId: String){
let authToken = UserDefaults.standard.string(forKey: "authToken")
print("id for process instance", ProcessInstId)
let bearerToken: String = "Bearer " + (authToken ?? "")
print("baearer token::\(bearerToken)")
let headers:HTTPHeaders = ["Content-Type":"Application/json",
"Authorization": "Bearer " + (authToken ?? ""),
"Accept":"application/json"]
AF.request("https://api url/process-instance/\(ProcessInstId)/variables", method: .get, parameters: nil, encoding: URLEncoding.default, headers: headers).responseJSON { (response:AFDataResponse<Any>) in
print("process instance id api",response.result)
switch response.result {
case .success:
print("instance response", response.value )
guard let data = response.value else {
// print("request failed \(error)")
return
}
self.anyValueJson = response.value
self.jsonStringProcessInstanceID = self.JSONStringify(value: data as AnyObject)
print("raw response: \(String(describing: self.jsonStringProcessInstanceID))")
case .failure(let error):
print("Error:", error)
}
}
}//api call end
public func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
if message.name == "jsHandler" {
// print(message.body)
} else if message.name == "saveHandler" {
let values = message.body
print(values)
let jsonString = JSONStringify(value: values as AnyObject)
print(jsonString)
formValues = jsonString
let newSaveForm = self.makeSaveForm(ProcessInstanceId: self.processInstanceId ?? "", FullFormKey: self.fullFormKey ?? "", TaskIdValue: self.taskIdValue ?? "", FormValues: jsonString )
//realm create/update saveform based task id
let realm = try! Realm()
if realm.object(ofType: saveFormModel.self, forPrimaryKey: newSaveForm.TaskIdValue) != nil {
try! realm.write {
print("already exist")
//.all is equivalent to true and .error is equivalent to false
realm.add(newSaveForm, update: .all)
}
} else {
try! realm.write {
print("new document written")
realm.add(newSaveForm) //RLMException occurs here
}
}
} else if message.name == "openCamera" {
print("open camera",message.body)
let base64Encoded = message.body
let jsonString = JSONStringify(value: base64Encoded as AnyObject)
do{
if let json = jsonString.data(using: String.Encoding.utf8){
if let jsonData = try JSONSerialization.jsonObject(with: json, options: .allowFragments) as? [String:AnyObject]{
let id = jsonData["scannerData"] as! String
print("scanner data ::", id)
let vc1 = ScannerViewController()
let v = vc1.scanParameters(scannerDataBase64: id)
print("v", v)
let newVC = A8Scan(self)
newVC.showScanner()
}
}
}catch {
print(error.localizedDescription)
}
func loadFormView(){
let setPath = "https://api url/\(formKey ?? "")/index.html";
let js = "setFrame('" + setPath + "')";
print("js::\(js)")
webView.evaluateJavaScript(js) { (r, error) in
if error == nil {
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0){
print(r ?? "empty")
let realm = try! Realm()
let object = realm.object(ofType: saveFormModel.self, forPrimaryKey: self.taskIdValue)
print("object", object ?? "")
print("json api string", self.jsonStringProcessInstanceID ?? "")
let authValue = "Bearer \(self.authTokenValue ?? "")"
if object?.FullFormKey != nil {
if let jsonStr = self.jsonStringProcessInstanceID {
let l = "loadform('\(object?.FullFormKey ?? "")', '\(authValue)', '\(object?.ProcessInstanceId ?? "")', \(object?.FormValues ?? ""), \(jsonStr))"
self.webView.evaluateJavaScript(l, completionHandler: nil)
}
} else {
if let jsonStr = self.jsonStringProcessInstanceID {
print("json str::::", jsonStr)
let l = "loadform('\(self.fullFormKey ?? "")', '\( authValue)', '\(self.processInstanceId ?? "")', \(jsonStr))"
self.webView.evaluateJavaScript(l, completionHandler: nil)
}
}
self.tapCallback = {
print("tap called save")
// let s = "submitEvent('\(self.saveArg)')"
let save = "submitEvent('save');"
self.webView.evaluateJavaScript(save, completionHandler: nil)
}
}
} else {
print("web view didfinish loading error",error)
}
}
}
public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
print("Web View didFinish Loading");
loadFormView()
}
My issue when I'm returning to wkweb view after from scanner SDK it shows a blank white screen. How to refresh the screen when I return to the web view each time scanner SDK close?
Any help much appreciated, please...
The problem is being caused by AVG AntiVirus's webshield. For some reason AVG webshield treats all network communication from the simulator as fraudulent.
The following screenshot shows the safari app running on simulator. It says that www.apple.com is not safe or any other website.
The following screenshot is from system.log showing errors with webkit.
You can replicate this problem by installing AVG antivirus and turning on the webshield. WKWebview in your App(On the simulator) wouldn't load anything.
taken from here
I have an application where I need to validate some information(zip code) from a database before I allow my iOS application to proceed to the next view. I used the zip code project to import a DB Table will all valid US Zip codes, and I want to have the zip code the inputed by the user validated before I allow them to proceed. If the zip code isn't valid, I hold them up at the current view and display an alert. I have a class to validate the zip code, but the zip code isn't being validated until after the next view is loaded. I've been leaning towards using a completion handler, but I'm not exactly sure if that's my best/only option. Thanks in advance.
EDIT:
The following is the whole class for retrieve the data
protocol ZipCodeLocationProtocol: class {
func zipCodeLocationDownloaded(zipLocation: Location)
}
class RetrieveZipCodeLocation: NSObject, NSURLSessionDataDelegate {
// MARK: Properties
weak var delegate: ZipCodeLocationProtocol!
var data: NSMutableData = NSMutableData()
let urlPath: String = "xxxx"
func downloadZipCodeLocation(zipcode: Int) {
let path = self.urlPath + "?zipcode=\(zipcode)"
let url: NSURL = NSURL(string: path)!
var session: NSURLSession!
let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
session = NSURLSession(configuration: configuration, delegate: self, delegateQueue: nil)
let task = session.dataTaskWithURL(url)
task.resume()
}
func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData) {
self.data.appendData(data)
}
func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {
if error != nil {
print("Failed to download data")
}else {
print("Data downloaded")
self.parseJSON()
}
}
func parseJSON() {
var jsonResult: NSMutableArray = NSMutableArray()
var location = Location(title: "TITLE", coordinate: CLLocationCoordinate2D(latitude: 0, longitude: 0))
do {
jsonResult = try NSJSONSerialization.JSONObjectWithData(self.data, options:[]) as! NSMutableArray
} catch let error as NSError {
print(error)
}
var jsonElement: NSDictionary = NSDictionary()
for(var i = 0; i < jsonResult.count; i++) {
jsonElement = jsonResult[i] as! NSDictionary
let point = CLLocationCoordinate2D(latitude: (jsonElement["LATITUDE"] as! NSString).doubleValue, longitude: (jsonElement["LONGITUDE"] as! NSString).doubleValue)
// Get Information
location = Location(title: "TITLE", coordinate: point)
self.delegate.zipCodeLocationDownloaded(location)
}
}
I'm going to assume that a button triggers the segue to the next view. I'm also going to assume that the button is hooked up to a function for target-action. I'm also going to assume that you have the code to get the zip codes, otherwise you'll have to ask a separate question for that.
Assumptions aside, you need to present a UIAlertController instead of going to the next view controller when tapping the button. In order to do that:
func buttonAction() {
if verifyZipCode() {
let alert = UIAlertController(title: "Hold Up", message: "That zip code is invalid.", preferredStyle: .Alert)
let fixIt = UIAlertAction(title: "Fix It!", style: .Default, handler: nil) // handler could also contain code to make text field red or something interesting
alert.addAction(fixIt)
presentViewController(alert, animated: true, completion: nil)
} else {
// existing segue code
}
}
func verifyZipCode() -> Bool {
// Take text field text and verify zip code
}
I've been learning swift rather quickly, and I'm trying to develop an OS X application that downloads images.
I've been able to parse the JSON I'm looking for into an array of URLs as follows:
func didReceiveAPIResults(results: NSArray) {
println(results)
for link in results {
let stringLink = link as String
//Check to make sure that the string is actually pointing to a file
if stringLink.lowercaseString.rangeOfString(".jpg") != nil {2
//Convert string to url
var imgURL: NSURL = NSURL(string: stringLink)!
//Download an NSData representation of the image from URL
var request: NSURLRequest = NSURLRequest(URL: imgURL)
var urlConnection: NSURLConnection = NSURLConnection(request: request, delegate: self)!
//Make request to download URL
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue(), completionHandler: { (response: NSURLResponse!, data: NSData!, error: NSError!) -> Void in
if !(error? != nil) {
//set image to requested resource
var image = NSImage(data: data)
} else {
//If request fails...
println("error: \(error.localizedDescription)")
}
})
}
}
}
So at this point I have my images defined as "image", but what I'm failing to grasp here is how to save these files to my local directory.
Any help on this matter would be greatly appreciated!
Thanks,
tvick47
In Swift 3:
Write
do {
let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let fileURL = documentsURL.appendingPathComponent("\(fileName).png")
if let pngImageData = UIImagePNGRepresentation(image) {
try pngImageData.write(to: fileURL, options: .atomic)
}
} catch { }
Read
let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let filePath = documentsURL.appendingPathComponent("\(fileName).png").path
if FileManager.default.fileExists(atPath: filePath) {
return UIImage(contentsOfFile: filePath)
}
The following code would write a UIImage in the Application Documents directory under the filename 'filename.jpg'
var image = .... // However you create/get a UIImage
let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
let destinationPath = documentsPath.stringByAppendingPathComponent("filename.jpg")
UIImageJPEGRepresentation(image,1.0).writeToFile(destinationPath, atomically: true)
In swift 2.0, stringByAppendingPathComponent is unavailable, so the answer changes a bit. Here is what I've done to write a UIImage out to disk.
documentsURL = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first!
if let image = UIImage(data: someNSDataRepresentingAnImage) {
let fileURL = documentsURL.URLByAppendingPathComponent(fileName+".png")
if let pngImageData = UIImagePNGRepresentation(image) {
pngImageData.writeToURL(fileURL, atomically: false)
}
}
UIImagePNGRepresentaton() function had been deprecated. try image.pngData()
#IBAction func savePhoto(_ sender: Any) {
let imageData = UIImagePNGRepresentation(myImg.image!)
let compresedImage = UIImage(data: imageData!)
UIImageWriteToSavedPhotosAlbum(compresedImage!, nil, nil, nil)
let alert = UIAlertController(title: "Saved", message: "Your image has been saved", preferredStyle: .alert)
let okAction = UIAlertAction(title: "Ok", style: .default)
alert.addAction(okAction)
self.present(alert, animated: true)
}
}
Update for swift 5
just change filename.png to something else
func writeImageToDocs(image:UIImage){
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
let destinationPath = URL(fileURLWithPath: documentsPath).appendingPathComponent("filename.png")
debugPrint("destination path is",destinationPath)
do {
try image.pngData()?.write(to: destinationPath)
} catch {
debugPrint("writing file error", error)
}
}
func readImageFromDocs()->UIImage?{
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
let filePath = URL(fileURLWithPath: documentsPath).appendingPathComponent("filename.png").path
if FileManager.default.fileExists(atPath: filePath) {
return UIImage(contentsOfFile: filePath)
} else {
return nil
}
}