Swift protocol defining class method returning self - swift

I had code that was working in XCode 6 beta but stopped working recently after updating to xcode 6.1.
This is my protocol:
protocol CanDeserialiseFromJson {
class func FromJson(json : JSONValue) -> Self
}
This is implementation:
extension Invoice : CanDeserialiseFromJson {
class func FromJson(json : JSONValue) -> Self {
return Invoice()
}
}
This fails giving error:
'Invoice' is not convertable to 'Self'
As I said, this used to work and I can't work out why it doesn't anymore

It's right. Your method is declared to return Self, whereas you are returning Invoice. Class methods are inherited, and in subclasses, Self will be that subclass type, and Invoice is not a subtype of that type.
To actually return Self, assuming Invoice has a required init() constructor, you can do something like this:
extension Invoice : CanDeserialiseFromJson {
class func FromJson(json : JSONValue) -> Self {
return self()
}
}

Self in a protocol is a requirement that implementations of the protocol use their own type. Since Invoice is the type you're adopting the protocol in, your implementation of FromJson should have a return type of Invoice.

In case you really need to return Self (in my case I have an Objective-C protocol that translates a method into swift function returning Self) and not mark your class as final, you need to create a required initializer and use that:
class Foo {
static func bar() -> Self {
return self.init()
}
required init() {
}
}
The final/required requirement comes from the fact that you might subclass this class and have a different initialiser.
Final removes the option for a subclass, while the required init makes sure that any subclass will implement the required initialiser used in the static method.

Related

Why do I have to cast an instance of a class to Self to match the return type? [duplicate]

