Bunch of errors when I updated swift version - ios

I updated an iOS application (not developed by myself) because as many of all you know if you want to upload a new build or a new application it should be now with the new SDK 13.
I haven't much experience with Swift and iOS but know I need to update this app previously running on swift 3 without problems, but when I converted it on Xcode 10.1 to swift 4 there were also a lot of new errors for me, I already found similar topics here about these type of errors, but since there isn't any documentation of the app and also I'm a newby on swift I not sure how to solve them. So at least I hope someone can help me to understand why there are this new errors just by updating the swift version.
The most recurrent errors I have are like this example, the following function was working, but with the update I have the following errors:
func showDeleteView()
{
let view: EliminarDialogView = try! SwiftMessages.viewFromNib()
view.configureDropShadow()
view.eliminarAction = { _ in self.handleDeleteToken() ; SwiftMessages.hide() }
view.cancelAction = { SwiftMessages.hide() }
var config = SwiftMessages.defaultConfig
config.interactiveHide = true
config.presentationContext = .window(windowLevel: UIWindowLevelStatusBar)
config.duration = .forever
config.presentationStyle = .bottom
config.dimMode = .gray(interactive: true)
SwiftMessages.show(config: config, view: view)
Unable to infer complex closure return type; add explicit type to disambiguate
&
Cannot infer contextual base in reference to member 'window'
Also if I select to fix it by the IDE there's another error:
Value of type 'SwiftMessages.Config' has no member 'presentationContext'
What I found here and surfing on the Internet was about this need to receive the same kind of variable on the list but since there's also the use of "_" I'm not sure how to handle this here.
EDITED
The update of the pod helped! but about which line of code is having the errors:
Unable to infer complex closure return type; add explicit type to disambiguate
Cannot convert value of type '(_) -> ()' to expected argument type '(() -> Void)?'
Value of type 'ActivarViewController' has no member 'startAnimating'
On the following lines:
view.eliminarAction = { _ in self.handleDeleteToken() ; SwiftMessages.hide() }
self.present(alert, animated: true, completion: { _ in }) }
`self.startAnimating(nil, message: "Procesando código de activación", messageFont: nil, type: NVActivityIndicatorType.ballScaleMultiple)`

Could you please try to update SwiftMessages as follows:
pod 'SwiftMessages', '~> 5.0'

Cannot convert value of type '(_) -> ()' to expected argument type '(() -> Void)?' - If there is no arguments then don't use Void in at all.
Value of type 'ActivarViewController' has no member 'startAnimating' - startAnimating starts the animation of the progress indicator, so it can be called via UIActivityIndicator.

Related

Error "nil requires a contextual type" using Swift

I'd like to achieve the following in code:
class MyService {
let mySubject = BehaviorSubject<MyData>(value: nil)
//....
}
Unfortunately, I get the "nil requires a contextual type" error. I want the subject to be "empty" till I actually put something in there. How can I pass nil as the argument then? Can I cast it to my own type to make it work?
Based on the reference for RxSwift BehaviorSubject, the init(value:) initializer is declared as
public init(value: Element)
Where the value parameter is described as:
value
Initial value sent to observers when no other value has been received
by the subject yet.
And where Element is the placeholder type of BehaviorSubject:
public final class BehaviorSubject<Element> ...
This means you need to specify the placeholder type Element as an Optional type if you are to be able to set the initial value (used when no other value has been received) to nil. E.g.:
class MyService {
let mySubject = BehaviorSubject<MyData?>(value: nil)
//....
}
Or, letting the compiler infer the placeholder as MyData? by using the non-sugared .none form for the nil argument:
class MyService {
let mySubject = BehaviorSubject(value: Optional<MyData>.none)
//....
}
As for understanding the actual error message better, consider the following self-contained example:
struct Foo<T> {
init(value: T) {}
}
struct Bar {}
let bar = Bar()
_ = Foo<Bar>(value: bar) // OK
_ = Foo(value: bar) // OK, T inferred as Bar
_ = Foo<Bar>(value: nil) // Error: error: 'nil' requires a contextual type
_ = Foo<Bar?>(value: nil) // OK
_ = Foo(value: Optional<Bar>.none) // OK, T inferred as Bar?
While dfri's answer is technically correct, you might want to consider a different type when working with RxSwift. Since you want your subject to be empty only at the beginning, I'd suggest to use ReplaySubject or PublishSubject.
A similar question has also been asked on RxSwift's GitHub issue page. Allow BehaviorSubject without initial value. There, kzaher suggests the ReplaySubject.
Your subject would then look like this, without any initial value and without MyData being Optional.
let subject = ReplaySubject<MyData>().create(bufferSize: 1)

Constant 'spacesLeft' inferred to have type '()', which may be unexpected Swift

