Web View crashes - ios

Hello and thanks for reading this,
I'm building a simple app with 2-3 tabs (view controllers), and the first one is some kind of converter (miles to km), it's fine, and the second viewcontroller has to have a "webview" element.
So, when I build a separate app with only ONE view controller, (with "import WebKit") it works fine:
super.viewDidLoad()
webview.load(URLRequest(url: URL(string: "https://www.google.com")!))
BUT when I copy this to my 2-tabbed app code under the line #super.viewDidLoad()#, it crashes saying "Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value".
I'm really new with this all, so I don't know how to fix this. And I didn't find solutions to similar problem on this forum. Thank you in advance!
p.s. how am I creating web view - visually add it. I see the tip to create it by coding, I will try, thank you
p.p.s. Im adding here my code:
import UIKit
import SafariServices
import WebKit
extension String {
func toDouble() -> Double? {
return NumberFormatter().number(from: self)?.doubleValue
} }
class ViewController: UIViewController {
#IBOutlet var mileField: UITextField!
#IBOutlet var mileResult: UILabel!
#IBOutlet var meters: UILabel!
#IBOutlet var cmeters: UILabel!
#IBAction func mileButton(_ sender: UIButton) {
let mile: Double = mileField.text?.toDouble() ?? 0
let km = mile * 1.6
let m = km * 1000
let cm = m * 100
meters.text = String(m)+" m"
mileResult.text = String(km)+" km"
cmeters.text = String(cm)+" cm"
}
#IBOutlet var vw: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
vw.load(URLRequest(url: URL(string: "google.com")!)) // this is where I got Fatal error blah blah blah
}
#IBAction func bTapped() {
let vc = SFSafariViewController(url: URL(string: "https://www.apple.com")!)
present(vc, animated: true) // this works fine but I need to use webview element
}
}
a little screenshot

Declare your two view controllers. Also please assign this class names to your view controller in storyboard.
https://i.stack.imgur.com/BDoY6.png
class ViewController1: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}
class ViewController2: UIViewController {
#IBOutlet var webview: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
webview.load(URLRequest(url: URL(string: "https://www.google.com")!))
}
}

Related

Problems Updating View with Swift 5

I am having some trouble updating my secondViewController view in Xcode using Swift 5. I want my app to add two numbers together and show the result in the second ViewController. Although it works the first time, if I return to my previous view and change the numbers, the view does not update.
I tried using viewWillAppear, viewWillDisappear, amongst others, including NSNotificationCenter addObserve, but I have had no luck whatsoever.
Do you have any recommendations? Am I missing something?
Please see below for the code and a screenshot of my ViewControllers:
//
// ViewController.swift
//
import UIKit
var result = ""
var resultFinal = Float(result)
let finalResult = resultFinal!
class ViewController: UIViewController {
#IBOutlet weak var firstNumber: UITextField!
#IBOutlet weak var secondNumber: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
func getResult()-> Float{
guard let fNumber = firstNumber.text else {
return 0
}
let firstFloat = Float(fNumber)
guard let sNumber = secondNumber.text else {
return 0
}
let secondFloat = Float(sNumber)
let sumNumber: Float = firstFloat! + secondFloat!
return sumNumber
}
#IBAction func submitSum(_ sender: Any) {
resultFinal = getResult()
print(resultFinal!)
}
}
//
// secondViewController.swift
//
import UIKit
class secondViewController: UIViewController {
#IBOutlet weak var test: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
self.test.text!=""
// Do any additional setup after loading the view.
}
override func viewWillAppear(_ animated: Bool) {
test.text = String(finalResult)
}
}
Screenshot:
Thanks.
Your problem is with the global variables. It seems from your code that you expect these three to reevaluate every time one of them changes:
var result = ""
var resultFinal = Float(result)
let finalResult = resultFinal!
For example, if you set resultFinal = 4, then finalResult will equal 4. However, those variables only evaluate once––the first time. You can simplify your use of these variables significantly. Replace these three with:
var result: Float?
Then, in ViewController:
class ViewController: UIViewController {
#IBOutlet weak var firstNumber: UITextField!
#IBOutlet weak var secondNumber: UITextField!
func getResult() -> Float {
guard let number1 = Float(firstNumber.text ?? "0") ?? 0
guard let number2 = Float(secondNumber.text ?? "0") ?? 0
return number1 + number2
}
#IBAction func submitSum(_ sender: Any) {
result = getResult()
}
}
Note: I simplified getResult and made it treat empty fields as 0.
In SecondViewController:
class SecondViewController: UIViewController {
#IBOutlet weak var test: UITextField!
override func viewWillAppear(_ animated: Bool) {
test.text = String(result ?? 0)
}
}
Note: self.test.text!="" doesn't really do anything, so I removed it.

