Using Swift's optional binding to get NSData's bytes directly? - swift

I have the following code, assuming data is of type NSData?:
if let myData = data {
let bytes = UnsafePointer<UInt8>(myData.bytes)
...
}
How do I reduce this to a single statement, such as:
if let bytes = UnsafePointer<UInt8>?(data?.bytes) {
...
}
The above gives an error of: Cannot invoke initializer for type 'UnsafePointer<UInt8>?' with an argument list of type '(UnsafePointer<Void>?)'

Similarly as in Getting the count of an optional array as a string, or nil, you can use the map()
method of Optional:
/// If `self == nil`, returns `nil`. Otherwise, returns `f(self!)`.
#warn_unused_result
#rethrows public func map<U>(#noescape f: (Wrapped) throws -> U) rethrows -> U?
In your case:
if let bytes = (data?.bytes).map({ UnsafePointer<UInt8>($0) }) {
}
(data?.bytes) uses optional chaining and has the type
UnsafePointer<Void>?. The map function is used to convert that
to UnsafePointer<UInt8>?, which is finally unwrapped with the
optional binding.

Related

Determine Collection type in Swift

I've a function whose header looks like this
func doSomethingOnCollection<T:Collection>(_ array: T) -> [T]
as you can see it takes Collection as a parameter, meaning it can be Array, Set or Dictionary, how can I check type of parameter passed in this function at runtime ?
Swift documentation says:
Use the type check operator (is) to check whether an instance is of a
certain subclass type. The type check operator returns true if the
instance is of that subclass type and false if it is not.
func doSomethingOnCollection<T: Collection>(_ param: T) -> [T] {
if param is Array<Any> {
print("Array")
}
// We can't say 'Set<Any>', since type of set should conform
// protocol 'Hashable'
else if param is Set<Int> {
print("Set")
}
// For the same reason above, we can't say 'Dictionary<Any, Any>'
else if param is Dictionary<Int, Any> {
print("Dictionary")
}
return []
}

Cannot convert value type... when using generics and polymorphism in Swift 3

In my simplified example I'm getting the error: Cannot convert value of type 'Foo' to expected argument type BaseItem<Any>
But the class Foo extends BaseItem<String>.
This is the example code:
class BaseItem<T> {
var param: T?
}
class Foo: BaseItem<Int> {
}
func checkItem(item: BaseItem<Any>) -> Bool{
return item.param != nil;
}
I get the error when calling
checkItem(item: Foo())
What am I missing?
You need to define your checkItem function in terms of generics too:
func checkItem<T>(item: BaseItem<T>) -> Bool {
return item.param != nil
}
Gotta define checkItem function with generics too.
func checkItem<T>(item: BaseItem<T>) -> Bool {
return item.param != nil
}
The problem is that generics are invariant – consider if your checkItem(item:) function had said:
func checkItem(item: BaseItem<Any>) {
item.param = "foo"
}
That would be illegal for a BaseItem<Int>, as you cannot possibly assign a String instance to an Int? property – which is why it (an instance of Foo) cannot be typed as a BaseItem<Any>.
The solution, as other answers have said, is to use a generic placeholder for the function:
func checkItem<T>(item: BaseItem<T>) -> Bool {
return item.param != nil
}
Now, rather than saying that you're taking a BaseItem<Any>, that has a param of type Any? (can be assigned a value of any type) – you're now saying that you're taking a BaseItem with any specific placeholder type; which will be satisfied at the call-site of the function.
The function implementation itself therefore cannot make any assumptions about this type, and will disallow the assignment of an arbitrary value to param. The compiler will only allow an assignment of a value of type T.
The signature of checkItem function should be: checkItem<T>(item: BaseItem<T>) -> Bool, as follows:
func checkItem<T>(item: BaseItem<T>) -> Bool {
return item.param != nil
}
Usage:
checkItem(item: Foo()) // false
let myFoo = Foo()
myFoo.param = 0
checkItem(item: myFoo) // true
The reason of why the compiler complains about
Cannot convert value of type 'Foo' to expected argument type
BaseItem
is that you are trying to pass BaseItem<Int> instance as BaseItem<Any> which is invalid (Any data type is not T generic type).

What is the syntax for a closure argument in swift

