how to keep onPrgressChanged from updating when I change edit field - android-edittext

I have created a Seekbar and have coded it to update an Editable text field with a number based on what the seekBar is moved to. I also have set the seekBar to be updated when I type into the editable text field. However, what I don't want is the Editable text to update from the seekBar change every time I type one number into the Editabl text field. It is causing the cursor to move to the front of the editabl text field every number I type.
here is some of the code I have:
private const val TAG = "MainActivity"
private const val INITIAL_OUNCE_AMOUNT = 0.0
class MainActivity : AppCompatActivity() {
private lateinit var etEditOunceAmount: EditText
private lateinit var seekBarTip: SeekBar
private lateinit var tvNumberOunces: TextView
private lateinit var seekBarOunces: SeekBar
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
etEditOunceAmount = findViewById(R.id.etEditOunceAmount)
seekBarOunces = findViewById(R.id.seekBarOunces)
tvNumberOunces = findViewById(R.id.tvNumberOunces)
seekBarOunces.progress = INITIAL_OUNCE_AMOUNT.toInt()
tvNumberOunces.text = "$INITIAL_OUNCE_AMOUNT"
Below is the meet of whats going on:
seekBarOunces.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
Log.i(TAG, "onProgressChanged $progress")
val str = ("$progress")
val nStr = str.toFloat1()
val aStr = nStr * 0.5
val rStr = aStr.toString()
tvNumberOunces.text = ("$rStr OZ.")
etEditOunceAmount.setText("$rStr")
//computeTipAndTotal()
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {}
override fun onStopTrackingTouch(seekBar: SeekBar?) {}
})
etEditOunceAmount.addTextChangedListener(object : TextWatcher {
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
if (!etEditOunceAmount.equals(null)) {
var NEW_S = s.toString().toFloatOrNull()
if (NEW_S != null) {
NEW_S = NEW_S * 2
}
if (NEW_S != null) {
seekBarOunces.progress = NEW_S.toInt()
}
}
}
override fun afterTextChanged(s: Editable?) {
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
})
}
}

Related

Generic class of generic class with one argument/parameter

