Save and Load PDF in my App - swift

I am downloading a .PDF file from a URL into a webview. It works fine , but because the pdf get updated mid month. I would like to download that file on the first of every month into my app, then the rest of the month load that saved file from the app rather than the web. Thank you for any help. I am using Swift.
following is my code so far :
import UIKit
import Social
// var justOnceThree:Bool = true
class KeyPagesViewController: UIViewController {
#IBOutlet weak var photoButton: UIButton!
#IBOutlet weak var baseKeypagesLabel: UILabel!
#IBOutlet weak var titleLabel: UILabel!
#IBOutlet weak var keyPages: UIWebView!
var urlFra = "http://someURL.pdf"
var urlLhr = "http://someURL.pdf"
let requestURL = NSURL()
override func viewDidAppear(animated: Bool) {
PhotoButton()
}
override func viewDidLoad() {
super.viewDidLoad()
animationtitle()
let sharedDefaults = NSUserDefaults(suiteName: "group.birkyboy.TodayExtensionSharingDefaults")
var based = sharedDefaults!.objectForKey("base") as? String
if based == "HNL" {
let requestURL = NSURL(string:self.urlHnl)
let request = NSURLRequest(URL: requestURL!)
UIApplication.sharedApplication().networkActivityIndicatorVisible = true
self.keyPages.hidden = false
self.keyPages.loadRequest(request)
self.baseKeypagesLabel.text = "HONOLULU"
}
if based == "IAH" {
let requestURL = NSURL(string:self.urlIah)
let request = NSURLRequest(URL: requestURL!)
UIApplication.sharedApplication().networkActivityIndicatorVisible = true
self.keyPages.hidden = false
self.keyPages.loadRequest(request)
self.baseKeypagesLabel.text = "HOUSTON"
}
}

You can save the PDF in the users Documents folder. See "iOS Standard Directories: Where Files Reside" in the Apple documentation. There are various ways to get the PDF from a URL. See NSInputStream for one way to do it. Once you have it (as an NSData object, for example), you can save it as a file.

Related

Update NSTextField based on selection in NSPopupButton

I've only been coding for a few weeks so forgive my no-doubt clumsy code.
I have a NSTextField that needs to update based upon a selection from an NSPopupButton
These are my outlets:
#IBOutlet weak var inputText: NSTextField!
#IBOutlet weak var outputText: NSTextField!
#IBOutlet weak var inputBrowseButton: NSButton!
#IBOutlet weak var outputBrowseButton: NSButton!
#IBOutlet weak var codecSelector: NSPopUpButton!
These are my variables:
// derive default path and filename from #IBAction of inputBrowseButton
var defaultUrl: URL!
// derived from default of inputBrowse unless outputBrowse is used
var outputUrl: URL!
// change output path from #IBAction of outputBrowseButton
var outputDirectory: URL!
// change path extension from #IBAction of codecSelector NSPopupButton
var codecChosen: String = ""
// dictionary of arguments to form script for ffmpeg
var ffmpegCodecArg: String = ""
And here is my method to pull all that together:
// construct output path for use in ffmpegArguments dictionary and display in outputText NSTextField
func updateOutputText(defaultUrl: URL?, outputDirectory: URL?) -> String {
if defaultUrl != nil && outputDirectory != nil {
let outputFile = defaultUrl!.deletingPathExtension()
let outputFilename = outputFile.lastPathComponent
outputUrl = outputDirectory!.appendingPathComponent(outputFilename)
outputText.stringValue = outputUrl.path + "\(codecChosen)"
} else if defaultUrl == nil && outputDirectory != nil {
outputText.stringValue = outputDirectory!.path
} else {
outputUrl = defaultUrl!.deletingPathExtension()
outputText.stringValue = outputUrl.path + "\(codecChosen)"
}
return outputText.stringValue
}
Now at the present this function isn't working because I haven't figured out how to call it yet. But that's an issue for another time, not what I'm asking about here.
Previously I was running
outputUrl = defaultUrl!.deletingPathExtension()
outputText.stringValue = outputUrl.path + "\(codecChosen)"
as part of my inputBrowseButton #IBAction method, and I was running
let outputFile = defaultUrl!.deletingPathExtension()
let outputFilename = outputFile.lastPathComponent
outputUrl = outputDirectory!.appendingPathComponent(outputFilename)
outputText.stringValue = outputUrl.path + "\(codecChosen)"
as part of my outputBrowseButton #IBAction method.
Which worked fine, EXCEPT when it came to updating outputText.stringValue when the codecChosen variable was assigned a new value in my #IBAction for the codecSelector NSPopupButton method.
I suspect the problem is that I don't have my outputText NSTextField set up to update when the codecSelector NSPopupButton changes. What do I need to do to make that happen?
How do you set the text in an NSTextField?
Which worked fine, EXCEPT when it came to updating outputText.stringValue when the codecChosen variable was assigned a new value in my #IBAction for the codecSelector NSPopupButton method.
Try using a separate method to change the text.
func changeText(inputString: String, inputField: NSTextField) {
inputField.stringValue = inputString
}
Separating your code more might make it easier for you to keep track of while you are starting out. I am not entirely familiar with macOS, so that method may not work, but try working with the principle of it and see if you can progress.

How do I store a calculated result in UserDefaults to display in a "results" View controller [duplicate]

This question already has answers here:
How can I use UserDefaults in Swift?
(14 answers)
Closed 4 years ago.
First time poster so sorry for the incorrect format/length of the question.
I am building an app in Xcode that allows users to input various inputs among numerous view controllers and then have output in a single view controller with results displayed through labels.
The raw inputted textfield data is stored into UserDefaults and can display them later in the resulting VC with no problem. Im having trouble with calculated outputs (in this example "papiresult") however.
Can anyone provide guidance how to print out the calculated result several view controllers later using UserDefaults?
This is the rough layout
Here is the code I have in the first ViewController:
import UIKit
let userDefaults = UserDefaults()
var papiresult = Double()
class ViewController1: UIViewController, UITextFieldDelegate {
#IBOutlet weak var textField1: UITextField!
#IBOutlet weak var textField2: UITextField!
#IBOutlet weak var textField3: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
textField1.delegate = self
textField2.delegate = self
textField3.delegate = self
}
//Declaring data input into UserDefaults//
#IBAction func sendDataToVC2(_ sender: Any) {
let systPA = Double(textField1.text!)
let diastPA = Double(textField2.text!)
let cvPressure = Double(textField3.text!)
papiresult = ((systPA!-diastPA!)/cvPressure!)
userDefaults.set(textField1.text, forKey: "PASP")
userDefaults.set(textField2.text, forKey: "PADP")
userDefaults.set(textField3.text, forKey: "CVP")
userDefaults.set(papiresult, forKey: "PAPI")
}
}
Here is the code in the last (result) view controller:
import UIKit
class ViewController3: UIViewController {
#IBOutlet weak var label1: UILabel!
#IBOutlet weak var label2: UILabel!
#IBOutlet weak var label3: UILabel!
#IBOutlet weak var label4: UILabel!
#IBOutlet weak var label5: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
//Recalling data from UserDefaults//
override func viewWillAppear(_ animated: Bool) {
if let data1 = userDefaults.object(forKey: "PASP") {
if let message1 = data1 as? String {
self.label1.text = message1}
}
if let data2 = userDefaults.object(forKey: "PADP") {
if let message2 = data2 as? String {
self.label2.text = message2}
}
if let data3 = userDefaults.object(forKey: "CVP") {
if let message3 = data3 as? String {
self.label3.text = message3}
}
if let data4 = userDefaults.object(forKey: "Age") {
if let message4 = data4 as? String {
self.label4.text = message4}
}
if let data5 = userDefaults.object(forKey: "PAPI") {
if let message5 = data5 as? Double {
self.label5.text = "\(message5)"}
}
}
Basically, you should use UserDefaults.standard rather than creating a new instance of UserDefaults class. So I think this code
let userDefaults = UserDefaults()
should be replaced with this:
let userDefaults = UserDefaults.standard

image is complaining fatal error: unexpectedly found nil while unwrapping an Optional value

I have a master/detail app, where I need to get the image from the master and put it in the detail
It's complaining on the imageView line although I have a file called Gerbera.png image but it won't show. Also how do I call the image from the master to the detail page?
class DetailViewController: UIViewController {
#IBOutlet weak var webView: UIWebView!
#IBOutlet weak var detailDescriptionLabel: UILabel!
#IBOutlet weak var imageView: UIImageView!
#IBOutlet weak var btnCall: UIButton!
func configureView() {
// Update the user interface for the detail item.
if let detail: AnyObject = detailItem {
if let myWebview = webView {
let stringRepresentation = MasterViewController.MyVariables.urlString?.joined(separator:"")
print ("urlString", MasterViewController.MyVariables.urlString)
print ("sR",stringRepresentation)
let url = NSURL(string: stringRepresentation as! String)
let request = URLRequest(url: url! as URL)
myWebview.scalesPageToFit = true
myWebview.loadRequest(request)
}
imageView.image = UIImage(named:"Gerbera.png")!
}
}
Please try this line
imageView.image = UIImage(named:"Gerbera")!
I found the answer for this. My Detail View shows image on the top then web view on the bottom. I realized that the detail view should show code for the image first before code for the web view. So I put it under viewDidLoad() and it worked!
override func viewDidLoad() {
super.viewDidLoad()
imageView1.image = MasterViewController.MyVariables.flowerImage!.first

How to grab the value of a WebView in Swift

Suppose I have a label that is a NSTextField. I know I can access the value of that label by:
#IBOutlet weak var label: NSTextField!
let labelValue = label.stringValue
And then I can use that variable accordingly.
The same is easily said for an NSImage:
#IBOutlet weak var productImageView: NSImageView!
let img = productImageView.image
My question is how do I grab the value of a WebView. I am unsure which property allows me to use a WebView.
#IBOutlet weak var videoTemp: WebView!
let videoPassed = videoTemp //how do I access this videoTemp's value much like .stringValue and .image
I am trying to load dynamic video URL's to Youtube videos when I click on a collection view item. The line that I have commented in my setupAppVideo method is where my fatal error occurs:
"fatal error: unexpectedly found nil while unwrapping an Optional value"
but when I print out the url and request variables their are no nil values and all of them are the correct links in the console.
import Cocoa
import WebKit
class test1: NSCollectionViewItem {
#IBOutlet weak var label: NSTextField!
#IBOutlet weak var label2: NSTextField!
#IBOutlet weak var productImageView: NSImageView!
#IBOutlet weak var videoTemp: WKWebView!
var buildProduct: ProductModel? {
didSet{
label.stringValue = (buildProduct?.product_name)!
label2.stringValue = (buildProduct?.product_price)!
setupAppIconImage()
setupAppVideo()
}
}
override func viewDidLoad() {
super.viewDidLoad()
}
func setupAppIconImage() {
if let appIconImageURL = buildProduct?.product_image {
let url = NSURL(string: appIconImageURL)
URLSession.shared.dataTask(with: url! as URL,completionHandler:{(data, response, error) in
if error != nil {
print(error)
return
}
DispatchQueue.main.async(){
self.productImageView.image = NSImage(data: data!)
}
}).resume()
}
}
func setupAppVideo(){
if let appVideoURL = buildProduct?.product_video{
let url = NSURL(string: appVideoURL)
print(url)
let request = NSURLRequest(url: url as! URL)
print(request)
//self.videoTemp.load(request as URLRequest)
}
}
}

Preloaded database with Realm Swift

I'm having a little trouble in getting PreLoaded data to work. At first, here is code:
if firstRun {
userDefaults.set(1, forKey: "dayCount")
userDefaults.set(dateFormatter.string(from: date), forKey: "date")
let newPath = defaultPath.deletingLastPathComponent()
let v0Path = bundleURL("default")
do {
//try FileManager.default.removeItem(at: defaultPath)
try FileManager.default.copyItem(at: v0Path!, to:defaultPath)
} catch {
print(error)
}
} ...
v0Path:
file:///Users/dimasalbuquerque/Library/Developer/CoreSimulator/Devices/7FE635BA-AA7A-4241-AF3B-88AD60693AE7/data/Containers/Bundle/Application/B6739B92-B7D8-4DD8-9DA8-CD9BBD84B109/Example.app/default.realm
defaultPath:
file:///Users/dimasalbuquerque/Library/Developer/CoreSimulator/Devices/7FE635BA-AA7A-4241-AF3B-88AD60693AE7/data/Containers/Data/Application/A86C4337-9006-497C-A688-AD781F49EF04/Documents/default.realm
I followed this guide: https://github.com/realm/realm-cocoa/blob/master/examples/ios/swift-2.2/Migration/AppDelegate.swift
Problem is that when the program is running by the first time, it executes the code correctly, but when I try to access realm database, it says it's empty. Although when I open the app for the second time, it works, the data is there. It's already over 1 week that I'm trying to solve this, I've searched through all the net but without success.
Here is where Realm is first called:
class HomeViewController: UIViewController {
#IBOutlet weak var message: UILabel!
#IBOutlet weak var backward: UIButton!
#IBOutlet weak var forward: UIButton!
#IBOutlet weak var background: UIImageView!
#IBOutlet weak var timeBtn: UIButton!
#IBOutlet weak var favoriteBtn: UIButton!
#IBOutlet weak var googleAd: GADBannerView!
let userDefaults = UserDefaults.standard
let realm = try! Realm()
var currentDate = 1
var time = 0 {
didSet {
if time != oldValue {
randomBackground(time)
}
}
}
var dailyMessage: DailyMessagesRealm?
var currentMsg: Message?
override func viewDidLoad() {
super.viewDidLoad()
let first = userDefaults.bool(forKey: "notFirstRun")
if !first {
userDefaults.set(true, forKey: "notFirstRun")
reNew()
}
let day = userDefaults.integer(forKey: "dayCount")
currentDate = day
let empty = realm.objects(DailyMessagesRealm.self).isEmpty
let dailyMessage = realm.objects(DailyMessagesRealm.self).filter("date == '\(day)'").first
//*********Error occurs here***********
self.dailyMessage = dailyMessage!
self.currentMsg = dailyMessage?.morningMessage
self.currentMsg = dailyMessage?.morningMessage
changeMessage((dailyMessage?.morningMessage?.message)!)
initAds()
changeBackground("morning1")
checkFavorite()
} ...
From the sound of it, you must be calling Realm() somewhere before you're performing your copy operation here.
default.realm is only opened when you call Realm() for the first time. Once it's open though, it stores cached information about the file in memory, so if you replace it after the fact, you'll end up with unpredictable behavior.
If you absolutely need to do some kind of operation with Realm(), you can enclose it in an #autoreleasepool { } block to ensure its cached entries in memory are predictably flushed before you do the file copy.
Other than that, I recommended checking your code to ensure you're performing this file copy before touching any instances of Realm() pointing at it.