I have the following classes in Swift:
class A {}; class B {}
class Collection<T> {
var parent: Collection?
}
When I want to build a hierarchy like
var rootCol = Collection<A>()
var childCol = Collection<B>()
childCol.parent = rootCol
The last line produces this error:
Cannot assign value of type 'Collection<A>' to type 'Collection<B>?'
What type does parent have to be, so that one can assign it with different generic types?
The problem is that you are trying to assign an instance of type Collection<A> to a variable of type Collection<B>? which is not possible , You can only assign Collection<A> to Collection<A> or Collection<B> to Collection<B>.
Although your aren't writing <T> at the end of the parent type but swift infers that to be of the type Collection<T> and then also optional.
In This case I would recommend using protocol.
One more thing,it's advisable to NOT use names for classes that conflict with swift protocols.
class A {}
class B {}
protocol Foo{}
class Bar<T>:Foo {
var parent: Foo?
}
var rootCol = Bar<A>()
var childCol = Bar<B>()
childCol.parent = rootCol
Your structure can either be a tree of "containers" using a generic class based on the contained data (which can work on both reference and value types).
For example:
class TreeOf<T>
{
var value:T? = nil
weak var parent:TreeOf<T>? = nil
var children:[TreeOf<T>] = []
init(_ value:T? = nil)
{ self.value = value }
func addChild(_ value:T) -> TreeOf<T>
{
let newNode = TreeOf<T>()
newNode.value = value
children.append(newNode)
return newNode
}
}
var directory = TreeOf<String>("/")
directory.addChild("usr")
directory.addChild("library")
let users = directory.addChild("users")
users.addChild("paul")
users.addChild("John")
users.addChild("Mary")
let userNames = directory.children[2].children.map{$0.value}
Or your tree nodes themselves (i.e. the objects that are linked in the tree structure) can implement the linking variables and use a common protocol to obtain all the tree manipulation functionality for free. This however, only works on reference types and requires a final class.
For example:
protocol TreeNode:class
{
var parent :Self? { get set }
var children :[Self] { get set }
}
extension TreeNode
{
func removeFromParent()
{
parent?.children = parent!.children.filter{$0 !== self}
parent = nil
}
func childOf(_ newParent:Self) -> Self
{
removeFromParent()
parent = newParent
newParent.children.append(self)
return self
}
// ... more generic tree related functions provided by protocol for all classes
// e.g. root, count descendants, searches, traversal, prune and graft, etc.
}
final class FamilyMember:TreeNode
{
var parent:FamilyMember? = nil
var children:[FamilyMember] = []
var name = ""
init(_ newName:String) {name = newName}
}
let paul = FamilyMember("Paul")
let mary = FamilyMember("Mary").childOf(paul)
let john = FamilyMember("John").childOf(paul)
let suzie = FamilyMember("Suzie").childOf(mary)
let luke = FamilyMember("Luke").childOf(mary)
let irene = FamilyMember("Irene").childOf(john)
let miniPaul = paul.children.map{$0.name}
let miniMary = mary.children.map{$0.name}
Related
class SQS_Record {
var table: SQS_Table? = nil
}
class SQS_Table<RecordType: SQS_Record> {
func newRecord() -> RecordType {
let new = RecordType()
new.table = self <<< ERROR:
return new
}
}
COMPILER ERROR: Cannot assign value of type 'SQS_Table' to type 'SQS_Table<SQS_Record>'
In future i wish:
class Project: SQS_Record {
var name: String = ""
}
let projectsTbl = SQS_Table<Project>(...)
and create object like this
let item = projectsTbl.newRecord()
Given what you've described, you're looking for protocols, not classes. For example:
// TableRecords know their table (and know other things)
// Note that TableRecord is a PAT (protocol with an associated type).
// There can not be any variables of type "TableRecord." It can only
// be used to constrain other types (as in Table below).
protocol TableRecord {
init(table: Table<Self>)
var table: Table<Self> { get }
}
// Project is a concrete TableRecord that also has a name.
// There can be variables of type Project.
struct Project: TableRecord {
let table: Table<Self>
var name: String = ""
init(table: Table<Self>) {
self.table = table
}
}
// Tables can create new records of the Record type
class Table<Record: TableRecord> {
func newRecord() -> Record {
let new = Record(table: self)
return new
}
}
let projects = Table<Project>()
let item = projects.newRecord() // item is of type Project
Impossible to use generic type in recursive reference between two classes with inheritance
Whats why we need to do:
var table: AnyObject? - field can store any class (ref)
(table as! SQS_Table).reloadRecord(record: self as! Self) - exotic type cast based on Self.
I cant solve this problem with Protocol. Inheritance from reference type (Class - NOT struct) and type cast - prohibited
class SQS_Record {
var table: AnyObject? = nil
// Example - access to referenced table method and pass self param
func reload() {
guard __table != nil else { return }
(table as! SQS_Table<Self>).reloadRecord(record: self as! Self)
}
}
class SQS_Table<RecordType: SQS_Record> {
// RecordType - subclass of SQS_Record
func newRecord() -> RecordType {
let new = RecordType()
new.table = self
return new
}
func reloadRecord(record: RecordType) {
...
}
}
class Project: SQS_Record {
...
}
let projectsTable = SQS_Table<Project>(...)
let newProjectRecord = projectsTable.newRecord()
newProjectRecord.reload()
I am attempting to declare a linked list in Swift, with a finger type that is a reference to either a node, allowing to insert or remove beyond that node, or to the linked list itself, in which case inserting or removing at the top of the linked list.
I want to see if this can be made uniform down to the implementation, instead of having to special-case everything: Swift is object-oriented, after all.
I previously had a version which required forced casts, but again I'd like to see if this can be made to work without them (e.g. even if they never end up faulting they still imply runtime checks each time).
I currently have this code:
protocol ContainerNodeInterface: class {
associatedtype ContainedItem;
var contents: ContainedItem { get };
}
protocol ParentNodeInterface: class {
associatedtype LinkedItem: ContainerNodeInterface;
var next: LinkedItem? {get set};
}
class ProtoNode<Contents, NodeType: ParentNodeInterface>: ParentNodeInterface where NodeType.ContainedItem==Contents, NodeType.LinkedItem==NodeType { // not meant to be instantiated or directly referenced
typealias LinkedItem = NodeType;
var next: NodeType?;
init() {
next = nil;
}
final func insertThisAfterMe(_ node: NodeType) {
node.next = next;
next = .some(node);
}
final func removeNodeAfterMe() -> NodeType? {
guard let nextNode = next else {
return nil;
}
let result = nextNode;
next = result.next;
result.next = nil;
return nextNode;
}
}
class Node<Contents>: ProtoNode<Contents, Node<Contents>>, ContainerNodeInterface {
typealias ContainedItem = Contents;
typealias NextItem = Node<Contents>;
var contents: Contents;
init(withContents: Contents) {
contents = withContents;
super.init();
}
}
typealias ParentNode<Contents> = ProtoNode<Contents, Node<Contents>>;
But the Swift compiler, via Xcode, is complaining that Type 'Node<Contents>' does not conform to protocol 'ParentNodeInterface'. This makes no sense! And if I add explicit conformance to ParentNodeInterface to Node, then I get simultaneously that error and one of redundant conformance to the same protocol.
What is missing here?
Xcode Version 10.2 (10E125), Swift 5
I resolved it by splitting ProtoNode into an initial declaration and an extension:
protocol ContainerNodeInterface: class {
associatedtype ContainedItem;
var contents: ContainedItem { get };
}
protocol ParentNodeInterface: class {
associatedtype LinkedItem: ContainerNodeInterface;
var next: LinkedItem? {get set};
}
class ProtoNode<Contents, NodeType: ContainerNodeInterface>: ParentNodeInterface where NodeType.ContainedItem==Contents { // not meant to be instantiated or directly referenced
typealias LinkedItem = NodeType;
var next: NodeType?;
init() {
next = nil;
}
}
extension ProtoNode where NodeType: ParentNodeInterface, NodeType.LinkedItem==NodeType
{
final func insertThisAfterMe(_ node: NodeType) {
node.next = next;
next = .some(node);
}
final func removeNodeAfterMe() -> NodeType? {
guard let nextNode = next else {
return nil;
}
let result = nextNode;
next = result.next;
result.next = nil;
return nextNode;
}
}
class Node<Contents>: ProtoNode<Contents, Node<Contents>>, ContainerNodeInterface {
typealias ContainedItem = Contents;
typealias NextItem = Node<Contents>;
var contents: Contents;
init(withContents: Contents) {
contents = withContents;
super.init();
}
}
typealias ParentNode<Contents> = ProtoNode<Contents, Node<Contents>>;
I figure it helps the compiler break the dependency loop, where it has to determine whether Node, as a generic parameter, conforms to the protocol before it can determine the declaration is valid and consider the declared type, i.e. Node, as conforming to the protocol, but still it feels a bit silly for me to have to make this seemingly pointless extension declaration.
At the very least, the compiler could be slightly more helpful…
First, I would start with a simple linked-list Node type:
final class Node<Value> {
let value: Value
var next: Node<Value>?
init(_ value: Value) {
self.value = value
}
func insert(_ node: Node<Value>) {
node.next = next
next = node
}
func removeNext() -> Node<Value>? {
guard let removedNode = next else { return nil }
next = removedNode.next
removedNode.next = nil
return removedNode
}
}
Then, you can add the concept that you describe: a pointer to "either a node...or to the linked list itself." When you see "or" in a description, that implies a sum type, which in Swift is an enum, either a pointer to the head of a (possibly empty) list, or a pointer to a node. Each has slightly different behaviors, which you manage with switch.
enum NodePointer<Value> {
case head(Node<Value>?)
case node(Node<Value>)
mutating func insert(_ node: Node<Value>) {
switch self {
case .head(let n):
self = .head(node)
node.next = n
case .node(let n):
n.insert(node)
}
}
mutating func removeNext() -> Node<Value>? {
switch self {
case .head(let n):
self = .head(n?.next)
return n
case .node(let n):
return n.removeNext()
}
}
var pointee: Node<Value>? {
switch self {
case .head(let n): return n
case .node(let n): return n
}
}
}
With that you would have an interface like:
var list = Node(1)
list.insert(Node(2))
var ptr = NodePointer.head(list)
ptr.insert(Node(1))
ptr.pointee?.next?.next?.value // 2
Note that the specific problem you ran into (that the compiler couldn't work out the conformance) I believe is a compiler bug, though I also believe it's one that's fixed on master currently. I haven't tested that out though. But I don't believe the protocol-based approach is correct for this problem.
I am building a function that will take an instance of a class object and convert it to an XML request to be sent to a web service. To accomplish this, I am using mirroring to iterate through the key/value pairs in the class. In my testing, I see it is working great, with one major problem, none of the inherited class parameters are coming across. For example, in the code below, the loop is executed three times for "descriptionText, modelNumber and serialNumber, name and uuid are never collected. Is there a way for me to use mirroring and pick up all the parameters of the base class, as well as the widget? Also, if there is a better way to do this, I am all ears.
import UIKit
class BaseObject: NSObject {
var name = String()
var uuid = String()
}
class Widget: BaseObject {
var descriptionText = String()
var modelNumber = String()
var serialNumber = String()
}
var widget1 = Widget()
widget1.name = "Generic Widget"
widget1.uuid = "A guid"
widget1.descriptionText = "Class A Extra Larget Widget"
widget1.modelNumber = "1234"
widget1.serialNumber = "4321"
let widgetMirror = Mirror(reflecting: widget1)
for attr in widgetMirror.children {
print(attr.label!)
}
You need to use the superclassMirror: Mirror? property for that. For instance:
for attr in widgetMirror.superclassMirror!.children {
print(attr.label!)
}
prints the expected results:
name
uuid
Update. If you keep running into this, add this Mirror extension to your toolkit:
extension Mirror {
var allChildren: [Mirror.Child] {
var allChildren: [Mirror.Child] = []
var mirror: Mirror! = self
repeat {
allChildren.append(contentsOf: mirror.children)
mirror = mirror.superclassMirror
} while mirror != nil
return allChildren
}
}
Usage:
for attr in widgetMirror.allChildren {
print(attr.label!)
}
A partial answer was already posted, but here is a way to wrap it all up.
var mirror: Mirror? = Mirror(reflecting: widget1)
repeat {
for (index, child) in mirror!.children.enumerated() {
print (child.label!)
}
mirror = mirror?.superclassMirror
} while mirror != nil
I thought about a bit more. I think this is more Swifty.
extension Mirror {
var posterity: Children {
if let superclassMirror = superclassMirror {
return Children([children, superclassMirror.posterity].joined())
} else {
return children
}
}
}
let widgetMirror = Mirror(reflecting: widget1)
for child in widgetMirror.posterity {
print(child.label!)
}
I'm trying to print all the values from an object that inherits from a class, here is my example:
I create the class:
class Pokemon {
var name: String?
var type: String?
var level: Int?
var exp = 0.0
}
Create the object and assign some values:
var pikachu = Pokemon()
pikachu.name = "Pika Pika"
pikachu.level = 1
pikachu.type = "electricity"
pikachu.exp = 0
Now I would like to loop through all the pikachu object attributes and print the values. I'm thinking in a for each loop but I'm not sure how to implement it.
I know I can do something like this:
func printStats(pokemon: Pokemon) {
if pokemon.name != nil {
print(" name: \(pokemon.name!)\n level:\(pokemon.level!)\n type:\(pokemon.type!)\n exp: \(pokemon.exp!)")
}
}
printStats(pokemon: pikachu)
output:
name: Pika Pika
level:1
type:electricity
exp: 0.0
But I just want to loop through all values, instead of explicit writing every attribute in the function.
I found it the way of doing it:
let pokeMirror = Mirror(reflecting: pikachu)
let properties = pokeMirror.children
for property in properties {
print("\(property.label!) = \(property.value)")
}
output:
name = Optional("Pika Pika")
type = Optional("electricity")
level = Optional(1)
exp = Optional(0.0)
and if you want to remove the "Optional" just initialize the attributes.
Looks like a duplicate of Does Swift support reflection?
Alternatively, you can use a dictionary to store the attributes of Any? type.
e.g.
class Pokemon {
var attributes = [String:Any?]()
}
var pikachu = Pokemon()
pikachu.attributes["name"] = "Pika Pika"
pikachu.attributes["level"] = 1
pikachu.attributes["type"] = "electricity"
pikachu.attributes["exp"] = 0
func printStats(pokemon: Pokemon) {
pokemon.attributes.forEach { key, value in
if let value = value {
print("\(key): \(value)")
}
}
}
In Swift 5 you can create a new func in your class:
func debugLog() {
print(Mirror(reflecting: self).children.compactMap { "\($0.label ?? "Unknown Label"): \($0.value)" }.joined(separator: "\n"))
}
And then call it with MyObject().debugLog()
use Mirror API to get instance's properties
if you are developing iOS app, using NSObject, you may want to override description. Then can use print to print the instance.
A mirror describes the parts that make up a particular instance, such as the instance’s stored properties, collection or tuple elements, or its active enumeration case.
class YourClass: NSObject {
public override var description: String {
var des: String = "\(type(of: self)) :"
for child in Mirror(reflecting: self).children {
if let propName = child.label {
des += "\(propName): \(child.value) \n"
}
}
return des
}
}
let instance = YourClass()
print(instance)
see more in Reflection in Swift
Is it possible to get the object type from an optional?
For example, if I have a class that has a property that is an optional string, can I somehow just get back the string type?
The exact use case I have is I have many custom classes all of which have a property that is storing another custom class as an optional value. I would like to write a generic function that will create an instance of the object class stored in the optional.
Here is an example of what I am looking for, although .dynamicType does not work since it is an optional:
class Class1 {
}
class Class2 {
var myOp: Class1?
}
var c = Class2()
c.myOp = c.myOp.dynamicType()
Since you wanted to use this with Generics I tried it for you. It works, but it may not be so useful.
First some setup:
This is a helper protocol to make sure our Generic type will have a known init method.
protocol ZeroParameterInit {
init()
}
This is an extension to get the type from an optional:
extension Optional {
var dynamicWrappedType : Wrapped.Type {
return Wrapped.self
}
}
Implemented in your code:
class Class1 : ZeroParameterInit {
required init() {}
}
class Class2 {
var myOp: Class1?
}
var c = Class2()
c.myOp = c.myOp.dynamicWrappedType.init()
Generic implementation:
class Class1 : ZeroParameterInit {
required init() {}
}
class Class2<T where T : ZeroParameterInit> {
var attribute: Optional<T>// used long syntax to remind you of : Optional<Wrapped>
init(attr:T) {
attribute = attr
attribute = nil
}
}
The function to create the instance:
func myFunc<T>(instance: Class2<T>) -> T {
return instance.attribute.dynamicWrappedType.init()
}
Some tests:
let alpha = Class1()
let beta = Class2(attr: alpha)
beta.attribute = myFunc(beta)
The issue:
You can't create an instance of Class2 without informing it about the type of it's generic attribute. So you need to pass it some object/type and that complicates things again.
Some extra methods that might improve how it all works:
init() {
}
let delta = Class2<Class1>()
delta.attribute = myFunc(delta)
init(type:T.Type) {
}
let epsilon = Class2(type: Class1.self)
epsilon.attribute = myFunc(epsilon)
You just need to check if the optional exist:
func myFunc(c: Class2) -> Class1? {
if let c1 = c.myOp{
return c1.dynamicType()
}
return nil
}
OR
func myFunc(c: Class2) -> Class1? {
if c.myOp != nil{
return c.myOp!.dynamicType()
}
return nil
}
Note the your return type need to be optional as well.
Tried this in simulator, seems like doing the right thing, if I understood you
class Class1 {
}
class Class2 {
var myOp: Class1?
}
func myFunc(c: Class2) -> AnyObject {
if let c1 = c.myOp{
return c1.self
}
return c
}
var object = Class2()
object.myOp = Class1()
myFunc(object) // Class1