I'm trying to capture a user input (textfield + button) and reuse the result later in the program but I don't know how to do that.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var resultLabel: UILabel!
#IBOutlet weak var moneyTextField: UITextField!
#IBAction func convert(_ sender: Any) {
let convertion:Double = Double(moneyTextField.text!)!
print(convertion)
}
override func viewDidLoad() {
super.viewDidLoad()
let url = URL(string: "https://www.x-rates.com/calculator/?from=EUR&to=USD&amount=1")!
let request = NSMutableURLRequest(url : url)
let task = URLSession.shared.dataTask(with: request as URLRequest) {
data, response, error in
var rateValue:Double = 0.0;
if let error = error {
print(error)
} else {
if let unwrappedData = data {
let dataString = NSString(data: unwrappedData, encoding: String.Encoding.utf8.rawValue)
var stringSeperator = "<span class=\"ccOutputRslt\">"
if let contentArray = dataString?.components(separatedBy: stringSeperator){
if contentArray.count > 0 {
stringSeperator = "<span"
let newContentArray = contentArray[1].components(separatedBy: stringSeperator)
if newContentArray.count > 0 {
rateValue = Double(newContentArray[0])!
print(newContentArray[0])
}
}
}
}
}
//
print("Rate is \(rateValue)");
DispatchQueue.main.sync(execute: {
self.resultLabel.text = "the value of the dollar is " + String(rateValue)
}
)}
task.resume()
}
}
What I want to do is take the let convertion and multiply it by rateValue at the end of the code. I tried different thing but without any results.
after the advice from Joakim Danielson
I did that :
import UIKit
class ViewController: UIViewController {
var fxRate: Double?
#IBOutlet weak var resultLabel: UILabel!
#IBOutlet weak var moneyTextField: UITextField!
#IBAction func convert(_ sender: Any) {
let convertion:Double = Double(moneyTextField.text!)!
print(convertion)
var convertedAmount = 0.0
if let rate = fxRate, let money = Double(moneyTextField.text) {
convertedAmount = rate * money
}
print(convertedAmount)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let url = URL(string: "https://www.x-rates.com/calculator/?from=EUR&to=USD&amount=1")!
let request = NSMutableURLRequest(url : url)
let task = URLSession.shared.dataTask(with: request as URLRequest) {
data, response, error in
var rateValue:Double = 0.0;
if let error = error {
print(error)
} else {
if let unwrappedData = data {
let dataString = NSString(data: unwrappedData, encoding: String.Encoding.utf8.rawValue)
var stringSeperator = "<span class=\"ccOutputRslt\">"
if let contentArray = dataString?.components(separatedBy: stringSeperator){
if contentArray.count > 0 {
stringSeperator = "<span"
let newContentArray = contentArray[1].components(separatedBy: stringSeperator)
if newContentArray.count > 0 {
rateValue = Double(newContentArray[0])!
print(newContentArray[0])
rateValue = Double(newContentArray[0])!
self.fxRate = rateValue
}
}
}
}
}
//
print("Rate is \(rateValue)");
DispatchQueue.main.sync(execute: {
self.resultLabel.text = "the value of the dollar is " + String(rateValue)
}
)}
task.resume()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
but I have the error : Cannot invoke initializer for type 'Double' with an argument list of type '(String?)' on line 26. Can you please help me? thx!
create a variable outside of your function
var anyVariableYouWantToAccessLater: Double?
And use this variable anywhere you want.
Since you're downloading the rate during viewDidLoad I am assuming this is what you want to keep.
Add a new property to the class
class ViewController: UIViewController {
var fxRate: Double?
...
In viewDidLoad update this property with the downloaded value
rateValue = Double(newContentArray[0])!
fxRate = rateValue
In the convert func (or wherever you want to use the rate)
#IBAction func convert(_ sender: Any) {
var convertedAmount = 0.0
if let rate = fxRate, let money = Double(moneyTextField.text ?? "0") {
convertedAmount = rate * money
}
print(convertedAmount)
}
Related
I have a file which is parsing the JSON data and another file which calls the function and tries to retrieve the data. However, it seems that it can't update into the variable I want it too. I used this format (using tables) in another project when parsing data and it used tableView.reloadData(). Is there something like this but not for tables?
Here is the code for the file that calls the function to parse the JSON and tries to set it as member. However when I print(member.first_name), it just appears as hi
class ProfileVC: UIViewController {
#IBOutlet weak var NameText: UILabel!
#IBOutlet weak var IDText: UILabel!
#IBOutlet weak var GenderText: UILabel!
var MemberManager = GetMember()
var member: MemberModel = MemberModel(id: " ", first_name: "hi ", last_name: " ", gender: " ")
override func viewDidLoad() {
super.viewDidLoad()
MemberManager.delegate = self
MemberManager.fetchMember()
print(member.first_name)
NameText.text = "member?.first_name"
}
}
//MARK: - GetMemberDelegate
extension ProfileVC: GetMemberDelegate {
func didUpdateStatus(_ getMember: GetMember, member: MemberModel) {
DispatchQueue.main.async {
self.member = member
}
}
func didFailWithError(_ error: Error) {
print("ei")
print(error)
}
}
Here is the code I used to parse the JSON.
import Foundation
protocol GetMemberDelegate {
func didUpdateStatus(_ getMember: GetMember, member: MemberModel)
func didFailWithError(_ error: Error)
}
struct GetMember {
// GET https://api.propublica.org/congress/v1/members/{member-id}.json
let getMemberString = "https://api.propublica.org/congress/v1/members/M001157.json"
var delegate: GetMemberDelegate?
var urlUpcomingFinalString: String?
// Forms URL
func fetchMember() {
let urlMember = NSURL(string: getMemberString)!
let request = NSMutableURLRequest(url: urlMember as URL)
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue(Constant.APIKEY, forHTTPHeaderField: "X-API-Key")
performRequest(request)
}
// Performs request
func performRequest (_ urlRequest: NSURLRequest) {
let session = URLSession.shared.dataTask(with: urlRequest as URLRequest) {data, response, error in
if error != nil {
self.delegate?.didFailWithError(error!)
print("No")
return
}
if let safeData = data {
if let mem = self.parseJSONMember(safeData) {
self.delegate?.didUpdateStatus(self, member: mem)
}
}
}
session.resume()
}
// Parsing JSON
func parseJSONMember(_ memberData: Data) -> MemberModel?{
// var member: [MemberModel] = []
let decoder = JSONDecoder()
do {
let decodedDataGetMember = try decoder.decode(MemberJSONFormat.self, from: memberData)
let id = decodedDataGetMember.results[0].id
let first_name = decodedDataGetMember.results[0].first_name
// let middle_name = decodedDataGetMember.results[0].middle_name
let last_name = decodedDataGetMember.results[0].last_name
let gender = decodedDataGetMember.results[0].gender
print(first_name)
let memberItem = MemberModel(id: id, first_name: first_name, last_name: last_name, gender: gender)
return memberItem
} catch {
self.delegate?.didFailWithError(error)
print("error")
return nil
}
}
}
In my ThirdScreenViewController I change the variable number with the IBAction pressed.
import Foundation
import UIKit
class ThirdScreenViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
var weatherManager = WeatherManager()
var team = "leer"
static var number = 1
#IBAction func bayernMunchen(_ sender: UIButton) {
team = "bayernMunchen"
}
#IBAction func borussiaDortmund(_ sender: UIButton) {
team = "borussiaDortmund"
}
#IBAction func schalke(_ sender: UIButton) {
team = "schalke"
}
#IBAction func pressed(_ sender: UIButton) {
switch team {
case "bayernMunchen":
ThirdScreenViewController.number = 46
case "borussiaDortmund":
ThirdScreenViewController.number = 41
case "schalke":
ThirdScreenViewController.number = 45
default: print(8)
}
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let nextViewController = storyBoard.instantiateViewController(withIdentifier: "WeatherViewController") as! WeatherViewController
self.present(nextViewController, animated:true, completion:nil)
}
}
In an other swift (not a View Controller) file I have a function which takes number and does something with it.
import Foundation
import UIKit
var TeamOne = ""
var TeamTwo = ""
var ScoreOne = ""
var ScoreTwo = ""
var TeamThree = ""
var TeamFour = ""
var ScoreThree = ""
var ScoreFour = ""
var cityName = ThirdScreenViewController.number
struct WeatherManager {
let weatherURL = "https://livescore-api.com/api-client/teams/matches.json?number=10&team_id=19&key=d33FTnnd6qwvEmjz&secret=BbO3REPYFXvb7fpkit0cQnpXNWssiL1U&number=3&team_id=\(cityName)"
func fetchWeather () {
let urlString = "\(weatherURL)"
perfromRequest(urlString: urlString)
}
func perfromRequest(urlString: String)
{
//1.Url erstellen
if let url = URL(string: urlString) {
//2. URLSession starten
let session = URLSession(configuration: .default)
//3. Give session a task
let task = session.dataTask(with: url) { (gettingInfo, response, error) in
if error != nil{
print(error!)
return
}
if let safeFile = gettingInfo {
self.parseJSON(weatherFile: safeFile)
}
}
//4. Start the task
task.resume()
}
}
//Das Ergebnis von oben wird hier ausgegeben
func parseJSON(weatherFile: Data) {
let decoder = JSONDecoder()
do{
let decodedFile = try decoder.decode(WeatherFile.self, from: weatherFile)
TeamOne = decodedFile.data[0].home_name
ScoreOne = decodedFile.data[0].score
TeamTwo = decodedFile.data[0].away_name
ScoreTwo = decodedFile.data[0].score
TeamThree = decodedFile.data[1].home_name
ScoreThree = decodedFile.data[1].score
TeamFour = decodedFile.data[1].away_name
ScoreFour = decodedFile.data[1].score
} catch {
print(error)
}
}
}
In a third swift file I use this func weatherManager.fetchWeather() to call what happens in my second swift file.
But here is the problem. It takes the variable number with the default value 1 and not with the value 41/46/45. What am I doing wrong?
Basically global variables outside of any class and static variables to share data is bad practice.
Apart from that to get the team ID dynamically delete the line
var cityName = ThirdScreenViewController.number
In the struct replace
let weatherURL = "https://livescore-api.com/api-client/teams/matches.json?number=10&team_id=19&key=d33FTnnd6qwvEmjz&secret=BbO3REPYFXvb7fpkit0cQnpXNWssiL1U&number=3&team_id=\(cityName)"
with
let weatherURL = "https://livescore-api.com/api-client/teams/matches.json?number=10&team_id=19&key=d33FTnnd6qwvEmjz&secret=BbO3REPYFXvb7fpkit0cQnpXNWssiL1U&number=3&team_id="
and
let urlString = "\(weatherURL)"
with
let urlString = weatherURL + String(ThirdScreenViewController.number)
Note: Consider to rename the weather related stuff to the team related stuff
I was wondering if I could ask a question regarding csv/http posting. I want my data to update within my app after I pull the data from my github csv file, but when I do, it doesn't update within the app but just prints the numbers. What's wrong with my code? Thanks!
class NewStats: UITableViewController {
var didTapMenuType: ((NewMenu) -> Void)?
var Num2:String = "2"
#IBOutlet weak var MultnomahText: UILabel!
#IBOutlet weak var MultnomahView: UIProgressView!
override func viewDidLoad() {
let url = URL(string: "SampleUrl.csv")!
let task = URLSession.shared.dataTask(with: url) {(data, response, error) in
guard let data = data else { return }
let str = (String(data: data, encoding: .utf8)!)
let fullNameArr = str.components(separatedBy: ",")
let Num1 = fullNameArr[0]
self.Num2 = fullNameArr[1]
let Num3 = fullNameArr[2]
let Num4 = fullNameArr[3]
let Num5 = fullNameArr[4]
let Num6 = fullNameArr[5]
let Num7 = fullNameArr[6]
let Num8 = fullNameArr[7]
let Num9 = fullNameArr[8]
let Num10 = fullNameArr[9]
print(Num1);
print(self.Num2);
print(Num3);
print(Num4);
print(Num5);
print(Num6);
print(Num7);
print(Num8);
print(Num9);
print(Num10);
}
task.resume()
super.viewDidLoad()
DispatchQueue.main.async {
self.tableView.reloadData()
}
print(self.Num2);
self.MultnomahText.text = "Multnomah:" + self.Num2
self.MultnomahView.setProgress(0.5, animated: true)
}
After the print(Num10)
DispatchQueue.main.async {
self.MultnomahText.text = "Multnomah:" + self.Num2
self.MultnomahView.setProgress(0.5, animated: true)
self.tableView.reloadData()
}
Hopefully this helps!
I want to use variables (depAirportLat and depAirportLong) outside ViewController class in order to display coordinates on a map but it doesn't works, could you help me ? This is my program :
import UIKit
import MapKit
class ViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var resultWeather: UIImageView!
#IBOutlet weak var arrairport: UITextField!
#IBOutlet weak var depairport: UITextField!
#IBOutlet weak var resultAirport: UILabel!
#IBOutlet weak var fontAirports: UIImageView!
#IBOutlet weak var resultTemp: UILabel!
#IBOutlet weak var resultTempfar: UILabel!
#IBOutlet weak var resultHum: UILabel!
#IBOutlet weak var resultCeiling: UILabel!
#IBOutlet weak var resultClouds: UILabel!
#IBOutlet weak var resultWind: UILabel!
#IBOutlet weak var resultPressure: UILabel!
#IBOutlet weak var resultMetar: UILabel!
#IBOutlet weak var resultTaf: UILabel!
#IBOutlet weak var arrMap: MKMapView!
#IBOutlet weak var depMap: MKMapView!
#IBAction func getWeather(_ sender: UIButton) {
sender.pulsate()
if let url = URL(string: "http://fr.allmetsat.com/metar-taf/france.php?icao=" + depairport.text!.replacingOccurrences(of: " ", with: "-"))
{ let request = NSMutableURLRequest(url: url)
let task = URLSession.shared.dataTask(with: request as URLRequest) { data, response, error in
var message = ""
if error != nil { print(error!) } else { if let unwrappedData = data {
let dataString = NSString(data: unwrappedData, encoding: String.Encoding.utf8.rawValue); var stringSeparator = "METAR:</b> "
if let contentArray = dataString?.components(separatedBy: stringSeparator) {
if contentArray.count > 1 { stringSeparator = "</p></div><div class=\"c1\""
let newContentArray = contentArray[1].components(separatedBy: stringSeparator); if newContentArray.count > 1 { message = newContentArray[0]
print(message)
if (dataString?.contains("CAVOK"))!{
DispatchQueue.main.async { self.resultWeather.image = UIImage(named: "sun.png") }}
else if (dataString?.contains("SKC"))!{
DispatchQueue.main.async { self.resultWeather.image = UIImage(named: "sun.png")}
}
else if (dataString?.contains("SCT"))!{
DispatchQueue.main.async { self.resultWeather.image = UIImage(named: "scattered.png")} }
else if (dataString?.contains("OVC"))!{
DispatchQueue.main.async { self.resultWeather.image = UIImage(named: "overcast.png")} }
else if (dataString?.contains("BKN"))!{
DispatchQueue.main.async { self.resultWeather.image = UIImage(named: "broken.png")} }
else if (dataString?.contains("FEW"))!{
DispatchQueue.main.async { self.resultWeather.image = UIImage(named: "few.png")} }
else if (dataString?.contains("NSC"))!{
DispatchQueue.main.async { self.resultWeather.image = UIImage(named: "sun.png")} }
else if (dataString?.contains("RAIN"))!{
DispatchQueue.main.async { self.resultWeather.image = UIImage(named: "rain.png")}
}}}}}}
}
task.resume();
if let url = URL(string: "http://fr.allmetsat.com/metar-taf/france.php?icao=" + self.depairport.text!.replacingOccurrences(of: " ", with: "-"))
{ let requesta = NSMutableURLRequest(url: url)
let taska = URLSession.shared.dataTask(with: requesta as URLRequest) { data, response, error in
var messagea = ""
if error != nil { print(error!) } else { if let unwrappedData = data {
let dataStringa = NSString(data: unwrappedData, encoding: String.Encoding.utf8.rawValue); var stringSeparatora = "<div class=\"c1b\""
if let contentArray = dataStringa?.components(separatedBy: stringSeparatora) { if contentArray.count > 1 { stringSeparatora = "</h1><p>"
let newContentArray = contentArray[1].components(separatedBy: stringSeparatora); if newContentArray.count > 1 { messagea = newContentArray[0]
print(messagea) }}}};
}
if messagea == "" { messagea = "No data..." }
DispatchQueue.main.sync(execute: { self.resultAirport.text = self.depairport.text! })}; taska.resume() } else { self.resultAirport.text = "0" };
//latitude variable (depAirportLat)
if let urlcoord = URL(string:"https://flyawaysimulation.com/airports/" + self.depairport.text!.replacingOccurrences(of: " ", with: "-"))
{ let requestad = NSMutableURLRequest(url: urlcoord)
let taskad = URLSession.shared.dataTask(with: requestad as URLRequest) { data, response, error in
var depAirportLat = ""
if error != nil { print(error!) } else { if let unwrappedData = data {
let dataStringad = NSString(data: unwrappedData, encoding: String.Encoding.utf8.rawValue); var stringSeparatorad = "<dt>Latitude</dt>"
if let contentArray = dataStringad?.components(separatedBy: stringSeparatorad) { if contentArray.count > 1 { stringSeparatorad = "</dd>"
let newContentArray = contentArray[1].components(separatedBy: stringSeparatorad); if newContentArray.count > 1 { depAirportLat = newContentArray[0]
print(depAirportLat) }}}}}};
taskad.resume()
}
}
override func viewDidLoad() {
super.viewDidLoad()
//Do any additional setup after loading the view, typically from a nib.
class gloVarDep {
var depAirportLatReal = depAirportLat.dropFirst(5)
var depAirportLatRealCoord = String(depAirportLatReal)
var depAirportLatRealCoordFloat = (depAirportLatRealCoord as NSString).floatValue
If you want to be able to use those variables outside the class, then you have to declare them as global variables. Just declare them outside of the class scope and you should be fine.
Alternatively, you could create a structure and define static variables that can be used everywhere. The aforementioned makes things a bit more readable and retainable.
When I try to press on any button on my calculator it gives me the error unrecognized selector sent to instance 0x7f7f85e04e40 I updated this code from Swift 2 to Swift 4 but back then it used to work. What's wrong with the code?
import UIKit
class Valuta: UIViewController {
#IBOutlet weak var euro: UILabel!
#IBOutlet weak var zloty: UILabel!
#IBOutlet weak var topButton: UIButton!
#IBOutlet weak var bottomButton: UIButton!
var valutas : [ValutaWaarde] = []
var number = 0;
var isTypingNumber = false
var currentNumber = 0;
var currency = "PLN";
#IBAction func numberTapped(sender: AnyObject) {
let number = sender.currentTitle!
var disable = false
if number == "."{
if euro.text!.range(of: ".") != nil{
disable = true
}
}
if(disable == false){
if isTypingNumber {
euro.text = euro.text!+number!
} else {
euro.text = number
isTypingNumber = true
}
var output : Float;
if(currency == "EUR"){
output = (euro.text! as NSString).floatValue*Float((valutas[0].rates?.pLN!)!)
}
else{
output = (euro.text! as NSString).floatValue/Float((valutas[0].rates?.pLN!)!)
}
zloty.text = String(format: "%.2f", output)
}
}
#IBAction func resetCalculator(sender: AnyObject) {
isTypingNumber = false;
zloty.text = "0";
euro.text = "0";
}
override func viewDidLoad() {
super.viewDidLoad()
UINavigationBar.appearance().isTranslucent = false;
UINavigationBar.appearance().barTintColor = UIColor(red: CGFloat(51/255.0), green: 51/255, blue: 51/255, alpha: 1)
UINavigationBar.appearance().titleTextAttributes = [NSAttributedStringKey.foregroundColor:UIColor.white]
//Get list
let url = URL(string: "https://api.fixer.io/latest?symbols=PLN&base=EUR")
var request = NSMutableURLRequest(url: url! as URL, cachePolicy: NSURLRequest.CachePolicy.returnCacheDataElseLoad, timeoutInterval: Double.infinity)
if Reachability.isConnectedToNetwork(){
request = NSMutableURLRequest(url: url! as URL, cachePolicy: NSURLRequest.CachePolicy.useProtocolCachePolicy, timeoutInterval: Double.infinity);
}
let session = URLSession.shared
let task = session.dataTask(with: request as URLRequest,
completionHandler: { data, response, error -> Void in
do {
if let json = try JSONSerialization.jsonObject(with: data!) as? [[String: String]] {
for valutaData in json {
let valuta = ValutaWaarde(dictionary: valutaData as NSDictionary)
self.valutas.append(valuta!)
}
}
} catch { print(error) }
})
task.resume()
}
...
}
Try to re-connect #IBOutlets and #IBActions in storyboard.