How to get WKWebView to show in background

I am trying to get an animated gif to play in the background, and have some labels and buttons appear on top. This code runs and shows the animated gif, however it does not show the buttons or label text.
import Foundation
import UIKit
import WebKit
class LoginViewController: UIViewController {
#IBOutlet var containerView: UIView! = nil
var webViewBG: WKWebView?
#IBOutlet weak var loginButton: UIButton!
#IBOutlet weak var signUpButton: UIButton!
override func loadView() {
super.loadView()
self.webViewBG = WKWebView()
self.view = self.webViewBG
}
override func viewDidLoad() {
super.viewDidLoad()
let htmlPath = Bundle.main.path(forResource: "WebViewContent", ofType: "html")
let htmlURL = URL(fileURLWithPath: htmlPath!)
let html = try? Data(contentsOf: htmlURL)
var req = NSURLRequest(url:htmlURL)
self.webViewBG!.load(req as URLRequest)
webViewBG?.isUserInteractionEnabled = false;
self.loginButton.layer.borderColor = UIColor.white.cgColor
self.loginButton.layer.borderWidth = 2
self.signUpButton.layer.borderColor = UIColor.white.cgColor
self.signUpButton.layer.borderWidth = 2
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override var preferredStatusBarStyle : UIStatusBarStyle {
return UIStatusBarStyle.lightContent
}
}
It looks like this line overrides your view controller's view where the buttons are:
self.view = self.webViewBG
Try
self.view.addSubview(self.webViewBG)
You might also need to tweak the z position so that the webView is located 'behind' the buttons, like this:
self.webViewBG.layer.zPosition = 0.5
Higher zPosition means the view stands out more 'towards' the user

Difficulty with IBOutlets in Protocol/Delegate

I'm having difficulty with IBOutlets. I'm trying to allow the user to input a goal (called nameOfRewardText) in a table view controller (LoLAddGoalsTableViewController) and then when they click "Done", have that goal show up in a label called "currentGoalTextField" in a different view controller (LoLGoalViewController). I had been trying to implement this using a Save segue, but was advised to use a protocol with a delegate instead (Updating text in ViewController using Save function). Now that I've replaced the Save segue with the protocol and delegate, the inputted "nameOfRewardText" text is not showing up in the "currentGoalTextField" label, I suspect because the IBOutlets are no longer tied together properly. I've attached the code and screenshots of the Outlets below to try to clarify where I'm at. Does anyone know how I could fix the IBOutlets or if there's something else I need to add to get this working? I deleted the line where I assign nameOfRewardText.text to be goal.goalText, so I think nameOfRewardText isn't getting assigned to var goal? Maybe I'm using too many names for this text (nameOfRewardText, goalText, and currentGoalTextField) and that's complicating things? Any help at all would be greatly appreciated, as I'm very new to this! Thank you everybody!
Here is the struct goal:
import UIKit
struct Goal {
var goalText: String
var pointsToCompleteGoal: Int
var pointsEarnedTowardsGoal: Int
var repeatGoal: Bool
init(goalText: String, pointsToCompleteGoal: Int, pointsEarnedTowardsGoal: Int, repeatGoal: Bool = false) { //Made String non-optional. If issue later, can revert.
self.goalText = goalText
self.pointsToCompleteGoal = pointsToCompleteGoal
self.pointsEarnedTowardsGoal = pointsEarnedTowardsGoal
self.repeatGoal = repeatGoal
}
}
Here is the public protocol:
import Foundation
import UIKit
protocol GoalDelegate: class {
func passGoal(_ goal: Goal?)
}
Here is where the delegate is created, and as you can see, the statement where I assign nameOfRewardText.text to be goal.goalText is now gone:
import UIKit
class AddGoalsTableViewController: UITableViewController {
var goal:Goal?
var delegate: GoalDelegate?
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// HASHED OUT THE BELOW BECAUSE REPLACING WITH DELEGATE:
// if segue.identifier == "SaveGoal" {
// let pointsNeededInt = Int(pointsNeededText.text!)
// let pointsEarnedInt = Int(goalProgressText.text!)
// goal = Goal(goalText: nameOfRewardText.text!, pointsToCompleteGoal: pointsNeededInt!, pointsEarnedTowardsGoal: pointsEarnedInt!)
// }
if let secondViewController = segue.destination as? LoLGoalViewController{
delegate = secondViewController
delegate?.passGoal(goal)
}
}
#IBOutlet var goalTableTitleText : UILabel!
#IBOutlet weak var goalProgressText: UILabel!
#IBOutlet weak var nameOfRewardText: UITextField!
#IBOutlet weak var pointsNeededText: UITextField!
#IBOutlet weak var repeatSwitch: UISwitch!
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
Screen cap of AddGoalsTableViewController with Outlets:
Here I conform to the protocol and call the function passGoal:
import UIKit
class LoLGoalViewController: UIViewController, GoalDelegate {
#IBOutlet weak var currentGoalTextField: UILabel!
func passGoal(_ goal: Goal?) {
currentGoalTextField.text = goal?.goalText
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
extension LoLGoalViewController {
#IBAction func cancelToLoLGoalViewController(_ segue: UIStoryboardSegue) {
}
}
Screen cap of LoLGoalViewController with Outlets:
Your LoLGoalViewController view controller might not have fully loaded with all of its outlets. Adding on to my answer to your previous question, you can declare another variable in LolGoalViewController:
#IBOutlet weak var currentGoalTextField: UILabel!
var goalText: String = ""
In your passGoal method, set your string to the goalText variable instead of the label's text:
func passGoal(_ goal: Goal?) {
goalText = goal?.goalText
}
Lastly, in your viewDidLoad of LolGoalViewController, set the label text to be goalText:
override func viewDidLoad() {
super.viewDidLoad()
currentGoalTextField.text = goalText
}

iOS app crashes on Segue

I'm trying to build an app for school but I keep getting error messages. It's probably a really obvious mistake I made.
Basically I am trying to build a view that displays a UIWebView and changes to a 2nd view if a segment controller switch is pressed.
My Code is:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var myWebView: UIWebView!
override func viewDidLoad() {
super.viewDidLoad()
let url = URL(string: "http://google.de")
myWebView.loadRequest(URLRequest(url: url!))
}
#IBAction func Heute(_ sender: UISegmentedControl) {
performSegue(withIdentifier: "Switch", sender: self)
}
}
//Vertretung2
class Vertretung2: UIViewController {
#IBOutlet weak var UIWebView1: UIWebView!
override func viewDidLoad() {
super.viewDidLoad()
let url = URL(string: "http://google.de")
UIWebView1.loadRequest(URLRequest(url: url!))
}
#IBAction func Morgen(_ sender: UISegmentedControl) {
performSegue(withIdentifier: "Switch", sender: self)
}
}
My app keeps crashing when I switch from 1st view to 2nd view.
Is that UIWebView1 in Vertretung2 nil when viewDidLoad() is called on Vertretung2?
Ok, Sorry. I just read your crash log above, and it looks like you maybe forgot to set the Custom Class name in the storyboard for the viewController? Check that here.
The Class text entry field should have your custom class in it.