In Swift headers, the isSeparator: argument accepts a closure
public func split(maxSplit: Int = default, allowEmptySlices: Bool = default, #noescape isSeparator: (Self.Generator.Element) throws -> Bool) rethrows -> [Self.SubSequence]
But in the documentation, it lists closure syntax differently
{ (parameters) -> return type in
statements
}
How are you supposed to know that (Self.Generator.Element) throws -> Bool rethrows refers to a closure / requires a closure? Are there other ways that the headers/docs might list argument as meaning a closure?
The "thing" giving away that this is a closure is the ->. The full type is
(Self.Generator.Element) throws -> Bool
It means that the closure takes a variable of type Self.Generator.Element and has to return a Bool upon some calculation based on the input. It may additionally throw some error while doing so - that is what the throws is for.
What you then write
{ (parameters) -> return type in
statements
}
would be an actual implementation, a value of some generic closure type.
The type of a closure is for example (someInt:Int, someDouble:Double) -> String:
var a : ((someInt:Int, someDouble:Double) -> String)
Once again the thing giving away that a is actually a closure is the -> in the type declaration.
Then you assign something to a via some code snippet following your second code block:
a = { (integer, floating) -> String in
return "\(integer) \(floating)"
}
You can tell by the argument's type. Everything in Swift has a type, including functions and closures.
For example, this function...
func add(a: Int, to b: Int) -> Int { return a + b }
...has type (Int, Int) -> Int. (It takes two Ints as parameters, and returns an Int.)
And this closure...
let identity: Int -> Int = { $0 }
...has type Int -> Int.
Every function and closure has a type, and in the type signature there is always a -> that separates the parameters from the return value. So anytime you see a parameter (like isSeparator) that has a -> in it, you know that the parameter expects a closure.
the isSeparator definition means (Self.Generator.Element) throws -> Bool that you will be given an Element and you should return a Bool. When you will call split, you then can do the following :
[1,2,3].split(…, isSeparator : { element -> Bool in
return false
})
This is a pure silly example but that illustrates the second part of your question

Shorthand for wrapping a swift variable in an optional?

Swift allows us to use the shorthand notation str! to unwrap an optional. But what if we want to do the opposite?
Say I have a variable:
var str = String() // String
Is there any shorthand notation to convert this to an optional (i.e. String? or String!)?
(E.g. I want to do something like var strOptional = ?(str).)
Alternatively, if there is no shorthand for this notation, how can I convert it to an optional without explicitly mentioning its type (e.g. I don't want to mention String).
In other words, I know that I can wrap a variable as an optional with any of these methods:
var strOptional = str as String?
var strOptional: String? = str
var strOptional = String?(str)
... but in each case, I must explicitly write String.
I would rather write something like: var strOptional = str as typeof?(str), if there is no shorthand syntax. (The advantage is that if the variable's type is frequently changed in the code base, it would be one less place to update.)
As far as a real world example of where this would be useful, imagine I want to use an AVCaptureDevice and I use the following code:
let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
device.lockForConfiguration(nil)
lockForConfiguration() will crash at runtime on a device that has no video camera, and the compiler won't warn me about it. The reason is that defaultDeviceWithMediaType may return nil according to the documentation[1], yet it is defined to return a AVCaptureDevice!.
To fix a faulty API like this, it would be nice to do something like:
let device = ?(AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo))
... to get a AVCaptureDevice?, and have the compiler catch any mistakes I might make.
Currently, I must resort to the more verbose:
let device: AVCaptureDevice? = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
Another example:
In this case, I want to give a default value to my variable that is a string, but later on, I may want to assign it a nil value.
var myString = "Hi"
// ...
if (someCondition()) {
myString = nil // Syntax error: myString is String
}
Currently I have to resort to var myString: String? = "Hi" but something like var myString = ?("Hi") would be less verbose.
[1] If you open AVCaptureDevice.h, you will see the following documentation about the return value: "The default device with the given media type, or nil if no device with that media type exists."
Optional is just an enum in swift, so you can do: Optional(str)
From the swift interface:
/// A type that can represent either a `Wrapped` value or `nil`, the absence
/// of a value.
public enum Optional<Wrapped> : _Reflectable, NilLiteralConvertible {
case None
case Some(Wrapped)
/// Construct a `nil` instance.
public init()
/// Construct a non-`nil` instance that stores `some`.
public init(_ some: Wrapped)
/// If `self == nil`, returns `nil`. Otherwise, returns `f(self!)`.
#warn_unused_result
public func map<U>(#noescape f: (Wrapped) throws -> U) rethrows -> U?
/// Returns `nil` if `self` is `nil`, `f(self!)` otherwise.
#warn_unused_result
public func flatMap<U>(#noescape f: (Wrapped) throws -> U?) rethrows -> U?
/// Create an instance initialized with `nil`.
public init(nilLiteral: ())
}
To wrap up a variable you could use operator overloading and generic functions. For example:
prefix operator ??? {}
prefix func ??? <T> (x: T) -> T? {
return Optional(x)
}
To relate this to your second example, you would do the following:
var myString = ???"Hi" // Optional("Hi")
if someCondition() {
myString = nil
}
In the lighthearted spirit that, as I understand, the question was posed, you can define a postfix operator that uses one character less than your ideal solution (a pair of parens and a question mark):
postfix operator =? {}
postfix func =? <T> (rhs: T) -> T? { return rhs }
postfix func =? <T> (rhs: T!) -> T? { return rhs ?? nil }
var x = 3=?
x is Int? //--> true
var imp: Int! = 3
var opt = imp=?
opt is Int? //--> true
As to Apple's APIs you mention, since they already return an optional, albeit an implicitly unwrapped optional, you could use the nil coalescing operator ?? to convert it to a plain optional:
let y: Int! = 3 // posing for a rogue API
y is Int? //--> false
let z = y ?? nil
z is Int? //--> true
Perhaps a sligtly more interesting use of a dodgy operator is a higher order operator function that lifts T -> Us into T? -> U?s...
func opt <T, U> (f: T -> U) -> T? -> U? { // we'll implement this as an operator
return { $0.map(f) }
}
postfix operator ->? {}
postfix func ->? <T, U> (f: T -> U) -> T? -> U? {
return { $0.map(f) }
}
Now, let's use it:
let square: Int -> Int = { $0 * $0 }
let i: Int? = 3
square->? (i)
Which is equivalent to:
opt(square)(i)
Which is equivalent to (but potentially a little more versatile than):
i.map(square)
This all makes much more sense when used along with the pipe forward operator:
infix operator |> { associativity left precedence 89 }
func |> <A, B>(a: A, f: A -> B) -> B {
return f(a)
}
Then you can do:
i |> opt(square)
or
i |> square->?
Or we can conflate these into an optional pipe forward, which can take care of implicitly unwrapped optionals too:
infix operator ?> { associativity left precedence 89 }
func ?> <T, U> (lhs: T?, rhs: T -> U) -> U? {
return lhs.map(rhs)
}
let im: Int! = 5
let op: Int? = 5
im ?> square |> debugPrintln //--> Optional(25)
op ?> square |> debugPrintln //--> Optional(25)
Which is equivalent to:
debugPrintln(op.map(square))

'Cannot convert the expression's type' with optional in closure body

I have come across (most definitely) a feature that I don't quite understand. I have a closure, that takes in a Float and has no return value, aka (number: Float) -> Void. In that closure, I perform a call on optional value, not forcing its unwrapping, because I like the behavior since the optional is a delegate (= if it's nil, don't do anything).
But when I do that, I get an error:
Cannot convert the expression's type '...' to type Float.
Interestingly enough, when I simply add println(), the error disappears. I have simplified my case to tiny little example for illustration:
var optional: [String : Int]?
let closure: (number: Int) -> Void = { (number) -> Void in
optional?.updateValue(number, forKey: "key")
//println() <-- when this gets uncommented, error disappears
}
My bet would be that the compiler maybe doesn't like that in some cases I'm not handling the float number, but since I am not returning the value then it should just disappear right? What am I missing?
An expression containing a single expression is inferred to return that result, hence:
let closure: (number: Int) -> Void = { (number) -> Void in
optional?.updateValue(number, forKey: "key")
}
is equivalent to:
let closure: (number: Int) -> Void = { (number) -> Void in
return optional?.updateValue(number, forKey: "key")
}
You now have conflicting return types between Void and Int? (remember, updateValue returns the old value)
Splitting it up with an explicit return clarifies the inferred typing.
let closure: (number: Int) -> Void = { (number) -> Void in
optional?.updateValue(number, forKey: "key")
return
}
I think your closure won't like returning nil because Void can't be converted to nil.
If you do that in a playground:
var n: Void = ()
n = nil
You'll get this error:
error: type 'Void' does not conform to protocol 'NilLiteralConvertible'