Xcode Swift 2 Weather App problems - ios

import UIKit
class ViewController: UIViewController {
#IBOutlet weak var cityNameTextField: UITextField!
#IBOutlet weak var cityNameLabel: UILabel!
#IBOutlet weak var cityTempLabel: UILabel!
#IBAction func getDataButtonClicked(sender: AnyObject) {
getWeatherData("http://api.openweathermap.org/data/2.5/weather?q=\(cityNameTextField.text)&APPID=6de03a1d1554874e7594a89fad719dd0")
}
override func viewDidLoad() {
super.viewDidLoad()
getWeatherData("http://api.openweathermap.org/data/2.5/weather?q=London&APPID=6de03a1d1554874e7594a89fad719dd0")
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func getWeatherData(urlString: String) {
let url = NSURL(string: urlString)
let task = NSURLSession.sharedSession().dataTaskWithURL(url!) {(data, response, error) in
dispatch_async(dispatch_get_main_queue(), {
self.setLabels(data!)
})
}
task.resume()
}
var jsonData: AnyObject?
func setLabels(weatherData: NSData) {
do {
self.jsonData = try NSJSONSerialization.JSONObjectWithData(weatherData, options: []) as! NSDictionary
} catch {
//error handle here
}
if let name = jsonData!["name"] as? String {
cityTempLabel.text = "\(name)"
}
if let main = jsonData!["main"] as? NSDictionary {
if let temp = main["temp"] as? Double {
cityTempLabel.text = String(format: "%.1f", temp)
}
}
}
};
Yesterday I had the app running and this morning I've just been getting new error messages that won't even allow the code to be compiled. They say 'Missing "Default-568h#2x.png" launch image' and 'Command /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftcode'. Thanks in advance.

You need to add something to your info.plist file:
It's because the URL link you're trying to get data from is not a secured link, so adding this to you info.plist allows you to access that link. Just go to you info.plist and right-click and select Add Row, then add exactly what you see in the image above.
Also, remove the getWeatherData function from the viewDidLoad method, as you don't need that, as you call it when you press your button.
Also, I've noticed one of your labels isn't set correctly in your setLabels function, as they both try to set the cityTempLabel label, so update the other one to be cityNameLabel.
Build and run and it should all work.

Related

Load WebView before transitioning to it

I had to update an app that i didn't touch for quite a while and now am facing an 'Fatal error: Unexpectedly found nil while unwrapping an Optional value' in DetailViewController::refreshWebView() when executing webView.loadRequest(myRequest) because webView is nil at this point in time.
I didn't change anything relating to how the DetailViewController is loaded and assigned to MasterViewController, so I am very confused as why this does not work anymore.
Was there something changed that i am not aware of? Or did I implement this whole thing incorrectly in the first place and it was coincidence that it worked?
import UIKit
protocol EventSelectionDelegate: class {
func eventSelected(_ newEvent: String)
}
class MasterViewController: UIViewController, UIWebViewDelegate {
var activityView: UIActivityIndicatorView!
weak var delegate: EventSelectionDelegate?
func detailChosen(_ detailUrlString: String) {
delegate?.eventSelected(detailUrlString)
activityView.startAnimating()
}
func transitionToDetail() {
if let detailViewController = self.delegate as? DetailViewController {
DispatchQueue.main.async {
self.activityView.stopAnimating()
self.splitViewController?.showDetailViewController(detailViewController, sender: nil)
}
}
}
}
// Helper function inserted by Swift 4.2 migrator.
fileprivate func convertToUIApplicationOpenExternalURLOptionsKeyDictionary(_ input: [String: Any]) -> [UIApplication.OpenExternalURLOptionsKey: Any] {
return Dictionary(uniqueKeysWithValues: input.map { key, value in (UIApplication.OpenExternalURLOptionsKey(rawValue: key), value)})
}
import UIKit
class DetailViewController: UIViewController, UIWebViewDelegate {
#IBOutlet weak var webView: UIWebView!
var animationWaitDelegate: MasterViewController!
var eventUrl: String! {
didSet {
self.refreshWebView()
}
}
override func viewDidLoad() {
super.viewDidLoad()
webView.delegate = self
}
func refreshWebView() {
let myURL = URL(string:eventUrl!)
let myRequest = URLRequest(url: myURL!)
webView.loadRequest(myRequest)
}
func webViewDidFinishLoad(_ webView: UIWebView) {
animationWaitDelegate.transitionToDetail()
}
}
extension DetailViewController: EventSelectionDelegate {
func eventSelected(_ newEvent: String) {
eventUrl = newEvent
}
}
// Helper function inserted by Swift 4.2 migrator.
fileprivate func convertToUIApplicationOpenExternalURLOptionsKeyDictionary(_ input: [String: Any]) -> [UIApplication.OpenExternalURLOptionsKey: Any] {
return Dictionary(uniqueKeysWithValues: input.map { key, value in (UIApplication.OpenExternalURLOptionsKey(rawValue: key), value)})
}
PS: I found a workaround in the meantime where I added a flag in DetailViewController that allows me to call refreshWebView in viewDidLoad if webView was nil the first time it was called.
First you have to update following code for null check, which will prevent crashing your app.
func refreshWebView() {
if webView != nil {
let myURL = URL(string:eventUrl!)
let myRequest = URLRequest(url: myURL!)
webView.loadRequest(myRequest)
}
}
After at transition add following code will fix your issue.
func transitionToDetail() {
if let detailViewController = self.delegate as? DetailViewController {
DispatchQueue.main.async {
self.activityView.stopAnimating()
detailViewController.loadViewIfNeeded() // Add this line of code
self.splitViewController?.showDetailViewController(detailViewController, sender: nil)
}
}
}
loadViewIfNeeded() method will load your controls before open screen if required.