Iphone App Swift main screen works. Aborts on the second page

I am extremely new to Swift. Before I go on to my issue, I would like to thank everyone that takes time out of their day to help solve issues people are having.
I have been experimenting with swift by making a pool calculator app. I have the basic function to figure out how much chlorine someone needs to put in the pool etc...
The main page is just a filler but then when I click "Pool Calculator" , it aborts and gives me the error " SignalBRT"
The code (sloppy as it is) works and i have been experimenting with just a simple addition app that works fine.
But for this one, the code works fine and it gives me an issue. Since it is the "SignalBRT" error, it is such a broad meaning to what the error would be and I do not know what is causing it. I feel like it could be the scrolling view that i added but before i added any functions, it scrolled up and down fine so my assumption would be the "CalculateChlorine" part of the code
Here is my code:
import UIKit
class ViewController: UIViewController {
// #IBOutlet var Number1: UILabel!
//#IBOutlet var Number2: UILabel!
//#IBOutlet var Field1: UITextField!
// #IBOutlet var Field2: UITextField!
#IBOutlet var VolOfpool: UITextField!
#IBOutlet var CurrentR: UITextField!
#IBOutlet var DesiredR: UITextField!
#IBOutlet var labelResult: UILabel!
var DefaultChlorineWeight: Float = 2.0// in oz
var CurrentReading: Float = 1.0
var DesiredReading: Float = 2.0
#IBAction func CalculateChlorine(sender: AnyObject) {
//let a = (Field1.text! as NSString).floatValue
//let b = (Field2.text! as NSString).floatValue
//let sum = a + b
// labelResult.text = "\(sum)"
let Volume = (VolOfpool.text! as NSString).floatValue
let CurrentReading = (CurrentR.text! as NSString).floatValue
let DesiredReading = (DesiredR.text! as NSString).floatValue
let resultForChlorine = (DefaultChlorineWeight * (Volume/10000) * ((DesiredReading - CurrentReading) / 1))
labelResult.text = "\(resultForChlorine)"
}
override func viewDidLoad() {
super.viewDidLoad()
// 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.
}
}
here is my error:
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate { // it says error SignalBRT here
kind of hard to see without a picture but the first screen of the app has a button called " Pool Calculator" where it sends it to another screen where the user would input the values . The second screen aborts and gives me the error.

Resources