Only instance methods can be declared #IBAction | XCODE ERROR | Swift 5 - xcode

Here's my code do not suggest to remove IBAction I'm a beginner making a browser. I'm also
pretty new to this program:
import Cocoa
import WebKit
class ViewController: NSViewController, WKNavigationDelegate {
#IBOutlet weak var webView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
webView.navigationDelegate = self
// Do any additional setup after loading the view.
}
override var representedObject: Any? {
didSet {
}
}
#IBAction func didEnterKeyTapped( sender: NSTextField){
let urlString = sender.stringValue
guard let url = URL(string: urlString) else {return}
let urlRequest = URLRequest(url: url)
webView.load(urlRequest)
#IBAction func didnavigationButtonTapped ( sender: NSSegmentedControl){
if sender.selectedSegment == 0 {
webView.goBack()
}else {
webView.Forward()
}
}
func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
let currentUrl = webView.url?.absoluteString ?? ""
guard let windowController = view.window?.windowController as? WindowController else {return}
let textField = windowController.urlTextField
textField?.stringValue = currentUrl
}
}
}

You declared the #IBActions outside of the ViewController class. An IBAction must be a member of a class. Move the IBActions inside the class to fix the compiler error.
Another problem in your code is you declared the didNavigationButtonTapped IBAction inside the didEnterKeyTapped IBAction. The two IBActions should be separate functions, such as the following:
#IBAction func didEnterKeyTapped( sender: NSTextField){
let urlString = sender.stringValue
guard let url = URL(string: urlString) else {return}
let urlRequest = URLRequest(url: url)
webView.load(urlRequest)
}
#IBAction func didnavigationButtonTapped ( sender: NSSegmentedControl) {
if sender.selectedSegment == 0 {
webView.goBack()
}else {
webView.Forward()
}
}

Related

webView didFinish Navigation never gets called

