Swift 1.2 redeclares Objective-C method - swift

I just updated from swift 1.1 to swift 1.2 and get compiler Error:
Method 'setVacation' redeclares Objective-C method 'setVacation:'
Here some code:
var vacation : Vacation?
func setVacation(_vacation : Vacation)
{...}
But I need call setVacation
Is any suggestions how fix this?

This is cause by the change stated in Xcode 6.3beta release notes:
Swift now detects discrepancies between overloading and overriding in
the Swift type system and the effective behavior seen via the
Objective-C runtime. (18391046, 18383574) For example, the following
conflict between the Objective-C setter for “property” in a class and
the method “setProperty” in its extension is now diagnosed:
class A : NSObject {
var property: String = "Hello" // note: Objective-C method 'setProperty:’
// previously declared by setter for
// 'property’ here
}
extension A {
func setProperty(str: String) { } // error: method ‘setProperty’
// redeclares Objective-C method
//'setProperty:’
}
To fix this you need to make all you method signatures unique (as Objective-C does not provide method overload)
Or don't inherit from NSObject if you need Swift only class.

Cappy: For the Standford problem I used simply this, because it looks like the Xcode Beta simply says that the operation: (Double, Double) -> Double is the same as operation: Double -> Double, I don't know if it is a bug or not...
But the code below works, but is NOT clean :(
func performOperation(r:String? = "2", operation: (Double, Double) -> Double) {
if operandStack.count >= 2 {
displayValue = operation(operandStack.removeLast(), operandStack.removeLast())
enter()
}
}
func performOperation(operation: Double -> Double) {
if operandStack.count >= 1 {
displayValue = operation(operandStack.removeLast())
enter()
}
}

As noted by #Kirsteins, Swift now detects conflicting symbols between Swift and Obj-C, and swift symbols that would cause Obj-C grief. In addition to the answer given, you can avoid this in general by specifying a required label for the additional types, thus changing the call signature:
import Foundation
extension NSObject {
func foo(d:Double, i:Int) { println("\(d), \(i)") }
func foo(withInt d:Int, i:Int) { println("\(d), \(i)") }
}
let no = NSObject()
no.foo(withInt:1, i: 2)
Beyond that though, and to answer your immediate question, you are trying to apply Obj-C idioms to Swift. What you really want, is to either implement didSet (most likely), or possibly set:
class WhatIDidLastSummer {
var vacation:Bool = false {
didSet {
// do something
}
}
var staycation:Bool {
get { return true }
set {
// do something
}
}
}

Related

Swift generic sequence observable ambiguity

I've got following code
protocol NamedOption {
var optionTitle: String { get }
}
struct DebugOption: NamedOption {
let optionTitle: String
let debugViewControllerType = UIViewController.self
}
func testFunk<T: Sequence>(d: Observable<T>) where T.Element == NamedOption {
}
func bindFullResultsRx() {
let dd: Observable<[DebugOption]> = self.dataModel.debugOptions // this is defined and properly assigned earlier
testFunk(d: dd)
}
and at the line where I call testFunk Xcode gives me following error:
Expression type '()' is ambiguous without more context
I have no idea why this is happening :( So far I was able to make it working by changing constraints on testFunk into this:
func funk<T: NamedOption>(d: Observable<[T]>) {
}
which seems to me more restrictive then version at the top. Does any one knows how to make it working with T: Sequence ?
Xcode version is 9.4, Swift version is 4.1.
After some digging and help from work colleagues I was able to make it working by simply changing == into : so it looks like this
func testFunk<T: Sequence>(d: Observable<T>) where T.Element: NamedOption {
}
It's just a matter of swift syntax
https://docs.swift.org/swift-book/ReferenceManual/GenericParametersAndArguments.html
conformance-requirement → type-identifier : protocol-composition-type
OO and generics don't play too well together. In order to do what you want, you have to manually cast up as in:
testFunk(d: dd.map { $0.map { $0 as NamedOption } })

Swift 4 way to fake existentials with protocols and `Self`

There are hundreds of solutions to fake existentials in Swift with protocols and Self, but they mostly refer to Swift 2 and the bright future that Swift 3 might bring...
Now Swift 4 is out, with nice additions for Generics. But I couldn't find any suggestions how to fit that into the missing existentials problem.
Any Ideas how to solve this the Swift 4 way?
Example:
import UIKit
protocol Bla {
func compare(other: Self)
}
extension CGFloat : Bla {
func compare(other: CGFloat) {
print("Extended CGFloat")
}
}
extension UIEdgeInsets : Bla {
func compare(other: UIEdgeInsets) {
print("Extended UIEdgeInsets")
}
}
/* Possible, but what if we want to CGFloat _and_ UIEdgeInsets inside here?
Well, that would _not_ work! */
class Possible<T: Bla> {
var array: [T]!
}
/* This is open to everything...
And therefore fails to compile, no dynamic type info at runtime I guess. */
class Fail {
var array: [Bla]!
}
// Works, but I don't need that.
let list = Possible<CGFloat>()
// I need that:
let list = Fail()
let f: CGFloat = 1.23
let edge = UIEdgeInsets()
list.array.append(f)
list.array.append(edge)
Fundamentally, it can't be done. If you could have:
class Fail {
var array: [Bla]!
}
You could then try to write code like this:
func compareAll(foo: Fail)
{
for x in foo.array
{
x.compare(other: y)
}
}
What type is y? The protocol says it has to be the same type as the object adopting the protocol but you don't know the type of x until runtime. There is no way to write that code with y being both a UIEdgeInsets and a CGFloat at the same time.
I think you could make it work by removing the dependency on Self by making compare generic. Your protocol would look like this:
protocol Bla {
func compare<T: Bla>(other: T)
}
Implementations of compare would have to test the type of other and cast to the right type.
extension CGFloat: Bla
{
func compare<T: Bla>(other: T)
{
if let casted = other as? CGFloat
{
// do whatever
}
}
}
I think this approach is better than using type erasure (see Daniel Hall's answer) for a couple of reasons:
There's no overhead of having to wrap everything in a wrapper object or the indirection of compare.
The compare function can work when other is an arbitrary type, not just the same type of self if it makes sense e.g.
func compare<T: Bla>(other: T)
{
if let casted = other as? CGFloat
{
// do whatever
}
else if let casted = other as? UIEdgeInsets
{
// Do something else
}
}
Of course, if you are simply given the protocol and you can't change it, type erasure is your only option.
This is typically handled with a type eraser, for example:
struct AnyBla: Bla {
private let compareClosure: (Any) -> ()
func compare(other: AnyBla) {
compareClosure(other)
}
init<T: Bla>(_ bla: T) {
compareClosure = {
if let other = $0 as? T {
bla.compare(other: other)
} else {
print("Can't compare type \(type(of: bla)) with \(type(of: $0))")
}
}
}
}
Then you would change your array to any array of the type eraser, i.e.
class Fail {
var array: [AnyBla]!
}
Then you can accomplish what you want to do like this:
let list = Fail()
let f: CGFloat = 1.23
let edge = UIEdgeInsets()
list.array.append(AnyBla(f))
list.array.append(AnyBla(edge))
Swift 4 didn't make any generics changes that address this issue. For the full roadmap, see the Generics Manifesto. That said, the protocol you're describing is equivalent to Equatable, and so would have all the same problems. There is no current roadmap to create what you're describing. The closest is discussed at the very end of the Manifesto, in the section called "Opening existentials."
As you've described the problem, it isn't clear how it would be useful, so I suspect your actual problem is different. You should go back to your actual program and consider what its real requirements are. For example, if your real requirement is "an array of CGFloat or UIEdgeInsets" that is absolutely buildable in Swift. "An array" translates to [T], and "OR" translates to enum (Swift's "sum type" in type theory parlance). So what you mean is:
enum Element {
case scalar(CGFloat)
case insets(UIEdgeInsets)
}
let list: [Element]
That is completely different than "an array of things that can be compared to themselves." If, on the other hand, you really mean "an array of value-like things," then that also is pretty easy to build in Swift with NSValue (and its subclass, NSNumber):
class Things {
var array: [NSValue] = []
func append(_ value: CGFloat) {
array.append(NSNumber(value: Double(value)))
}
func append(_ insets: UIEdgeInsets) {
array.append(NSValue(uiEdgeInsets: insets))
}
}
let list = Things()
let f: CGFloat = 1.23
let edge = UIEdgeInsets()
list.append(f)
list.append(edge)
list.array[0] == list.array[0] // true
list.array[0] == list.array[1] // false

Ambiguous reference when using selectors

Ready to use example to test in Playgrounds:
import Foundation
class Demo {
let selector = #selector(someFunc(_:))
func someFunc(_ word: String) {
// Do something
}
func someFunc(_ number: Int) {
// Do something
}
}
I'm getting an Ambiguous use of 'someFunc' error.
I have tried this answer and getting something like:
let selector = #selector(someFunc(_:) as (String) -> Void)
But still getting the same result.
Any hints on how to solve this?
Short answer: it can't be done.
Long explanation: when you want to use a #selector, the methods need to be exposed to Objective-C, so your code becomes:
#objc func someFunc(_ word: String) {
// Do something
}
#objc func someFunc(_ number: Int) {
// Do something
}
Thanks to the #objc annotation, they are now exposed to Objective-C and an compatible thunk is generated. Objective-C can use it to call the Swift methods.
In Objective-C we don't call a method directly but instead we try to send a message using objc_msgSend: the compiler is not able to understand that those method are different, since the generated signature is the same, so it won't compile. You will face the error:
Method 'someFunc' with Objective-C selector 'someFunc:' conflicts with previous declaration with the same Objective-C selector.
The only way to fix it is to have different signatures, changing one or both of them.
The selector is obviously ambiguous, neither methods have external parameter names. Remove the empty external parameters to solve this:
#objc func someFunc(word: String) {
// Do something
}
#objc func someFunc(number: Int) {
// Do something
}
After that, you should specify a selector with the parameter name:
#selector(someFunc(word:))
or
#selector(someFunc(number:))