I have this syntactical issue with my data structure. What makes it worse is that I can not talk about it in detail. The company I am employed at operates in the public transportation sector and I am under NDA and boss would kill me if I posted anything too specific. I hope you understand!
I have this perfect example though. There are no inconsistencies at all ;)
Well, okay, there are. However I am convinced that most of you out there are smart enough to get what is of importance here.
Basic structure:
class Propulsion {
var horsePower: Double
init(horsePower: Double) {
self.horsePower = horsePower
}
static let pedes = Propulsion(horsePower: 0.2)
}
class Motor: Propulsion {
var range: Double
init(range: Double, horsePower: Double) {
self.range = range
super.init(horsePower: horsePower)
}
static let otto = Motor(range: 1000, horsePower: 100)
static let electric = Motor(range: 400, horsePower: 200)
}
class Vehicle<P: Propulsion> {
var propulsion: P
init(propulsion: P) {
self.propulsion = propulsion
}
}
class Bicycle<P: Propulsion>: Vehicle<P> {
var hasFrontSuspension: Bool
init(hasFrontSuspension: Bool, propulsion: P) {
self.hasFrontSuspension = hasFrontSuspension
super.init(propulsion: propulsion)
}
}
class Car<P: Propulsion>: Vehicle<P> {
func rangePerHorsePower() -> Double where P: Motor {
propulsion.range / propulsion.horsePower
}
}
Now I would like to declare a parking spot for a car. Like so:
var carParkingSpot: ParkingSpot<Car<Motor>>
For the class ParkingSpot I have some class like this in mind:
class ParkingSpot<V: Vehicle<P>> where P: Propulsion {
var vehicle: Vehicle<P>
init(vehicle: Vehicle<P>) {
self.vehicle = vehicle
}
func taxForRange() -> Double where P: Motor {
vehicle.propulsion.range * 50
}
}
From the last bit I get back a bunch of
Cannot find type 'P' in scope
This one doesn’t work either:
class ParkingSpot<V: Vehicle<P: Propulsion>>
Expected '>' to complete generic argument list
This implementation works though:
class ParkingSpot<V: Vehicle<P>, P: Propulsion> {
var vehicle: Vehicle<P>
init(vehicle: Vehicle<P>) {
self.vehicle = vehicle
}
func taxForRange() -> Double where P: Motor {
vehicle.propulsion.range * 50
}
}
However I don’t want to duplicate the Motor bit:
var carParkingSpot: ParkingSpot<Car<Motor>, Motor>
How can I accomplish this with just one generic parameter?
You may use the "Protocol oriented" approach:
protocol PropulsionP {
var horsePower: Double { get }
}
protocol MotorP: PropulsionP {
var range: Double { get }
}
struct MotorS: MotorP {
var range: Double
var horsePower: Double
init(range: Double, horsePower: Double) {
self.range = range
self.horsePower = horsePower
}
}
protocol VehicleP {
associatedtype P: PropulsionP
var propulsion: P { get }
}
struct BicycleS<Prop: PropulsionP>: VehicleP {
let hasFrontSuspension: Bool
var propulsion: Prop
init(
hasFrontSuspension: Bool,
propulsion: Prop
) {
self.hasFrontSuspension = hasFrontSuspension
self.propulsion = propulsion
}
}
struct CarS<Prop: PropulsionP>: VehicleP {
var propulsion: Prop
func rangePerHorsePower() -> Double where P: MotorP {
propulsion.range / propulsion.horsePower
}
}
struct ParkingSpotS<V: VehicleP> {
var vehicle: V
init(vehicle: V) {
self.vehicle = vehicle
}
func taxForRange() -> Double where V.P: MotorP {
vehicle.propulsion.range * 50
}
}
var carParkingSpot: ParkingSpotS<CarS<MotorS>>
No double MotorS bit.
Quod erat demonstrandum.
I used the somewhat unusual naming to emphasize the point.
(needed to make some edit, erronously typed Motor where I actually need MotorP)
Update
I was on the road with my preferred car and tried it out:
var carParkingSpot: ParkingSpotS<CarS<MotorS>> = .init(
vehicle: .init(
propulsion: .init(
range: 760,
horsePower: 240
)
)
)
print(carParkingSpot.taxForRange())
38000.0
Alternatively you can use this initialiser:
var carParkingSpot: ParkingSpotS = .init(
vehicle: CarS(
propulsion: MotorS(
range: 760,
horsePower: 240
)
)
)
Update
Now suppose you are utilising a third party library which already provides a nice implementation of a motor.
What you need to do is to implement an extension for their given class or struct TheirMotor which conforms to your protocol MotorP:
import FancyMotors
extension TheirMotor: MotorP {
let range: Double {
// calculate `range` in terms of the
// given API of `TheirMotor`:
...
return range
}
}
Then, you can use it like below:
var carParkingSpot: ParkingSpotS = .init(
vehicle: CarS(
propulsion: TheirMotor(
distance: 760,
power: 240
)
)
)
Note, that you use TheirMotor and need to use the appropriate initialiser to create it.
This seems to work:
class ParkingSpot<V: Vehicle<Propulsion>>
{
var vehicle: V
init(vehicle: V)
{
self.vehicle = vehicle
}
func taxForEngineeNoise() -> Double
{
switch vehicle.propulsion
{
case is Motor:
return vehicle.propulsion.horsePower * 50
default:
...
}
}
func taxForRange() -> Double
{
if let motor = vehicle.propulsion as? Motor
{
return motor.range * 50
}
else
{
...
}
}
}
Alternatively, perhaps hide the duplication where you can?
typealias ParkingSpotX = ParkingSpot<Car<Motor>, Motor>
var parkingSpot: ParkingSpotX

Get Context of a Service