I am trying to get the splash view ( back_button ) to remove itself once the webpage fully loads, I had done quite a bit of researching and they always point to the same code as an answer. However, mine will not get called. Can somebody advise what I am doing wrong?
import UIKit
import WebKit
class ViewController: UIViewController {
#IBOutlet weak var LoadingView: UIImageView!
var webView: WKWebView?
var bgImage: UIImageView?
var imageViewObject :UIImageView?
override func viewDidLoad() {
super.viewDidLoad()
//var imageViewObject :UIImageView
let screenSize: CGRect = UIScreen.main.bounds
imageViewObject = UIImageView(frame:CGRect(x:0,y: 0, width: screenSize.width, height: screenSize.height))
imageViewObject?.image = UIImage(named:"back_image")
webView?.navigationDelegate = self as? WKNavigationDelegate
self.view.addSubview(imageViewObject!)
let myURL = URL(string: "https://www.google.com")
let myRequest = URLRequest(url: myURL!)
_ = webView?.load(myRequest)
}
override func loadView() {
super.loadView()
//self.view.sendSubview(toBack: imageViewObject)
//self.view = self.LoadingView
self.webView = WKWebView()
self.view = self.webView
}
#IBAction func BackButton(_ sender: Any) {
if(webView?.canGoBack)!
{
webView?.goBack();
}
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
print("TEST")
imageViewObject?.removeFromSuperview()
}
func webViewDidFinishLoad(webView: WKWebView) {
imageViewObject?.removeFromSuperview()
self.view = self.webView
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
you have to conform to it's protocol delegate by putting this line of code in viewDidLoad
webView?.uiDelegate = self
after doing that , now if you want to use delegation method's you have to put your viewController as a subclass of UIWebViewDelegate
class ViewController: UIViewController ,UIWebViewDelegate{
I fixed this by making
webView?.navigationDelegate = self
and adding this to the Class
class ViewController: UIViewController, WKNavigationDelegate

swift 4- Save the last data of a text field in a label so that they are displayed when the app is restarted

I have a problem, I want to create a small app in which data in a formula can be charged.
Currently the data from three ViewControllers and one PickerViewController will be given back to the first ViewController.
That works very well too.
Now I want that the data at the start not on "nil" set but have a certain value.
Thereafter, the data entered last should reappear when the app is restarted.
I would like to apologize for my english, it is not my preferred language ...
Here is a part of my code how I wrote it
Main ViewController:
import UIKit
class RecivingViewController: UIViewController, SendDataBack, SendDataBack2, SendDataBack3, SendDataBack4 {
#IBOutlet weak var recivingData: UILabel!
#IBOutlet weak var recivingData2: UILabel!
#IBOutlet weak var recivingData3: UILabel!
#IBOutlet weak var recivingData4: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
func userData(data: String) {
recivingData.text = data
}
func userData2(data: String) {
recivingData2.text = data
}
func userData3(data: String) {
recivingData3.text = data
}
func PickerData(data: String){
recivingData4.text = data
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "view1" {
let SendingVC: SendingViewController = segue.destination as! SendingViewController
SendingVC.delegate = self
}
if segue.identifier == "view2" {
let SendingVC2: Sending2ViewController = segue.destination as! Sending2ViewController
SendingVC2.delegate = self
}
if segue.identifier == "view3" {
let SendingVC3: Sending3ViewController = segue.destination as! Sending3ViewController
SendingVC3.delegate = self
}
if segue.identifier == "picker" {
let SendingVC4: PickerViewController = segue.destination as! PickerViewController
SendingVC4.delegate = self
}
}
}
one of the other ViewControllers:
import UIKit
protocol SendDataBack {
func userData(data: String)
}
class SendingViewController: UIViewController {
#IBOutlet weak var DataTxt: UITextField!
var delegate: SendDataBack? = nil
#IBAction func done(_ sender: Any) {
if delegate != nil {
if DataTxt.text != nil {
let data = DataTxt.text
delegate?.userData(data: data!)
dismiss(animated: true, completion: nil)
}
}
}
In order to see data after app is restarted you should use user defaults.
For saving data
UserDefaults.standard.set(newValue, forKey: "data")
For loading data in your view controller, if it's first load, when data is nil
UserDefaults.standard.string(forKey: "data")

How to get UIActivityIndicator to disappear once appearing?

I currently have my app linking to a certain URL upon opening the app, and this obviously can have a delay between opening it and the webView actually loading, so I want it to display an activity indicator whenever the webView is loading, I have the following code in my ViewController.swift:
class ViewController: UIViewController, UIWebViewDelegate {
#IBOutlet weak var webView: UIWebView!
#IBOutlet weak var activityIndicator: UIActivityIndicatorView!
override func viewDidLoad() {
super.viewDidLoad()
webView.delegate = self
let url = URL(string: "url to site")
webView.loadRequest(URLRequest(url: url!)
}
func webViewDidStartLoad(webView: UIWebView){
activityIndicator.startAnimating()
}
func webViewDidFinishLoad(webView: UIWebView){
activityIndicator.stopAnimating()
}
The activity indicator shows up from the beginning but it does not disappear once the webView loads and stays their forever.
The way you have your code organized is a bit confusing. It appears you are declaring your funcs inside the #IBAction function. If this is the case, this will not work.
Try this instead
class ViewController: UIViewController, UIWebviewDelegate {
override func viewDidLoad() {
...
webView.delegate = self
// You should add this to your Storyboard, above the webview instead of here in the code
activityIndicator.center = self.view.center
activityIndicator.hidesWhenStopped = true
activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
// I forget the actual method name - look it up
view.insertSubview(activityIndicator, above: webView)
}
#IBAction func openButton(_ sender: Any) {
let url = URL(string: "websiteURL")
webView.loadRequest(URLRequest(url: url!))
}
func webViewDidStartLoad(webView: UIWebView){
activityIndicator.startAnimating()
}
func webViewDidFinishLoad(webView: UIWebView){
activityIndicator.stopAnimating()
}
// You'll also want to add the "didFail" method
}
The issue is a syntax issue, you have to add an underscore in the functions.
override func viewDidLoad() {
super.viewDidLoad()
webView.delegate = self
let url = URL(string: "your URL")
webView.loadRequest(URLRequest(url: url!))
}
func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool{
activityIndicator.startAnimating()
return true
}
func webViewDidStartLoad(_ webView: UIWebView){
activityIndicator.startAnimating()
}
func webViewDidFinishLoad(_ webView: UIWebView){
activityIndicator.stopAnimating()
}
func webView(_ webView: UIWebView, didFailLoadWithError error: Error){
activityIndicator.stopAnimating()
}

Pass data via segue between 2 view controllers and update labels

I am trying to pass var projectNumber from ViewController to Project1ViewController via segue and save it as var projectNum. Then use projectNum to update the labels in Project1ViewController. The segue and action/outlets are all set up. The app runs fluently (no errors), however, projectNum in Project1ViewController is not getting the projectNumber value and making it projectNum.
How do I pass the projectNumber value from ViewController to Project1ViewController and save it in projectNum? I've seen tutorials that describe similar actions being performed via delegates, but I'm unsure if delegates are applicable to my question. Any feedback helps.
ViewController
import UIKit
class ViewController: UIViewController{
var projectNumber:String = ""
#IBOutlet var projectButton1 : UIButton!
#IBOutlet var projectButton2 : UIButton!
#IBOutlet var projectButton3 : UIButton!
#IBOutlet var projectButton4 : UIButton!
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.
}
#IBAction func updateLabels(sender: UIButton!) {
projectNumber = String(sender.tag)
println(projectNumber)
sender.setTitle(String(projectNumber), forState: UIControlState.Normal)
func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
//if user presses Project 3921 button
if segue.identifier == "Project3921Segue"
{
if var destinationVC = segue.destinationViewController as? Project1ViewController{
destinationVC.projectNum = projectNumber
}
}
//if user presses Project 3922 button
else if segue.identifier == "Project3922Segue"
{
if var destinationVC = segue.destinationViewController as? Project1ViewController{
destinationVC.projectNum = projectNumber
}
}
//if user presses Project 3923 button
else if segue.identifier == "Project3923Segue"
{
if var destinationVC = segue.destinationViewController as? Project1ViewController{
destinationVC.projectNum = projectNumber
}
}
//otherwise user presses Project 3924 button
else if segue.identifier == "Project3924Segue"
{
if var destinationVC = segue.destinationViewController as? Project1ViewController{
destinationVC.projectNum = projectNumber
}
}
}
}
}
Project1ViewController
import UIKit
class Project1ViewController: UIViewController {
var projectNum:String!
#IBOutlet var projectNumLabel: UILabel!
#IBOutlet var projectNumTitle: UINavigationItem!
override func viewDidLoad() {
super.viewDidLoad()
projectNumLabel.text = projectNum
projectNumTitle.title = projectNum
println(projectNum)
// Do any additional setup after loading the view.
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Thanks!
You are defining prepareForSegueinside the button action function. It is a ViewController function to be overridden.
Your solution can be way more simpler:
class ViewController: UIViewController{
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.
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if var destinationVC = segue.destinationViewController as? Project1ViewController{
destinationVC.projectNum = segue.identifier
}
}
}
Note you do not need the button outlets, since you just configure them in the storyboard with the proper segue identifier. Unless you need some other custom action to be triggered by the buttons.
And:
class Project1ViewController: UIViewController {
var projectNum:String!
#IBOutlet var projectNumLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
projectNumLabel.text = projectNum
self.title = projectNum
println(projectNum)
}
}
Note I just set the title property of Project1ViewController in order to present the projectNum as the title in the navigation controller. I assume your controllers are embedded in a navigation controller and the ViewController's buttons has show segues to Project1ViewController.

