Use of Unresolved Identifier 'self' in swift [closed] - ios

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 4 years ago.
Improve this question
Here is the code:
import UIKit
import SafariServices
import AVFoundation
import AWSAuthCore
class ViewController: UIViewController, SPTAudioStreamingPlaybackDelegate, SPTAudioStreamingDelegate {
// Variables
var auth = SPTAuth.defaultInstance()!
var session:SPTSession!
// Initialzed in either updateAfterFirstLogin: (if first time login) or in viewDidLoad (when there is a check for a session object in User Defaults
var player: SPTAudioStreamingController?
var loginUrl: URL?
// Outlets
#IBOutlet weak var loginSpotify: UIButton!
#IBOutlet weak var testLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
self.setup()
}
func setup () {
// insert redirect your url and client ID below
let redirectURL = "splitter-app://callback" // put your redirect URL here
let clientID = "client id goes here" // put your client ID here
auth.redirectURL = URL(string: redirectURL)
auth.clientID = "client id goes here"
auth.requestedScopes = [SPTAuthStreamingScope, SPTAuthPlaylistReadPrivateScope, SPTAuthPlaylistModifyPublicScope, SPTAuthPlaylistModifyPrivateScope]
loginUrl = auth.spotifyWebAuthenticationURL()
print("test")
}
func initializePlayer(authSession:SPTSession){
if self.player == nil {
self.player = SPTAudioStreamingController.sharedInstance()
self.player!.playbackDelegate = self
self.player!.delegate = self
try! player!.start(withClientId: auth.clientID)
self.player!.login(withAccessToken: authSession.accessToken)
}
func updateAfterFirstLogin () {
loginSpotify.isHidden = true
let userDefaults = UserDefaults.standard
if let sessionObj:AnyObject = userDefaults.object(forKey: "SpotifySession") as AnyObject? {
let sessionDataObj = sessionObj as! Data
let firstTimeSession = NSKeyedUnarchiver.unarchiveObject(with: sessionDataObj) as! SPTSession
self.session = firstTimeSession
initializePlayer(authSession: session)
}
}
func initializaPlayer(authSession:SPTSession){
if self.player == nil {
self.player = SPTAudioStreamingController.sharedInstance()
self.player!.playbackDelegate = self
self.player!.delegate = self
try! player?.start(withClientId: auth.clientID)
self.player!.login(withAccessToken: authSession.accessToken)
}
}
}
}
func audioStreamingDidLogin(_ audioStreaming: SPTAudioStreamingController!) {
// after a user authenticates a session, the SPTAudioStreamingController is then initialized and this method called
print("logged in")
self.player?.playSpotifyURI("spotify:track:58s6EuEYJdlb0kO7awm3Vp", startingWith: 0, startingWithPosition: 0, callback: { (error) in
if (error != nil) {
print("playing!")
}
})
}
The error is on line 91. Xcode says:
"Use of unresolved identifier 'self'"
however I have used that same variable in multiple different places in the code and it is declared at the top of the class. Why is it giving me an error on this specific line? I have tried making it a lazy variable as other people online have suggested, however Xcode tells me lazy variables need to be initialized and I am not sure how to do that.