Swift 2: understanding AnyObject and Self

I couldn't find any good explanation to my questions so I'd like to ask you directly. First of all I'd like to refine my code in this post.
My problem is the protocol AnyObject and the Self type. I didn't implement AnyObject into my code because it is marked with #objc and I don't want any Objective-C stuff involved in my code (don't judge me for that). I also couldn't find any explanation about the Self type. It just worked as expected, but Xcode does not replace Self with the type the static function is called at.
Here is some example:
extension Int : Instance {}
Int.singleton { (customInstanceName) -> Self in 0 } // Self shall be replaced with Int
As you can see Xcode produces a Self instead an Int. Is there any chance I could fix this? Am I right that Self does return the dynamicType and my implementation is fine as it is in my post above? I would really appreciate any good explanation about the Self type.
As you have seen in my code. I am using a custom protocol to check whether my instance is a class or not. Is there any other shiny implementation to check my instances if they are classes or structure types, or am I forced to use AnyObject if I want to get rid of my ClassInstance protocol?
Thank you for your time.
UPDATE:
protocol Test {}
class A : Test {}
struct B : Test {}
let aClass : Test = A()
let aStruct : Test = B()
if let someClass = aClass as? AnyObject {
print(someClass) // only this will print
}
if let someStruct = aStruct as? AnyObject {
print(someStruct)
}
This will work, but AnyObject is still marked as an #objc protocol.
The Self type can be only used in protocols where it is a implicit typealias of the type which conforms to it:
protocol Testable {
func test() -> Self
}
If you want to conform to this protocol you than have to replace Self with the name of the type. For instance:
struct Product: Testable {
func test() -> Product {
return Product()
}
}
Important Edit:
As DevAndArtist pointed out in the comments there is a working class check in Swift 1.2 (without automatic bridging to Objective C) but not Swift 2 (Xcode 7 beta 3; probably a bug):
if instance.dynamicType is AnyClass {
// instance is a class
} else {
// instance is not a class
}
You can see workaround (mainly) for Swift 2 below.
End Edit
With respect to classes you should use AnyObject if you want to keep it simple but you can also use reflection which would be much more effort.
Below you can see some reflection results of string interpolations (only the first few characters):
"\(reflect(classType))" // Swift._ClassMirror
"\(reflect(0))" // Swift._LeafMirror
"\(reflect(enumType))" // Swift._EnumMirror
"\(reflect(structure))" // Swift._StructMirror
"\(reflect([0, 4]))" // Swift._ArrayTypeMirror
"\(reflect(NSDate()))" // Foundation._NSDateMirror
"\(reflect(NSURLRelationship.Contains))" // Swift._EnumMirror
"\(reflect(Int?(2)))" // Swift._OptionalMirror
As you can see enums are consistent if they are not defined in the Swift standard library (unfortunately also Optional...). So you can distinguish also structs and enums:
public enum Type {
case Enum, Class, Struct
}
public func getType<T>(anything: T) -> Type {
if anything is AnyObject {
return .Class
}
if "\(reflect(anything))".hasPrefix("Swift._EnumMirror") {
return .Enum
}
return .Struct
}
So for a better result you have to put some effort into it to differentiate between all the different cases.
But the easiest way to distinguish only between reference types and value types (aka classes and structs/enums) is still (unfortunately only works for own declared structs and not built in types because they can be bridged to Objective C; I'm working on it...):
if instance is AnyObject {}
// or: if instance is of type Any
if let classInstance = instance as? AnyObject {}

Check if a func exists in Swift

I wish to check if a func exists before I call it. For example:
if let touch: AnyObject = touches.anyObject() {
let location = touch.locationInView(self)
touchMoved(Int(location.x), Int(location.y))
}
I would like to call touchMoved(Int, Int) if it exists. Is it possible?
You can use the optional chaining operator:
This seems to only work with ObjC protocols that have #optional functions defined. Also seems to require a cast to AnyObject:
import Cocoa
#objc protocol SomeRandomProtocol {
#optional func aRandomFunction() -> String
#optional func anotherRandomFunction() -> String
}
class SomeRandomClass : NSObject {
func aRandomFunction() -> String {
return "aRandomFunc"
}
}
var instance = SomeRandomClass()
(instance as AnyObject).aRandomFunction?() //Returns "aRandomFunc"
(instance as AnyObject).anotherRandomFunction?() //Returns nil, as it is not implemented
Whats weird is that in the example above, the protocol "SomeRandomProtocol" is not even declared for "SomeRandomClass"... yet without the protocol definition, the chaining operator gives an error-- in the playground at least. Seems like the compiler needs a prototype of the function declared previously for the ?() operator to work.
Seems like maybe there's some bugs or work to do there.
See the "swift interoperability in depth" session for more info on the optional chaining operator and how it works in this case.