Hide Swift "Will never be executed" warning - xcode

I've got some code that is generating warnings like so:
code path.swift:9:13: warning: will never be executed
fatalError()
^
code path.swift:9:13: note: a call to a noreturn function
fatalError()
^
The compiler output doesn't give any -W arguments I can use to silence these in my source file. How can I stop these warnings?
Please note this is testing code and everything is working as designed - removing the lines complained about is not a solution

The Swift compiler does not have an option to suppress warnings
(as far as I know). The only chance is to avoid the warnings.
In your particular case I don't have a full explanation
for the warning, but a possible workaround. As you said in the comments,
the problem occurs with the Nimble framework in
expect{ fatalError() }.to(throwError()) // Warning: Will never be executed
Here, { fatalError() } is a closure of type () -> Void,
and expect ultimately calls the Expression initializer
public init(expression: () throws -> T?, location: SourceLocation, isClosure: Bool = true)
which takes a closure of type () throws -> T? as the first parameter.
The problem is now related to the optional return type T?.
This can be stripped down to the following minimal self-contained example:
let cl1 : () -> Void = { fatalError() } // No warning
let cl2 : () -> Void? = { fatalError() } // Warning: Will never be executed
Only the second line generates a warning.
I assume that the compiler creates some wrapper code to convert
the Void return type from fatalError() to Void?, and then warns
that the wrapper code is never executed.
As a workaround, you can make the closure type explicit as
let cl3 : () -> Void? = { _ -> Void in fatalError() } // No warning
or assign the closure to an intermediate variable:
let fatalClosure = { fatalError() }
let cl4 : () -> Void? = fatalClosure // No warning
This can be applied to your case:
expect {
_ -> Void in fatalError()
}.to(throwError())
But note that fatalError() – when called – terminates the program
immediately. There is no chance to "catch" that termination.

Related

How to use try with data.withUnsafeBytes() in Swift 5, Swift5?

