How to set UISwitch state when receiving data from API - swift

I have a screen with Two UISwitch buttons.
I am receiving a data in API:
"CustomerSubscribed": [
{
"Customer_ID": "100132",
"Mobile": "3213103428",
"Subscription": "Bill Payment",
"Mnemonic": "BILL",
"IsActive": 0
},
{
"Customer_ID": "100132",
"Mobile": "3213103428",
"Subscription": "Funds Transfer",
"Mnemonic": "IBFT",
"IsActive": 1
}
]
These are my two switches:
private var fundSwitch: UISwitch = {
let switchView = UISwitch()
switchView.isOn = false
switchView.onImage = UIImage(named: "switchOn")
switchView.offImage = UIImage(named: "switchOff")
switchView.onTintColor = UIColor.purple
switchView.tag = 1
switchView.addTarget(self, action: #selector(switchStateDidChange), for: .valueChanged)
switchView.translatesAutoresizingMaskIntoConstraints = false
return switchView
}()
private var billSwitch: UISwitch = {
let switchView = UISwitch()
switchView.isOn = false
switchView.onImage = UIImage(named: "switchOn")
switchView.offImage = UIImage(named: "switchOff")
switchView.onTintColor = UIColor.purple
switchView.tag = 2
switchView.addTarget(self, action: #selector(switchStateDidChange), for: .valueChanged)
switchView.translatesAutoresizingMaskIntoConstraints = false
return switchView
}()
On the basis of isActive, I have to set the values of UISWitch. If it is true, then switch must be on, otherwise if it is false then it must be Off.
This is what im trying right now:
#objc func switchStateDidChange(_ sender: UISwitch) {
if sender.tag == Switch.fundTrasnfer.rawValue {
print( sender.isOn ? customerSubscribe?[0].isActive ?? false: "Fund Transfer Switch is Off" )
} else {
print( sender.isOn ? customerSubscribe?[1].isActive ?? false: "Bill Payment Fund Transfer Switch is Off" )
}
}
and another what I tried:
#objc func switchStateDidChange(_ sender: UISwitch) {
for customer in self.customerSubscribe! {
if customer.isActive == true {
print(sender.isOn ? "Switch is ON": "Switch is Off")
} else {
print(sender.isOn ? "Switch is ON": "Switch is Off")
}
}
}
these are two approaches I have tried. I am using VIP Architecture, and I received response here:
extension SubscriptionViewController: SubscribeViewProtocol {
func saveSuccessCustomerData(response: CustomerSubscribeEntity.CustomerServiceResponse) {
}
func successSetupSubscription(response: SubscriptionEntity.SubscriptionServicesResponse) {
DispatchQueue.main.async {
print("Id \(response.customerSubscribed?[0].customerID)")
self.customerSubscribe = response.customerSubscribed
self.fundTransferLbl.text = self.customerSubscribe?[0].subscription
self.billPaymentLbl.text = self.customerSubscribe?[1].subscription
}
}
}
Then I created customerSubscribe to have the response in it:
var customerSubscribe: [SubscriptionEntity.CustomerSubscribed]?
My screen:
UI Is is programmatically, and i have both fund and bill switch defined.
Can I make a loop and check too instead of comparing taking index?

You are still hiding a lot of implementation detail that would be neccassary to give a definitive answer. So I have to make some assumptions.
isActive is of type boolean
successSetupSubscription lives in the same place as your switch vars
you create your switches programaticly and add them to your view.
Your function switchStateDidChange will react to changes done by the user. If you want to change the state of the switch programmaticly you need to set it to the switch itself.
func successSetupSubscription(response: SubscriptionEntity.SubscriptionServicesResponse) {
DispatchQueue.main.async {
print("Id \(response.customerSubscribed?[0].customerID)")
self.customerSubscribe = response.customerSubscribed
self.fundTransferLbl.text = self.customerSubscribe?[0].subscription
self.billPaymentLbl.text = self.customerSubscribe?[1].subscription
//add this
self.fundSwitch.isOn = response.customerSubscribed[0].isActive
self.billSwitch.isOn = response.customerSubscribed[1].isActive
}
}

