I've encountered this issue a few times where I am trying to either pass a function from one swift file, to another, and I get the error, "Cannot find '_' in scope". I am wondering why this occurs and how to fix it? I have tried creating a public function, public func fetchJokesAPI() , along with making the class of this function an Observable object so that I am able to pass this function throughout my swift files. Why is the compiler not finding my function in the scope? Below is some code to further give reference to the issue.
//Model
import Foundation
struct DecodingError: Error{}
struct JokesModel: Codable {
let type: String
let value: Value
}
// MARK: - Value
struct Value: Codable {
let id: Int
let joke: String
}
class JokesAPI {
var session: URLSession?
// MARK: Getting random jokes from API endpoint
func fetchJokes() {
guard let url = URL(string: "https://api.icndb.com/jokes/random/") else {
print("Cannot generate URL")
return
}
var request = URLRequest(url: url)
request.httpMethod = "GET"
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print(error.localizedDescription)
return
}
guard (response as? HTTPURLResponse) != nil else {
print("No Response")
return
}
struct JokesResponse: Decodable {
let data: [JokesModel]
}
guard let data = data, let dataString = String(data: data, encoding: .utf8)
else {
print("No Data")
return
}
do {
let jokeResponse = try JSONDecoder().decode(JokesResponse.self, from: data)
print(jokeResponse.data)
} catch {
print("Error decoding joke response:", error)
}
}
task.resume()
}
}
// Another Swift File that is a Coco touch file.
import UIKit
import Foundation
class HomeViewController: UIViewController {
private let service = JokesAPI()
private var joke: [JokesModel]?
@IBOutlet var tellAeAJokeButton: UIButton!
@IBOutlet var jokeLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
service.fetchJokes()
}
@IBAction func didPressBtn() {
// MARK: Actions for both fetching a joke from the API, & Text-Speech using AI Voice
service.fetchJokes()
joke = [JokesModel]()
jokeLabel.text = JokesModel().joke
// Value of type 'JokesModel' has no member 'joke'
// Missing argument for parameter 'from' in call
CodePudding user response:
You are getting the error because you need an instance of the class to call your function on.
To get your code working you can do something like this where your viewController takes a service the JokesWebService
like so, the better option would be to have the service on a viewModel if you already have one but if not this should do the trick to get you started:
import UIKit
class HomeViewController: UIViewController {
@IBOutlet var tellAeAJokeButton: UIButton!
private let service: JokesWebService!
init(service: JokesWebService) {
self.service = service
}
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func didPressBtn() {
service.fetchJokesAPI()
}
}
Usage:
let viewController = HomeViewController(service: JokesWebService())
CodePudding user response:
You are getting this error due to not having an instance of JokesWebService
on which to call fetchJokesAPI()
on. Seeing as you're using Storyboards for your UI, I'd recommend placing the initializer for your service in the viewDidLoad()
call like so:
class HomeViewController: UIViewController {
@IBOutlet var tellAeAJokeButton: UIButton!
private var jokesService: JokesWebService!
override func viewDidLoad() {
super.viewDidLoad()
jokesService = JokesWebService()
}
@IBAction func didPressBtn() {
jokesService.fetchJokesAPI()
}
}