I am building a Tic Tac Toe game with an AI using Xcode 8 and Swift. Here are the relevant variables I am using that are contributing to the error:
var allSpaces: Set<Int> = [1,2,3,4,5,6,7,8,9]
var playerOneMoves = Set<Int>()
var playerTwoMoves = Set<Int>()
var nextMove: Int? = nil
Inside a function defining how the AI will play there are these variables:
var count = 0
let spacesLeft = allSpaces.subtract(PlayerOneMoves.union(playerTwoMoves))
The latter results in the compiler warning:
Constant 'spacesLeft" inferred to have type '()', which may be unexpected
There is an if statement just below that says:
if allSpaces.subtract(playerOneMoves.union(playerTwoMoves)).count > 0 {
nextMove = spacesLeft[spacesLeft.startIndex.advancedBy(Int(arc4random_uniform(UInt32(spacesLeft.count))))]
}
The condition gives the following error:
Value of tuple type '()' has no member 'count'
The statement gives the following error:
Type '()' has no subscript members
I am struggling to find a solution.
subtract modifies Set in place and doesn't return a value, you want to use subtracting
For the first warning, subtract returns Void, so use subtracting:
let spacesLeft = allSpaces.subtracting(playerOneMoves.union(playerTwoMoves))
For the second error, advancedBy is deprecated, you may change like this:
if spacesLeft.count > 0 {
nextMove = spacesLeft[spacesLeft.index(spacesLeft.startIndex, offsetBy: Int(arc4random_uniform(UInt32(spacesLeft.count))))]
}
Set.subtract is a mutating function, so it modifies the Set in place and its return value is Void, which is just a type alias for an empty tuple, (), hence the warning.
You should call Set.substracting, which is the non-mutating version of subtract and returns Set<Set.Element>.
The subtract(_:) function is a mutating function so it will mutate the Set your using to call the function.
From Apple Docs:
subtract(_:)
Removes the elements of the given set from this set.
The reason you're getting the errors is because this function returns Void which in Swift is a typealias for an empty tuple(from Swift's source code). Since Void has no subscripts nor count property/variable you get those errors.
Maybe you should take a look at the subtracting(_:) function, which returns a different Set.
From Apple Docs:
subtracting(_:)
Returns a new set containing the elements of this set that do not occur in the given set.

Swift3 error 'cannot be applied to operands of type

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

participantQuitInTurnWithOutcome:nextParticipants:turnTimeout:matchData:completionHandler: in Swift - xcode compile error

When I attempt to use
participantQuitInTurnWithOutcome:nextParticipants:turnTimeout:matchData:completionHandler:
in Swift (found in GameKit), I get the following Xcode compile error...
"Extra argument 'turnTimeout' in call".
If I take out the turnTimeout: argument, Xcode complains with,
"Missing argument for parameter 'turnTimeout' in call".
Has anyone else encountered this and is there any way to solve? I obviously can't satisfy each requirement.
func turnBasedMatchmakerViewController(viewController: GKTurnBasedMatchmakerViewController!, playerQuitForMatch match: GKTurnBasedMatch!) {
var nextParts:Array<GKTurnBasedParticipant> = []
for participant in match.participants {
if (participant.matchOutcome == GKTurnBasedMatchOutcome.None) {
nextParts.append(participant as GKTurnBasedParticipant)
}
}
match.participantQuitInTurnWithOutcome(matchOutcome: GKTurnBasedMatchOutcome.Quit, nextParticipants: nextParts, turnTimeout: nil, matchData: self.currentMatch, completionHandler: nil)
}
MartinR got me thinking in the right direction. It turned out that I was passing the match as the matchData argument. They are obviously two different objects.
MartinR - please post your suggestion as an answer and I will accept.

Create PDF in Swift

I am following Apple's Docs to create a PDF file using Xcode6-Beta6 in Swift
var currentText:CFAttributedStringRef = CFAttributedStringCreate(nil, textView.text as NSString, nil)
if (currentText) { // <-- This is the line XCode is not happy
// More code here
}
Compiler throws Type 'CFAttributedStringRef' does not conform to protocol 'BooleanType' error
If I use if(currentText != nil) I get 'CFAttributedStringRef' is not convertible to 'UInt8'
From Apple's Docs for CFAttributedStringCreate
Return Value
An attributed string that contains the characters from str and the attributes specified by attributes. The result is NULL if there was a problem in creating the attributed string. Ownership follows the Create Rule.
Any idea how to resolve this? Thanks!
First you have to give it an explicit optional type (using the ?):
var currentText: CFAttributedStringRef? = ...
Then you can compare it to nil:
if currentText != nil {
// good to go
}
Your code compiles at the moment, because Apple hasn't yet "swiftified" CoreFoundation to return properly annotated types.
Be prepared that in the final release your code will not even compile, forcing you to use the optional type.

Resources