You can try
switchOne.isOn = customerSubscribe?.first?.isActive == 1
switchTwo.isOn = customerSubscribe?.last?.isActive == 1

Related

Eureka in swift List Selection Selected Value Automatically Deselect when navigating away

I am implementing Eureka list selection. On the language selections, there are 7 values to choose from. Value 1 to 6 is good. But when the last one selected and user navigates away from the VC, it's deselected automatically. I wonder if there is something wrong with my code. I have tried to "hardcode" the last selection on viewWillAppear just so the app goes smoothly and yes it is. But it's a little weird because none of the selection selected. I am a beginner to programming and greatly appreciated any help. Thank you
import Eureka
class ListSectionsController: FormViewController {
let defaults = UserDefaults.standard
var languageSelected = "English (default)"
override func viewDidAppear(_ animated: Bool) {
defaults.set(languageSelected, forKey: "LanguageSelection")
}
override func viewWillAppear(_ animated: Bool) {
if let language = defaults.string(forKey: "LanguageSelection") {
if language == "Korean 한국어" {
languageSelected = language
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
let languageSelections = ["English (default)", "Spanish", "Japanese 日本語", "Chinese Mandarin 普通话", "Indonesian", "Dutch - het Nederlands", "Korean 한국어"]
form +++ SelectableSection<ImageCheckRow<String>>() { section in
section.header = HeaderFooterView(title: "Language Selection")
}
for option in languageSelections {
if let language = self.defaults.string(forKey: "LanguageSelection") {
self.form.setValues([language : language])
} else {
self.form.setValues([languageSelected : languageSelected])
}
form.last! <<< ImageCheckRow<String>(option){ lrow in
lrow.title = option
lrow.selectableValue = option
lrow.value = nil
}
}
}
override func valueHasBeenChanged(for row: BaseRow, oldValue: Any?, newValue: Any?) {
if row.section === form[0] {
if let selected = (row.section as! SelectableSection<ImageCheckRow<String>>).selectedRow()?.baseValue {
print("Selected: \(selected)")
languageSelected = selected as! String
defaults.set(languageSelected, forKey: "LanguageSelection")
}
} else if row.section === form[1] {
print("Mutiple Selection:\((row.section as! SelectableSection<ImageCheckRow<String>>).selectedRows().map({$0.baseValue}))")
}
}
}

pushViewController for once

I have one UIButton which called Get Started in the welcome screen, by clicking on this button it will goes to the PhoneNumberViewController to type and click on the next button. For new users it will require to fill out some personal information in the ProfileViewController before going to the HomeViewController. Now I am struggling how can I pop that profile for once since I do not need registered users to check their information when they logout and re-login later.
Here is my code :
private func checkUser(userId: String) {
userService.getUser(Uid: userId) { (tutor) in
if let user = user,
!user.name.isEmpty && !user.email.isEmpty {
Router.route(to: .home)
} else {
let profileViewController = UIStoryboard.main.viewController(of: ProfileViewController.self)
profileViewController.isFromOnboarding = true
self.navigationController?.pushViewController(profileViewController, animated: true)
}
}
}
You can save a value in userDefault
private func checkUser(userId: String) {
let isPresented = UserDefaults.standard.bool(forKey: "isPresented")
userService.getUser(Uid: userId) { (tutor) in
if let user = user,
!user.name.isEmpty && !user.email.isEmpty {
Router.route(to: .home)
} else if !isPresented {
UserDefaults.standard.set(true, forKey: "isPresented")
let profileViewController = UIStoryboard.main.viewController(of: ProfileViewController.self)
profileViewController.isFromOnboarding = true
self.navigationController?.pushViewController(profileViewController, animated: true)
}
}
}
Create a hasPushedProfile flag in the controller which can be used to check if the profile view has already been shown or not. On the first time through the flag will be false and will then be set to be true when the profile is displayed, next time through the profile will not display and you can do something else instead.
import UIKit
class LoginController: UIViewController {
static var hasPushedProfile = false
private func checkUser(userId: String) {
userService.getUser(Uid: userId) { (tutor) in
if let user = user,
!user.name.isEmpty && !user.email.isEmpty {
Router.route(to: .home)
} else {
if hasPushedProfile == false {
hasPushedProfile = true
let profileViewController = UIStoryboard.main.viewController(of: ProfileViewController.self)
profileViewController.isFromOnboarding = true
self.navigationController?.pushViewController(profileViewController, animated: true)
} else {
// Already pushed profile, do something else...
}
}
}
}
}

How to reflect select result of UISegmentedControl in Firebase'S Database

Hello I'm newbie in programming (Swift/Firebase) and developing application. Now is trying to make a user profile to be connected to database. I could do it for TextFields data, but cannot do the same with UISegmentedControl for Male/Female switch.
#IBAction func saveProfileButton(_ sender: Any) {
if nameTextField.text! == "" {
print("enter something")
} else {
addUser()
}
}
#objc func valuChange() {
switch genderSegControl.selectedSegmentIndex {
case 0:
let zero = String("Male")
case 1:
let one = String("Female")
default:
return
}
}
func addUser() {
let genderChanged = genderSegControl?.addTarget(self, action: #selector(MainViewController.valuChange), for: UIControlEvents.valueChanged)
let userGender = String(describing: genderChanged!)
let uidUser = Auth.auth().currentUser?.uid
let user = ["...": ..., "userGender": userGender as! String]
refUsers.child(uidUser!).setValue(user)
}
but when I check Firebase's Database nodes it shows "userGender: Optional(())" and only. I tried in many different ways but couldn't get it to be shown like "userGender: Male" or "userGender: Female".
Would appreciate any advice.
Create outlet for UISegementControl in your ViewController, say genderControl.
In addUser() function, use the selectedIndex of the UISegementControl to determine the value as follows, say index 0 is for MALE & 1 is for FEMALE then:
let gender = genderControl.selectedIndex == 0 ? "Male" : "Female"
Now set this value gender in user dictionary, i.e.
let user = ["...": ..., "userGender": gender]

How to add PayPal (live) to my Swift app?

This app is a two-part app - Uber-like app with a rider and a driver.
I am trying to make an app that requires PayPal. The person using the app (driver) will be accepting payments from others users of the app (rider). I have tried to follow the PayPal docs but just running into complications.
AppDelegate.swift:
PayPalMobile .initializeWithClientIds(forEnvironments:
[PayPalEnvironmentProduction: "CLIENT ID FOR PRODUCTION",
PayPalEnvironmentSandbox: "CLIENT ID FOR SANDBOX"])
ViewController.swift:
// create PayPal object:
var payPalConfig = PayPalConfiguration()
// Declare Payment Configuration
var environment: String = PayPalEnvironmentSandbox {
willSet(newEnvironment) {
if (newEnvironment != environment) {
PayPalMobile.preconnect(withEnvironment: newEnvironment)
}
}
}
var acceptCreditCards: Bool = true {
didSet {
payPalConfig.acceptCreditCards = acceptCreditCards
}
}
override func viewDidLoad() {
super.viewDidLoad()
payPalConfig.acceptCreditCards = acceptCreditCards
payPalConfig.merchantName = "DevHopes"
payPalConfig.merchantPrivacyPolicyURL = URL(string: "https://www.paypal.com/webapps/mpp/ua/privacy-full")
payPalConfig.merchantUserAgreementURL = URL(string: "https://www.paypal.com/webapps/mpp/ua/useragreement-full")
payPalConfig.languageOrLocale = Locale.preferredLanguages[0]
payPalConfig.payPalShippingAddressOption = .both
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
PayPalMobile.preconnect(withEnvironment: environment)
}
payPalPressed:
#IBAction func payPalPressed(_ sender: Any) {
let item1 = PayPalItem(name: "Staying Uptown", withQuantity: 1, withPrice: NSDecimalNumber(string: "0.01"), withCurrency: "CAD", withSku: "UPTOWN")
let item2 = PayPalItem(name: "North-South", withQuantity: 1, withPrice: NSDecimalNumber(string: "0.01"), withCurrency: "CAD", withSku: "North-South")
let item3 = PayPalItem(name: "South-SJRH", withQuantity: 1, withPrice: NSDecimalNumber(string: "0.01"), withCurrency: "CAD", withSku: "South-SJRH")
let items = [item1, item2, item3]
let subtotal = PayPalItem.totalPrice(forItems: items)
// Optional: include payment details
let paymentDetails = PayPalPaymentDetails(subtotal: subtotal, withShipping: nil, withTax: nil)
let total = subtotal
let payment = PayPalPayment(amount: total, currencyCode: "CAD", shortDescription: "Transportation", intent: .sale)
payment.items = items
payment.paymentDetails = paymentDetails
if (payment.processable) {
let paymentViewController = PayPalPaymentViewController(payment: payment, configuration: payPalConfig, delegate: self)
present(paymentViewController!, animated: true, completion: nil)
}
else {
// This particular payment will always be processable. If, for
// example, the amount was negative or the shortDescription was
// empty, this payment wouldn't be processable, and you'd want
// to handle that here.
print("Payment not processable: \(payment)")
}
}
// PayPalPaymentDelegate
func payPalPaymentDidCancel(_ paymentViewController: PayPalPaymentViewController) {
print("PayPal Payment Cancelled")
paymentViewController.dismiss(animated: true, completion: nil)
}
func payPalPaymentViewController(_ paymentViewController: PayPalPaymentViewController, didComplete completedPayment: PayPalPayment) {
print("PayPal Payment Success !")
paymentViewController.dismiss(animated: true, completion: { () -> Void in
// send completed confirmaion to your server
print("Here is your proof of payment:\n\n\(completedPayment.confirmation)\n\nSend this to your server for confirmation and fulfillment.")
})
}
When I run this, I get an error, even though the client id is correct:
When I put in my live credentials and change ..Sandbox to ..Production, I get an error: dictionary literal has duplicate keys?
I have the PayPal iOS SDK installed.

