Getting error: Argument passed to call that takes no arguments - swift

I'm getting this error in the AppDelegate, but I'm not sure what the problem might be. Any help is appreciated, thanks!
(the exact line that has the error is: "let detailsViewModel = DetailsJobView(details: details)" in the "private func loadDetails" section)
Btw, the error underlines the "d" in the second "details" in (details: details)
I've noted it in the code, but it might be hard to find.
import UIKit
import Firebase
import CoreLocation
import Moya
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
let window = UIWindow()
let locationService = LocationService()
let homeStoryboard = UIStoryboard(name: "Home", bundle: nil)
let service = MoyaProvider<YelpService.BusinessesProvider>()
let jsonDecoder = JSONDecoder()
var navigationController: UINavigationController?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
// Change color of tab bar items
UITabBar.appearance().tintColor = .black
FirebaseApp.configure()
jsonDecoder.keyDecodingStrategy = .convertFromSnakeCase
locationService.didChangeStatus = { [weak self] success in
if success {
self?.locationService.getLocation()
}
}
locationService.newLocation = { [weak self] result in
switch result {
case .success(let location):
self?.loadJobs(with: location.coordinate)
case .failure(let error):
assertionFailure("Error getting the users location \(error)")
}
}
switch locationService.status {
case .notDetermined, .denied, .restricted:
let locationViewController = homeStoryboard.instantiateViewController(withIdentifier: "LocationViewController") as? LocationViewController
locationViewController?.delegate = self
window.rootViewController = locationViewController
default:
let nav = homeStoryboard
.instantiateViewController(withIdentifier: "JobNavigationController") as? UINavigationController
self.navigationController = nav
window.rootViewController = nav
locationService.getLocation()
(nav?.topViewController as? JobTableViewController)?.delegete = self
}
window.makeKeyAndVisible()
return true
}
private func loadDetails(for viewController: UIViewController, withId id: String) {
service.request(.details(id: id)) { [weak self] (result) in
switch result {
case .success(let response):
guard let strongSelf = self else { return }
if let details = try? strongSelf.jsonDecoder.decode(Details.self, from: response.data) {
let detailsViewModel = DetailsJobView(details: details) //ERROR IS HERE
(viewController as? DetailsJobViewController)?.viewModel = detailsViewModel
}
case .failure(let error):
print("Failed to get details \(error)")
}
}
}
private func loadJobs(with coordinate: CLLocationCoordinate2D) {
service.request(.search(lat: coordinate.latitude, long: coordinate.longitude)) { [weak self] (result) in
guard let strongSelf = self else { return }
switch result {
case .success(let response):
let root = try? strongSelf.jsonDecoder.decode(Root.self, from: response.data)
let viewModels = root?.jobs
.compactMap(JobListViewModel.init)
.sorted(by: { $0.distance < $1.distance })
if let nav = strongSelf.window.rootViewController as? UINavigationController,
let jobListViewController = nav.topViewController as? JobTableViewController {
jobListViewController.viewModels = viewModels ?? []
} else if let nav = strongSelf.homeStoryboard
.instantiateViewController(withIdentifier: "JobNavigationController") as? UINavigationController {
strongSelf.navigationController = nav
strongSelf.window.rootViewController?.present(nav, animated: true) {
(nav.topViewController as? JobTableViewController)?.delegete = self
(nav.topViewController as? JobTableViewController)?.viewModels = viewModels ?? []
}
}
case .failure(let error):
print("Error: \(error)")
}
}
}
}
extension AppDelegate: LocationActions, ListActions {
func didTapAllow() {
locationService.requestLocationAuthorization()
}
func didTapCell(_ viewController: UIViewController, viewModel: JobListViewModel) {
loadDetails(for: viewController, withId: viewModel.id)
}
}
Here is the DetailsJobView as requested by #heitormurara:
import UIKit
import MapKit
#IBDesignable class DetailsJobView: CoreView {
#IBOutlet weak var collectionView: UICollectionView?
#IBOutlet weak var pageControl: UIPageControl?
#IBOutlet weak var priceLabel: UILabel?
#IBOutlet weak var hoursLabel: UILabel?
#IBOutlet weak var locationLabel: UILabel?
#IBOutlet weak var ratingsLabel: UILabel?
#IBOutlet weak var mapView: MKMapView?
#IBAction func handleControl(_ sender: UIPageControl) {
}
}

