Reputation: 21870
I've got a ServiceGroup
entity with a one-to-many relationship to ServiceItem
called items
. I want to iterate over the items
but swift seems completely ignorant of the variable type because items
is just defined as an NSOrderedSet?
.
The only way I've found to be able to iterate over my items is that I have to cast them using the new case syntax added to for loops recently, but this seems ridiculous since the code -should- know what the type is already.
Anyone have suggestions so that I don't have to constantly case/coerce my relationship entities?
if let items = self.items {
for case let item as ServiceItem in items {
mins += item.calculateTotalMinutes()
}
}
Upvotes: 1
Views: 1005
Reputation: 658
You can convert the NSSet
used to model the CoreData one-to-many relationship to an array :
let serviceItems: [ServiceItem] = (myServiceGroup.items?.allObjects as? [ServiceItem]) ?? []
From there on, you can use usual forEach()
, map()
or reduce()
operations.
Upvotes: 0
Reputation: 285082
NSOrderedSet
has a property array
to get the backing array. As the property returns [Any]
you have to cast the type. And for convenience you could use forEach
if let items = self.items {
(items.array as! [ServiceItem]).forEach {
mins += $0.calculateTotalMinutes()
}
}
or reduce
if let items = self.items {
mins = (items.array as! [ServiceItem]).reduce(mins, { $0 + $1.calculateTotalMinutes() })
}
Upvotes: 0
Reputation: 449
Something slightly more elegant (in my opinion) would be to use higher order functions like so:
let minutes = items
.map({$0 as? ServiceItem})
.flatMap({$0})
.reduce(0) { (result, serviceItem) -> Double in
return result + serviceItem.calculateTotalMinutes()
}
Upvotes: 2