I have a flutter code and I compile it swift and every thing is working except one error
(Argument labels '(rawValue:)' do not match any available overloads
(xcode error))
Code:
func close() {
dismiss(animated: true)
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(400), execute: {() -> Void in
self.tmpWindow?.windowLevel = UIWindow.Level(rawValue: 0.0)
UIApplication.shared.delegate?.window??.makeKeyAndVisible()
if (self.statusDelegate != nil) {
self.statusDelegate?.safariExit(uuid: self.uuid)
}
})
}
please help
You are initialising the UIWindow.Level with the wrong type. You are using a a literal value of 0.0 which will be inferred to be a Double when the method signature is: init(rawValue: CGFloat). You need to either use a CGFloat variable or cast the literal to a CGFloat
self.tmpWindow?.windowLevel = UIWindow.Level(rawValue: CGFloat(0.0))
Related
I am building some classes and code that store and perform arithmetic on currency values. I was originally using Doubles, but converted to Decimal due to arithmetic errors.
I am trying to find the best way to run unit tests against functions working with Decimal type.
Consider position.totalCost is a Decimal type.
XCTAssertEqual(position.totalCost, 3571.6, accuracy: 0.01)
This code does not compile because Decimal does not conform to FloatingPoint. XCTAssertEqual requires parameters to be Doubles or Floats.
I got around this by doing the following:
XCTAssertTrue(position.totalCost == 3571.6)
Which does work, but if an error arises during the unit test, I get a vague message:
XCTAssertTrue failed rather than the more useful XCTAssertEqual failed: ("2.0") is not equal to ("1.0")
So using XCTAssertEqual is ideal.
Potential Options (as a novice, no clue which is better or viable)
Code my Position class to store all properties as Decimal but use computed properties to get and set them as Doubles.
Write a custom assertion that accepts Decimals. This is probably the most 'proper' path because the only issue I've encountered so far with using Decimals is that XCT assertions cannot accept them.
Write a goofy Decimal extension that will return a Double value. For whatever reason, there is no property or function in the Decimal class that returns a Double or Floag.
Don't convert Decimal to a floating point if you don't have to since it will result in a loss of precision. If you want to compare two Decimal values with some accuracy you can use Decimal.distance(to:) function like so:
let other = Decimal(35716) / Decimal(10) // 3571.6
let absoluteDistance = abs(position.totalCost.distance(to: other))
let accuracy = Decimal(1) / Decimal(100) // 0.01
XCTAssertTrue(absoluteDistance < accuracy)
You can write an extension on Decimal:
extension Decimal {
func isEqual(to other: Decimal, accuracy: Decimal) -> Bool {
abs(distance(to: other)).isLess(than: accuracy)
}
}
And then use it in your tests:
XCTAssertTrue(position.totalCost.isEqual(to: 3571.6, accuracy: 0.01))
This is likely good enough. However, to get better error messages in the case of a failing test would require writing an overload for XCTAssertEqual, which is actually a bit tricky because elements of XCTest are not publicly available.
However, it is possible to approximate the behaviour:
Firstly, we need some plumbing to evaluate assertions, this can more or less be lifted straight from swift-corelibs-xctest.
import Foundation
import XCTest
internal enum __XCTAssertionResult {
case success
case expectedFailure(String?)
case unexpectedFailure(Swift.Error)
var isExpected: Bool {
switch self {
case .unexpectedFailure: return false
default: return true
}
}
func failureDescription() -> String {
let explanation: String
switch self {
case .success: explanation = "passed"
case .expectedFailure(let details?): explanation = "failed: \(details)"
case .expectedFailure: explanation = "failed"
case .unexpectedFailure(let error): explanation = "threw error \"\(error)\""
}
return explanation
}
}
internal func __XCTEvaluateAssertion(testCase: XCTestCase, _ message: #autoclosure () -> String = "", file: StaticString = #file, line: UInt = #line, expression: () throws -> __XCTAssertionResult) {
let result: __XCTAssertionResult
do {
result = try expression()
}
catch {
result = .unexpectedFailure(error)
}
switch result {
case .success: return
default:
let customMessage = message()
let description = customMessage.isEmpty ? result.failureDescription() : "\(result.failureDescription()) - \(customMessage)"
testCase.record(.init(
type: .assertionFailure,
compactDescription: description,
detailedDescription: nil,
sourceCodeContext: .init(
location: .init(filePath: String(describing: file), lineNumber: Int(line))
),
associatedError: nil,
attachments: [])
)
}
}
Now, for all of this to work, requires us to have access to the currently running XCTestCase, inside a global XCTAssert* function, which is not possible. Instead we can add our assert function in an extension.
extension XCTestCase {
func AssertEqual(
_ expression1: #autoclosure () throws -> Decimal,
_ expression2: #autoclosure () throws -> Decimal,
accuracy: #autoclosure () throws -> Decimal,
_ message: #autoclosure () -> String = "",
file: StaticString = #file,
line: UInt = #line
) {
__XCTEvaluateAssertion(testCase: self, message(), file: file, line: line) {
let lhs = try expression1()
let rhs = try expression2()
let acc = try accuracy()
guard lhs.isEqual(to: rhs, accuracy: acc) else {
return .expectedFailure("(\"\(lhs)\") is not equal to (\"\(rhs)\")")
}
return .success
}
}
}
All of which allows us to write our test cases as follows...
class MyTests: XCTestCase {
// etc
func test_decimal_equality() {
AssertEquals(position.totalCost, 3571.6, accuracy: 0.01)
}
}
And if the assertion fails, the test case will fail, with the message: ("3571.5") is not equal to ("3571.6") at the correct line.
We also cannot call our function XCTAssertEquals, as this will override all the global assert functions.
You milage may vary, but once you have the plumbing in place, this allows you to write bespoke custom assertions for your test suite.
Do you really need to specify the accuracy of 0.01?
Because if you omit this argument, it compiles just fine.
struct Position {
let totalCost: Decimal
}
let position = Position(totalCost: 3571.6)
//passes
XCTAssertEqual(position.totalCost, 3571.6)
// XCTAssertEqual failed: ("3571.6") is not equal to ("3571.61")
XCTAssertEqual(position.totalCost, 3571.61)
I have following function:
func myNSLog(_ givenFormat: String, _ args: CVarArg..., _ function:String = #function) {
let format = "\(function): \(givenFormat)"
NSLog(format, args)
Which results in the following error:
'NSLog' has been explicitly marked unavailable here (Foundation.NSLog)
Within the documentation is it explicit listed as available. What do I miss?
Similar as in C, you cannot pass a variable argument list directly
to another function. You have to create a CVaListPointer (the Swift
equivalent of va_list) and pass that to the NSLogv variant:
func myNSLog(_ givenFormat: String, _ args: CVarArg..., _ function:String = #function) {
let format = "\(function): \(givenFormat)"
withVaList(args) { NSLogv(format, $0) }
}
(Swift 3 code.)
Let's say I have the following:
var didConnectObserver: NSObjectProtocol?
didConnectObserver = NSNotificationCenter.defaultCenter().addObserverForName(
MyKey, object: nil, queue: nil, usingBlock: { (note) -> Void in
...
})
At some point I unregister:
NSNotificationCenter.defaultCenter().removeObserver(didConnectObserver)
This doesn't work, though, because didConnectObserver is an optional. Is there a more compact way to write this than:
if let obs = didConnectObserver {
NSNotificationCenter.defaultCenter().removeObserver(obs)
}
that still does the right thing if didConnectObserver is nil?
I'm still getting the hang of map with Optionals, but I believe this will work:
_ = didConnectObserver.map(NSNotificationCenter.defaultCenter().removeObserver)
If didConnectObserver is nil, the result of this is nil, otherwise it executes the function with didConnectObserver!. The _ = is necessary to suppress a warning Result of call to 'map' is unused.
Here's what autocomplete shows when you type didConnectObserver.map:
Here is another example of the same concept:
func add5(i: Int) {
print("add 5 called")
print(i + 5)
}
let a: Int? = 10
_ = a.map(add5)
If a is nil, then add5 is not called. If a is Optional(10), then add5 is called and 15 is printed.
It works just like:
if a != nil {
add5(a!)
}
I am working on Swift 1.2 with Xcode 6 but now I've installed Xcode 7 with Swift 2.1. There are many errors in Swift 2.1 and many syntax changes, even though my code works well with Swift 1.2. The first problem is with this method:
func getSubstringUpToIndex(index: Int, fromString str: String) -> String
{
var substring = ""
for (i, letter) in enumerate(str) {
substring.append(letter)
if i == index - 1 {
break
}
}
return substring
}
Another problem occurs on this line, "extra argument 'error' in call":
let jsonResult: Dictionary = NSJSONSerialization.JSONObjectWithData(self.mutableData, options: NSJSONReadingOptions.MutableContainers, error: &error) as! Dictionary<String, AnyObject>
In both cases it's Swift 1.2 code, not 2.0.
In the first snippet of code, the enumerate method does not exist anymore, you can update it this way:
func getSubstringUpToIndex(index: Int,
fromString str: String) -> String
{
var substring = ""
for (i, letter) in str.characters.enumerate() {
substring.append(letter)
if i == index - 1 {
break
}
}
return substring
}
Or this way, using substringRithRange :
func getSubstringUpToIndex2(index: Int,
fromString str: String) -> String {
let range = str.startIndex.advancedBy(0)..<str.startIndex.advancedBy(index)
return str.substringWithRange(range)
}
Try them out on swiftstub.
The second line you pasted does not work anymore because swift 2 now handles errors with try/do/catch, the last parameter NSErrorPointer does not exist anymore, learn more about swift2 error handling here.
My goal is to write something that can convert something like [AnyObject] to Result<[SomeObject], NSError> to easily do safe and chainable casting while working with a mixed Swift/Obj-C codebase. The conditional downcast operator as? seems to support that just fine, but I can't get a generic function working that utilizes that behavior. I've simplified the problem I'm encountering below:
class A { }
let obj = A()
let array: [AnyObject] = [obj]
func cast<T, U>(x: T, type: U.Type) -> U? {
if let x = x as? U {
return x
} else {
return nil
}
}
// This works
if let array = array as? [A] {
println(array)
}
// This works
println(cast(obj, A.self))
// This doesn't
println(cast(array, [A].self))
Note: This works in Swift 2.0, I don't know about 1.2, try it out
If you want to do something like this you'd have to overload your cast method with one for SequenceTypes:
func cast<T : SequenceType, U : SequenceType>(x: T, type: U.Type) -> [U.Generator.Element]? {
let y = x.map{ $0 as? U.Generator.Element }
if y.contains({ $0 == nil }) {
return nil
} else {
return y.flatMap{ $0 } // Swift 1.2 : y.map{ $0! }
}
}
EDIT: Changed according to your edit
Generally, Swift doesn't support GenericType<A> as? GenericType<B> cast, even if B is a subtype of A. Array<A> as? Array<B> is just a exception for our convenience.
There is a undocumented internal builtin function:
func _arrayConditionalDownCastElements<SourceElement, TargetElement>(a: Array<SourceElement>) -> [TargetElement]?
With my assumption, Swift implicitly calls this function when we do someArray as? [B]. But, with a generics type, just like your case, the Swift compiler cannot bind that to _arrayConditionalDownCastElements because it's unpredictable in compile time.
Anyway, you can call it manually, and implement cast as overloaded function:
func cast<T,U>(x:T, _: U.Type) -> U? {
return x as? U
}
func cast<T,U>(x:[T], _: [U].Type) -> [U]? {
return _arrayConditionalCast(x)
}
Similarly, there is _dictionaryDownCastConditional for Dictionary and _setDownCastConditional for Set:
func _dictionaryDownCastConditional<BaseKey, BaseValue, DerivedKey, DerivedValue>(source: Dictionary<BaseKey, BaseValue>) -> Dictionary<DerivedKey, DerivedValue>?
func _setDownCastConditional<BaseValue, DerivedValue>(source: Set<BaseValue>) -> Set<DerivedValue>?
Using this:
func cast<TKey,TValue, UKey, UValue>(x:[TKey: TValue], _: [UKey:UValue].Type) -> [UKey: UValue]? {
return _dictionaryDownCastConditional(x)
}
func cast<T, U>(x: Set<T>, _: Set<U>.Type) -> Set<U>? {
return _setDownCastConditional(x)
}
Again, they are undocumented. use them at your own risk :)