My guess is you are trying to instance a UIView child in an improper way. Try initialising it without arguments and having your details variable as a public variable:
let detailsViewModel = DetailsJobView()
detailsViewModel.details = details
Also, you need to create the variable details in your DetailsJobView:
import UIKit
import MapKit
#IBDesignable class DetailsJobView: CoreView {
...
var details: Details?

Related

How do I access the variables that google provides outside of the function?

i'm trying to access the emailAddress variable in a different view controller however its always not in scope.
i want to call something like
login.emailAddress
in a different vc.
heres my code for your refeerence, i understand that there are similar questions however i struggle to translate that into my code. .
import UIKit
import GoogleSignIn
let login = LoginController()
class LoginController: UIViewController {
#IBOutlet weak var signInButton: GIDSignInButton!
let signInConfig = GIDConfiguration(clientID: "12345-abcdef.apps.googleusercontent.com")
#IBAction func signIn(_ sender: Any) {
GIDSignIn.sharedInstance.signIn(with: signInConfig, presenting: self) { user, error in
guard error == nil else { return }
guard let user = user else { return }
var emailAddress = user.profile?.email
var fullName = user.profile?.name
var givenName = user.profile?.givenName
var familyName = user.profile?.familyName
var profilePicUrl = user.profile?.imageURL(withDimension: 320)
let userProfile = (fullName, givenName, emailAddress, profilePicUrl)
print("Sign in Sucessfull")
print(fullName!)
print(givenName!)
print(familyName!)
print(emailAddress!)
print(profilePicUrl!)
// If sign in succeeded, display the app's main content View.
let vc = self.storyboard?.instantiateViewController(withIdentifier: "NavigationViewController") as! UINavigationController
self.navigationController?.pushViewController(vc, animated: true)
self.present(vc, animated: true, completion: nil)
}
}
}
An option would be storing the value in a class property:
class LoginController: UIViewController {
#IBOutlet weak var signInButton: GIDSignInButton!
private var userMail: String?
let signInConfig = GIDConfiguration(clientID: "12345-abcdef.apps.googleusercontent.com")
#IBAction func signIn(_ sender: Any) {
GIDSignIn.sharedInstance.signIn(with: signInConfig, presenting: self) { user, error in
guard error == nil else { return }
guard let user = user else { return }
self.userMail = user.profile?.email
[...]
}
}
}

Presenting view controller from detached view controller is discouraged. Keeping User logged in issue

