Error combining NSCalendarUnit with OR (pipe) in Swift 2.0
NSCalendarUnit
is an OptionSetType
in Swift 2, instead of a RawOptionSetType
. This means that you can't logical-or it anymore. Instead, you can use an array literal representation of it:
formatter.allowedUnits = [.Year, .Month, .WeekOfMonth, .Day, .Hour, .Minute]
How can I set an NSDate object to midnight?
Your statement
The problem with the above method is that you can only set one unit of
time ...
is not correct. NSCalendarUnit
conforms to the RawOptionSetType
protocol which
inherits from BitwiseOperationsType
. This means that the options can be bitwise
combined with &
and |
.
In Swift 2 (Xcode 7) this was changed again to be
an OptionSetType
which offers a set-like interface, see
for example Error combining NSCalendarUnit with OR (pipe) in Swift 2.0.
Therefore the following compiles and works in iOS 7 and iOS 8:
let date = NSDate()
let cal = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
// Swift 1.2:
let components = cal.components(.CalendarUnitDay | .CalendarUnitMonth | .CalendarUnitYear, fromDate: date)
// Swift 2:
let components = cal.components([.Day , .Month, .Year ], fromDate: date)
let newDate = cal.dateFromComponents(components)
(Note that I have omitted the type annotations for the variables, the Swift compiler
infers the type automatically from the expression on the right hand side of
the assignments.)
Determining the start of the given day (midnight) can also done
with the rangeOfUnit()
method (iOS 7 and iOS 8):
let date = NSDate()
let cal = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
var newDate : NSDate?
// Swift 1.2:
cal.rangeOfUnit(.CalendarUnitDay, startDate: &newDate, interval: nil, forDate: date)
// Swift 2:
cal.rangeOfUnit(.Day, startDate: &newDate, interval: nil, forDate: date)
If your deployment target is iOS 8 then it is even simpler:
let date = NSDate()
let cal = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
let newDate = cal.startOfDayForDate(date)
Update for Swift 3 (Xcode 8):
let date = Date()
let cal = Calendar(identifier: .gregorian)
let newDate = cal.startOfDay(for: date)
Declaring and using a bit field enum in Swift
Updated for Swift 2/3
Since swift 2, a new solution has been added as "raw option set" (see: Documentation), which is essentially the same as my original response, but using structs that allow arbitrary values.
This is the original question rewritten as an OptionSet
:
struct MyOptions: OptionSet
{
let rawValue: UInt8
static let One = MyOptions(rawValue: 0x01)
static let Two = MyOptions(rawValue: 0x02)
static let Four = MyOptions(rawValue: 0x04)
static let Eight = MyOptions(rawValue: 0x08)
}
let m1 : MyOptions = .One
let combined : MyOptions = [MyOptions.One, MyOptions.Four]
Combining with new values can be done exactly as Set
operations (thus the OptionSet part), .union
, likewise:
m1.union(.Four).rawValue // Produces 5
Same as doing One | Four
in its C-equivalent. As for One & Mask != 0
, can be specified as a non-empty intersection
// Equivalent of A & B != 0
if !m1.intersection(combined).isEmpty
{
// m1 belongs is in combined
}
Weirdly enough, most of the C-style bitwise enums have been converted to their OptionSet
equivalent on Swift 3, but Calendar.Compontents
does away with a Set<Enum>
:
let compontentKeys : Set<Calendar.Component> = [.day, .month, .year]
Whereas the original NSCalendarUnit
was a bitwise enum. So both approaches are usable (thus the original response remains valid)
Original Response
I think the best thing to do, is to simply avoid the bitmask syntax until the Swift devs figure out a better way.
Most of the times, the problem can be solved using an enum
and and a Set
enum Options
{
case A, B, C, D
}
var options = Set<Options>(arrayLiteral: .A, .D)
An and check (options & .A
) could be defined as:
options.contains(.A)
Or for multiple "flags" could be:
options.isSupersetOf(Set<Options>(arrayLiteral: .A, .D))
Adding new flags (options |= .C
):
options.insert(.C)
This also allows for using all the new stuff with enums: custom types, pattern matching with switch case, etc.
Of course, it doesn't have the efficiency of bitwise operations, nor it would be compatible with low level things (like sending bluetooth commands), but it's useful for UI elements that the overhead of the UI outweighs the cost of the Set operations.
Find out if an NSDate is today, yesterday, tomorrow
Check our Erica Sadun's great NSDate
extension
class: http://github.com/erica/NSDate-Extensions
There are lots of date comparisons, among them exactly what you need :)
Return NSArray from NSDictionary
Call valueForKey
on the array object returned from the fetch request. That will in-turn call valueForKey
on each object and return an array of all resulting values.
NSArray *timestamps = [objects valueForKey:@"timeStamp"];
Related Topics
Using Auto Layout to Orientate Stack Views Vertically in Portrait and Horizontally in Landscape
Swiftui Vertically Misaligned Text
Solve Equations of Type A*X = B Using Dgtsv_ or Sgtsv_
Using Nsdate to Get Date for Easter
Extension for Array Where Element Is Optional
Pass Custom Parameter to UIbutton #Selector Swift 3
Why Does a Function Have Long-Term Write Access to All of Its In-Out Parameters
Prevent Retain Cycle in Swift Function Pointers
In Swift, Dynamic Height for UItextview in UIcollectionview
How to Use This Fetchrequest() in Swift
Wkwebview Calayer to Image Exports Blank Image
Tvos Button Inside Navigationlink Is Not Working
Print Not Working in Swift 3 Extensions
Support Arkit in Lower End Devices
How to Specify The Name of The Output Executable