Swift Xcode attach an action to a checkbox using a checkbox subclass

I’m new to swift so I am stumped on something that is probably very simple.
I want to have checkboxes for each day of the week and be able to toggle their states a bit like the standard Apple clock app alarm repeat page. I am using a subclass borrowed from https://github.com/kenthinson/checkbox/ to create a set of checkboxes. All that works like a charm in the storyboard but now I am struggling with how to refer to the subclass checkbox ‘state’ in my view controller to actually do something.
So here is the subclass:
import UIKit
class checkBox: UIButton {
//images
let checkedImage = UIImage(named: "checkBoxChecked")
let unCheckedImage = UIImage(named: "checkBoxUnchecked")
//bool property
var isChecked:Bool = false{
didSet{
if isChecked == true{
self.setImage(checkedImage, forState: .Normal)
}else{
self.setImage(unCheckedImage, forState: .Normal)
}
}
}
override func awakeFromNib() {
self.addTarget(self, action: "buttonClicked:", forControlEvents: UIControlEvents.TouchUpInside)
self.isChecked = false
}
func buttonClicked(sender:UIButton) {
if(sender == self){
if isChecked == true{
isChecked = false
}else{
isChecked = true
}
}
}
}
Here is an outlet example:
#IBOutlet weak var sun: checkBox!
Here is my empty array ready to be appended (working):
var daysArray:[String] = []
Here is an example action:
#IBAction func setSunday(sender: checkBox) {
if (****what do I do here to retrieve the button state?****) {
daysArray.append("0")
print(daysArray) // Check the array is working then delete
} else {
daysArray.removeAtIndex(0)
print(daysArray) // Check the array is working then delete
}
}
If I can get this working then I can apply to all days of the week and make the state of the array persistent using NSUserDefaults.
Hope you guys can help.
Use sender.isChecked to retrieve the state:
#IBAction func setSunday(sender: checkBox) {
if sender.isChecked {
daysArray.append("0")
print(daysArray) // Check the array is working then delete
} else {
daysArray.removeAtIndex(0)
print(daysArray) // Check the array is working then delete
}
}