I'm trying to get the context of my Service in order. The service opens up an overlay that draws on other apps. The overlay comes up but if I interact with any of the views, the app crashes and gives this error.
android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?
Here is the full error.
android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?
at android.view.ViewRootImpl.setView(ViewRootImpl.java:1068)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:409)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:109)
at android.app.Dialog.show(Dialog.java:340)
at android.widget.Spinner$DialogPopup.show(Spinner.java:1146)
at android.widget.Spinner.performClick(Spinner.java:792)
at android.view.View.performClickInternal(View.java:7425)
at android.view.View.access$3600(View.java:810)
at android.view.View$PerformClick.run(View.java:28305)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
From what I've been able to determine through Google Search and SO is that the issue is with the context. Below is the code for my Service.
class Dooa: Service() {
private lateinit var floatView: ViewGroup
private lateinit var floatWindowLayoutParams: WindowManager.LayoutParams
private var LAYOUT_TYPE: Int? = null
private lateinit var windowManager: WindowManager
private lateinit var spinnerAccount: Spinner
private lateinit var tvDateAT: TextView
private lateinit var spinnerType: Spinner
private lateinit var etTitle: EditText
private lateinit var etMemo: EditText
private lateinit var spinnerCategory: Spinner
private lateinit var spinnerDebitOrCredit: Spinner
private lateinit var etAmount: EditText
private lateinit var ibSave: ImageButton
private lateinit var ibCancel: ImageButton
private var account: String = "Joint"
private var debitOrCredit: String = "Debit"
private var category: String = ""
private var type: String = "CC"
private var mils: Long = 0
private var balance: String = ""
private var context: Context? = null
private lateinit var db : FirebaseFirestore
override fun onBind(intent: Intent?): IBinder? {
return null
}
override fun onCreate() {
super.onCreate()
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
context = MyApp().getContext()
Log.d("blocks", "context: $context")
if (intent != null) {
if (intent.action == START) {
db = FirebaseFirestore.getInstance()
val metrics = applicationContext.resources.displayMetrics
val width = metrics.widthPixels
val height = metrics.heightPixels
windowManager = getSystemService(WINDOW_SERVICE) as WindowManager
val inflator = this.getSystemService(LAYOUT_INFLATER_SERVICE) as LayoutInflater
floatView = inflator.inflate(R.layout.dooa_transaction_card, null) as ViewGroup
spinnerAccount = floatView.findViewById(R.id.spinnerAccount)
tvDateAT = floatView.findViewById(R.id.tvDateAT)
spinnerType = floatView.findViewById(R.id.spinnerType)
etTitle = floatView.findViewById(R.id.etTitle)
etMemo = floatView.findViewById(R.id.etMemo)
spinnerCategory = floatView.findViewById(R.id.spinnerCategory)
spinnerDebitOrCredit = floatView.findViewById(R.id.spinnerDebitOrCredit)
etAmount = floatView.findViewById(R.id.etAmount)
ibSave = floatView.findViewById(R.id.ibSave)
ibCancel = floatView.findViewById(R.id.ibCancel)
//ACCOUNT SPINNER
ArrayAdapter.createFromResource(
this,
R.array.accounts,
R.layout.spinner_item
).also { adapter ->
Log.d("blocks", "AS ArrayAdapter ran")
adapter.setDropDownViewResource(R.layout.spinner_dropdown_item)
spinnerAccount.adapter = adapter
spinnerAccount.setSelection(0)
}
spinnerAccount.onItemSelectedListener = object : AdapterView.OnItemSelectedListener{
override fun onItemSelected(
parent: AdapterView<*>?,
view: View?,
position: Int,
id: Long
) {
val selection = parent?.getItemAtPosition(position)
account = selection.toString()
getDB()
}
override fun onNothingSelected(parent: AdapterView<*>?) {
}
}
tvDateAT.setOnClickListener {
val c = Calendar.getInstance()
val year = c.get(Calendar.YEAR)
val month = c.get(Calendar.MONTH)
val day = c.get(Calendar.DAY_OF_MONTH)
val dpd = DatePickerDialog(
this#Dooa,
{ view, year, monthOfYear, dayOfMonth ->
// Save milliseconds for date picked.
mils = c.timeInMillis
val m = monthOfYear + 1
// Display Selected date in textbox
tvDateAT.text = getString(
R.string.date_picked,
m.toString(),
dayOfMonth.toString(),
year.toString()
)
},
year,
month,
day
)
dpd.show()
}
//TYPE
ArrayAdapter.createFromResource(
this,
R.array.type,
R.layout.spinner_item
).also { adapter ->
adapter.setDropDownViewResource(R.layout.spinner_dropdown_item)
spinnerType.adapter = adapter
spinnerType.setSelection(0)
}
spinnerType.onItemSelectedListener = object : AdapterView.OnItemSelectedListener{
override fun onItemSelected(
parent: AdapterView<*>?,
view: View?,
position: Int,
id: Long
) {
val selection = parent?.getItemAtPosition(position)
type = selection.toString()
}
override fun onNothingSelected(parent: AdapterView<*>?) {
TODO("Not yet implemented")
}
}
etTitle.setOnTouchListener(object : View.OnTouchListener {
override fun onTouch(v: View?, event: MotionEvent?): Boolean {
etTitle.isCursorVisible = true
val updatedFloatParamsFlag = floatWindowLayoutParams
updatedFloatParamsFlag.flags =
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
updatedFloatParamsFlag.flags = WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE
windowManager.updateViewLayout(floatView, updatedFloatParamsFlag)
return false
}
})
//CATEGORY
ArrayAdapter.createFromResource(
this,
R.array.category,
R.layout.spinner_item
).also { adapter ->
adapter.setDropDownViewResource(R.layout.spinner_dropdown_item)
spinnerCategory.adapter = adapter
spinnerCategory.setSelection(0)
}
spinnerCategory.onItemSelectedListener = object : AdapterView.OnItemSelectedListener{
override fun onItemSelected(
parent: AdapterView<*>?,
view: View?,
position: Int,
id: Long
) {
val selection = parent?.getItemAtPosition(position)
category = selection.toString()
}
override fun onNothingSelected(parent: AdapterView<*>?) {
TODO("Not yet implemented")
}
}
//DEBIT OR CREDIT
ArrayAdapter.createFromResource(
this,
R.array.debit_or_credit,
R.layout.spinner_item
).also { adapter ->
adapter.setDropDownViewResource(R.layout.spinner_dropdown_item)
spinnerDebitOrCredit.adapter = adapter
spinnerDebitOrCredit.setSelection(0)
}
spinnerDebitOrCredit.onItemSelectedListener = object : AdapterView.OnItemSelectedListener{
override fun onItemSelected(
parent: AdapterView<*>?,
view: View?,
position: Int,
id: Long
) {
val selection = parent?.getItemAtPosition(position)
debitOrCredit = selection.toString()
}
override fun onNothingSelected(parent: AdapterView<*>?) {
TODO("Not yet implemented")
}
}
ibSave.setOnClickListener {
// save all the info.
val date = tvDateAT.text
val memo = etMemo.text
val title = etTitle.text
val amount = etAmount.text
val uid = FirebaseAuth.getInstance().currentUser!!.uid
val serverTS = FieldValue.serverTimestamp()
val collection = account
var nb = 0.0
val newBalance = if (debitOrCredit.contains("Debit")){
nb = (balance.toDouble() - etAmount.text.toString().toDouble())
} else {
nb = (balance.toDouble() + etAmount.text.toString().toDouble())
}
val info = hashMapOf(
"date" to date.toString(),
"type" to type,
"title" to title.toString(),
"memo" to memo.toString(),
"category" to category,
"debitOrCredit" to debitOrCredit,
"amount" to amount.toString(),
"clearReconcile" to "NA",
"mils" to mils,
"timeStamp" to serverTS
)
if (date != "Date"){
if (title?.isNotEmpty() == true && amount?.isNotEmpty() == true){
val dbAccountTransaction = db.collection("Users").document(uid).collection(collection)
dbAccountTransaction.add(info)
.addOnSuccessListener {
db.collection("Users").document(uid).collection(collection).document("balance")
.update("balance", nb.toString())
.addOnSuccessListener {
Toast.makeText(this, "Transaction was saved.", Toast.LENGTH_SHORT).show()
val i = Intent(this, MainActivity::class.java)
startActivity(i)
}
}
.addOnFailureListener{
Toast.makeText(this, "There was an error. Transaction wasn't saved.", Toast.LENGTH_SHORT).show()
}
} else {
Toast.makeText(this, "Please fill out Title and Amount.", Toast.LENGTH_SHORT).show()
}
} else {
Toast.makeText(this, "Please select a date.", Toast.LENGTH_SHORT).show()
}
}
ibCancel.setOnClickListener {
stopSelf()
windowManager.removeView(floatView)
}
LAYOUT_TYPE = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
} else {
WindowManager.LayoutParams.TYPE_TOAST
}
floatWindowLayoutParams = WindowManager.LayoutParams(
(width * 0.55f).toInt(),
(height * 0.55f).toInt(),
LAYOUT_TYPE!!,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
PixelFormat.TRANSLUCENT
)
floatWindowLayoutParams.gravity = Gravity.CENTER
floatWindowLayoutParams.x = 0
floatWindowLayoutParams.y = 0
windowManager.addView(floatView, floatWindowLayoutParams)
floatView.setOnTouchListener(object : View.OnTouchListener{
val updatedFloatWindowLayoutParam = floatWindowLayoutParams
private var initialX = 0.0
private var initialY = 0.0
private var initialTouchX = 0.0
private var initialTouchY = 0.0
override fun onTouch(v: View?, event: MotionEvent): Boolean {
when (event.action) {
MotionEvent.ACTION_DOWN -> {
initialX = updatedFloatWindowLayoutParam.x.toDouble()
initialY = updatedFloatWindowLayoutParam.y.toDouble()
initialTouchX = event.rawX.toDouble()
initialTouchY = event.rawY.toDouble()
return true
}
MotionEvent.ACTION_MOVE -> {
updatedFloatWindowLayoutParam.x = (initialX + event.rawX - initialTouchX).toInt()
updatedFloatWindowLayoutParam.y = (initialY + event.rawY - initialTouchY).toInt()
windowManager.updateViewLayout(floatView, updatedFloatWindowLayoutParam)
return true
}
}
return false
}
})
spinnerAccount.setOnTouchListener(object : View.OnTouchListener {
override fun onTouch(v: View?, event: MotionEvent?): Boolean {
val updatedFloatParamsFlag = floatWindowLayoutParams
updatedFloatParamsFlag.flags =
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
windowManager.updateViewLayout(floatView, updatedFloatParamsFlag)
return false
}
})
}
}
return START_NOT_STICKY
}
private fun getDB() {
try {
db.collection("Users").document(FirebaseAuth.getInstance().currentUser!!.uid)
.collection(account).document("balance")
.get()
.addOnSuccessListener { document ->
if (document != null) {
val balanceResult = StringBuffer()
balanceResult.append(document.data?.getValue("balance"))
balance = balanceResult.toString()
}
}
} catch (e: Exception){
e.printStackTrace()
}
}
override fun onDestroy() {
super.onDestroy()
stopSelf()
windowManager.removeView(floatView)
}
companion object {
var FOREGROUND_SERVICE_ID = 101
var START = "start"
var STOP_ACTION = "stop"
private const val CHANNEL = "default"
}
}
I have tried several ways of getting the context, but it always seems to come back null. I have tried this, this#Dooa, this.applicationContext, I also created a class MyApp to get context that way. it didn't work either. I used this link. Code below.
class MyApp: Application() {
private var context: Context? = null
override fun onCreate() {
super.onCreate()
context = applicationContext
}
fun getContext(): Context? {
return context?.applicationContext
}
}
I've also checked out this answer about Service is a Context, but I still haven't been able to get this to work.
I have tried the code in the onCreate first then I tried the onStartCommand to no avail. What am I missing?
The window pops up, It pops up with a button click, or from a notification, either way if I click on a view, it gives me the error at the top of this question.
You are doing this:
context = MyApp().getContext()
This is definitely wrong. MyApp is an Android component. You are not allowed to instantiate Android components yourself. Only the Android framework can do this (as it also sets up the Context and other important values.
If you want the Service context, just use this (A Service is a Context).
If you want the application context, just use getApplication() (Application is also a Context).

Observing multiple published variable changes inside ObservableObject

I have an ObservableObject that contains multiple published variables to handle my app state.
Whenever one of those published variables change, I want to call a function inside my ObservableObject. What's the best way to do that?
class AppModelController: ObservableObject {
#Published var a: String = "R"
#Published var b: CGFloat = 0.0
#Published var c: CGFloat = 0.9
// Call this function whenever a, b or c change
func check() -> Bool {
}
}
You can use didSet, like this code:
class AppModelController: ObservableObject {
#Published var a: String = "R" { didSet(oldValue) { if (a != oldValue) { check() } } }
#Published var b: CGFloat = 0.0 { didSet(oldValue) { if (b != oldValue) { check() } } }
#Published var c: CGFloat = 0.9 { didSet(oldValue) { if (c != oldValue) { check() } } }
func check() {
// Some Work!
}
}
The simplest thing you can do is listen to objectWillChange. The catch is that it gets called before the object updates. You can use .receive(on: RunLoop.main) to get the updates on the next loop, which will reflect the changed values:
import Combine
class AppModelController: ObservableObject {
#Published var a: String = "R"
#Published var b: CGFloat = 0.0
#Published var c: CGFloat = 0.9
private var cancellable : AnyCancellable?
init() {
cancellable = self.objectWillChange
.receive(on: RunLoop.main)
.sink { newValue in
let _ = self.check()
}
}
// Call this function whenever a, b or c change
func check() -> Bool {
return true
}
}

Turning Java object class into Swift class

So I'm learning how to make my Android apps into an iOS app. I've gotten pretty far though I'm having an issue when it comes creating the object. In my android app I read in a csv file and create a FireworkList object that contains info. Here is the code from my Android app:
import java.util.ArrayList;
public class FireworksList{
private ArrayList<Integer> _category = new ArrayList<>();
private ArrayList<String> _name = new ArrayList<>();
private ArrayList<String> _shotCount = new ArrayList<>();
private ArrayList<String> _price = new ArrayList<>();
private ArrayList<String> _description = new ArrayList<>();
private ArrayList<String> _videoUrl = new ArrayList<>();
private ArrayList<Integer> _imageResourceNumber = new ArrayList<>();
private ArrayList<Boolean> _favorite = new ArrayList<>();
private ArrayList<Boolean> _special = new ArrayList<>();
private Integer _specialCategoryNumer =15;
private Integer _nextId;
public FireworksList() {
_nextId=0;
}
public ArrayList<Integer> get_category() {
return _category;
}
public ArrayList<String> get_name() {
return _name;
}
public ArrayList<String> get_shotCount() {
return _shotCount;
}
public ArrayList<String> get_price() {
return _price;
}
public ArrayList<String> get_description() {
return _description;
}
public ArrayList<String> get_videoUrl() {
return _videoUrl;
}
public ArrayList<Integer> get_imageResourceNumber() {
return _imageResourceNumber;
}
public ArrayList<Boolean> get_favorite() {
return _favorite;
}
public void set_favorite(int index, Boolean bool) {
_favorite.set(index,bool);
}
public ArrayList<Boolean> get_special(){return _special;}
public void Add(int cat, String name, String shot, String price, String description, String video, int image, Boolean fav, Boolean special){
_category.add(_nextId,cat);
_name.add(_nextId,name);
_shotCount.add(_nextId,shot);
_price.add(_nextId,price);
_description.add(_nextId,description);
_videoUrl.add(_nextId,video);
_imageResourceNumber.add(_nextId,image);
_favorite.add(_nextId,fav);
_special.add(_nextId,special);
_nextId++;
}
public int Count(){
return _nextId;
}
public FireworksList CategorySort(int position){
FireworksList fireworksListTemp = new FireworksList();
for(int i=0; i<_nextId;i++){
if(position==0){
fireworksListTemp.Add(_category.get(i),_name.get(i),_shotCount.get(i),_price.get(i),_description.get(i),_videoUrl.get(i),_imageResourceNumber.get(i),_favorite.get(i),_special.get(i));
}
else if(position==_category.get(i)){
fireworksListTemp.Add(_category.get(i),_name.get(i),_shotCount.get(i),_price.get(i),_description.get(i),_videoUrl.get(i),_imageResourceNumber.get(i),_favorite.get(i),_special.get(i));
}
else if(position==_specialCategoryNumer&&_special.get(i)==true){
fireworksListTemp.Add(_category.get(i),_name.get(i),_shotCount.get(i),_price.get(i),_description.get(i),_videoUrl.get(i),_imageResourceNumber.get(i),_favorite.get(i),_special.get(i));
}
}
return fireworksListTemp;
}
public FireworksList FavoriteSort(){
FireworksList fireworksListTemp = new FireworksList();
for(int i = 0; i<_nextId;i++){
if(_favorite.get(i)==true){
fireworksListTemp.Add(_category.get(i),_name.get(i),_shotCount.get(i),_price.get(i),_description.get(i),_videoUrl.get(i),_imageResourceNumber.get(i),_favorite.get(i),_special.get(i));
}
}
return fireworksListTemp;
}
public int FindIndex(String name, FireworksList fireworksList){
int found=0;
for(int j=0;j<fireworksList.Count();j++){
if(fireworksList.get_name().get(j).equals(name)){
found=j;
}
}
return found;
}
}
I've started rewriting my code yet I ran into an issue when it came to creating a new Firework list then appending to it with what is needed in the categorySort function. Here is my modified code so far:
class FireworkList {
var _category = [Int]()
var _name = [String]()
var _shotCount = [String]()
var _price = [String]()
var _description = [String]()
var _videioUrl = [String]()
var _imageResourceNumber = [Int]()
var _favorite = [Bool]()
var _special = [Bool]()
private var _specialCategoryNumber : Int = 15
private var _nextId : Int = 0
func FireworksList(){_nextId = 0}
func get_category() -> Array<Int>{return _category}
func get_name() -> Array<String>{return _name}
func get_shotCount() -> Array<String>{return _shotCount}
func get_price() -> Array<String>{return _price}
func get_discription() -> Array<String>{return _description}
func get_videoUrl() -> Array<String>{return _videioUrl}
func get_imageResourceNumber() -> Array<Int>{return _imageResourceNumber}
func get_favorite() -> Array<Bool>{return _favorite}
func get_special() -> Array<Bool>{return _special}
func set_favorite(index : Int, bool : Bool){_favorite[index] = bool}
func add(cat : Int, name : String, shot : String, price : String, description : String, video : String, image : Int, fav : Bool, special : Bool){
_category.insert(cat, at: _nextId)
_name.insert(name, at: _nextId)
_shotCount.insert(shot, at: _nextId)
_price.insert(price, at: _nextId)
_description.insert(description, at: _nextId)
_videioUrl.insert(video, at: _nextId)
_favorite.insert(fav, at: _nextId)
_special.insert(special, at: _nextId)
_nextId+=1
}
func Count()->Int{return _nextId}
func CategorySort(position : Int)-> [FireworkList]{
var fireworkListTemp = [FireworkList]()
for i in 0..._nextId{
if(position == 0){
fireworkListTemp.append(FireworkList())
}
}
return fireworkListTemp
}
}
I'm thankful for any help.
The main issue here is that your java class is poorly designed and you are taking this design with you when writing it in swift. Rather than having a bunch of properties that are collections you should create a struct for those properties and have one array with the struct. (I didn't include all properties to keep the code shorter).
struct Firework {
var category: Int
var name: String
var shotCount: String
var price: String
var special: Bool
}
and then declare it in the main class
class FireworkList {
private var fireworks = [Firework]()
Below is the class with the add, count and categorySort functions to show some examples of how to use this struct. As you can see this means much less code. I also taken the liberty to rename properties and functions to follow recommended swift naming practices.
For the categorySort I have made use of the high order function filter to collect the correct items. If you are going to work with swift I would recommend you learn more about it and the other high order functions like sort, map etc.
Also worth mentioning to someone coming from java is that we don't use get/set methods to the same extent in swift. We most access the property directly like let x = myObject.someValue or myObject.someValue = 10
class FireworkList {
var fireworks = [Firework]()
private let specialCategoryNumber = 15
func add(cat : Int, name : String, shot : String, price : String, special: Bool) {
self.fireworks.append(Firework(category: cat, name: name, shotCount: shot, price: price, special: special))
}
func count() -> Int { return fireworks.count }
func categorySort(position : Int) -> [Firework] {
switch position {
case 0:
return self.fireworks
case specialCategoryNumber:
return self.fireworks.filter { $0.category == specialCategoryNumber && $0.special}
default:
return self.fireworks.filter {$0.category == position}
}
}
}
Here's how I would do it:
public class FireworksList {
private var _category = [Int]()
private var _name = [String]()
private var _shotCount = [String]()
private var _price = [String]()
private var _description = [String]()
private var _videoURL = [String]()
private var _imageResourceNumber = [Int]()
public var favorite = [Bool]()
private var _special = [Bool]()
private let specialCategoryNumber = 15
private var nextId = 0
public var category: [Int] {
get {
return _category
}
}
public var name: [String] {
get {
return _name
}
}
public var shotCount: [String] {
get {
return _shotCount
}
}
public var price: [String] {
get {
return _price
}
}
public var description: [String] {
get {
return _description
}
}
public var videoURL: [String] {
get {
return _videoURL
}
}
public var imageResourceNumber: [Int] {
get {
return _imageResourceNumber
}
}
public var special: [Bool] {
get {
return _special
}
}
public var count: Int {
get {
return nextId
}
}
public func add( cat: Int, name: String, shot: String, price: String, description: String, video: String, image: Int, fav: Bool, special: Bool) {
self._category.append(cat)
self._name.append(name)
self._shotCount.append(shot)
self._price.append(price)
self._description.append(description)
self._videoURL.append(video)
self._imageResourceNumber.append(image)
self.favorite.append(fav)
self._special.append(special)
nextId += 1
}
public func categorySort(at position: Int) -> FireworksList {
let tmp = FireworksList()
for i in 0...nextId {
if position == 0 || position == category[i] ||
(position == specialCategoryNumber && special[i] == true) {
tmp.add(cat: category[i], name: name[i], shot: shotCount[i], price: price[i], description: description[i], video: videoURL[i], image: imageResourceNumber[i], fav: favorite[i], special: special[i])
}
}
return tmp
}
public func favouriteSort() -> FireworksList {
let tmp = FireworksList()
for i in 0...nextId {
if favorite[i] {
tmp.add(cat: category[i], name: name[i], shot: shotCount[i], price: price[i], description: description[i], video: videoURL[i], image: imageResourceNumber[i], fav: favorite[i], special: special[i])
}
}
return tmp
}
// I'm putting this function as static as it isn't directly related to any particular instance of FireworksList at any point of time.
public static func findIndex(name: String, fireworksList: FireworksList) -> Int {
var found = 0
for j in 0...fireworksList.count {
if fireworksList.name[j] == name {
found = j
}
}
return found
}
}
My code simply almost directly follows your Java code.
This is my first time trying to contribute in Stack Overflow, and I hope this can be helpful to you.

Enum case 'case' is not a member of type 'Type'

I'm a complete new-be in programming and have just started learning swift and iOS development.
The idea is to create a kind of 'set game' (a simple card game).
And I'm trying to implement .contains methods to find if an array contains a particular case but I'm stuck - in line 67 (if case Card.Symbol.oval = element) I get this error: Enum case 'oval' is not a member of type 'Card'
What am I doing wrong?
import Foundation
struct Deck {
private (set) var cards = [Card] ()
init() {
for symbol in Card.Symbol.all {
cards.append(Card(symbol: symbol))
}
}
}
struct Card: Hashable {
static func == (lhs: Card, rhs: Card) -> Bool {
return lhs.identifier == rhs.identifier
}
func hash(into hasher: inout Hasher) {
hasher.combine(identifier)
}
var symbol: Symbol
enum Symbol: String {
case squiggle = "■"
case oval = "●"
case diamond = "▲"
static var all = [Symbol.squiggle, .oval, .diamond]
}
private var identifier: Int
private static var identifierFactory = 0
private static func getUniqueIdentifier() -> Int {
identifierFactory += 1
return identifierFactory
}
init(symbol: Symbol) {
self.identifier = Card.getUniqueIdentifier()
self.symbol = symbol
}
}
struct SetGame {
var deck = Deck ()
lazy var cardsInDeck = deck.cards
var cardsOpen = [Card] ()
var cardsChosen = [Card] ()
mutating func chooseCard(at index: Int) {
if cardsChosen.count < 3 {
cardsChosen.append(cardsOpen[index])
}
let itemFound = cardsChosen.contains { element in
if case Card.Symbol.oval = element {
return true
} else {
return false
}
}
}
}

Resources