How to use a Set in Swift 3.0 without generic usage - swift

First of all i have to say i come from Java programming and compared with Java everything in Swift 3.0 seems to be totally complicated. I thought what i want to do is easy but it turned out it is not.
I have two objects:
protocol Customer {
}
and:
class Consulter {
}
I want my Consulter class to hold a Set of Customer:
class Consulter {
var customers: Set<Customer>;
}
Ok here the first thing. The Compiler now is complaining that Customer has to implement Hashable... really? Swift isnt doing that for me? Ok. So lets go for it:
func ==(lhs: Customer, rhs: Customer) -> Bool {
return lhs.hashValue == rhs.hashValue;
}
protocol Customer: Hashable {
var: hashValue: Int {
return "123".hashValue;
}
}
And in my Consulter class i now would have to do the following:
class Consulter<T: Customer> {
var customers: Set<T>;
}
Ok this is working. But now i have another class:
func ==(lhs: Location, rhs: Location) -> Bool { // here the error!
return lhs.hashValue == rhs.hashValue;
}
class Location<T: Customer> : Hashable {
var customer: T;
....
}
For the Equatable of the class Location i now get the error:
Reference to generic type 'Location' requires arguments in <...>
So what argument is the compiler expecting here? I dont know any concrete types at this point.
EDIT
my Customer protocol will later have different concrete implementations. A Customer can for example be a Family or a Person. In the Consulter class i want to have a Set of Customer containing both: families and persons. I think this is a simple and logical approach.

Since you intend to use types conforming to Customer in applications where they must be Hashable (e.g. as members of a Set), there is no reason why not to add this Hashable constraint directly to the Customer protocol. This way you move the responsibility to conformance to Hashable to the actual types that you consider to be Customer's
protocol Customer: Hashable {}
class Consulter<T: Customer> {
var customers: Set<T>?
}
class Location<T: Customer>: Hashable {
var customer: T
init(customer: T) { self.customer = customer }
var hashValue: Int {
return customer.hashValue
}
}
func ==<T: Customer>(lhs: Location<T>, rhs: Location<T>) -> Bool {
return lhs.customer == rhs.customer /* && ... test other properties */
}
Also, be careful using X.hashValue == Y.hashValue for testing for equality, since there is no guarantee that hashvalues are unique (consider them mainly used for clever "bin" categorization).
Or, since Swift 3
// ... as above
class Location<T: Customer>: Hashable {
var customer: T
init(customer: T) { self.customer = customer }
var hashValue: Int {
return customer.hashValue
}
static func ==(lhs: Location<T>, rhs: Location<T>) -> Bool {
return lhs.customer == rhs.customer /* && ... test other properties */
}
}

Related

How to conform to a protocol with a generic superscript affordance in Swift?