open text files in same ViewController

I am making app for iPhone in Xcode using Swift i have added multiple buttons on Main.Storyboard and there is one txt file for each Button, Like
class ViewController: UIViewController {
#IBAction func Button1(_ sender: Any) {
opneTextFile(fileName: "example")
}
#IBAction func Button2(_ sender: Any) {
opneTextFile(fileName: "example1")
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
func opneTextFile(fileName : String) {
if let filepath = Bundle.main.path(forResource: fileName, ofType: "txt") {
do {
let contents = try String(contentsOfFile: filepath)
print(contents)
// Now push second ViewController form here with contents.
if let secondVC = self.storyboard?.instantiateViewController(withIdentifier: "TextViewVC") as? TextViewVC {
secondVC.content = contents
self.navigationController?.pushViewController(secondVC, animated: true)
}
} catch {
// contents could not be loaded
}
} else {
// example.txt not found!
}
}
This Is My TextViewVC and i have create a new ViewController in storyboard with TextView and linked it with TextViewVC file
class TextViewVC: UIViewController {
#IBOutlet var textView: UITextView!
var content : String?
override func viewDidLoad() {
super.viewDidLoad()
textView.text = content
// Do any additional setup after loading the view.
}
Error
but i don't know how to open file when user click on button, it should be something like when user click on button1 the txt1 file should open in ViewController2 and when user click on button2 the txt2 file should open in Same when user click on button1 the txt1 file should open in ViewController as Button1 and the same for rest Buttons..
create a common code for pushing the new viewController.
have created a opneTextFile method in which you just pass a fileName.
func opneTextFile(fileName : String) {
if let filepath = Bundle.main.path(forResource: fileName, ofType: "txt") {
do {
let contents = try String(contentsOfFile: filepath)
print(contents)
// Now push second ViewController form here with contents.
if let secondVC = self.storyboard?.instantiateViewController(withIdentifier: "ViewController2") as? ViewController2 {
secondVC.content = contents
self.navigationController?.pushViewController(secondVC, animated: true)
}
} catch {
// contents could not be loaded
}
} else {
// example.txt not found!
}
}
// action methods
#IBAction func Button1(_ sender: Any) {
opneTextFile(fileName: "example")
}
#IBAction func Button2(_ sender: Any) {
opneTextFile(fileName: "example1")
}
// ViewController2
class ViewController2: UIViewController {
#IBOutlet weak var txt_view: UITextView!
var content : String?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
txt_view.text = content
}
}
NOTE : you can open different files in a same VC.
You should get the text data extracted and show it like you'd show any other string.
let path = Bundle.main.path(forResource: "terms", ofType: "txt")!
let content = try! String(contentsOfFile: path, encoding: .utf8)
note that this is a quick working solution, you should be using try catch block or your app will crash if try! fails.

UIWebView is not shown

WebView in Mainstoryboard is not shown anything. I wanna show yahoo page in my app.When I run my app in an emulator(that is not my real iPhone), it is like only black screen.
Any error does not happen in that time, but
warning
In this part, I got a warning
"signal SIGABRT"
My code is like
import Foundation
import Alamofire
import UIKit
class webViewController: UIViewController {
#IBOutlet var webBrowser: UIWebView! = nil
var targetURL = "https://www.yahoo.co.jp"
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
//loadAddressURL()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func loadAddressURL() {
let requestURL = NSURL(string: targetURL)
let req = NSURLRequest(url: requestURL as! URL)
webBrowser.loadRequest(req as URLRequest)
}
}
I think a connection of WebView & WebViewController is ok. I tried to do Add Exception Breakpoint,and find a point of this error.
The result is
result
My app dropped in
"Thread1:breakpoint4.1".
What is wrong with my app?
You cannot assign nil value to #IBOutlet var webBrowser: UIWebView!.
Leave:
#IBOutlet weak var webBrowser: UIWebView!
BTW, I'm assuming that you create correctly #IBOutlet by holding ctr and dragging from storyboard to you view controller. But I'm afraid that because of lack weak next to your #IBOutlet you created it manually in code so you need to clip it to the view in storyboard
CTRL + DRAG to create IBOutlet for UIWebView like mentioned in below image and it should be:
#IBOutlet weak var webBrowser: UIWebView!
Initialize your targetURL like :
let targetURL = "https://www.yahoo.co.jp".addingPercentEncoding( withAllowedCharacters: .urlQueryAllowed)
Then in your func loadAddressURL must be
func loadAddressURL() {
if NSURL(string: targetURL!) != nil {
let url = URL(string: targetURL!)!
webBrowser.loadRequest(URLRequest(url: url))
}
}
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var webBrowser: UIWebView!
var targetURL = "https://www.yahoo.co.jp"
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.loadAddressURL()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func loadAddressURL() {
let requestURL = NSURL(string: targetURL)
let req = NSURLRequest(url: requestURL! as URL)
webBrowser.loadRequest(req as URLRequest)
}
}
Use this.