I'm trying to have the user move to automatically go to the Home Screen and not have to log in again. Basically, to remember the user. I used User Defaults to save the user login info and put the listener for the key in the viewDidLoad of the first login page. I used an if statement to switch the view controllers but it doesn't work and prints (Presenting view controller from detached view controller is discouraged).
LoginViewController:
import UIKit
import FirebaseAuth
import AVKit
class LoginViewController: UIViewController {
var videoPlayer:AVPlayer?
var videoPlayerLayer:AVPlayerLayer?
#IBOutlet weak var emailTextField: UITextField!
#IBOutlet weak var Back: UIButton!
#IBOutlet weak var passwordtextField: UITextField!
#IBOutlet weak var loginButton: UIButton!
#IBOutlet weak var errorLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
setupElements()
}
func dismissKeyboard() {
//Causes the view (or one of its embedded text fields) to resign the first responder status.
view.endEditing(true)
}
func setupElements(){
errorLabel.alpha = 0
Utilities.styleTextField(emailTextField)
Utilities.styleTextField(passwordtextField)
Utilities.styleFilledButton(loginButton)
}
func validateFields() -> String?
{
//make sure fields are filled
if emailTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) == "" || passwordtextField.text?.trimmingCharacters(in: .whitespacesAndNewlines) == ""
{
return "Please fill all fields"
}
return nil
}
#IBAction func loginTapped(_ sender: Any) {
//creates a clean version of the text field
let email = emailTextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
let password = passwordtextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
let error = validateFields()
//sign in user
Auth.auth().signIn(withEmail: email, password: password) { (result, error) in
UserDefaults.standard.set(Auth.auth().currentUser!.uid, forKey: "user_uid_key")
UserDefaults.standard.synchronize()
if error != nil{
self.errorLabel.text = "Invalid Username/Password try again."
self.errorLabel.alpha = 1
}
else{
let homeViewController = self.storyboard?.instantiateViewController(identifier: Constants.StoryBoard.homeViewController) as?
HomeViewController
self.view.window?.rootViewController = homeViewController
self.view.window?.makeKeyAndVisible()
}
}
//make sure all fields are filled
}
override func viewWillAppear(_ animated: Bool) {
setUpVideo()
}
func setUpVideo(){
//Get path to resource bundle
let bundlePath = Bundle.main.path(forResource: "IMG_7211 2", ofType: "mov")
guard bundlePath != nil else{
return
}
//create the url from it
let url = URL(fileURLWithPath: bundlePath!)
//Create The video Player item
let item = AVPlayerItem(url: url)
//create the player
videoPlayer = AVPlayer(playerItem: item)
//create the layer
videoPlayerLayer = AVPlayerLayer(player: videoPlayer!)
//adjust the size and frame
videoPlayerLayer?.frame = CGRect(x: -self.view.frame.size.width*1.5, y:0, width: self.view.frame.size.width*4, height: self.view.frame.size.height)
view.layer.insertSublayer(videoPlayerLayer!, at: 0)
//add and play
videoPlayer?.playImmediately(atRate: 0.8)
}
}
ViewController:
import UIKit
import AVKit
import Firebase
import FirebaseAuth
class ViewController: UIViewController {
var videoPlayer:AVPlayer?
var videoPlayerLayer:AVPlayerLayer?
#IBOutlet weak var signUpButton: UIButton!
#IBOutlet weak var logInButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
if UserDefaults.standard.object(forKey: "user_uid_key") != nil {
print("i see u")
let navController = UINavigationController(rootViewController: HomeViewController())
navController.navigationBar.barStyle = .black
self.present(navController, animated: false, completion: nil)
}
else {
let homeViewController = self.storyboard?.instantiateViewController(identifier: Constants.StoryBoard.homeViewController) as?
ViewController
self.view.window?.rootViewController = homeViewController
self.view.window?.makeKeyAndVisible()
}
// Do any additional setup after loading the view.
setupElements()
}
func showhomepage() {
let homeViewController = self.storyboard?.instantiateViewController(identifier: Constants.StoryBoard.homeViewController) as?
HomeViewController
self.view.window?.rootViewController = homeViewController
self.view.window?.makeKeyAndVisible()
}
override func viewWillAppear(_ animated: Bool) {
//Set up video in background
setUpVideo()
}
func setUpVideo(){
//Get path to resource bundle
let bundlePath = Bundle.main.path(forResource: "Project", ofType: "mp4")
guard bundlePath != nil else{
return
}
//create the url from it
let url = URL(fileURLWithPath: bundlePath!)
//Create The video Player item
let item = AVPlayerItem(url: url)
//create the player
videoPlayer = AVPlayer(playerItem: item)
//create the layer
videoPlayerLayer = AVPlayerLayer(player: videoPlayer!)
//adjust the size and frame
videoPlayerLayer?.frame = CGRect(x: -self.view.frame.size.width*1.5, y:0, width: self.view.frame.size.width*4, height: self.view.frame.size.height)
view.layer.insertSublayer(videoPlayerLayer!, at: 0)
//add and play
videoPlayer?.playImmediately(atRate: 1)
}
func setupElements(){
Utilities.styleFilledButton(signUpButton)
Utilities.styleHollowButton(logInButton)
}
}
Looks like you're using Firebase. Do not store any login information in the User defaults. What you should do is create a blank view controller that will check if the user is signed in. If the user is signed it, it will present your HomeViewController; if the user is not signed in, it will present the login screen. You can also choose to perform these checks in your AppDelegate/SceneDelegate if you want to avoid the extra view controller.
The empty ViewController should be the initial/root ViewController.
You cannot present view controllers from inside viewDidLoad, use viewDidAppear.
Here is a basic example for the view controller way:
// in the new empty view controller, import FirebaseAuth
var handle: AuthStateDidChangeListenerHandle!
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(false)
handle = Auth.auth().addStateDidChangeListener { auth, user in
if user != nil {
// Go to Home Screen/ switch root
} else {
// Go to sign in screen/ switch root
}
}
}