This code produces Xcode error messages that lead you in a circle. Let's say I have a protocol called Marker and I'd like Markers to copy themselves. Here's a first guess...
protocol Marker {
func copy() -> Self
}
class Marker1 : Marker {
func copy() -> Self {
return Marker1() // error here
}
}
(I'm not sure how to use Self correctly, because I can't find it in the The Swift Programming Language document. If you know where it's documented, please include that in answer.)
That code gives an error on the marked line: Cannot convert return expression of type 'Marker1' to return type 'Self' and it suggests a fix: Insert ' as! Self'.
I accept the fix:
...
return Marker1() as! Self
...
This leads to another compiler error: 'Self' is only available in a protocol or as the result of a method in a class; did you mean 'Marker1'?
If I accept that "fix" it goes back to the original error. I'd call that a bug in Xcode. Let's try something else:
func copy() -> Marker1 {
return Marker1()
}
Another error: Method 'copy()' in non-final class 'Marker1' must return `Self` to conform to protocol 'Marker'
Making the class final does fix the error. But is there a way to do this without making a class final? And where is Self documented?
With such a hierarchy, you would have to make the class conforming to the protocol final:
protocol Marker {
func copy() -> Self
}
final class Marker1 : Marker {
func copy() -> Marker1 {
return Marker1()
}
}
The final is needed because when you don't apply final and you create a subclass Marker2: Marker1 then copy would not return the correct class Self any more.
You can workaround that by creating a required initializer and always create the correct instance:
protocol Marker {
init()
func copy() -> Self
}
class Marker1 : Marker {
required init() {
}
func copy() -> Self {
let copy = type(of: self).init()
return copy
}
}
(original code removed because does not work)
Related: Implementing copy() in Swift
The issue with your current implementation is that Self is an abstract type, so you cannot simply return a concrete type, such as Marker1 from a function with a return type of Self. If you changed the return type to Marker1, you'd need to make your class final to ensure that no subclass can override the method, since in a subclass, Self would correspond to the subclass type. However, this is still not good since in this case the subclass won't conform to the protocol, since in a subclass of Marker1, the return type of Marker1 is not the same as self.
You can solve this problem by getting the metatype of your current class using type(of: self), then calling a designated initializer on the metatype, which will indeed return an instance of type Self. The final step is to create a required initializer for your class to ensure that all subclasses need to implement the same initializer that's called in your copy() method in order to make copy work for subclasses as well.
protocol Marker {
func copy() -> Self
}
class Marker1 : Marker {
func copy() -> Self {
let result = type(of: self).init()
return result
}
required init() {}
}

Swift: "failable initializer 'init()' cannot override a non-failable initializer" vs. default parameters

If I declare
public class A: NSObject {
public class X { }
public init?(x: X? = nil) { }
}
all is fine. When using it like let a = A(), the initializer is called as expected.
Now, I'd like to have the nested class X private, and the parameterized init as well (has to be, of course). But a simple init?() should stay publicly available as it was before. So I write
public class B: NSObject {
private class X { }
private init?(x: X?) { }
public convenience override init?() { self.init(x: nil) }
}
But this gives an error with the init?() initializer: failable initializer 'init()' cannot override a non-failable initializer with the overridden initializer being the public init() in NSObject.
How comes I can effectively declare an initializer A.init?() without the conflict but not B.init?()?
Bonus question: Why am I not allowed to override a non-failable initializer with a failable one? The opposite is legal: I can override a failable initializer with a non-failable, which requires using a forced super.init()! and thus introduces the risk of a runtime error. To me, letting the subclass have the failable initializer feels more sensible since an extension of functionality introduces more chance of failure. But maybe I am missing something here – explanation greatly appreciated.
This is how I solved the problem for me:
I can declare
public convenience init?(_: Void) { self.init(x: nil) }
and use it like
let b = B(())
or even
let b = B()
— which is logical since its signature is (kind of) different, so no overriding here. Only using a Void parameter and omitting it in the call feels a bit strange… But the end justifies the means, I suppose. :-)
After a bit of fiddling I think I understand. Let's consider a protocol requiring this initializer and a class implementing it:
protocol I {
init()
}
class A : I {
init() {}
}
This gives the error: "Initializer requirement 'init()' can only be satisfied by a required initializer in non-final class 'A'". This makes sense, as you could always declare a subclass of A that doesn't inherit that initializer:
class B : A {
// init() is not inherited
init(n: Int) {}
}
So we need to make our initializer in A required:
class A : I {
required init() {}
}
Now if we look at the NSObject interface we can see that the initializer is not required:
public class NSObject : NSObjectProtocol {
[...]
public init()
[...]
}
We can confirm this by subclassing it, adding a different initializer and trying to use the normal one:
class MyObject : NSObject {
init(n: Int) {}
}
MyObject() // Error: Missing argument for parameter 'n:' in call
Now here comes the weird thing: We can extend NSObject to conform to the I protocol, even though it doesn't require this initializer:
extension NSObject : I {} // No error (!)
I honestly think this is either a bug or a requirement for ObjC interop to work (EDIT: It's a bug and already fixed in the latest version). This error shouldn't be possible:
extension I {
static func get() -> Self { return Self() }
}
MyObject.get()
// Runtime error: use of unimplemented initializer 'init()' for class '__lldb_expr_248.MyObject'
Now to answer your actual question:
In your second code sample, the compiler is right in that you cannot override a non-failable with a failable initializer.
In the first one, you aren't actually overriding the initializer (no override keyword either), but instead declaring a new one by which the other one can't be inherited.
Now that I wrote this much I'm not even sure what the first part of my answer has to do with your question, but it's nice to find a bug anyways.
I suggest you to do this instead:
public convenience override init() { self.init(x: nil)! }
Also have a look at the Initialization section of the Swift reference.

Conform to a protocol misunderstanding

class SuperDelegate <T: AnyObject> {
func addDelegate(delegate: T)
{
}
}
My question is about T key, does it mean the same as id in Objective-c? I mean about case of uses.
how to understand the first line class SuperDelegate <T: AnyObject> Sorry I am new in Swift.
As Objective C program for me this line means that we make class to conform a protocol that has to implement all required method. But I don't understand func addDelegate(delegate: T) is this the same like
- (void)addDelegate:(id)delegate which is a property id <T> delegate.
Yes you are correct in your assumptions that AnyObject behaves like id:
You can call any Objective-C method and access any property on an
AnyObject value without casting to a more specific class type. This
includes Objective-C compatible methods and properties marked with the
#objc attribute.
but you have used it here as a generic type rather than as a concrete type that should be cast to. The class is requiring a type that adheres to the AnyObject protocol but it isn't forcing it to be AnyObject (see header files: cmd + click on AnyObject inside Xcode).
So your instance could be instantiated SuperDelegate<AnyObject> but it could also be instantiated SuperDelegate<NSDate>. This means that the whole subset of ObjC methods and properties cannot be guaranteed as they can with a cast to AnyObject as a concrete type because at runtime T might represent NSDate or NSNumber or any other class.
To achieve what you want you would need to write:
class SuperDelegate {
func addDelegate(delegate: AnyObject)
{
}
}
But Swift is a strongly-typed language and it would normally be the case that you had a delegate protocol and that the delegate for your type adhered to the delegate protocol:
protocol DelegateProtocol {
func somethingHappened()
}
struct MyTypeDelegate:DelegateProtocol {
func somethingHappened() {
print("Thanks for telling me!")
}
}
struct MyType {
var delegate:DelegateProtocol?
func tellDelegateSomethingHappened() {
delegate?.somethingHappened()
}
}
let del = MyTypeDelegate()
var type = MyType()
type.delegate = del
type.tellDelegateSomethingHappened()

Swift: Generic Protocols

I have some swift structs for which protocol compliance is generated with individual extensions with equal methods names which just differ in their return types which are struct dependent. On top of That I want to use them in a generic function which Calls a protocol conforming function for a generic type).
I tried to accomplish this like that:
//: Playground - noun: a place where people can play
import UIKit
protocol FooProt {
typealias T;
static func createMe<T>()->T;
}
struct FooStruct{
}
extension FooStruct: FooProt{
typealias T = FooStruct;
static func createMe () -> FooStruct{
return FooStruct();
}
}
class Creator{
fun createOne<T where T:FooProt>(type:T.Type){
let instance = T.createMe();
}
}
Unfortunately I get the following error :
/var/folders/sn/78_zvfd15d74dzn01mdv258h0000gq/T/./lldb/3741/playground6.swift:7 :17: note: protocol requires function 'createMe()' with type ' () -> T' (aka '<τ_1_0> () -> τ_1_0')
static func createMe()->T;
What exactly doesn't comply here and is there a workaround ?
There are several problems with your code. On the one hand you have defined a protocol with an associated type. However, you define your createMe() method as a generic which uses some other type. I don't think that was your intent. I think your intent was to have a createMe() method that returns the same type as the protocol's associated type. In this case you need to remove the from the createMe() method. Also, the name createMe() implies that you aren't just returning any type, but the type of the object on which this method is being called. In this case, you don't even need an associated type protocol. You just need a protocol with a Self constraint which allows your code to be a bit simpler. In your Creator's createOne method, your type constraint is more complex than needed.
I think you want the following code:
protocol FooProt {
static func createMe()->Self;
}
struct FooStruct{
}
extension FooStruct: FooProt {
static func createMe() -> FooStruct {
return FooStruct();
}
}
class Creator{
func createOne<T:FooProt>(type: T.Type) -> T {
return T.createMe()
}
}
let foo = Creator().createOne(FooStruct.self)
Here is an alternate solution using an initializer in the protocol instead of a static method.
protocol FooProt {
init()
}
struct FooStruct{
}
extension FooStruct: FooProt {
}
class Creator{
func createOne<T:FooProt>(type: T.Type) -> T {
return T.init()
}
}
let foo = Creator().createOne(FooStruct.self)

Final self class for generics, in method signature, in Swift

I have a BaseObject model that defines common behaviour I want to share across all my data entities. It has a method like this:
class BaseObject {
static func fetch(block: ((Results<BaseObject>) -> Void)) {
// networking code here
}
}
Naturally, I need the signature of this method be dynamic enough so that a model of class Products
class Products: BaseObject { //...
yields a Results<Product> list instead of Results<BaseObject>. I don't want to re-implement the fetch method in every subclass, because, save for the exact final subclass name used in the body and in the signature, it would be identical.
I cannot use Self:
Do I have any options at all?
You can now do this as of Swift 2.0 as it allows default implementations of methods in protocols. To do so, you would make your base class a protocol, and use Self, as you tried in your example.
https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html#//apple_ref/doc/uid/TP40014097-CH25-ID521
Edit:
This compiles in Swift 2.0 / Xcode 7.0 Beta:
class Results<T> {
}
protocol BaseObject {
static func fetch(block: ((Results<Self>) -> Void))
}
extension BaseObject {
static func fetch(block: ((Results<Self>) -> Void)) {
// networking code here
}
}
This feature is only available in Swift 2.0, to my knowledge, there is no solution in Swift 1.2 or previous.