The formatting of the code makes it challenging to see what's going on, but it looks like the function audioStreamingDidLogin(:SPTAudioStreamingController!) is not a class function. Maybe global, because it's declared outside the class where self is available.
You may be able to:
move it into the class
pass some instance of ViewController into the method as a parameter
Moving it into the class makes most sense to me.
Edit: Fix code
class ViewController: UIViewController, SPTAudioStreamingPlaybackDelegate, SPTAudioStreamingDelegate {
// Variables
var auth = SPTAuth.defaultInstance()!
var session:SPTSession!
// Initialzed in either updateAfterFirstLogin: (if first time login) or in viewDidLoad (when there is a check for a session object in User Defaults
var player: SPTAudioStreamingController?
var loginUrl: URL?
// Outlets
#IBOutlet weak var loginSpotify: UIButton!
#IBOutlet weak var testLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
self.setup()
}
func setup () {
// insert redirect your url and client ID below
let redirectURL = "splitter-app://callback" // put your redirect URL here
let clientID = "client id goes here" // put your client ID here
auth.redirectURL = URL(string: redirectURL)
auth.clientID = "client id goes here"
auth.requestedScopes = [SPTAuthStreamingScope, SPTAuthPlaylistReadPrivateScope, SPTAuthPlaylistModifyPublicScope, SPTAuthPlaylistModifyPrivateScope]
loginUrl = auth.spotifyWebAuthenticationURL()
print("test")
}
func initializePlayer(authSession:SPTSession){
if self.player == nil {
self.player = SPTAudioStreamingController.sharedInstance()
self.player!.playbackDelegate = self
self.player!.delegate = self
try! player!.start(withClientId: auth.clientID)
self.player!.login(withAccessToken: authSession.accessToken)
}
}
func updateAfterFirstLogin () {
loginSpotify.isHidden = true
let userDefaults = UserDefaults.standard
if let sessionObj:AnyObject = userDefaults.object(forKey: "SpotifySession") as AnyObject? {
let sessionDataObj = sessionObj as! Data
let firstTimeSession = NSKeyedUnarchiver.unarchiveObject(with: sessionDataObj) as! SPTSession
self.session = firstTimeSession
initializePlayer(authSession: session)
}
}
func initializaPlayer(authSession:SPTSession){
if self.player == nil {
self.player = SPTAudioStreamingController.sharedInstance()
self.player!.playbackDelegate = self
self.player!.delegate = self
try! player?.start(withClientId: auth.clientID)
self.player!.login(withAccessToken: authSession.accessToken)
}
}
func audioStreamingDidLogin(_ audioStreaming: SPTAudioStreamingController!) {
// after a user authenticates a session, the SPTAudioStreamingController is then initialized and this method called
print("logged in")
self.player?.playSpotifyURI("spotify:track:58s6EuEYJdlb0kO7awm3Vp", startingWith: 0, startingWithPosition: 0, callback: { (error) in
if (error != nil) {
print("playing!")
}
})
}
}

Related

Swift : Delegate is nil