If I option click on withUnsafeBytes in my code, the declaration states that the function throws:
func withUnsafeBytes<R>(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R
When I put in do try catch in my code (see below) I get a warning for the try:
No calls to throwing functions occur within 'try' expression
and a matching warning for the catch:
'catch' block is unreachable because no errors are thrown in 'do' block
Is my code incorrect or is this a problem with Xcode?
func getIntValue(data:Data)->Int
{
var d = -1
do {
d = try data.withUnsafeBytes {
$0.load(as: Int.self)
}
} catch {
return d
}
return d
}
Your input is appreciated.
The throws -> rethrows syntax does the following:
If the code in the closure body contains a throwing function the error is rethrown and you have to add try
If there is no throwing function nothing happens and you must not use try.
In your example the second case occurs so remove try and the do - catch block

Generic parameter 'Element' could not be inferred?

"Generic parameter 'Element' could not be inferred" - this error comes as I write guard statement - what is inside guard statement which causes error that element could not be inferred.
static func makeTokenForCard(with cardinfo: CardInfo) -> Single<String> {
return Single.create {
single in guard let ck = try CheckoutKit.getInstance("pk_123456789876543234567, env: Environment.SANDBOX, debug: true)
else {
let descr = "Unexpectedly Checkout got invalid private key. You may need to update the app."
single(.error(NSError.recreate(error: CheckoutError.invalidPK as NSError, description: descr)))
return
}
single(.success("123456"))
return Disposables.create()
}
}
When I remove this Guard statement - it returns simple String and errors in Single.
Edit :
After getting more into error, I found that its due to throws.
open class func getInstance(_ pk: String, env: Environment, debug: Bool) throws -> CheckoutKit? {
In Simple Guard & wrapping its fine.
So, How to call a method in Single when it has throws some expected error
?
This isn't RxSwift related but more Swift and handling errors.
The simplest answer to your question is to use try? instead try. This will fix the issue.
You can read more about error handling here https://docs.swift.org/swift-book/LanguageGuide/ErrorHandling.html

VS2012 complains when using +[]{} sorcery

I want automatic deduction of the arguments of a templated function which accepts a function, while using lambdas. This Example shows some of my options:
template <class T>
void foo(void (*func)(T)) {
T val;
// do something with val and func...
}
int main() {
auto pfunc0 = [] (int) { /*...*/ };
void (*pfunc1)(int) = [] (int) { /*...*/ };
auto* pfunc2 = +[] (int) { /*...*/ };
foo(pfunc0); // not ok
foo<int>(pfunc0); // ok, but redundant
foo(pfunc1); // ok, but redundant
foo(pfunc2); // ok
}
pfunc2 uses a trick I learned here: Obtaining function pointer to lambda?. So actually I should be happy with the pfunc2 case as it is concise and non repeating code, unfortunately the Visual C++ 2012 IDE complains it was erroneous code even though it compiles just fine.
Are there any workarounds or recommendations for this problem?
IDE error messages:
In the "auto* pfunc2" line: The IDE underlines 'auto' and says
Error: cannot deduce 'auto' type
also it underlines '[' where it complains
Error: more than one conversion function from "lambda[]void (int)->void" to a build-in type applies:
function "lambda[]void (int)->void::operator void (*)(int)() const"
function "lambda[]void (int)->void::operator void (*)(int)() const"
function "lambda[]void (int)->void::operator void (*)(int)() const"
This is related to this bug (closed as "by design"). VC++ supports several calling conventions on x86 and lambdas with empty capture lists provide conversions to them all. That's why there's ambiguity.
Unfortunately, there's no workaround listed that you haven't already tried.
By the way, this bug is listed as fixed in Visual C++ 2015 Update 2

JDK8 type inference issue

I'm trying to run the following code which is compiled fine under JDK8 thanks to type inference:
public static <A,B> B convert(A a) {
return (B) new CB();
}
public static void main(String[] args) {
CA a = new CA();
CB b = convert(a); //this runs fine
List<CB> bl = Arrays.asList(b); //this also runs fine
List<CB> bl1 = Arrays.asList(convert(a)); //ClassCastException here
}
However, running this throws ClassCastException: CB cannot be cast to [Ljava.lang.Object, but the CB b = convert(a) works fine.
Any idea why?
Whenever you create a generic method with a signature that promises to return whatever the caller wishes, you are asking for trouble. You should have got an “unchecked” warning from the compiler which basically means: unexpected ClassCastExceptions may occur.
You expect the compiler to infer
List<CB> bl1 = Arrays.asList(YourClass.<CA,CB>convert(a));
whereas the compiler actually inferred
List<CB> bl1 = Arrays.asList(YourClass.<CA,CB[]>convert(a));
as far as I know, because it prefers method invocations not requiring a varargs packaging (which is compatible with pre-varargs code).
This fails because your convert method does not return the expected array type.

Call to swift method from JavaScript hangs xcode and application

I am writing an iOS App (using xcode 7.3 and swift 2.2) using JavascriptCode framework. Calling javascript methods from swift works perfect, but when I call the swift method from javascript, xcode simply shows a "loading" type of symbol and nothing happens. I need to "force quit" xcode to get out of this state.
I have followed https://www.raywenderlich.com/124075/javascriptcore-tutorial and http://nshipster.com/javascriptcore/ and I am trying pretty simple calls.
Has anyone faced this kind of issue?
My swift code is as follows:
#objc protocol WindowJSExports : JSExport {
var name: String { get set }
func getName() -> String
static func createWindowWithName(name: String) -> WindowJS
}
#objc class WindowJS : NSObject, WindowJSExports {
dynamic var name: String
init(name: String) {
self.name = name
}
class func createWindowWithName(name: String) -> WindowJS {
return WindowJS(name: name)
}
func getName() -> String {
NSLog("getName called from JS context")
return "\(name)"
}
}
I am initializing the context as follows:
runContext = JSContext()
runContext.name = "test_Context"
windowToJs = WindowJS(name: "test")
runContext.setObject(windowToJs.self, forKeyedSubscript: "WindowJS")
If I replace the last two lines in above code with below code without instantiating it, the code simply fails to load.
runContext.setObject(WindowJS.self, forKeyedSubscript: "WindowJS")
And the javascript code is as simple as
function check() {
return WindowJS.getName()
}
I do see the breakpoint being hit in the JS function check and when the WindowJS.getName gets called, xcode simply becomes unresponsive.
The setTimeout could be solved by adding following piece of code to my swift function.
let setTimeout: #convention(block) (JSValue, Int) -> () =
{ callback, timeout in
let timeVal = Int64(timeout)
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, timeVal), dispatch_get_main_queue(), { callback.callWithArguments(nil)})
}
To expose this native code to the JS context, I also added following.
runContext.setObject(unsafeBitCast(setTimeout, AnyObject.self), forKeyedSubscript: "setTimeout")
Things then worked fine.
You're creating a deadlock since you are calling from Swift to JavaScript back to Swift. I'm not sure exactly why it is a deadlock but I had a similar issue with WKWebView on Mac recently.
You need to decouple this and make the communication asynchronous. This obviously means you cannot simply return a value from your JS function in this case.
To decouple, you can break the deadlock by deferring the work the JavaScript function needs to do out of the current runloop iteration using setTimeout:
function myFunction() {
setTimeout(function() {
// The actual work is done here.
// Call the Swift part here.
}, 0);
}
The whole native ↔︎ JavaScript communication is very, very tricky. Avoid it if you can. There's a project called XWebView that may be able to help you as it tries to ease bridging between the two worlds.

Resources