Generic and (Early) Binding in Swift 1.2

Swift generic method should use overloaded generic function

This currently cannot be achieved for reasons that you have mentioned yourself (you can't overload instance/class methods for specific types of <T>).

However, instead of using function overloading, you can check the type during runtime and act accordingly:

func printSomething<T>(something: T)
{
if let somestring = something as? String
{
println("This is using the specific version.")
println(somestring)

return
}

println("This is using the generic version.")
println(something)
}

The impact on performance should be negligible unless you call this function thousands of times.

Map and flatMap difference in optional unwrapping in Swift 1.2

(Remark: The answer has been updated to reflect the syntax changes in Swift 3 and later, such as the abolishment of ImplicitlyUnwrappedOptional.)

Optional.map() and Optional.flatMap() are declared as follows (I have omitted the throws/rethrows modifiers which are irrelevant here):

func map<U>(_ transform: (Wrapped) -> U) -> U?
func flatMap<U>(_ transform: (Wrapped) -> U?) -> U?

Let's consider a simplified version of your first example using “map”:

let number: Int? = 1
let res1 = number.map { $0 + 1 }
print(res1) // Optional(2)

number has the type Int? and the closure type is inferred as (Int) -> Int. U is Int, and the type of the return value is Int?. number is not nil, so it is unwrapped and passed 1 is passed to the closure. The closure returns 2 and map returns Optional(2). If number were nil then the result would be nil.

Now we consider a simplified version of your second example with “flatMap”:

let number: Int? = 1
let res2 = number.flatMap { $0 + 1 }
print(res2) // Optional(2)

flatMap expects a closure of type (Wrapped) -> U?, but { $0 + 1 } does not return an optional. In order to make it compile, the compiler converts this to

let res2 = number.flatMap { return Optional($0 + 1) }

Now the closure has type (Int) -> Int?, and U is Int again. Again, number is unwrapped and passed to the closure. The closure returns Optional(2) which is also the return value from flatMap. If number were nil or if the closure would return nil then the result would be nil.

So there is indeed no difference between these invocations:

let res1 = number.map { $0 + 1 }
let res2 = number.flatMap { $0 + 1 }

However that is not what flatMap is meant for. A more realistic example would be

func foo(_ s : String?) -> Int? {
return s.flatMap { Int($0) }
}

print(foo("1")) // Optional(1)
print(foo("x")) // nil (because `Int($0)` returns nil)
print(foo(nil)) // nil (because the argument is nil)

Generally, map takes a closure of type (Wrapped) -> U and transforms

Optional<Wrapped>.none          --> Optional<U>.none
Optional<Wrapped>.some(wrapped) --> Optional<U>.some(transform(wrapped))

flatMap takes a closure of type (Wrapped) -> U? and transforms

Optional<Wrapped>.none          --> Optional<U>.none
Optional<Wrapped>.some(wrapped) --> transform(wrapped)

Here transform(wrapped) can be Optional<U>.none as well.

If (as in your example) flatMap is called with a closure which does not return an optional then the compiler converts it to an optional automatically, and there is no difference to map anymore.

Cannot assign value of type NSDictionary to a value of type NSDictionary

You can force the cast as NSDictionary with ! (but it's better to use "guard" like in @robertvojta's answer).

Also, you can use [] instead of MutableContainers:

weatherData = try NSJSONSerialization.JSONObjectWithData(data!, options: []) as! NSDictionary

Playground screenshot

EDIT: Following @robertvojta's answer and explanations, I've edited out my wrong assertions about Swift 2 and force casting within "do ... catch". Also, note that in the screenshot NSData was only here for quick testing in the Playground, of course.

How to iterate through a enum to create a custom picker?

You're trying to use ForEach on a single ActivityLevelSelector item. For ForEach to work, it needs to be a collection of items (an Array, for example). This might be more what you're looking for:

struct ContentView: View {
let activityLevels: [ActivityLevelSelector] = ActivityLevelSelector.allCases

var body: some View {
NavigationView {
VStack {
Text("Please select your activity level.")
.font(.caption)
LazyHGrid(rows: [GridItem(.fixed(2))]) {
ForEach(activityLevels, id: \.self) { levelSelection in
Text(levelSelection.description)
}
}
}
}
}
}

If .allCases is indeed what you want, you could simplify even a bit more, getting rid of the let activityLevels and doing::

ForEach(ActivityLevelSelector.allCases, id: \.self) { levelSelection in

Note also that you can't just print inside the ForEach -- you need to return a View of some sort.

How to move to next TextField in SwiftUI?

iOS 15+

Use @FocusState

Before iOS 15

I've taken @Philip Borbon answer and cleaned it up a little bit. I've removed a lot of the customization and kept in the bare minimum to make it easier to see what's required.

struct CustomTextfield: UIViewRepresentable {
let label: String
@Binding var text: String

var focusable: Binding<[Bool]>? = nil

var returnKeyType: UIReturnKeyType = .default

var tag: Int? = nil

var onCommit: (() -> Void)? = nil

func makeUIView(context: Context) -> UITextField {
let textField = UITextField(frame: .zero)
textField.placeholder = label
textField.delegate = context.coordinator

textField.returnKeyType = returnKeyType

if let tag = tag {
textField.tag = tag
}

return textField
}

func updateUIView(_ uiView: UITextField, context: Context) {
uiView.text = text

if let focusable = focusable?.wrappedValue {
var resignResponder = true

for (index, focused) in focusable.enumerated() {
if uiView.tag == index && focused {
uiView.becomeFirstResponder()
resignResponder = false
break
}
}

if resignResponder {
uiView.resignFirstResponder()
}
}
}

func makeCoordinator() -> Coordinator {
Coordinator(self)
}

final class Coordinator: NSObject, UITextFieldDelegate {
let parent: CustomTextfield

init(_ parent: CustomTextfield) {
self.parent = parent
}

func textFieldDidBeginEditing(_ textField: UITextField) {
guard var focusable = parent.focusable?.wrappedValue else { return }

for i in 0...(focusable.count - 1) {
focusable[i] = (textField.tag == i)
}
parent.focusable?.wrappedValue = focusable
}

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
guard var focusable = parent.focusable?.wrappedValue else {
textField.resignFirstResponder()
return true
}

for i in 0...(focusable.count - 1) {
focusable[i] = (textField.tag + 1 == i)
}

parent.focusable?.wrappedValue = focusable

if textField.tag == focusable.count - 1 {
textField.resignFirstResponder()
}

return true
}

@objc func textFieldDidChange(_ textField: UITextField) {
parent.text = textField.text ?? ""
}
}
}


Related Topics



Leave a reply



Submit