Apparently Xcode doesn't let me modify the UI (iOS) from a background thread. I have to type:
let res = somethingReturningaString()
dispatch_async(dispatch_get_main_queue(), {
self.txtError.text = res!
})
My idea was: 'hey, let's simplify my life and define a custom operator, so I can type something like:'
prefix operator ~> {}
prefix func ~> (closure: ()-> ()) {
dispatch_async(dispatch_get_main_queue(), closure)
}
//usage example
~> {self.txtError.text = res!}
Apparently the operator of type '()' cannot be applied to '()->()'
Does anybody know how to declare this to get this working?
The swift compiler got a little confused there. You must not ever separate a unary operator from its operand, meaning there must not be a whitespace in between.
Consider the following example code
let k = 12
~> {
self.txtError.text = res!
}
Swift now expects ~> to be a binary operand because there is a whitespace.
binary operator '~>' cannot be applied to operands of type 'Int' and '() -> ()'
If you insert a ; after the first line:
let k = 12;
~> {
self.txtError.text = res!
}
You receive something a little bit more helpful:
Unary operator cannot be separated from its operand
Which simply means that there must in fact be no whitespace.
Fix
Remove the whitespace:
~>{ self.txtError.text = res! }
Related
I was wondering, what is a good way to fix the following compiler error?
class A {
var x: Int32
init() {
x = -1
}
}
let a: A? = nil
// No issue.
let ok: Int = Int(a?.x ?? -1)
// Type of expression is ambiguous without more context
let CONSTANT: Int = -1
let not_ok: Int = Int(a?.x ?? CONSTANT)
Any idea why we are getting Type of expression is ambiguous without more context if we use CONSTANT instead of -1?
What is a good way to fix the compiler error (retain same class, same type and same CONSTANT), yet still retain 1 liner?
It's for the same reason that you can say this:
let d = 3.0
let d2 = d + 1
But not this:
let i = 1
let d3 = d + i
Swift will cast the literal 1 to the required numeric type (here, Double), but it won't cast a variable away from its type.
So the answer is: make the types match.
The ?? operator is declared like this:
func ?? <T>(optional: T?, defaultValue: #autoclosure () throws -> T)
rethrows -> T
In the expression Int(a?.x ?? -1), the compiler needs to infer T for the
?? operator. It successfully infers T == Int32, because
the expression a?.x has the type Int32?.
it is okay for ?? to return Int32 here, because Int has an initialiser that takes Int32.
most relevantly, the literal -1 can be converted to Int32, because Int32 conforms to ExpressibleByIntegerLiteral.
If you instead do Int(a?.x ?? CONSTANT), however, that last point wouldn't work. ExpressibleByIntegerLiteral only works with literals, not any constant. The compiler sees CONSTANT as an expression of type Int, and tries very hard to find a type for the expression a?.x ?? CONSTANT, but it can't, and spits out a not-so-useful error message.
I suppose the error message is not very useful because it needs to consider quite a lot of things in this case (return type, the two parameters, overload resolution for Int.init), and it could be rather hard to pinpoint exactly where went wrong.
Anyway, to fix this, you can just convert the constant to Int32:
Int(a?.x ?? Int32(CONSTANT))
Or if you don't want to convert CONSTANT to an Int32 then back to Int again, you can rewrite this as:
a.map { Int($0.x) } ?? CONSTANT
"Map a to its x as an Int if a is not nil, otherwise CONSTANT".
I’m just learning swift and can’t seem to figure out a problem.
I’ve tried changing the function text but nothing seems to be working
func multiply(_ a: Double, _ b: Double) -> Double {
a * b
}
solution.swift:2:7: warning: result of operator '*' is unused
a * b
~ ^ ~ solution.swift:3:1: error: missing return in a function expected to return 'Double' } ^
That code uses the new feature introduced in Swift 5.1 - implicit returns from single expression functions. (New features in Swift 5.1)
Make sure you are using Swift 5.1/Xcode 11. If you are not, you have to write return:
func multiply(_ a: Double, _ b: Double) -> Double {
return a * b
}
Getting the following error:
Binary operator '==' cannot be applied to operands of type 'UInt16' and '() -> UInt16'
in this section of code:
let array: [UInt16] = [3,4, 7]
let x = NSNumber(value: 4)
let option = array.filter { (test) -> Bool in
return test == x.uint16Value // compiler complains here
}
print(option) // "[4]"
Normally this type of error means two values of separate class are being compared. Here the compiler thinks I'm comparing a uint16 value with a function that returns a uint16 value.
What I mean to do is call NSNumber's uint16 property getter.
// defined in NSNumber
open var uint16Value: UInt16 { get }
I'm told to instead make a function call by adding parenthesis (e.g .uint16Value()). But this leads to the follow up error:
Cannot call value of non-function type 'UInt16'
I have dropped this exact code into a playground and it runs fantastically.
Has anyone else run into this? Or seen this type of behavior? Have you beaten it?
Update:
When setting to a local variable, no difference is made. I have recently run the migration tool from Swift 2.2 or 2.3 up to swift 3 in Xcode 8.0. It doesn't seem like there is anything wrong with syntax or migration.
let y = x.uint16Value
return test == y // compiler complains here
I'm trying to update some of my swift code to comply with the swift 2.2 guide lines. I'm trying to update my for loops this is what I have currently
for(var i = 0; persons?.count > i; i += 1){}
and this is what I thought I should be using
for i in (0..<persons?.count){}
But I'm getting this error "Binary operator '..<' cannot be applied to operands of type 'Int' and 'Int?'"
I'm just not sure what I'm missing.
The problem is that persons?.count might be nil and 0..<nil doesn't make any sense. you can easily fix this by using nil coalescing though:
for i in 0..<(persons?.count ?? 0) {
doStuff(i)
}
Or if you prefer you could overload the ..< operator to accept an optional as its second argument:
func ..<<T:ForwardIndexType where T:Comparable>(lower: T, upper: T?) -> Range<T> {
return lower..<(upper ?? lower)
}
This allows you to just write:
for i in 0..<persons?.count {
doStuff(i)
}
As Sulthan points out in the comments, this is probably not the best solution for your problem though. You should likely handle the case of persons being nil earlier in your code:
guard let persons = persons else {
// take care of business
}
for person in persons {
doStuff(person)
}
I'm trying to declare a custom postfix operator that calculates the factorial of a given number, is there a way to make this function recursive (number-1)!!?
postfix operator !! {}
postfix func !! (number: Double) -> Double {
if (number <= 1) { return 1.0 }
return number * (number-1)!!
}
I believe this is impossible simply because it conflicts with the ! which is used for unwrapping optionals.
From The Swift Programming Language: Keywords and Puncutation
The following tokens are reserved as punctuation and can’t be used as custom operators: (, ), {, }, [, ], ., ,, :, ;, =, #, #, & (as a prefix operator), ->, `, ?, and ! (as a postfix operator).
However, in my opinion, if this is the case then it's a bug that postfix operator !! {} is valid. I'd recommend filing a bug.
You could get around this by using ‼ for example (Double exclamation mark; U+203C).
It's doable, but not if you use !!- it interprets it as two implicit optional deferences. Some other symbol will work - e.g:
postfix operator £ {}
postfix func £(number : Double) -> Double {
if number<=1 {
return 1.0
}
return number * (number-1)£
}
We need to specify postfix operator on file level:
import UIKit
postfix operator !
struct A {
var a = 5
var b = 10
}
extension A {
static postfix func !(m: A) -> A {
return A(a: -m.a, b: -m.b)
}
}
var obj1 = A(a:45, b: 46)
var obj4 = obj1!
Now, obj4 values will be -45, -46