TL;DR
How can I conform to the supscript function of a protocol in my implementation?
Protocol:
protocol DataStore {
//...
subscript<T>(id: T.ID) -> T where T: Identifiable { get set }
}
Neither
subscript<T>(id: T.ID) -> T where T : Identifiable {
get { Project() }//just to return anything for the time being…
set {}
}
nor
subscript(id: Task.ID) -> Task {
get { Project() }//just to return anything for the time being…
set {}
}
work...
The details:
I have developed a habit of creating specific data stores for my models. They all have the same functionality. A specific example could look like this:
final class ProjectDataStore: ObservableObject {
{
static let shared = ProjectDataStore()
let persistence = AtPersistLocally.shared // that's from a personal package I made that handles saving and loading locally as json files
#Published var projects: [Project] {
didSet { //save }
}
private init(projects: [Project]? = nil) {
//load from persistence
}
subscript(id: Project.ID) -> Project? {
get { //return project with id }
set { //set project at id }
}
func getBinding(by id: Project.ID) -> Binding<Project> {
//return Binding
}
func getProjectBy(taskId: Task.ID) -> Project {
//return instance
}
private func getIndex(by id: Project.ID) -> Int? {
//return index in array
}
private func load() -> [Project] {
//load from persistence
}
private func save() {
//save from persistence
}
}
While this works as expected, I'd like to be able to introduce a protocol that I could when adding new functionality / models to have a blueprint on what's necessary for my DataStore.
Here is my first attempt:
protocol DataStore {
static var shared: Self { get }
}
extension DataStore {
var persistence: AtPersistLocally {
get {
AtPersistLocally.shared
}
}
}
To also conform to ObservableObject, I introduce a typealias
typealias ObservableObjectDataStore = DataStore & ObservableObject
and change my model to conform to this new typealias:
final class ProjectDataStore: ObservableObjectDataStore {
//...
}
With this, I already have a static instance and access to persistence available.
Next step of course is to move more and more properties to the protocol–which is what I am struggling with right now.
Let's look at superscript first of all: I guess I understand what needs to be added to the protocol:
protocol DataStore {
//...
subscript<T>(id: T.ID) -> T where T: Identifiable { get set }
}
My problem now is that I don't know how to go about conforming to this subscript now while also getting access to a concrete model from the generic T from the implementation. This attempt…
final class ProjectDataStore: ObservableObjectDataStore {
//...
subscript<T>(id: T.ID) -> T where T : Identifiable {
get { Project() }//just to return anything for the time being…
set {}
}
}
…leads to the error message Cannot convert return expression of type 'Task' to return type 'T'.
If I go with…
final class ProjectDataStore: ObservableObjectDataStore {
//...
subscript(id: Task.ID) -> Task {
get { Project() }//just to return anything for the time being…
set {}
}
}
…the error message changes to Type 'TaskDataStore' does not conform to protocol 'DataStore'.
So I guess basically what I am asking is: how can I conform to my protocol's generic superscript in my implementation of ProjectDataStore?
I have a feeling that I am not too far of, but a critical info is obviously missing…
subscript<T>(id: T.ID) -> T where T: Identifiable { get set }
This says that the caller may pick any Identifiable T, and this method promise return a value of that type. This can't be implemented (other than calling fatalError() and crashing). Identifiable doesn't even promise that the type has an init. Your protocol is impossible.
What you probably meant to write is, which says that a given DataStore will return some specific Identifiable type (not "whatever type the caller requests"):
protocol DataStore {
associatedType Item: Identifiable
subscript(id: Item.ID) -> Item { get set }
}
But I expect this would be much better implemented without a protocol, and just use a generic struct:
struct DataStore<Item: Identifiable> { ... }

Segmentation Fault in Swift

I get the following error when running swift run inside of an executable Swift Package:
zsh: segmentation fault swift run
I have been able to boil the code down to the following:
enum MyEnum {
case FirstCase
case SecondCase
case Other
}
struct MyEnumCollection {
private var enums: [MyEnum]
}
extension MyEnumCollection: RangeReplaceableCollection {
public init() {
self.enums = []
}
}
extension MyEnumCollection: Collection {
public var startIndex: Int {
0
}
public var endIndex: Int {
self.enums.count
}
public subscript(position: Int) -> MyEnum {
return self.enums[position]
}
public func index(after i: Int) -> Int {
return self.enums.index(after: i)
}
}
var collection = MyEnumCollection()
collection.append(MyEnum.FirstCase)
The segmentation fault happens on the last line, at the append statement.
Can someone help me understand why this is happening and how I should fix this?
Update
Thanks to a comment from #MartinR it turns out that a even better solution is to implement replaceSubrange(_:with:) from the RangeReplaceableCollection protocol instead of append
mutating func replaceSubrange<C>(_ subrange: Range<Int>, with newElements: C) where C : Collection, MyEnum == C.Element {
self.enums.replaceSubrange(subrange, with: newElements)
}
Old solution
You need to implement append() as well
public mutating func append(_ newElement: MyEnum) {
enums.append(newElement)
}
There is a default implementation of this function but of course it has no knowledge about your internal data source enums so it is not usable.
Going forward you might also need to implement other functions that has a default implementation.
Another thing, personally I would use the properties of the Array class as well when conforming to the protocol.
public var startIndex: Int {
return enums.startIndex
}
public var endIndex: Int {
return self.enums.endIndex
}

Swift 2 Generic data structure not conforming to Equatable protocol

I am working on building a flexible data structure in Swift called Node that, by itself, is not tied to any type of content. However, the Payload data within the Node is declared as the following generic Element struct that conforms to the Equatable protocol:
public struct Element<T>: Equatable {
var data: T;
}
public func ==<T:Equatable>(lhs: Element<T>, rhs: Element<T>) -> Bool {
return lhs.data == rhs.data;
}
The constraint is that the Element has to be tied to an equatable class type. The problem I'm having is with the Node containing this Element. The Node would be used in a Dictionary, Array, or any other container type. Here is what I have:
public class Node: Equatable {
var payload: Element<AnyObject>
init(_data: Element<AnyObject>) {
self.payload = _data
}
}
public func ==(lhs: Node, rhs: Node) -> Bool {
return lhs.payload == rhs.payload;
}
Of course, I'm getting the error that AnyObject does not conform to Equatable. Is there any way to constrain the declaration of the payload to only Objects that are equatable? At this point, I don't know what kind of objects may be stored in the payload.
Also just realized I need to put a class check in the == function in Node to make sure the two Node payloads are compatible to be compared--don't need them to be.
Thoughts? Thank you!
In order to constrain payload to a type that is Equatable, you'll need Node to be a generic class so that it can pass along that constraint.
You can specify the constraint in your class declaration:
public class Node<T: Equatable>: Equatable {...}
And then when declaring your payload you can set its Element type to just T:
var payload: Element<T>
When testing the code, I had to also make the generic constraint, T, in Element conform to Equatable. Entire code for reference:
public struct Element<T: Equatable>: Equatable {
var data: T
}
public func ==<T:Equatable>(lhs: Element<T>, rhs: Element<T>) -> Bool {
return lhs.data == rhs.data
}
public class Node<T: Equatable>: Equatable {
var payload: Element<T>
init(_data: Element<T>) {
self.payload = _data
}
}
public func ==<T: Equatable>(lhs: Node<T>, rhs: Node<T>) -> Bool {
return lhs.payload == rhs.payload
}
This will produce the following results:
Node(_data: Element(data: 1)) == Node(_data: Element(data: 1)) // true
Node(_data: Element(data: 1)) == Node(_data: Element(data: 2)) // false

How to define initializers in a protocol extension?

protocol Car {
var wheels : Int { get set}
init(wheels: Int)
}
extension Car {
init(wheels: Int) {
self.wheels = wheels
}
}
on self.wheels = wheels i get the error
Error: variable 'self' passed by reference before being initialized
How can I define the initializer in the protocol extension?
As you can see this doesn't work under these circumstances because when compiling, one has to make sure that all properties are initialized before using the struct/enum/class.
You can make another initializer a requirement so the compiler knows that all properties are initialized:
protocol Car {
var wheels : Int { get set }
// make another initializer
// (which you probably don't want to provide a default implementation)
// a protocol requirement. Care about recursive initializer calls :)
init()
init(wheels: Int)
}
extension Car {
// now you can provide a default implementation
init(wheels: Int) {
self.init()
self.wheels = wheels
}
}
// example usage
// mark as final
final class HoverCar: Car {
var wheels = 0
init() {}
}
let drivableHoverCar = HoverCar(wheels: 4)
drivableHoverCar.wheels // 4
As of Xcode 7.3 beta 1 it works with structs as expected but not with classes since if they are not final the init(wheels: Int) in the protocol is a required init and it can be overridden therefore it cannot be added through an extension. Workaround (as the complier suggests): Make the class final.
Another workaround (in depth; without final class)
To work with classes without making them final you can also drop the init(wheels: Int) requirement in the protocol. It seems that it behaves no different than before but consider this code:
protocol Car {
var wheels : Int { get set }
init()
// there is no init(wheels: Int)
}
extension Car {
init(wheels: Int) {
self.init()
print("Extension")
self.wheels = wheels
}
}
class HoverCar: Car {
var wheels = 0
required init() {}
init(wheels: Int) {
print("HoverCar")
self.wheels = wheels
}
}
// prints "HoverCar"
let drivableHoverCar = HoverCar(wheels: 4)
func makeNewCarFromCar<T: Car>(car: T) -> T {
return T(wheels: car.wheels)
}
// prints "Extension"
makeNewCarFromCar(drivableHoverCar)
So if you make a Car from a generic context where the type on which you call init is only to be known as Car the extension initializer is called even though an initializer is defined in HoverCar. This only occurs because there is no init(wheels: Int) requirement in the protocol.
If you add it you have the former problem with declaring the class as final but now it prints two times "HoverCar". Either way the second problem probably never occurs so it might be a better solution.
Sidenote: If I have made some mistakes (code, language, grammar,...) you're welcome to correct me :)
My understanding is that this isn't possible, because the protocol extension can't know which properties the conforming class or struct has - and therefore cannot guarantee they are correctly initialized.
If there are ways to get around this, I'm very interested to know! :)
#Qbyte is correct.
In addition, you can take a look at my Configurable
In that I have Initable protocol
public protocol Initable {
// To make init in protocol extension work
init()
}
public extension Initable {
public init(#noescape block: Self -> Void) {
self.init()
block(self)
}
}
Then in order to conform to it
extension Robot: Initable { }
I have 2 ways, using final or implement init
final class Robot {
var name: String?
var cute = false
}
class Robot {
var name: String?
var cute = false
required init() {
}
}
May not be the same but in my case instead of using init I used a static func to return the object of the class.
protocol Serializable {
static func object(fromJSON json:JSON) -> AnyObject?
}
class User {
let name:String
init(name:String) {
self.name = name
}
}
extension User:Serializable {
static func object(fromJSON json:JSON) -> AnyObject? {
guard let name = json["name"] else {
return nil
}
return User(name:name)
}
}
Then to create the object I do something like:
let user = User.object(fromJSON:json) as? User
I know its not the best thing ever but its the best solution I could find to not couple business model with the data layer.
NOTE: I'm lazy and I coded everything directly in the comment so if something doesn't work let me know.

Add "for in" support to iterate over Swift custom classes

As we know, we can use the for..in loop to iterate across Arrays or Dictionaries. However, I would like to iterate over my own CustomClass like this:
for i in CustomClass {
someFunction(i)
}
What operations/protocols does CustomClass have to support for this to be possible?
Say you have a class "Cars" that you want to be able to iterate over using a for..in loop:
let cars = Cars()
for car in cars {
println(car.name)
}
The simplest way is to use AnyGenerator with the classes like this:
class Car {
var name : String
init(name : String) {
self.name = name
}
}
class Cars : SequenceType {
var carList : [Car] = []
func generate() -> AnyGenerator<Car> {
// keep the index of the next car in the iteration
var nextIndex = carList.count-1
// Construct a AnyGenerator<Car> instance, passing a closure that returns the next car in the iteration
return anyGenerator {
if (nextIndex < 0) {
return nil
}
return self.carList[nextIndex--]
}
}
}
To try a complete working sample add the two classes above and then try to use them like this, adding a couple of test items:
let cars = Cars()
cars.carList.append(Car(name: "Honda"))
cars.carList.append(Car(name: "Toyota"))
for car in cars {
println(car.name)
}
That's it, simple.
More info: http://lillylabs.no/2014/09/30/make-iterable-swift-collection-type-sequencetype
All of the above answers can be a little tricky. If you have an array in your class, which you want to iterate over (like in #Lee Whitney's answer), there's a much simpler way to implement it. You have the following class, CustomClass:
class CustomClass: SequenceType {
let array: [String]
init(array: [String]) {
self.array = array
}
func generate() -> IndexingGenerator<[String]> {
return array.generate()
}
}
Simple as that. Tested to work in the latest Xcode version (6.1 at the time of writing), and iOS 8.1.2. This code should be stable through future versions, though.
P.S. With generics, you can easily do your own Array replica by following this pattern, and only implement the methods which you want.
#Matt Gibson is correct. However, I would like to add more information for future reference.
From Advanced Swift:
This code:
for x in someSequence {
...
}
Is converted into this:
var __g = someSequence.generate()
while let x = __g.next() {
...
}
Therefore, one must adopt Sequence, which gives the class generate() and next(). Here are these protocols:
protocol Generator {
typealias Element
mutating func next() -> Element?
}
protocol Sequence {
typealias GeneratorType : Generator
func generate() -> GeneratorType
}
That would be the SequenceType protocol, and its related Generator protocol.
The SequenceType protocol says that the class must implement generate(), which returns something that conforms to the Generator protocol, which is the bit that does the actual work; the Generator protocol is the one with the all-important next() method.
There's an example of implementing it to allow for..in in the WWDC 2014 video "Advanced Swift" (in the generics example "A Simple Generic Stack", starting around slide 183.)
The basic info on which protocol to implement for for..in is in the Statements section of the documentation, which gives a brief overview of SequenceType and Generator
NOTE AnyGenerator and SequenceType are old types that do not exist in recent versions. You need to implement Sequence protocol now.
There are two ways to implement Sequence.
Conform to Sequence, IteratorProtocol at the same time by just implementing next() method. This approach is the simplest and there is an example in the headers. See Sequence.swift. Implementing both protocols at the same time could be non-realistic or not fulfill your needs. (It might prevent two different instances to be iterated at the same time, etc)
Conform to Sequence and return an object that implements IteratorProtocol. I think this is the most common case in real world classes (when things become a bit complicated, not Hello Worlds). There is also an example in the Sequence.swift
Below is an example of approach 2. An custom class (Linked List) which is iterable:
/// Linked List Node:
public class LinkedListNode <T> {
public internal(set) var value: T
public internal(set) var next: LinkedListNode<T>?
internal init(_ value: T) {
self.value = value
self.next = nil
}
}
/// Linked List with append method only.
public class LinkedList<T> {
public internal(set) var first: LinkedListNode<T>? = nil
public internal(set) var last: LinkedListNode<T>? = nil
/// Appends a new node.
public func append(_ value: T) {
if first == nil {
first = LinkedListNode(value)
last = first
} else {
last.next = LinkedListNode(value)
last = last.next
}
}
}
Finally the Sequence implementation
/// Sequence protocol adoption. It allows `for ... in` and a bunch of other methods too.
extension LinkedList: Sequence {
/// Iterator implementation
public class Iterator<T>: IteratorProtocol {
/// Maintain a ref to current element so next element can be reached
var cur: LinkedListNode<T>?
/// IteratorProtocol protocol requirement
public func next() -> T? {
let res = cur?.value
cur = cur?.next
return res
}
}
/// Sequence protocol requirement
public func makeIterator() -> Iterator<T> {
let g = LinkedList.Iterator()
g.cur = first
return g
}
}
Usage:
let linkedList = LinkedList<Int>()
linkedList.append(3)
linkedList.append(6)
linkedList.append(9)
linkedList.append(12)
for element in linkedList {
print(element)
}
let odds = linkedList.filter { return $0 % 2 == 0 }
print(odds)
The accepted answer is correct, and up until recently was the accepted way to address this. However, given the introduction of Protocol Extensions in Swift 2.0, rather than conformance to SequenceTypeand implementing func generate() -> GeneratorOf<Car> there is now an abstract base class that handles the implementation of this functionality for you called AnyGenerator<T> (see Apple docs) since GeneratorOf<T> no longer exists.
What this means is that you can simply subclass this abstract base class, and by doing do, inherit all of the functionality of the aforementioned protocol conformance:
class Cars: AnyGenerator<Car> {
private var carList = [Car]()
private var currentIndex:Int
...
}
One then need only override the next() method declared by the GeneratorType protocol (which AnyGenerator<T> also conforms to) in order to define the desired iteration behavior:
class Cars: AnyGenerator<Car> {
private var carList = [Car]()
private var currentIndex:Int
override func next() -> Car? {
if (currentIndex < self.carList.count) {
currentIndex++
return self.carList[currentIndex-1]
} else {
currentIndex = 0;
return nil
}
}
}