I've tried to build a delegate design pattern. I have a simple delegate in WeatherManager , but it's always nil.
I've tried to add weatherManager.delegate = self in override func viewDidLoad() of WeatherViewController.
However, I have another Protocol and delegate, which works fine.
I'm using the API to obtain geographic coordinates from city names, and the URL of the API to get information about the weather is created and executed.
WeatherManager
import Foundation
// delegate design parttern
protocol WeatherManagerDelegate:AnyObject {
func didUpdateWeather(inputWeatherModel: WeatherModel)
}
class WeatherManager {
// delegate
weak var delegate: WeatherManagerDelegate?
// fetchCoordinate
func fetchWeather(urlString: String) {
performRequest(inputURLString: urlString)
}
// performRequest
func performRequest(inputURLString: String) {
// 1. Create URL
if let url = URL(string: inputURLString) {
// 2. Create URLSession
let session = URLSession(configuration: .default)
// 3. Give the URLSession a task
let task = session.dataTask(with: url) { (data, response, error) in
if error != nil {
print(error!)
return
}
if let safeData = data {
if let weather = self.parseJSON(JSONobject: safeData) {
// ---------------- problem here -------------------
self.delegate?.didUpdateWeather(inputWeatherModel: weather)
}
}
}
// 4. Start the task
task.resume()
}
}
// parse JSON object
func parseJSON(JSONobject: Data) -> WeatherModel? {
let decoder = JSONDecoder()
do {
let decodedData = try decoder.decode(WeatherData.self, from: JSONobject)
let id = decodedData.weather[0].id
let temp = decodedData.main.temp
let name = decodedData.name
let weather = WeatherModel(conditionId: id, cityName: name, temperature: temp)
return weather
} catch {
print(error)
return nil
}
}
}
WeatherModel
import Foundation
struct WeatherModel {
let conditionId: Int
let cityName: String
let temperature: Double
var temperatureString: String {
return String(format: "%.1f", temperature)
}
var conditionName: String {
switch conditionId {
case 200...232:
return "cloud.bolt"
case 300...321:
return "cloud.drizzle"
case 500...531:
return "cloud.rain"
case 600...622:
return "cloud.snow"
case 701...781:
return "cloud.fog"
case 800:
return "sun.max"
case 801...804:
return "cloud.bolt"
default:
return "cloud"
}
}
}
WeatherViewController
import UIKit
class WeatherViewController: UIViewController, UITextFieldDelegate, WeatherManagerDelegate {
#IBOutlet weak var conditionImageView: UIImageView!
#IBOutlet weak var temperatureLabel: UILabel!
#IBOutlet weak var searchTextField: UITextField!
#IBOutlet weak var cityLabel: UILabel!
let weatherManager = WeatherManager()
var coordinateManager = CoordinateManager()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
searchTextField.delegate = self
searchTextField.keyboardType = .asciiCapable
weatherManager.delegate = self
}
#IBAction func searchPressed(_ sender: UIButton) {
searchTextField.endEditing(true)
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
searchTextField.endEditing(true)
return true
}
func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
if textField.text != "" {
return true
} else {
textField.placeholder = "Type Something"
return false
}
}
func textFieldDidEndEditing(_ textField: UITextField) {
if let city = searchTextField.text {
coordinateManager.fetchCoordinate(cityName: city)
}
searchTextField.text = ""
}
func didUpdateWeather(inputWeatherModel: WeatherModel) {
print(inputWeatherModel.temperature)
}
}
CoordinateManager
import Foundation
struct CoordinateManager {
// WeatherManager
let weathetManager = WeatherManager()
// geographical coordinates(lat, lon) 地理座標
let coordinateURL = "https://api.openweathermap.org/geo/1.0/direct?limit=1&appid=c8e60c6317c653a1789294c00f54ae19"
// fetchCoordinate
func fetchCoordinate(cityName: String) {
let urlString = "\(coordinateURL)&q=\(cityName)"
performRequest(inputURLString: urlString)
}
// transformURLString
func transformURLString(_ string: String) -> URLComponents? {
guard let urlPath = string.components(separatedBy: "?").first else {
return nil
}
var components = URLComponents(string: urlPath)
if let queryString = string.components(separatedBy: "?").last {
components?.queryItems = []
let queryItems = queryString.components(separatedBy: "&")
for queryItem in queryItems {
guard let itemName = queryItem.components(separatedBy: "=").first,
let itemValue = queryItem.components(separatedBy: "=").last else {
continue
}
components?.queryItems?.append(URLQueryItem(name: itemName, value: itemValue))
}
}
return components!
}
// performRequest
func performRequest(inputURLString: String) {
// 1. Create URL
let components = transformURLString(inputURLString)
if let url = components?.url {
// 2. Create URLSession
let session = URLSession(configuration: .default)
// 3. Give the URLSession a task
let task = session.dataTask(with: url) {(data, response, error) in
if error != nil {
print(error!)
return
}
if let safeData = data {
self.parseJSON(JSONobject: safeData)
}
}
// 4. Start the task
task.resume()
}
}
// parseJSON
func parseJSON(JSONobject: Data) {
let decoder = JSONDecoder()
do {
let decodedData = try decoder.decode([CoordinateData].self, from: JSONobject)
let name = decodedData[0].name
let lat = decodedData[0].lat
let lon = decodedData[0].lon
let coordinateModel = CoordinateModel(name: name, lat: lat, lon: lon)
let weatherURL = coordinateModel.urlString
// ------- WeatherManager fetchWeather ---------
weathetManager.fetchWeather(urlString: weatherURL)
} catch {
print(error)
}
}
}
CoordinateModel
import Foundation
struct CoordinateModel {
let name: String
let lat: Double
let lon: Double
// wheather 地理座標を元に検索した天気の情報
let weatherstr = "https://api.openweathermap.org/data/2.5/weather?"
let str = "units=metric&appid=c8e60c6317c653a1789294c00f54ae19#"
// computedproperty
var urlString: String {
return "\(weatherstr)&lat=\(lat)&lon=\(lon)&\(str)"
}
}
You create a weatherManager in the WeatherViewController , and in the viewDidLoad method you set the WeatherViewController as a delegate to the weatherManager instance you created here. In the CoordinateManager class, you create a new weatherManager, and don't set a delegate for it.
2 solutions, use what is most convenient for you:
Create an initializer for the CoordinateManager, to pass it the WeatherManager that you have created and that you are listening to
// CoordinateManager class
let weatherManager: WeatherManager
init(weatherManager: WeatherManager) {
self.weatherManager = weatherManager
}
// WeatherViewController class
let weatherManager = WeatherManager()
var coordinateManager = CoordinateManager(weatherManager: weatherManager)
You can directly set WeatherViewController as a delegate to the desired weatherManager instance.
// WeatherViewController class
override func viewDidLoad() {
super.viewDidLoad()
searchTextField.delegate = self
searchTextField.keyboardType = .asciiCapable
// Instead weatherManager.delegate = self
coordinateManager.weatherManager.delegate = self
}

I get this error when i run my app. Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value

