I'm parsing the Swift Language Guide tutorial (from Apple iOS dev library) and for every chapter I create a separate swift file.
In each file I create multiple functions where I isolate snippets of code that they provide. Everything worked on until testing the Strong Reference Cycles for Closures.
For some reason if the class that contains a closure (for a computed property) is declared inside a function, then the closure cannot see the "self" reference of the enclosing class. Any ideas why ?
It works fine if the class is not declared inside a function.
func strongRefClosure() {
class HTMLElement {
let name: String
let text: String?
lazy var asHTML: () -> String = {
if let text = self.text {
return "<\(self.name)>\(text)</\(self.name)>"
} else {
return "<\(self.name) />"
}
}
init(name: String, text: String? = nil) {
self.name = name
self.text = text
}
deinit {
println("\(name) is being deinitialized")
}
}
var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world")
println(paragraph!.asHTML())
}
Looks very much like a bug (or at least, a behaviour of function-local structs/classes I can’t find documented). This works fine:
struct Foo {
let someVal = 5
lazy var someLazy: String = {
return toString(self.someVal)
}()
}
var foo = Foo()
foo.someLazy // string "5"
But this doesn’t:
func outer() {
struct Foo {
let someVal = 5
lazy var someLazy: String = {
// error: use of unresolved identifier 'self'
return toString(self.someVal)
}()
}
var foo = Foo()
foo.someLazy
}
An inner struct inside an outer struct works, though:
struct Outer {
struct Foo {
let someVal = 5
lazy var someLazy: String = {
return toString(self.someVal)
}()
}
var foo = Foo()
}
var outer = Outer()
outer.foo.someLazy
As #JeremyP says, you should file a radar.
For me, I have this bug in XCode 8GM, Swift 3, iOS 10.0.
tl;dr
Closure-as-instance-property has bug
Closure-as-computed-property is cured!
Actual code
Buggy:
let permissionStatusHandler = { (status: CKApplicationPermissionStatus, error: Error?) in
switch status {
case .granted:
self.fetchUserRecordID() // Buggy: Use of unresolved identifier 'self'
case .initialState:
self.requestDiscoverability() // Buggy: Use of unresolved identifier 'self'
case .couldNotComplete:
error.then { print(#function, $0.localizedDescription) }
fallthrough
case .denied:
self.iCloud.presentiCloudAlert(for: status)
}
}
Kosher:
var permissionStatusHandler: (CKApplicationPermissionStatus, Error?) -> () { return
{ (status: CKApplicationPermissionStatus, error: Error?) in
switch status {
case .granted:
self.fetchUserRecordID()
case .initialState:
self.requestDiscoverability()
case .couldNotComplete:
error.then { print(#function, $0.localizedDescription) }
fallthrough
case .denied:
self.iCloud.presentiCloudAlert(for: status)
}
}
}
Hope this helps some other soul out there.
Related
I've got the following code, that runs in a playground.
I'm attempting to allow subscript access to #Published variables in a class.
The only way I've found so far to retrieve the String value in the below implementation of
getStringValue
is to use the debugDescription, and pull it out -- I've looked at the interface for Published, but can't find any way to retrieve the value in a func like getStringValue
Any pointers would be greatly appreciated :)
Edited to include an example of how it works with a non-published variable.
Cheers
import Foundation
import Combine
protocol PropertyReflectable {}
extension PropertyReflectable {
subscript(key: String) -> Any? {
return Mirror(reflecting: self).children.first { $0.label == key }?.value
}
}
class Foo : PropertyReflectable {
#Published var str: String = "bar"
var str2: String = "bar2"
}
// it seems like there should be a way to get the Published value without using debugDescription
func getStringValue(_ obj: Combine.Published<String>?) -> String? {
if obj == nil { return nil }
let components = obj.debugDescription.components(separatedBy: "\"")
return components[1]
}
let f = Foo()
let str = getStringValue(f["_str"] as? Published<String>)
print("got str: \(str!)")
// str == "bar" as expected
let str2 = f["str2"]!
print("got non-published string easily: \(str2)")
Published seems to be steeped in some compiler magic, for lack of a better wording, since it can only be used as a property wrapper inside classes.
That being said, would something like this work?
final class PublishedExtractor<T> {
#Published var value: T
init(_ wrapper: Published<T>) {
_value = wrapper
}
}
func extractValue<T>(_ published: Published<T>) -> T {
return PublishedExtractor(published).value
}
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 have class
struct Word {
let text : String
let added: Date
let willShow: Date
let folder: Phase
let bestTranslation: String
let translationsProvider: ()->[String]
lazy var allTranslations : [String] = {self.translationsProvider()}()
}
and initializer
extension Word {
init(_ definition: Definition, context translationProvider:
#escaping ()->[String]){
self.text = definition.text!
self.added = definition.added!
self.willShow = definition.willShow!
self.folder = Phase(rawValue: definition.folder)!
self.bestTranslation = definition.best?.text ?? ""
self.translationsProvider = translationProvider
}
}
I'm getting error
Return from initializer without initializing all stored properties
with description
'self.allTranslations.storage' not initialized
How can I fix that?
I wonder if this is possibly a compiler bug. I don't see the same error you are getting, but this will create a Swift compiler segmentation fault 11:
struct Test {
let foo: String
lazy var bar: String = { return "" }()
}
extension Test {
init(_ foo: String) {
self.foo = foo
}
}
Lets say I have this class:
class Node {
var value: String
var children: [Node]?
}
If I have the name of one of its properties (for example "children") how can I get its type? (In this case [Node]?)
I imagine having a global function like below will solve my needs:
func typeOfPropertyWithName(name: String, ofClass: AnyClass) -> AnyClass? {
//???
}
// Example usage:
var arrayOfNodesClass = typeOfPropertyWithName("children", Node.self)
Swift 2 (Note: Reflection changed):
import Foundation
enum PropertyTypes:String
{
case OptionalInt = "Optional<Int>"
case Int = "Int"
case OptionalString = "Optional<String>"
case String = "String"
//...
}
extension NSObject{
//returns the property type
func getTypeOfProperty(name:String)->String?
{
let type: Mirror = Mirror(reflecting:self)
for child in type.children {
if child.label! == name
{
return String(child.value.dynamicType)
}
}
return nil
}
//Property Type Comparison
func propertyIsOfType(propertyName:String, type:PropertyTypes)->Bool
{
if getTypeOfProperty(propertyName) == type.rawValue
{
return true
}
return false
}
}
custom class:
class Person : NSObject {
var id:Int?
var name : String?
var email : String?
var password : String?
var child:Person?
}
get the type of the "child" property:
let person = Person()
let type = person.getTypeOfProperty("child")
print(type!) //-> Optional<Person>
property type checking:
print( person.propertyIsOfType("email", type: PropertyTypes.OptionalInt) ) //--> false
print( person.propertyIsOfType("email", type: PropertyTypes.OptionalString) //--> true
or
if person.propertyIsOfType("email", type: PropertyTypes.OptionalString)
{
//true -> do something
}
else
{
//false -> do something
}
Reflection is achieved in Swift using the global reflect() function. When passing an instance of some type to reflect() it returns a MirrorType, which has a range of properties allowing you to analyze your instance:
var value: Any { get }
var valueType: Any.Type { get }
var objectIdentifier: ObjectIdentifier? { get }
var count: Int { get }
var summary: String { get }
var quickLookObject: QuickLookObject? { get }
var disposition: MirrorDisposition { get }
subscript(i: Int) -> (String, MirrorType) { get }
This seems to work:
func getTypeOfVariableWithName(name: String, inInstance instance: Any) -> String? {
let mirror = reflect(instance)
var variableCollection = [String: MirrorType]()
for item in 0..<mirror.count {
variableCollection[mirror[item].0] = mirror[item].1
}
if let type = variableCollection[name] {
let longName = _stdlib_getDemangledTypeName(type.value)
let shortName = split(longName, { $0 == "."}).last
return shortName ?? longName
}
return nil
}
Here's some example code on SwiftStub.
Edit:
The result for optional values is only "Optional".
The result for arrays is only "Array".
The result for dictionaries is only "Dictionary".
I'm not sure if it is possible to extract what kind of optional/array/dictionary it is. But I guess this would also be the case for custom data structures using generics.
Building on #PeterKreinz answer I needed to be able to check types of inherited properties as well so added a little to his above code:
extension NSObject {
// Returns the property type
func getTypeOfProperty (name: String) -> String? {
var type: Mirror = Mirror(reflecting: self)
for child in type.children {
if child.label! == name {
return String(child.value.dynamicType)
}
}
while let parent = type.superclassMirror() {
for child in parent.children {
if child.label! == name {
return String(child.value.dynamicType)
}
}
type = parent
}
return nil
}
}
Hope this may help someone.
Swift 3 update:
// Extends NSObject to add a function which returns property type
extension NSObject {
// Returns the property type
func getTypeOfProperty (_ name: String) -> String? {
var type: Mirror = Mirror(reflecting: self)
for child in type.children {
if child.label! == name {
return String(describing: type(of: child.value))
}
}
while let parent = type.superclassMirror {
for child in parent.children {
if child.label! == name {
return String(describing: type(of: child.value))
}
}
type = parent
}
return nil
}
}
The solution provided by #peter-kreinz using Swift's class Mirror works beautifully when you have an instance of a class, and want to know the types of the properties. However if you want to inspect the properties of a class without having an instance of it you might be interested in my solution.
I have a solution that finds the name and type of a property given any class that inherits from NSObject.
I wrote a lengthy explanation on StackOverflow here, and my project is available here on Github,
In short you can do something like this (but really check out the code Github):
public class func getTypesOfProperties(inClass clazz: NSObject.Type) -> Dictionary<String, Any>? {
var count = UInt32()
guard let properties = class_copyPropertyList(clazz, &count) else { return nil }
var types: Dictionary<String, Any> = [:]
for i in 0..<Int(count) {
guard let property: objc_property_t = properties[i], let name = getNameOf(property: property) else { continue }
let type = getTypeOf(property: property)
types[name] = type
}
free(properties)
return types
}
This is a bit of a head banger (for me). Basically I want to have 2 different singletons that inherit from the same class. In either I want to use a certain class which itself is derived. So I have Utility and both AUtil:Utility and BUtil:Utility. And Singleton that is used as ASingleton using AUtility in its stomach and B respectively. I failed on all frontiers. The last attempt was a factory pattern which simply got Swift 1.2 to Segfault:
protocol Initializable { init() }
class A:Initializable {
var x = "A"
required init() {}
}
class B:Initializable {
var x = "B"
required init() {}
}
class C {
let t:Initializable
init(t:Initializable) {
self.t = t
println(t)
}
func factory() {
println(t.dynamicType())
}
}
As said I also tried to make the following pattern generic:
private let _SingletonSharedInstance = StaticClass()
class StaticClass {
class var sharedInstance : StaticClass {
return _SingletonSharedInstance
}
}
let s = StaticClass.sharedInstance
(This one isn't generic as you see. But all my attempts failed and so I show my starting point.)
Anyway I seem to be lost between doom and death.
Do you mean something like this?
protocol Initializable: class { init() }
private var instances = [String: Initializable]()
func singletonInstance<T: Initializable>(_ ty: T.Type = T.self) -> T {
let name = NSStringFromClass(ty)
if let o = (instances[name] as? T) {
return o
}
let o = ty()
instances[name] = o
return o
}
An use-side of it, for instance.
class Foo: Initializable { required init() {} }
class Bar: Initializable { required init() {} }
let foo1 = singletonInstance() as Foo // or `singletonInstance(Foo.self)`
let foo2 = singletonInstance() as Foo
assert(foo1 === foo2)
let bar1 = singletonInstance() as Bar
let bar2 = singletonInstance() as Bar
assert(bar1 === bar2)
(I've tested the code above and got it to work in Swift 1.2.)
Inspired by findalls implementation, I build my own singleton generator, which is a little more powerful.
You can create a singleton of any Class or Structure type in Swift. The only thing you have to do is to implement one of two different protocols to your type and use Swift 2.0 or newer.
public protocol SingletonType { init() }
private var singletonInstances = [String: SingletonType]()
extension SingletonType {
// this will crash Xcode atm. it's a Swift 2.0 beta bug. Bug-ID: 21850697
public static var singleton: Self { return singleton { $0 } }
public static func singleton(setter: (_: Self) -> Self) -> Self {
guard let instance = singletonInstances["\(self)"] as? Self else {
return setInstance(self.init(), withSetter: setter, overridable: true)
}
return setInstance(instance, withSetter: setter, overridable: false)
}
private static func setInstance(var instance: Self, withSetter setter: (_: Self) -> Self, overridable: Bool) -> Self {
instance = restoreInstanceIfNeeded(instance1: instance, instance2: setter(instance), overridable: overridable)
singletonInstances["\(self)"] = instance
return instance
}
private static func restoreInstanceIfNeeded(instance1 i1: Self, instance2 i2: Self, overridable: Bool) -> Self {
// will work if the bug in Swift 2.0 beta is fixed !!! Bug-ID: 21850627
guard i1.dynamicType is AnyClass else { return i2 }
return ((i1 as! AnyObject) !== (i2 as! AnyObject)) && !overridable ? i1 : i2
}
}
This may look a little scary, but don't be afraid of this code. The public function inside the protocol extension will create two access points for you.
For example you will be able to write code like this now:
// extend your type: as an example I will extend 'Int' here
extension Int : SingletonType {} // nothing else to do, because Int already has an 'init()' initializer by default
// let the magic happen
Int.singleton // this will generate a singleton Int with 0 as default value
Int.singleton { (_) -> Int in 100 } // should set your Int singleton to 100
Int.singleton { $0 - 55 } // your singleton should be 45 now
// I need to mention that Xcode will produce the setter like this and trow an error
Int.singleton { (yourCustomInstanceName) -> Self in // replace 'Self' with 'Int' and you should be fine
return yourCustomInstanceName
}
// btw. we just ignored the return value everywhere
print(Int.singleton) // will print 45 here
var singleton2 = Int.singleton { $0 + 5 }
singleton2 += 10
print(Int.singleton) // should print 50, because 'singleton2' is just a copy of an Int value type
class A : SingletonType {
var name = "no name"
required init() {}
}
A.singleton { $0; let i = A(); i.name = "hello world"; return i } // custom init on first singleton call for type A
print(A.singleton.name)
print(A.singleton { $0.name = "A"; return $0 }.name)
print(A.singleton.name)
// should print "hello world" and twice the string "A"
If you have any idea how to enhance this code and make it even safer, please let me know. I will push this code on GitHub (MIT License) soon, so everyone can benefit from it.
UPDATE: I modified the code a little so you can now pass a custom initialized instance of a class with the setter function when its called the first time.
UPDATE 2: I removed ClassInstance protocol and modified the private restore function. The Instance protocol is now called SingletonType. The setter function is not optional anymore. Right now Xcode 7 beta 3 will crash and provide an illegal instruction: 4 error when you will call the getter. But this is a confirmed beta bug.