implicit return in a closure causing an error
Not sure how to handle the above without having to have the dummy return statement, any advise.
You have solved the problem beautifully. Anonymous functions automatically use a one-line function body as a return value, so to prevent that from causing a type mismatch with the expected return type (Void) you have to add another line of code so that it is not a one-line function body. The dummy return statement, which itself returns Void, is a great way to handle it; I would just use that and move on. There are some snazzier workarounds but what you have is precisely what I would do.
EDIT: To understand the source of the type mismatch, try this:
struct Test {
func voider() -> Void {}
}
let testMaybe = Optional(Test())
let result = testMaybe?.voider()
Now result
is not a Void; it's an Optional wrapping a Void. That is what's happening to you; a Void is expected but your one-line anonymous function returns an Optional wrapping a Void. By adding another line that returns Void explicitly, you solved the problem.
How to Supress implicit return from a closure with Void return type in Swift
I recreated your example with your code (with minor tweaks) and didn't have the problem you described. I used a swift dictionary instead though, since I have no knowledge about Obj-C.
func doSomething(completionHandler: Bool -> Void) {
completionHandler(true)
}
doSomething() { finished in
var data = [String: String]()
data.updateValue("data1", forKey: "data1") // 1
data.updateValue("data2", forKey: "data2") // 2
data.updateValue("data3", forKey: "data3") // 3
for (key, value) in data {
println("Key: \(key) & Value: \(value)")
}
}
The output is:
Key: data2 & Value: data2
Key: data1 & Value: data1 // Not sure why data1 is second here
Key: data3 & Value: data3
I doubt using NSDictionary
could be the cause of it, maybe something else is causing it to return?
Why can't returns infer the type of the return, and I have to explicitly return instead of using closures?
Let's understand your code to more clearly see what happens.
pub fn bigger(a: i32, b: i32) -> i32 {
let biggest = if a > b { a } else { return b };
}
You're creating a locally-scoped binding with the name biggest
. If a > b
it will have value of a
, else the function will return b
.
So for a > b
there is no implicit or explicit return value for this function.
In this function, there is no need for an explicitly named biggest
binding. You can use Rust's property of implicit returns:
pub fn bigger(a: i32, b: i32) -> i32 {
if a > b {
a
} else {
b
}
}
I should mention that this function is equivalent to std::cmp::max
from the standard library.
Statement in SwiftUI closure body causes type error
This error occurs because multi-statement closures don't take part in type inference. The Content
generic parameter of the initialiser of GeometryReader
cannot be inferred because the only information you provide to it, the closure, is not considered for type-inference!
So you just need to specify what type you are returning:
.background(GeometryReader {
p -> Rectangle in // note here
print("Hello")
return Rectangle()
})
You probably shouldn't do this though, because you are supposed to only put View
s in a view builder closure. SwiftUI is designed to be very declarative, almost its own DSL, I would say.
Edit: I found this answer, which adds a View
called Print
. I guess you can put one of these alongside whatever view you are setting the background of, in a Group
.
Declare a temporary variable or constant inside a closure that returns some View (SwiftUI)
This is due to a limitation where the Swift compiler only tries to infer a closure's return type if it is a single expression. Closure's that are processed by a result builder, such as @ViewBuilder
, are not subject to this limitation. Importantly, this limitation also doesn't affect functions (only closures).
I was able to make this work by moving the closure to a method inside the structure. Note: this is the same as @cluelessCoder's second solution, just excluding the @ViewBuilder
attribute.
struct GameView: View {
@State private var cards = [
Card(value: 100),
Card(value: 20),
Card(value: 80),
]
var body: some View {
MyListView(items: cards, content: cardView)
}
func cardView(for card: Card) -> some View {
let label = label(for: card) // only called once, and can be reused.
return Text(label)
}
func label(for card: Card) -> String {
return "Card with value \(card.value)"
}
}
Thanks to @cluelessCoder. I would have never stumbled upon this discovery without their input and helpful answer.
Related Topics
Swiftui Set Position to Center of Different View
Swift Arrays and Contains, How to Determine If a Collection Contains an Object or Value
App Delegate Accessing Environment Object
Xcode Beta 6 "Type of Expression Is Ambiguous Without More Context" Navigationlink
Swift 5.5: Asynchronously Iterating Line-By-Line Through a File
Protocol Extending Encodable (Or Codable) Does Not Conform to It
Single-Element Parethesized Expressions/Tuples VS Common Use of Parentheses
Center Item Inside Horizontal Stack
Remove All Non-Numeric Characters from a String in Swift
How to Load Image in Swift Using Alamofire
Swift Uialertcontroller with Pickerview Button Action Stay Up
Differencebetween Http Parameters and Http Headers
Swift: How to Create External Interface for Static Library (Public Headers Analog in Objective-C .H)
How to Create Nsradiobutton Group in Xcode 7 Osx