Swift 3D Touch BSMachError

I am trying to 'preview' a view controller through 3D touch. The code, as it is, does work, however the exiting preview animation is jittery and the following error pops up on the terminal.
2019-07-16 11:22:51.049757+0100 VisualisationsUIKit[439:29734] [Common] _BSMachError: port d90f; (os/kern) invalid capability (0x14) "Unable to insert COPY_SEND"
Some googling showed me that this error often goes away if you remove all breakpoints or change the 'Localization native development region' in info.plist but neither helped.
The code for the 'peak & pop' is below:
//PEAK & POP
extension ViewController: UIViewControllerPreviewingDelegate {
func previewingContext(_ previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {
guard let indexPath = tableView.indexPathForRow(at: location) else { return nil }
let selectedVis = filteredVisualisations[indexPath.row]
//guard let cell = tableView.cellForRow(at: indexPath) as? TableViewCell else { return nil}
let identifier = "GIFViewController"
guard let GIFVC = storyboard?.instantiateViewController(withIdentifier: identifier) as? GIFViewController else { return nil}
GIFVC.selection = selectedVis
GIFVC.preferredContentSize = CGSize(width: 0, height: 190)
return GIFVC
}
func previewingContext(_ previewingContext: UIViewControllerPreviewing, commit viewControllerToCommit: UIViewController) {
let selectedVis = (viewControllerToCommit as! GIFViewController).selection
let identifier = "DetailViewController"
//force unwrap?
let detailVC = storyboard!.instantiateViewController(withIdentifier: identifier) as! DetailViewController
detailVC.selectedVis = selectedVis
self.show(detailVC, sender: self)
}
}
//PREVIEW VIEW CONTROLLER
import UIKit
import SDWebImage
class GIFViewController: UIViewController {
#IBOutlet weak var GIFView: UIImageView!
var selection = visualisations[0]
override func viewDidLoad() {
super.viewDidLoad()
//GIFView.loadGif(name: selection.name + "_gif")
GIFView.sd_setImage(with: URL(string: selection.gifURL))
// Do any additional setup after loading the view.
}
override func viewDidDisappear(_ animated: Bool = true) {
SDImageCache.shared.clearMemory()
}
deinit {
print("DEALLOCATED GIFViewController class")
}
}

How to show Tab Bar Controller?

I've tried everything to get a tabbar controller onto MainViewController and nothing seems to work.
Just a quick rundown on how app works:
Storyboard entry is AppContainerViewController and if user is logged in then MainViewController appears as it should however I can't get MainVC to become a TabBar controller to display tab bar for user navigation to various pages.
What am I doing wrong?!
appcontainerviewcontroller
class AppContainerViewController: UIViewController {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
AppManager.shared.appContainer = self
AppManager.shared.showApp()
}
}
import UIKit
import Firebase
import FirebaseDatabase
import FBSDKLoginKit
class AppManager {
static let shared = AppManager()
let storyboard = UIStoryboard(name: "Main", bundle: nil)
var appContainer: AppContainerViewController!
private init() {}
func showApp() {
var viewController: UIViewController
if (Auth.auth().currentUser == nil) && (FBSDKAccessToken.current() == nil) {
viewController = storyboard.instantiateViewController(withIdentifier: "LoginViewController")
} else {
viewController = storyboard.instantiateViewController(withIdentifier: "MainViewController")
}
appContainer.present(viewController, animated: true, completion: nil)
}
func logout() {
let loginManager = FBSDKLoginManager()
loginManager.logOut()
try! Auth.auth().signOut()
appContainer.presentedViewController?.dismiss(animated: true, completion: nil)
}
}
main view controller
import UIKit
import Firebase
import FirebaseDatabase
import FBSDKShareKit
class MainViewController: UIViewController {
#IBOutlet weak var name: UILabel!
#IBOutlet weak var email: UILabel!
#IBAction func logoutPressed(_ sender: Any) {
AppManager.shared.logout()
}
#IBAction func fbSharePressed(_ sender: Any) {
let content = FBSDKShareLinkContent()
content.contentURL = URL(string: "https://advice.com")
content.quote = "Hey, I'm one step closer to getting into the college of my dreams with this app. Download it and let's go together!"
let dialog : FBSDKShareDialog = FBSDKShareDialog()
dialog.fromViewController = self
dialog.shareContent = content
dialog.mode = FBSDKShareDialogMode.automatic
dialog.show()
}
func userProfile() {
guard let uid = Auth.auth().currentUser?.uid else { return }
let ref = Database.database().reference()
ref.child("users").child(uid).observeSingleEvent(of: .value, with: { (snapshot) in
guard let dict = snapshot.value as? [String: Any] else { return }
let user = CurrentUserProfile(uid: uid, dictionary: dict)
self.name.text = user.name
self.email.text = user.email
}, withCancel: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
userProfile()
}
}
Egg on my face. My storyboard IDs were wrong and Embedding MainViewController into a TabBarController via the storyboard and then applying MainVC's storyboard ID to the TabBarController did the trick.

