handle cases of Enums in Swift - ios

How can we handle the same case with different inputs from the response in Enum's
enum MyNotificationType: String, Codable {
case practice = "push"
case practice = "PracticeRecommendation"
case play = "PlayRecommendation"
case play = "pop"
}
Edit:
I need this because I've common practice image for
push, PracticeRecommendation
and play image for
PlayRecommendation, pop
Edit 2:
enum MyNotificationType: String, Codable {
case push = "push"
case practice = "PracticeRecommendation"
case play = "PlayRecommendation"
case pop = "pop"
}
And added a switch
private func showImage(_ type: MyNotificationType) {
switch type {
case .practiceRecommendation, .push:
self.typeImgView.image = UIImage(named: "Practice")
break
case .play, .pop:
self.typeImgView.image = UIImage(named: "Play")
break
}
}
To deal with Images

Hmm. You can use enums with associated types, though you wouldn't be able to statically ensure possible strings unless you change init(rawType) too. Though, I'm not sure what you are trying to achieve so there could be a different way
enum MyNotificationType{
case practice(value: String)
case play(value: String)
init(rawType: String){
//define what case based on string, do error if you can't handle or use a unknown case
}
}

Related

Swift enum with custom object raw value

I try to implement a state machine for my ViewController, so i create a enum to express the possible state of my ViewController :
enum SMState:RawRepresentable{
case empty,data(UIView),failed(UIView),noData(UIView)
}
The 4 state of enum is suitable for my ViewController, and some state associate with a custom view to show when ViewController enter the specify state.
Then i make SMState impl RawRepresentable Protocol
enum SMState:RawRepresentable{
case empty,data(UIView),failed(UIView),noData(UIView)
typealias RawValue = UIView
init?(rawValue: SMState.RawValue) {
// rawValue is a view but i can't judge what to return
return what???
}
var rawValue: UIView{
switch self {
case .data(let v):
return v
case .failed(let v):
return v
case .noData(let v):
return v
case .empty:
return UIView()
}
}
}
How should i implement init?(rawValue:SMState.RawValue) function above, i can't image how to do this.
Update
Why i implement RawRepresentable :
I think enum is more suitable for representable different state for ViewController instead of Class or Struct, but enum cannot contains stored property, it can only carry a UIView Object through RawRepresentable, any better idea or magic is welcome :D
#Hamish You are right, i shouldn't insist using RawRepresentable, after a nice sleep, i finally archive what i want :
//: Playground - noun: a place where people can play
import UIKit
enum SMState{
case empty,data(UIView),failed(UIView),noData(UIView)
}
extension SMState{
init() {
self = .empty
}
init(failed view:UIView) {
self = .failed(view)
}
init(data view:UIView) {
self = .data(view)
}
init(noData view:UIView) {
self = .noData(view)
}
}
let state = SMState(failed: UIView())
switch state {
case .failed(let v):
print(v)
default:break
}
This is what i want, each enum state own a separate View, i do different operation in different state, using the View that the state carry ~
This approach is much like using Class, in my situation, i am not sure that there may be more states, then it is impossible to extend or subclass the SMState because its a enum, i am think about using Class
What i am trying to do is much like this library StatefulViewController, and i want to make it more flexible.
Any suggestion is welcome ~
:D
There is already available a specific state machine you could use instead of inventing the wheels: GKStateMachine. It has all the required method to transition from state to state. We also use it for different view controller states. Just take you time to read a bit and find some examples, to have your code nice and clean. You will also be able to combine the implementation with a corresponding enum of states, which will just define the states without a need of having associated values there.

Swift custom UITableViewController: switch statement case label section enum

To make my code more readable & maintainable, what's the best way to use labels instead of hardcoded Ints for case labels in a switch statement with a control expression of type Int?
E.g., inside my SettingsTableViewController, I tried
enum Section : Int {
case Phone
case LogOut
case DeleteAccount
}
and in – tableView:didSelectRowAtIndexPath:
switch indexPath.section {
case .Phone:
// Push EditPhoneViewController
case .LogOut:
// Log out
case .DeleteAccount:
// Present action-sheet confirmation
}
but got the compile error
Enum case pattern cannot match values of the non-enum type 'Int'
In the switch you can't simply use indexPath.section as that is not the same type as your enum.
Use switch Section(rawValue: indexPath.section)!

Is it possible to add a case to an existing enumeration where there is no source?

