Swift 2 to 3 Migration Error Regarding String Concatenation - swift

I have the following code below.
let url = "http://websitehere.com/restapi/v1/userlogin?email="+username+"&password="+password+"&deviceid="+deviceid
For some reason the compiler won't take it. Gives me the following error below.
Expression was too complex to be solved in reasonable time; consider breaking up the expression into distinct sub-expressions
Why won't the old swift2 code work anymore, what is it even talking about here? If it is too complex, how would I fix it and why is it to complex?

I would always use this format:
let url = "http://websitehere.com/restapi/v1/userlogin?email=\(username)&password=\(password)&deviceid=\(deviceid)"

Related

String pattern matching in Swift switch statements

I have a problem with pattern matching in swift switches. I need to check a string to see if it contains some characters and return data according to that.
I have the following (shortened) code:
static func getCorrectChords(chord: String) -> [Chord] {
    let test = chord
switch test {
case let x where x.contains("-") && x.contains("2"):
return allChords[8]
///// other similar statements
default:
return allChords[0]
}
}
If I pass the string “RE-2” to the function, it switch over all the statements and then goes with the default case. If I try a very similar code in Playgrounds, it works correctly.
Is there anything I’m doing wrong? How can I obtain the proper return value?
Thank you very much!
Edit: corrected braces and indentation in the code. Solution is now in the answers.
I found the issue. I did not isolate the problem correctly.
The issue was that my source data had a slightly different "-" character which Swift (rightly so) did not consider equal to the condition in the switch cases. I sanitized the inputs and now it works correctly. In the playground I did manually write the input so the issue did not arise.
Thank you so much anyway!

How to automate adding explicit types to a large codebase?

What I'd like to do is automate updating code in an Xcode project that does not declare a type to code that does declare a type:
Input:
let str = "This is a string"
Output:
let str: String = "This is a string"
I'm not aware of a tool that does that already, however, looks like it's a weekend project that includes SwiftSyntax https://github.com/apple/swift-syntax and SourceKit https://github.com/jpsim/SourceKitten together. SwiftSyntax can read and output "fixed" code, while SourceKit can provide a type.
You can use the swiftlint rule explicit_type_interface to enforce it to a certain degree: https://realm.github.io/SwiftLint/explicit_type_interface.html.
But there doesn't seem to be a way to enforce this without swiftlint.
However, implicit typing is a benefit of swift, not a detriment, so I would advise caution if you're thinking of enforcing explicit typing just for compilation improvements. There are better ways to improve compile times.
I usually find ways to use find and replace, for instance search for space
= space " and then replace with : String = " That's the best way I have found.

Swift: Chaining String/Substring methods yields 'ambiguous use of' errors. Fix or alternative?

I'm trying to do the most basic string manipulation using Swift. It looks like String provides everything I need, even though it relies on Substring intermediate results. So this works
let myString = "0123456789"
let mySubstring = myString.dropFirst(2)
print(mySubstring.dropLast(2))
It successfully yields "234567" as a Substring.
However, when I attempt to chain the calls...
print(myString.dropFirst(2).dropLast(2))
I get the following error...
9> print(myString.dropFirst(2).dropLast(2))
error: repl.swift:9:7: error: ambiguous use of 'dropFirst'
print(myString.dropFirst(2).dropLast(2))
^
Swift.Collection:39:17: note: found this candidate
public func dropFirst(_ n: Int) -> Self.SubSequence
^
Swift.Sequence:20:17: note: found this candidate
public func dropFirst(_ n: Int) -> AnySequence<Self.Element>
^
So it seems like the compiler is understandably having trouble inferring which dropFirst method to invoke because it is defined twice with different return types.
Is there a way around this? Is this just really poor API design on Apple's part? I'm trying to just get a nice easy to read and concise bit of code. I can also make it work by resorting to NSString but this seems wasteful and even more verbose and obtuse.
UPDATE:
I am able to get a better result by adding as Substring after the chain as in...
print(myString.dropFirst(2).dropLast(2) as Substring)
...since that disambiguates the overloaded methods. I would still love to see a more concise solution. Thanks.
If you define the return type, it has no trouble resolving which function to use. There are a number of ways to do this, such as:
let mySubstring: Substring = myString.dropFirst(2).dropLast(2)
Of course, as you say, you can insert this Substring type within the expression:
let mySubstring = (myString.dropFirst(2) as Substring).dropLast(2)
Surprisingly, it works if you reverse the order and do the dropLast first:
print(myString.dropLast(2).dropFirst(2))

Swift 1.2: <unknown>:0: error: '[Set<T>]' is not convertible to 'Hashable'

I have used xCode 6.3's convertor to convert my project to swift 1.2,
After that i was still left with many errors, but i fixed them all manually.
Now when i compile i get:
<unknown>:0: error: '[Set<T>]' is not convertible to 'Hashable'.
The only place i use Set is:
var productID:Set<NSObject> = [subscriptionId]
var productsRequest:SKProductsRequest = SKProductsRequest(productIdentifiers: productID )
I have tried cleaning the project and also tried deleting the DerivedData folder, but that didn't help.
I have searched but i couldn't find anyone with the same problem.
Anyone know how to solve this?
This won’t be a problem with derived data. It looks like where previously you had an NSArray (probably of NSSet), you now have an Array of Set. Presumably you’re then trying to do something like use that value to key a dictionary type. In 6.3, several API calls that previously returned NSSomething now return native Swift types.
Swift Arrays aren’t hashable (because they might contain something that isn’t hashable). NSArrays are (though not always in a helpful way, depending on what they contain, so be wary).
Bear in mind, with type inference, that your explicit use of Set or Array won’t be the only places you might have a set. If you call a function that returns an array of sets, and you assign that value like so: let thing = funcThatReturnsArrayOfSets() then you will have a [Set<whatever>] even without explicitly writing that type in your code.
To fix this, you need to find the line where you’re getting the error, look at the types involved, then trace back to where those variables were declared. Option-click all the things to see what types they are.

Int extension not applied to raw negative values

My extensions to the Int type do not work for raw, negative values. I can work around it but the failure seems to be a type inference problem. Why is this not working as expected?
I first encountered this within the application development environment but I have recreated a simple form of it here on the Playground. I am using the latest version of Xcode; Version 6.2 (6C107a).
That's because - is interpreted as the minus operator applied to the integer 2, and not as part of the -2 numeric literal.
To prove that, just try this:
-(1.foo())
which generates the same error
Could not find member 'foo'
The message is probably misleading, because the error is about trying to apply the minus operator to the return value of the foo method.
I don't know if that is an intentional behavior or not, but it's how it works :)
This is likely a compiler bug (report on radar if you like). Use brackets:
println((-2).foo())