Whenever I run my app, it always crashes anywhere it states currentUserID. Not sure why.
I printed the the currentUserID value and its nil.
How can I correct it so it runs my app well. I can share the rest of the code if needed.
import UIKit
import MapKit
import CoreLocation
import Firebase
//import FirebaseDatabase
enum AnnotationType {
case pickup
case destination
case driver
}
enum ButtonAction {
case requestRide
case getDirectionsToPassenger
case getDirectionToDestination
case startTrip
case endTrip
}
class HomeVC: UIViewController, Alertable {
#IBOutlet weak var mapView: MKMapView!
#IBOutlet weak var centerMapBtn: UIButton!
#IBOutlet weak var destinationTextField: UITextField!
#IBOutlet weak var destinationCircle: UIView!
#IBOutlet weak var cancelBtn: UIButton!
#IBOutlet weak var actionBtn: UIButton!
var delegate: CenterVCDelegate?
var manager: CLLocationManager?
let currentUserId = Auth.auth().currentUser?.uid
// "IRD70YtgEyWRpaH8LkkjHZmjXPo1"
var ref: DatabaseReference!
var regionRadius: CLLocationDistance = 1000
var tableView = UITableView()
var matchingItems: [MKMapItem] = [MKMapItem]()
var route: MKRoute!
var selectedItemPlacemark: MKPlacemark? = nil
var actionForButton: ButtonAction = .requestRide
override func viewDidLoad() {
super.viewDidLoad()
ref = Database.database().reference()
// print(ref.child("users").value(forKey: "users"))
self.ref.child("userse").childByAutoId().setValue("wise")
self.ref.child("users").child("sdsd").setValue("data")
// print(Auth.auth().currentUser?.uid)
// print(currentUserId)
manager = CLLocationManager()
manager?.delegate = self
manager?.desiredAccuracy = kCLLocationAccuracyBest
checkLocationAuthStatus()
mapView.delegate = self
destinationTextField.delegate = self
centerMapOnUserLocation()
DataService.instance.REF_DRIVERS.observe(.value, with: { (snapshot) in
self.loadDriverAnnotationFromFB()
DataService.instance.passengerIsOnTrip(passengerKey: self.currentUserId!, handler: { (isOnTrip, driverKey, tripKey) in
if isOnTrip == true {
self.zoom(toFitAnnotationsFromMapView: self.mapView, forActiveTripWithDriver: true, withKey: driverKey)
}
})
})
cancelBtn.alpha = 0.0
UpdateService.instance.observeTrips { (tripDict) in
if let tripDict = tripDict {
let pickupCoordinateArray = tripDict["pickupCoordinate"] as! NSArray
let tripKey = tripDict["passengerKey"] as! String
let acceptanceStatus = tripDict["tripIsAccepted"] as! Bool
if acceptanceStatus == false {
//Broadcast to all driver
DataService.instance.driverIsAvailable(key: self.currentUserId!, handler: { (available) in
//check for errors
if let available = available {
if available == true {
let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
let pickupVC = storyboard.instantiateViewController(withIdentifier: "PickupVC") as? PickupVC
pickupVC?.initData(coordinate: CLLocationCoordinate2D(latitude: pickupCoordinateArray[0] as! CLLocationDegrees, longitude: pickupCoordinateArray[1] as! CLLocationDegrees), passengerKey: tripKey)
self.present(pickupVC!, animated: true, completion: nil)
}
}
})
}
}
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if self.currentUserId == nil {
print("login")
}
DataService.instance.userIsDriver(userKey: self.currentUserId!, handler: { (status) in
if status == true {
self.buttonsForDriver(areHidden: true)
}
})
DataService.instance.REF_TRIPS.observe(.childRemoved, with: { (removedTripSnapshot) in
let removedTripDict = removedTripSnapshot.value as? [String: AnyObject]
if removedTripDict?["driverKey"] != nil {
DataService.instance.REF_DRIVERS.child(removedTripDict?["driverKey"] as! String).updateChildValues(["driverIsOnTrip": false])
}
DataService.instance.userIsDriver(userKey: self.currentUserId!, handler: { (isDriver) in
if isDriver == true {
// Remove Overlays and annotation and hide request ride and cancel button
self.removeOverlaysAndAnnotations(forDrivers: false, forPassengers: true)
} else {
self.cancelBtn.fadeTo(alphaValue: 0.0, withDuration: 0.2)
self.destinationTextField.isUserInteractionEnabled = true
self.destinationTextField.text = ""
// Remove all map annotation and overlays
self.removeOverlaysAndAnnotations(forDrivers: false, forPassengers: true)
self.centerMapOnUserLocation()
}
})
})
DataService.instance.driverIsOnTrip(driverkey: self.currentUserId!, handler: { (isOnTrip, driverKey, tripKey) in
if isOnTrip == true {
DataService.instance.REF_TRIPS.observeSingleEvent(of: .value, with: { (tripSnapshot) in
if let tripSnapshot = tripSnapshot.children.allObjects as? [DataSnapshot] {
for trip in tripSnapshot {
if trip.childSnapshot(forPath: "driverKey").value as? String == self.currentUserId! {
let pickupCoordinateArray = trip.childSnapshot(forPath: "pickupCoordinate").value as! NSArray
let pickupCoordinate = CLLocationCoordinate2D(latitude: pickupCoordinateArray[0] as! CLLocationDegrees, longitude: pickupCoordinateArray[1] as! CLLocationDegrees)
let pickupPlacemark = MKPlacemark(coordinate: pickupCoordinate)
self.dropPinFor(placemark: pickupPlacemark)
self.searchMapKitForResultsWithPolyline(forOriginMapItem: nil, withDestinationMapItem: MKMapItem(placemark: pickupPlacemark))
self.setCustomRegion(forAnnotationType: .pickup, withCoordinate: pickupCoordinate)
self.actionForButton = .getDirectionsToPassenger
self.actionBtn.setTitle("GET DIRECTION", for: .normal)
// Fade in the action button
self.buttonsForDriver(areHidden: false)
}
}
}
})
There are a few issues that should be addressed and then a core issue.
The first thing is that Auth.auth().currentUser? is an optional - meaning that it could have a value or could be nil. Doing this..
let currentUserId = Auth.auth().currentUser?.uid
is telling your code that no matter if its got a value or nil, attempt to assign the .uid to currentUserId.
Protect your code by safely unwrapping options
guard let currentUser = Auth.auth().currentUser else {return}
//now you can access currentUser as it won't be nil
or
if let currentUser = Auth.auth().currentUser {
print("user is authenticated and currentUser is not nil")
} else {
print("not authenticated")
}
Now the core of the issue is, as far as I can see, you're not authenticating the user at all and that needs to happen prior to accessing Auth.auth().currentUser
Here's a complete authentication function with error handling
func authUser(user: String, pw: String) {
Auth.auth().signIn(withEmail: user, password: pw, completion: { (auth, error) in
if let x = error {
let err = x as NSError
switch err.code {
case AuthErrorCode.wrongPassword.rawValue:
print("wrong password")
case AuthErrorCode.invalidEmail.rawValue:
print("invalued email")
default:
print("unknown error")
}
} else {
if let user = auth?.user { //note; safely unwrap optional
print("uid: \(user.uid)")
}
}
})
}

Userdefaults to save switch state

I Have a switch that when turned to "on" will put the music and when the switch is set to "off" the music will resume playing. My problem is that when i leave the view controller the switch will appear as "off" when it is switch "on". The code for my switch is below, I'm not sure what to write in order for the app to remember the switch state, please help.
//
// SecondViewController.swift
// Urban Sphere
//
// Created by Oren Edrich on 9/11/16.
// Copyright © 2016 Oren Edrich. All rights reserved.
//
import Foundation
import UIKit
import SpriteKit
import AVFoundation
var bombSoundEffect: AVAudioPlayer!
var Ghost = SKSpriteNode()
class SecondViewController: UIViewController {
var sw = false
#IBOutlet var mySwitch: UISwitch!
#IBAction func switchpressed(_ sender: AnyObject) {
if mySwitch.isOn{
if bombSoundEffect != nil {
bombSoundEffect.stop()
bombSoundEffect = nil
}
}
else{
let path = Bundle.main.path(forResource: "newmusic.wav", ofType:nil)!
let url = URL(fileURLWithPath: path)
do {
let sound = try AVAudioPlayer(contentsOf: url)
bombSoundEffect = sound
sound.numberOfLoops = -1
sound.play()
} catch {
// couldn't load file :(
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Release any cached data, images, etc that aren't in use.
}
}
I found the correct answer and decided to post it incase anyone has the same question.
#IBAction func saveSwitchState(sender: AnyObject) {
var defaults = NSUserDefaults.standardUserDefaults()
if bluetoothSwitch.on {
defaults.setBool(true, forKey: "SwitchState")
} else {
defaults.setBool(false, forKey: "SwitchState")
}
}
and...
override func viewDidLoad() {
super.viewDidLoad()
var defaults = NSUserDefaults.standardUserDefaults()
if (defaults.objectForKey("SwitchState") != nil) {
bluetoothSwitch.on = defaults.boolForKey("SwitchState")
}
}
You want know where to insert the code , I guess.
updata
updata2
Then you can run directly. If it's useful , please UP this answer.
import Foundation
import UIKit
import SpriteKit
import AVFoundation
class SecondViewController: UIViewController {
static let bombSoundEffect = {()->(AVAudioPlayer) in
let path = Bundle.main.path(forResource: "newmusic.wav", ofType:nil)!
let url = URL(fileURLWithPath: path)
return try! AVAudioPlayer(contentsOf: url)
}()
var sw = false
var Ghost = SKSpriteNode()
#IBOutlet var mySwitch: UISwitch!
#IBAction func switchpressed() {
if mySwitch.isOn{
SecondViewController.bombSoundEffect.play()
}else{
SecondViewController.bombSoundEffect.stop()
}
//************* save status *************
UserDefaults.standard.set(mySwitch.isOn, forKey: "SwitchStatus");
}
override func viewDidLoad() {
super.viewDidLoad()
mySwitch.addTarget(self, action: #selector(switchpressed), for: .valueChanged)
//************* load status *************
mySwitch.isOn = UserDefaults.standard.bool(forKey: "SwitchStatus");
switchpressed()
}
}
I have a similar situation to yours, and I just use UserDefaults. Here's a step-by-step guide on how to do it.
Create a variable like the following example. This will set the default setting and store the state of the check box for use later:
var musicSetting = UserDefaults().string(forKey: "Music") ?? "On"
In your viewDidLoad, add an if statement that will check whether the Check Box should be On or Off, like this:
if musicSetting == "On" {
theNameOfYourSwitch.isOn = false
} else {
theNameOfYourSwitch.isOn = true
}
In the IBAction property for your check box, add an if statement like the following that will save your Setting, depending on what it is:
if theNameOfYourCheckbox.state == NSOnState {
UserDefaults().set("On", forKey: "Music")
} else {
UserDefaults().set("Off", forKey: "Music")
}
Here's a screenshot that might help:
If you want to save the state of Switch in user default, then can use the
native method
UserDefaults.standard.set(_ value: Bool, forKey defaultName: String)
Like this
UserDefaults.standard.set(mySwitch.isOn, forKey: "SwitchStatus");
UserDefaults.standard.synchronize();
While fetching switch status just use
let status = UserDefaults.standard.bool(forKey: "SwitchStatus");
UPDATE :
#IBAction func switchpressed(_ sender: AnyObject) {
UserDefaults.standard.set(mySwitch.isOn, forKey: "SwitchStatus");
if mySwitch.isOn{
if bombSoundEffect != nil {
bombSoundEffect.stop()
bombSoundEffect = nil
}
}
else{
let path = Bundle.main.path(forResource: "newmusic.wav", ofType:nil)!
let url = URL(fileURLWithPath: path)
do {
let sound = try AVAudioPlayer(contentsOf: url)
bombSoundEffect = sound
sound.numberOfLoops = -1
sound.play()
} catch {
// couldn't load file :(
}
}
}
Hope it helps
Happy coding ...

How to store my first textfield to not ask for the second time in swift

I created a UITextField where, when the user writes a link and enters, my textfield disappears and my webView appears.
What I am trying to do is, when the user writes the first time their link, the textfield saves that link and when the user opens again the app, the web view opens directly from the last link that the user wrote in the textfield. Basically the stored link should run the second time.
Here is all my code:
import UIKit
import Foundation
let urlKey = "User URL"
class ViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var textField: UITextField!
#IBOutlet weak var webView: UIWebView!
override func viewDidLoad() {
super.viewDidLoad()
self.webView.hidden = true
self.textField.addTarget(self, action: #selector(ViewController.textFieldDidUpdate(_:)), forControlEvents: UIControlEvents.EditingChanged)
if doesURLExist() {
self.textField.text = getURL()
}
}
// Text Field Delegate
func textFieldDidUpdate(textField: UITextField)
{
// Remove Spaces
textField.text = textField.text!.stringByReplacingOccurrencesOfString(" ", withString: "", options: [], range: nil)
// Validate URL
NSURL.validateUrl(textField.text, completion: { (success, urlString, error) -> Void in
dispatch_async(dispatch_get_main_queue(), { () -> Void in
if (success)
{
self.saveURL(urlString!)
self.webView.hidden = false
self.textField.hidden = true
let request = NSURLRequest(URL: NSURL(string: urlString!)!)
self.webView.loadRequest(request)
}
else
{
self.webView.stopLoading()
self.webView.hidden = true
}
})
})
}
#IBAction func dismissKeyboard(sender: AnyObject) {
self.resignFirstResponder()
self.view.endEditing(true)
}
func saveURL(urlString: String) {
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setObject(urlString, forKey: urlKey)
}
func getURL() -> String {
let defaults = NSUserDefaults.standardUserDefaults()
let urlString = defaults.objectForKey(urlKey) as! String
return urlString
}
func doesURLExist() -> Bool {
let defaults = NSUserDefaults.standardUserDefaults()
guard let _ = defaults.objectForKey(urlKey) where defaults.objectForKey(urlKey) is String else {
return false
}
return true
}
}
Here is my project in GitHub: https://github.com/anappleapp/NSURLvalidation
You'll want to check if the url exists first by calling doesURLExist, if it does, you opt out of presenting that textfield. If it does not exist, call saveURL. NSUserDefaults provides a simple means to store lightweight data.
let urlKey = "User URL"
func saveURL(urlString: String) {
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setObject(urlString, forKey: urlKey)
}
func getURL() -> String {
let defaults = NSUserDefaults.standardUserDefaults()
let urlString = defaults.objectForKey(urlKey) as! String
return urlString
}
func doesURLExist() -> Bool {
let defaults = NSUserDefaults.standardUserDefaults()
guard let _ = defaults.objectForKey(urlKey) where defaults.objectForKey(urlKey) is String else {
return false
}
return true
}
So your class should look something like:
import UIKit
import Foundation
let urlKey = "User URL"
class ViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var textField: UITextField!
#IBOutlet weak var webView: UIWebView!
override func viewDidLoad() {
super.viewDidLoad()
self.webView.hidden = true
self.textField.addTarget(self, action: #selector(ViewController.textFieldDidUpdate(_:)), forControlEvents: UIControlEvents.EditingChanged)
if(doesURLExist) {
self.textField.text = getURL()
}
// Demo UI Settings
}
}
// Text Field Delegate
func textFieldDidUpdate(textField: UITextField)
{
// Remove Spaces
textField.text = textField.text!.stringByReplacingOccurrencesOfString(" ", withString: "", options: [], range: nil)
// Validate URL
NSURL.validateUrl(textField.text, completion: { (success, urlString, error) -> Void in
dispatch_async(dispatch_get_main_queue(), { () -> Void in
if (success) {
self.saveURL(urlString)
self.webView.hidden = false
self.textField.hidden = true
let request = NSURLRequest(URL: NSURL(string: urlString!)!)
self.webView.loadRequest(request)
} else {
self.webView.stopLoading()
self.webView.hidden = true
}
})
})
}
Don't forget to add the original functions to your class.
You should save the entered string to user defaults. When your app opens you should check user defaults to see if there's already a saved string.
Swift 2 code to save your URL to user defaults:
NSUserDefaults.standardUserDefaults().setObject(urlString!, forKey: "EnteredURLString")
Swift 2 code to check whether there's a saved URL string:
if let urlString = NSUserDefaults.standardUserDefaults().stringForKey("EnteredURLString") {
}

.Type does not have a member named "x" when trying to get variable value in Struct(Swift)

I am currently working on an app and I am having an issue. When the user login the webservice, if the login is successful the server responds with JSON, where we use the "firstName" and "SecondName" to then create our "User" which is a struct defined in another file called User.swift . Then, what I want to do is user the "firstName" that has been given to the "User struct" as a UILabel in my homepageview that comes after a successful login. when I try to give my label User.prenom(which is firstName in french) I get the error: User.type does not have a member called...
Here is my code:
the client file where the Login Method is defined:
import Foundation
import Alamofire
import SwiftyJSON
private let _instance = Client()
class Client {
// Router is used to do a request to the server.
private enum Router: URLRequestConvertible {
private static let baseURL = "https://mobile.uqam.ca/portail_etudiant/"
// stores the authentication token.
static var code_perm: String?
static var nip:String?
// Login request.
case Login(String, String)
// URLRequestConvertible protocol.
var URLRequest: NSURLRequest {
// Returns the path, http method and parameters for the request.
var (path: String, method: Alamofire.Method, parameters: [String: AnyObject]) = {
switch self {
case .Login (let code_perm, let nip):
let params: [String: AnyObject] = [
"code_perm": code_perm,
"nip": nip,
]
return ("proxy_dossier_etud.php", .POST, params)
}
}()
// Setup the URLRequest.
let url = NSURL(string: Router.baseURL)
let urlRequest = NSMutableURLRequest(URL: url!.URLByAppendingPathComponent(path))
urlRequest.HTTPMethod = method.rawValue
if let code_perm = Router.code_perm {
if let nip = Router.nip{
parameters["nip"] = nip
parameters["code_perm"] = code_perm
}
}
let encoding = Alamofire.ParameterEncoding.URL
return encoding.encode(urlRequest, parameters: parameters).0
}
}
// Singleton
class var sharedInstance: Client {
return _instance
}
private init() {}
// Login logs in the user with his email and password.
func login(code_perm:String, nip:String, callback:(LoginResponse?) -> Void) {
Alamofire.request(Router.Login(code_perm, nip)).responseJSON { (_, _, data, error) in
if(error != nil) {
callback(nil)
return
}
var json = JSON(data!)
let prenom = json["socio"]["prenom"].stringValue
let nom = json["socio"]["nom"].stringValue
Router.code_perm = code_perm
Router.nip = nip
callback(LoginResponse(
user: User(prenom: prenom,nom: nom)
))
}
}
}
the loginViewController where the login function is called
import UIKit
class LoginViewController: UIViewController {
#IBOutlet weak var LoginScreenImage: UIImageView!
#IBOutlet weak var codeTextField: UITextField!
#IBOutlet weak var nipTextField: UITextField!
#IBOutlet weak var loadingLogin: UIActivityIndicatorView!
let client = Client.sharedInstance
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
LoginScreenImage.image = UIImage(named: "UQAMLOGO")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func connect() {
let code_perm = codeTextField.text
let nip = nipTextField.text
self.loadingLogin.startAnimating()
if code_perm != "" && nip != "" {
client.login(code_perm, nip: nip, callback: { (response) in
if let response = response {
self.loadingLogin.stopAnimating()
let homeViewController = self.storyboard!.instantiateViewControllerWithIdentifier("HomeViewController") as HomeViewController
self.showViewController(homeViewController, sender: self)
} else {
self.loadingLogin.stopAnimating()
let badLogin = UIAlertController(title: "Échec de connexion", message: "La combinaison du code permanent et du nip n'est pas bonne", preferredStyle: .Alert)
let reessayer = UIAlertAction(title: "Réessayer", style: .Default, handler: { (reessayer) -> Void in
self.dismissViewControllerAnimated(true , completion: nil)
})
badLogin.addAction(reessayer)
self.presentViewController(badLogin, animated: true, completion: nil)
}
})
}
}
}
the User.swift while where the user struct is
import Foundation
struct User {
var prenom :String
var nom: String
}
struct LoginResponse {
var user: User
}
and finally the HomePageViewController where I try to give the value to my label:
import UIKit
class HomeViewController: UIViewController {
#IBOutlet weak var schedule: UIImageView!
#IBOutlet weak var courses: UIImageView!
#IBOutlet weak var email: UIImageView!
#IBOutlet weak var grades: UIImageView!
#IBOutlet weak var bienvenueLabel: UILabel!
let client = Client.sharedInstance
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
schedule.image = UIImage(named:"schedule")
courses.image = UIImage(named: "courses")
email.image = UIImage(named:"mail")
grades.image = UIImage(named:"grades")
bienvenueLabel.text = User.prenom
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Thanks everyone for the help and have a great day/night
Charles
You are accessing the class instead of an instance. Instead, you should pass the response instance to your HomeViewController:
class HomeViewController : .. {
// ...
var loginResponse : LoginResponse
// ...
override func viewDidLoad() {
// ...
bienvenueLabel.text = loginResponse.user.prenom
}
}
// ...
client.login(code_perm, nip: nip, callback: { (response) in
if let loginResponse = response as LoginResponse {
self.loadingLogin.stopAnimating()
let homeViewController = self.storyboard!.instantiateViewControllerWithIdentifier("HomeViewController") as HomeViewController
homeViewController.loginResponse = loginResponse
// assign your instance ^^^^^^^^^^^^^^^^^^^^^^^^
self.showViewController(homeViewController, sender: self)
}
You are accessing the class instead of an instance. Instead, you should pass the response instance to your HomeViewController:
class HomeViewController : .. {
// ...
var loginResponse : LoginResponse
// ...
override func viewDidLoad() {
// ...
bienvenueLabel.text = loginResponse.user.prenom
}
}
// ...
client.login(code_perm, nip: nip, callback: { (response) in
if let loginResponse = response as LoginResponse {
self.loadingLogin.stopAnimating()
let homeViewController = self.storyboard!.instantiateViewControllerWithIdentifier("HomeViewController") as HomeViewController
homeViewController.loginResponse = loginResponse
// assign your instance ^^^^^^^^^^^^^^^^^^^^^^^^
self.showViewController(homeViewController, sender: self)
}
This really isn't very good structure, but it should at least answer your question.

Resources