How to use public NSURL Variable

I'm new to Swift and Xcode overall,
I want to create a new public NSURL variable which I want to use later in my code to give it value and use that value later from it. like below :
class AddUrlViewController: NSViewController {
#IBOutlet weak var txtPath: NSTextField!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func btnFileDialog(sender: NSButton) {
let myFiledialog:NSOpenPanel = NSOpenPanel()
myFiledialog.canChooseDirectories = true
myFiledialog.canChooseFiles = false
var returnCode:NSInteger = myFiledialog.runModal()
if (returnCode == NSOKButton) {
/////////// Use it here
var directoryUrl = myFiledialog.URL?.absoluteURL
}
}
#IBAction func btnStart(sender: NSButton) {
//////////// Use it here
}
}
How should I achieve this the best way ?
Simply define the variable as a property outside of the function scope -
class AddUrlViewController: NSViewController {
#IBOutlet weak var txtPath: NSTextField!
var directoryUrl:NSURL?
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func btnFileDialog(sender: NSButton) {
let myFiledialog:NSOpenPanel = NSOpenPanel()
myFiledialog.canChooseDirectories = true
myFiledialog.canChooseFiles = false
var returnCode:NSInteger = myFiledialog.runModal()
if (returnCode == NSOKButton) {
/////////// Use it here
self.directoryUrl = myFiledialog.URL?.absoluteURL
}
}
#IBAction func btnStart(sender: NSButton) {
if (self.directoryUrl != nil) {
//////////// Use it here
}
}
}

Resources