swift: Calling a function in another file

I would like to call functions residing in other files. In my given example I received no syntax errors, and the app runs. When I click the IBAction, the App crashes. I have no idea why. I am using Xcode 6.4 and coding for OS X
please advise.
// FileUtilties.swift
import Foundation
import Cocoa
class FileUtilities: NSObject, NSAlertDelegate {
var fileList : String!
func listFilesFromDocumentsFolder() -> [String]
{
var theError = NSErrorPointer()
let dirs = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.AllDomainsMask, true) as? [String]
if dirs != nil {
let dir = dirs![0]
let fileList = NSFileManager.defaultManager().contentsOfDirectoryAtPath(dir, error: theError)
return fileList as! [String] // edit: added ! for Swift 1.2 compatibitily
}
else{
let fileList : String!
}
return [fileList]
}
// Alert popup Window
func IdialogOKCancel(myQuestion: String, myText: String) -> Bool {
let myPopup: NSAlert = NSAlert()
myPopup.messageText = myQuestion
myPopup.informativeText = myText
myPopup.alertStyle = NSAlertStyle.WarningAlertStyle
myPopup.addButtonWithTitle("OK")
myPopup.addButtonWithTitle("Cancel")
let res = myPopup.runModal()
if res == NSAlertFirstButtonReturn {
return true
}
return false
}
}
// ViewController.swift
import Cocoa
class ViewController: NSViewController, NSTableViewDataSource, NSTableViewDelegate {
// setsup outlet to add data to ListViewer
#IBOutlet weak var ListViewer: NSScrollView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override var representedObject: AnyObject? {
didSet {
// Update the view, if already loaded.
}
}
#IBAction func AddButtonClicked(sender: AnyObject) {
var rtnText: String = "this is the text "
var rtn: Bool = false
let instance = FileUtilities()
rtn = instance.IdialogOKCancel("Ok?", myText: rtnText)
}
}