I am implementing my own TableView because I would like to have special animation when reloading a row using reloadRowsAtIndexPaths:withRowAnimation.
The problem is that I need to give a type of animation when I'm calling this method. So I would like to know if it's possible to add an extra case to UITableViewRowAnimation enumeration?
No, it's not possible, for at least one reason: switch statements not using a default case wouldn't compile, because they would be missing the newly added case.
Consider this enum:
enum TestEnum {
case ONE
case TWO
}
and some code using it:
let testOne = TestEnum.ONE
switch testOne {
case .ONE:
println("one")
case .TWO:
println("two")
}
If you were able to add one or more cases in an extension:
extension TestEnum {
case THREE
}
then the switch statement written above wouldn't compile because the new case is not handled.

Error when passing an int EXC_BREAKPOINT(code=1 Swift Xcode ios

I'm getting an error when passing a let variable as a tag in a for loop, but not when I replace the variable with a number. I can println(i) and return a number.
Why wont accept it as a key?
I have also tried setting a var as a counter with the same results
I get an error in:
swift_dynamicCastObjCClassUnconditional
full error:
Thread 1: EXC_BREAKPOINT(code=1, subcode=0x1001ee4b0)
func updateThing() {
for (i, img) in enumerate(thingState) {
switch img {
case 0:
image = UIImage(named: "0.png");
break
case 1:
image = UIImage(named: "1.png");
break
case 2:
image = UIImage(named: "2.png");
break
default:
image = UIImage(named: "x.png");
}
thing = self.view.viewWithTag(i) as UIButton;
thing.setImage(image, forState: .Normal);
}
But if I replace the i with a number there is no error and the image with the specified tag changes, and if I println(i) I get a number for each pass
thing = self.view.viewWithTag(2) as UIButton;
You want to be sure your views are Buttons, else it will fail to cast your view.
func updateThing() {
for (i, img) in enumerate(thingState) {
switch img {
case 0:
image = UIImage(named: "0.png");
break
case 1:
image = UIImage(named: "1.png");
break
case 2:
image = UIImage(named: "2.png");
break
default:
image = UIImage(named: "x.png");
}
if let thing = self.view.viewWithTag(i) as? UIButton {
thing.setImage(image, forState: .Normal)
}
}
}
The optional cast operator (as?) is preferred to the cast operator(as) since it doesn't make your app crash when it fails to cast.
Oh and semicolons are useless in Swift :)
EDIT:
In the latest Swift version, as has been replaced with as!, but as still exists.
as! is used to force cast with no check and is prone to craches. You mainly use it to down cast and you're absolutely sure of the type of the object.
as can be used as an upcast such as CAShapeLayer to CALayer or other special cases like [NSObject:AnyObject] to NSDictionary. Making downcast will fail to compile.
The problem is that you do not declare i but take it implicitly from thingState. Without seeing the declaration of the latter it's hard to tell, but I guess you need to do
thing = self.view.viewWithTag(Int(i)) as UIButton
And yes: semicolons are superfluous; as well as the break
This problem is to delete button by your mistake.
and You must see Your StoryBoard Screen or Xib file.
I think You Deleted Button.
I faced the same problem, i tried Shift+Cmd+K to clean the project and it fixed the problem

Swift: UIButton textLabel.text value not useable in switch statement

I am new to Swift and iOS development, so I am trying to build a calculator app for learning purposes. However, I am encountering an error. I have titled all of my buttons with the number they represent, so I am retrieving the title in the buttonPress IBAction via sender.titleLabel.text. Then, I pass that into a switch statement to determine if the button was a number or an operator.
func handleButton (sender:UIButton) {
switch sender.titleLabel.text {
case "1","2","3","4","5","6","7","8","9","0" :
println(sender.titleLabel.text)
default:
break
}
}
The error is that sender.titleLabel.text will not bind to the string values I have entered - nor any string values - even though it is is of type String.
There seems to be a bug in the complier at the moment where Implicitly Unwrapped Optionals cannot be used in switch statements. Instead you can use optional binding to satisfy the compiler. As an extra plus, this will handle the case where titleLabel.text is nil.
func handleButton (sender:UIButton) {
if let text = sender.titleLabel.text {
switch text {
case "1","2","3","4","5","6","7","8","9","0" :
println(sender.titleLabel.text)
default:
break
}
}
else {
// sender.titleLabel.text is nil
}
}

Resources