Fetch Request: error . . . Core Data Swift 3

Good Night;
Im creating an app that would save the name of people in a Core Data file, when I run the app and save what the user typed it works fine when I load (fetch ) the data it also works fine, the problem comes when I close or go to a different view controller when I hit the load data(fetch) the app crashed with : 'NSInvalidArgumentException',
reason: 'executeFetchRequest:error:
is not a valid NSFetchRequest.'
this is my code
#IBOutlet var PresidentTxt: UITextField!
#IBOutlet var SecDefenseTxt: UITextField!
let dataStack = CoreDataStack()
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func Save(_ sender: Any) {
let database = dataStack.persistenContainer.viewContext
let dbrRecord = Command(context: database)
dbrRecord.potus = PresidentTxt.text
dbrRecord.defsec = SecDefenseTxt.text
do{
try database.save()
}catch {}
}
func didTapView(){
self.view.endEditing(true)
}
#IBAction func Load(_ sender: Any) {
let database = dataStack.persistenContainer.viewContext
do{
let results = try database.fetch(Command.fetchRequest()) as! [Command]
for presidentUS in results{
if let _ = presidentUS.potus {
PresidentTxt.text = presidentUS.potus
}
}
for DefenseSec in results {
if let _ = DefenseSec.defsec {
SecDefenseTxt.text = DefenseSec.defsec
}
}
}catch {}
}

When I implement Parse I get "fatal error: unexpectedly found nil while unwrapping an Optional value"

I am trying to use Parse to edit profile and after I put the code in when I launch the app I clicked the button I made to edit profile and I get this:
fatal error: unexpectedly found nil while unwrapping an Optional value
The Segue I have leading to the edit profile controller does not open and the app crashes. When the Parse code is not implemented the segue to the view controller opens just fine.
import UIKit
import Parse
class EditProfileViewController: UIViewController {
#IBOutlet weak var profilePictureImageView: UIImageView!
#IBOutlet weak var firstNameTextField: UITextField!
#IBOutlet weak var lastNameTextField: UITextField!
#IBOutlet weak var passwordTextField: UITextField!
#IBOutlet weak var repeatPasswordTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Load user details
let userFirstName = PFUser.currentUser()?.objectForKey("first_name") as! String
let userLastName = PFUser.currentUser()?.objectForKey("last_name") as!String
firstNameTextField.text = userFirstName
lastNameTextField.text = userLastName
if(PFUser.currentUser()?.objectForKey("profile_picture") != nil)
{
let userImageFile:PFFile = PFUser.currentUser()?.objectForKey("profile_picture") as! PFFile
userImageFile.getDataInBackgroundWithBlock({ (imageData: NSData?, error: NSError?) -> Void in
self.profilePictureImageView.image = UIImage(data: imageData!)
})
}
let image = UIImage(named: "navbar.png")
self.navigationController!.navigationBar.setBackgroundImage(image,forBarMetrics: .Default)
var nav = self.navigationController?.navigationBar
nav?.tintColor = UIColor.whiteColor()
let titleDict: NSDictionary = [NSForegroundColorAttributeName: UIColor.whiteColor()]; self.navigationController!.navigationBar.titleTextAttributes = titleDict as [NSObject : AnyObject]
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true;
}
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
self.view.endEditing(true)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func doneButtonTapped(sender: AnyObject) {
self.dismissViewControllerAnimated(true, completion: nil)
}
#IBAction func chooseProfileButtonTapped(sender: AnyObject) {
}
#IBAction func saveButtonTapped(sender: AnyObject) {
}
}
You need to find out which line exactly throws the error. Basically, this error means that you try to access a variable with optional value, but it turns out the variable is nil!
Why don't you set some break points and see if any of your variables (esp. the ones related to Parse) return nil?
EDIT (just a shot in the dark)
From what I can see in your code, it could be that you have not correctly linked the textfields to your interface builder file. Thus, since you are not initializing them before accessing them, they will return nil and the app will crash here:
firstNameTextField.text = userFirstName
lastNameTextField.text = userLastName
Make sure the textfields are linked to your interface builder file, or, if you are unsure about how to do it, just check if this is indeed the case and insert these two lines before the above ones:
//Initialize them before accessing them
UITextField* firstNameTextField = [[UITextField alloc] init];
UITextField* lastNameTextField = [[UITextField alloc] init];
//Now you can securely access them
firstNameTextField.text = userFirstName
lastNameTextField.text = userLastName
In case the app now doesn't crash anymore, you know it's been these textfields and you need to properly link them to your xib file

Resources