简体   繁体   中英

Check if value is in array - DatePicker Swift

I need to check if the hour selected by the user is outside of working hours. I am trying to achieve this result with a for in loop and switch statement, but I am not sure how to implement this. If var components matches a value in the timeRestricted array, it should break from the switch statement. Thanks for your help.

class FourthViewController: UIViewController {


@IBOutlet weak var myDatePicker: UIDatePicker!
                var currentTime = NSDate()
                let timeRestricted = [00,01,02,03,04,05,06,19,20,21,22,23]
                var dateComponents = NSDateComponents()
var dateFormatter:NSDateFormatter = NSDateFormatter()

@IBOutlet weak var someLabel: UILabel!


override func viewDidLoad() {

    super.viewDidLoad()

    dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm"

    // load current time as minimum date
    self.myDatePicker.minimumDate = NSDate(timeInterval: 1, sinceDate: currentTime)

    myDatePicker.addTarget(self, action: #selector(self.datePickerAction(_:)), forControlEvents: UIControlEvents.ValueChanged)


}


func datePickerAction(sender: UIDatePicker) {

    var timeSelected = sender.date
    var unitFlags: NSCalendarUnit = [.Hour]
    var components = NSCalendar.currentCalendar().components(unitFlags, fromDate: timeSelected)



    for components in timeRestricted {
        switch components {
        case timeRestricted[0...12]: print("update label")

        default: print(" record input data and segue to next screen")
        }



     }

  }

}

You have several misunderstandings in your code.

First, you have an NSDateComponent in your local variable components . Using for components in timeRestricted {...} introduces another local variable components , which would not be what you intend.

Second, you cannot use array as a case label. So, both for-in and switch-case does not fit for checking if an hour is included in the timeRestricted .

Maybe your datePickerAction needs to be something like this:

func datePickerAction(sender: UIDatePicker) {

    let timeSelected = sender.date
    let unitFlags: NSCalendarUnit = [.Hour]
    let components = NSCalendar.currentCalendar().components(unitFlags, fromDate: timeSelected)
    let hour = components.hour

    if timeRestricted.contains(hour) {
        print("update label")
    } else {
        print(" record input data and segue to next screen")
    }
}

Ok, let's see some other ways. One important thing in this case is that you need to retrieve hour value from the date components , so, the following codes replace the last 5 lines of my datePickerAction(_:) above.

Start with using for-in .

    var isInArray = false
    for restrictedHour in timeRestricted {
        if hour == restrictedHour {
            isInArray = true
            //We have no need to check the rest...
            break
        }
    }
    if isInArray {
        print("update label")
    } else {
        print(" record input data and segue to next screen")
    }

This code is very similar to what contains(_:) method does internally. And, you know, the for-in syntax introduces a new variable. You'd better avoid using the same name as any of the existing variables. Which makes many readers of your code confused, including yourself.


To use switch-case , you need to write all comma-separated values directly after the case keyword.

    switch hour {
    case 00,01,02,03,04,05,06,19,20,21,22,23:
        print("update label")
    default:
        print(" record input data and segue to next screen")
    }

The two above were some examples using basic Swift control statements. But the last example is a little bit advanced.

Define an overload for ~= operator (read as "matches"), somewhere at the top level (meaning outside of any class definitions nor such).

func ~= <T: Equatable>(lhs: [T], rhs: T) -> Bool {
    return lhs.contains(rhs)
}

Having this definition somewhere in your project, you can use array variables or constants for case label of switch statement.

    switch hour {
    case timeRestricted:
        print("update label")
    default:
        print(" record input data and segue to next screen")
    }

In this case, Swift uses that ~= operator, so, this is nearly the same as the first example using contains . So confusing that I wouldn't recommend.


With just knowing you can retrieve hour as an Int , and some basics about Swift language, you have got so many ways to do the same thing. Do it as you like.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM