This question was inspired by a similar question on how to decrement the ASCII value of a character in Swift: How to decrement a Character that contains a digit?
The UnicodeScalar struct provides an interface to represent a Unicode scalar value in Swift. I am trying to extend UnicodeScalar and create an initializer that takes in a Swift Character and returns a UnicodeScalar value of that Character.
To create a UnicodeScalar from a String is very easy. There is a private initializer for _NSSimpleObjCType (which conforms to UnicodeScalar) which takes a the first character of a String and passes it to the rawValue constructor.
NSObjCRuntime.swift
extension _NSSimpleObjCType {
init?(_ v: UInt8) {
self.init(rawValue: UnicodeScalar(v))
}
init?(_ v: String?) {
if let rawValue = v?.unicodeScalars.first {
self.init(rawValue: rawValue)
} else {
return nil
}
}
}
The result:
let stringScalar = UnicodeScalar("8") // 56 (U+0038)
From a Character literal this is more verbose. I need to manually convert the Character to a String, get its unicodeScalars, and return the first scalar in the array:
let c = Character("8")
let str = String(c)
if let scalar = str.unicodeScalars.first { // 56 (U+0038)
// ...
}
My attempt at an init in an extension:
extension UnicodeScalar {
init?(_ v: Character?) {
if let rawValue = String(v).unicodeScalars.first {
String(v).unicodeScalars.first
self.init(rawValue)
} else {
return nil;
}
}
}
Testing this new init with "8" returns U+004F ("O"), when I would expect it to return "8" (U+0038).
let testChar = Character("8")
let scalar = UnicodeScalar(testChar) // U+004F
I've also tried calling the String initializer with self.init(String(v)) in the init above, but I get the error 'UnicodeScalar.init' with an argument list of type '(String)'. I know this isn't the case since the String initializer is provided with the extension on _NSSimpleObjCType.
Where did my initializer fail?
Your init method
init?(_ v: Character?)
takes an optional character as parameter, therefore the string
interpolation String(v) returns the string
Optional("8")
with capital "O" as the first Unicode scalar ...
Changing the parameter type to a non-optional (or unwrapping
the parameter) should solve the problem.
Related
I have a c api that returns a null terminated string that is an array of type unsigned char* (which would correspond to UnsafePointer<UInt8>).
Swift has the initializer String(validatingUTF8:), but the argument has to be UnsafePointer<CChar> (a.k.a. UnsafePointer<Int8>), and there is no trivial way to convert between the two.
How do I convert from this null-terminated c-string to a Swift string?
In Swift 3, String has two initializers
public init(cString: UnsafePointer<CChar>)
public init(cString: UnsafePointer<UInt8>)
therefore it can be created from (null-terminated) sequences of both signed and unsigned characters. So
let s = String(cString: yourCharPointer)
should just work.
String has another initializer
public init?(validatingUTF8 cString: UnsafePointer<CChar>)
which fails on ill-formed UTF-8 sequences instead of replacing them
by the replacement characters. This init method has no counterpart
taking unsigned characters.
Taking the existing implementations in CString.swift as examples, it is not too difficult to add this as an extension:
extension String {
public init?(validatingUTF8 cString: UnsafePointer<UInt8>) {
guard let (s, _) = String.decodeCString(cString, as: UTF8.self,
repairingInvalidCodeUnits: false) else {
return nil
}
self = s
}
}
and then
if let s = String(validatingUTF8: yourCharPointer) {
print(s)
} else {
print("invalid UTF-8")
}
also works with (null-terminated) sequences of both signed and unsigned characters.
protocol Measurement {
mutating func convert(#toUnit: String)
}
enum MassUnit : String {
case Milligram = "mg"
}
enum VolumeUnit : String {
case Milliliter = "ml"
}
struct Mass : Measurement {
mutating func convert(#toUnit: MassUnit)
// Build error: Does not adhere to 'Measurement'
}
struct Volume : Measurement {
mutating func convert(#toUnit: VolumeUnit)
// Build error: Does not adhere to 'Measurement'
}
func +<T: Measurement> (left:T, right:T) -> Measurement {
let newRightValue = right.convert(toUnit: left.unit)
return T(quantity: left.quantity + newRightValue.quantity , unit: left.unit)
}
How can I make Mass adhere correctly to Measurement? What change in the Measurement protocol is needed to get it to work with enum of type String?
Question updated with more information about why the convert method signature should say something about the argument given. The code is part of an open source Unit framework i'm building called Indus Valley
You probably confuse enum MassUnit : String with inheritance.
Contrary to class ChildClass : ParentClass which denotes that ChildClass inherits from ParentClass, enum MassUnit : String has a slightly different meaning, telling that the rawType of the enum is String, not that the enum inherits the String type.
So MassUnit is not of type String. You MassUnit's rawValues are of type String, but to access that you need to call the rawValue property of the enum to get that String equivalent.
Therefore, mutating func convert(#toUnit: String) and mutating func convert(#toUnit: MassType) are not compatible, as MassType is not a String itself. Only its rawValue is.
When dealing with your unit conversions, I advise not trying to use Strings to represent the units when converting the way you've got setup above. That's going to make your code complicated with checking the String can be converted to its respective enum every time you want to make a conversion. Also, what if you want to use the a MassUnit/VolumeUnit instead of a String?
I would recommend using the a setup similar to what I've outlined below. It references my previous answer - How to represent magnitude for mass in Swift?
(Note - I've excluded anything to do with the volume because it's basically the same as the implementation for the mass)
I'd make the units like so:
protocol UnitProtocol {
var magnitude: Int { get }
init?(rawValue: String)
}
// Taken from my previous answer.
enum MassUnit: String, UnitProtocol, Printable {
case Milligram = "mg"
case Gram = "g"
var magnitude: Int {
let mag: Int
switch self {
case .Milligram: mag = -3
case .Gram : mag = 0
}
return mag
}
var description: String {
return rawValue
}
}
// Not making this a method requirement of `UnitProtocol` means you've only got to
// write the code once, here, instead of in every enum that conforms to `UnitProtocol`.
func ordersOfMagnitudeFrom<T: UnitProtocol>(unit1: T, to unit2: T) -> Int {
return unit1.magnitude - unit2.magnitude
}
Then I'd make the masses/volumes like so:
protocol UnitConstruct {
typealias UnitType: UnitProtocol
var amount: Double { get }
var unit : UnitType { get }
init(amount: Double, unit: UnitType)
}
struct Mass : UnitConstruct {
let amount: Double
let unit : MassUnit
}
Now for the converting function! Using a global function means you don't need to rewrite the code for every type than conforms to UnitConstruct.
func convert<T: UnitConstruct>(lhs: T, toUnits unit: T.UnitType) -> T {
let x = Double(ordersOfMagnitudeFrom(lhs.unit, to: unit))
return T(amount: lhs.amount * pow(10, x), unit: unit)
}
// This function is for converting to different units using a `String`,
// as asked in the OP.
func convert<T: UnitConstruct>(lhs: T, toUnits unit: String) -> T? {
if let unit = T.UnitType(rawValue: unit) {
return convert(lhs, toUnits: unit)
}
return nil
}
You can then use the previous code like so:
let mass1 = Mass(amount: 1.0, unit: .Gram)
let mass2 = convert(mass1, toUnits: .Milligram) // 1000.0 mg
// Or, converting using Strings:
let right = convert(mass1, toUnits: "mg") // Optional(1000.0 mg)
let wrong = convert(mass1, toUnits: "NotAUnit") // nil
Quite often, you need to write code such as the following:
if someOptional != nil {
// do something with the unwrapped someOptional e.g.
someFunction(someOptional!)
}
This seems a bit verbose, and also I hear that using the ! force unwrap operator can be unsafe and best avoided. Is there a better way to handle this?
It is almost always unnecessary to check if an optional is not nil. Pretty much the only time you need to do this is if its nil-ness is the only thing you want to know about – you don’t care what’s in the value, just that it’s not nil.
Under most other circumstances, there is a bit of Swift shorthand that can more safely and concisely do the task inside the if for you.
Using the value if it isn’t nil
Instead of:
let s = "1"
let i = Int(s)
if i != nil {
print(i! + 1)
}
you can use if let:
if let i = Int(s) {
print(i + 1)
}
You can also use var:
if var i = Int(s) {
print(++i) // prints 2
}
but note that i will be a local copy - any changes to i will not affect the value inside the original optional.
You can unwrap multiple optionals within a single if let, and later ones can depend on earlier ones:
if let url = NSURL(string: urlString),
data = NSData(contentsOfURL: url),
image = UIImage(data: data)
{
let view = UIImageView(image: image)
// etc.
}
You can also add where clauses to the unwrapped values:
if let url = NSURL(string: urlString) where url.pathExtension == "png",
let data = NSData(contentsOfURL: url), image = UIImage(data: data)
{ etc. }
Replacing nil with a default
Instead of:
let j: Int
if i != nil {
j = i
}
else {
j = 0
}
or:
let j = i != nil ? i! : 0
you can use the nil-coalescing operator, ??:
// j will be the unwrapped value of i,
// or 0 if i is nil
let j = i ?? 0
Equating an optional with a non-optional
Instead of:
if i != nil && i! == 2 {
print("i is two and not nil")
}
you can check if optionals are equal to non-optional values:
if i == 2 {
print("i is two and not nil")
}
This also works with comparisons:
if i < 5 { }
nil is always equal to other nils, and is less than any non-nil value.
Be careful! There can be gotchas here:
let a: Any = "hello"
let b: Any = "goodbye"
if (a as? Double) == (b as? Double) {
print("these will be equal because both nil...")
}
Calling a method (or reading a property) on an optional
Instead of:
let j: Int
if i != nil {
j = i.successor()
}
else {
// no reasonable action to take at this point
fatalError("no idea what to do now...")
}
you can use optional chaining, ?.:
let j = i?.successor()
Note, j will also now be optional, to account for the fatalError scenario. Later, you can use one of the other techniques in this answer to handle j’s optionality, but you can often defer actually unwrapping your optionals until much later, or sometimes not at all.
As the name implies, you can chain them, so you can write:
let j = s.toInt()?.successor()?.successor()
Optional chaining also works with subscripts:
let dictOfArrays: ["nine": [0,1,2,3,4,5,6,7]]
let sevenOfNine = dictOfArrays["nine"]?[7] // returns {Some 7}
and functions:
let dictOfFuncs: [String:(Int,Int)->Int] = [
"add":(+),
"subtract":(-)
]
dictOfFuncs["add"]?(1,1) // returns {Some 2}
Assigning to a property on an optional
Instead of:
if splitViewController != nil {
splitViewController!.delegate = self
}
you can assign through an optional chain:
splitViewController?.delegate = self
Only if splitViewController is non-nil will the assignment happen.
Using the value if it isn’t nil, or bailing (new in Swift 2.0)
Sometimes in a function, there’s a short bit of code you want to write to check an optional, and if it’s nil, exit the function early, otherwise keep going.
You might write this like this:
func f(s: String) {
let i = Int(s)
if i == nil { fatalError("Input must be a number") }
print(i! + 1)
}
or to avoid the force unwrap, like this:
func f(s: String) {
if let i = Int(s) {
print(i! + 1)
}
else {
fatalErrr("Input must be a number")
}
}
but it’s much nicer to keep the error-handling code at the top by the check. This can also lead to unpleasant nesting (the "pyramid of doom").
Instead you can use guard, which is like an if not let:
func f(s: String) {
guard let i = Int(s)
else { fatalError("Input must be a number") }
// i will be an non-optional Int
print(i+1)
}
The else part must exit the scope of the guarded value, e.g. a return or fatalError, to guarantee that the guarded value will be valid for the remainder of the scope.
guard isn’t limited to function scope. For example the following:
var a = ["0","1","foo","2"]
while !a.isEmpty {
guard let i = Int(a.removeLast())
else { continue }
print(i+1, appendNewline: false)
}
prints 321.
Looping over non-nil items in a sequence (new in Swift 2.0)
If you have a sequence of optionals, you can use for case let _? to iterate over all the non-optional elements:
let a = ["0","1","foo","2"]
for case let i? in a.map({ Int($0)}) {
print(i+1, appendNewline: false)
}
prints 321. This is using the pattern-matching syntax for an optional, which is a variable name followed by ?.
You can also use this pattern matching in switch statements:
func add(i: Int?, _ j: Int?) -> Int? {
switch (i,j) {
case (nil,nil), (_?,nil), (nil,_?):
return nil
case let (x?,y?):
return x + y
}
}
add(1,2) // 3
add(nil, 1) // nil
Looping until a function returns nil
Much like if let, you can also write while let and loop until nil:
while let line = readLine() {
print(line)
}
You can also write while var (similar caveats to if var apply).
where clauses also work here (and terminate the loop, rather than skipping):
while let line = readLine()
where !line.isEmpty {
print(line)
}
Passing an optional into a function that takes a non-optional and returns a result
Instead of:
let j: Int
if i != nil {
j = abs(i!)
}
else {
// no reasonable action to take at this point
fatalError("no idea what to do now...")
}
you can use optional’s map operator:
let j = i.map { abs($0) }
This is very similar to optional chaining, but for when you need to pass the non-optional value into the function as an argument. As with optional chaining, the result will be optional.
This is nice when you want an optional anyway. For example, reduce1 is like reduce, but uses the first value as the seed, returning an optional in case the array is empty. You might write it like this (using the guard keyword from earlier):
extension Array {
func reduce1(combine: (T,T)->T)->T? {
guard let head = self.first
else { return nil }
return dropFirst(self).reduce(head, combine: combine)
}
}
[1,2,3].reduce1(+) // returns 6
But instead you could map the .first property, and return that:
extension Array {
func reduce1(combine: (T,T)->T)->T? {
return self.first.map {
dropFirst(self).reduce($0, combine: combine)
}
}
}
Passing an optional into a function that takes an optional and returns a result, avoiding annoying double-optionals
Sometimes, you want something similar to map, but the function you want to call itself returns an optional. For example:
// an array of arrays
let arr = [[1,2,3],[4,5,6]]
// .first returns an optional of the first element of the array
// (optional because the array could be empty, in which case it's nil)
let fst = arr.first // fst is now [Int]?, an optional array of ints
// now, if we want to find the index of the value 2, we could use map and find
let idx = fst.map { find($0, 2) }
But now idx is of type Int??, a double-optional. Instead, you can use flatMap, which “flattens” the result into a single optional:
let idx = fst.flatMap { find($0, 2) }
// idx will be of type Int?
// and not Int?? unlike if `map` was used
I think you should go back to the Swift programming book and learn what these things are for. ! is used when you are absolutely sure that the optional isn't nil. Since you declared that you are absolutely sure, it crashes if you're wrong. Which is entirely intentional. It is "unsafe and best avoided" in the sense that asserts in your code are "unsafe and best avoided". For example:
if someOptional != nil {
someFunction(someOptional!)
}
The ! is absolutely safe. Unless there is a big blunder in your code, like writing by mistake (I hope you spot the bug)
if someOptional != nil {
someFunction(SomeOptional!)
}
in which case your app may crash, you investigate why it crashes, and you fix the bug - which is exactly what the crash is there for. One goal in Swift is that obviously your app should work correctly, but since Swift cannot enforce this, it enforces that your app either works correctly or crashes if possible, so bugs get removed before the app ships.
You there is one way. It is called Optional Chaining. From documentation:
Optional chaining is a process for querying and calling properties,
methods, and subscripts on an optional that might currently be nil. If
the optional contains a value, the property, method, or subscript call
succeeds; if the optional is nil, the property, method, or subscript
call returns nil. Multiple queries can be chained together, and the
entire chain fails gracefully if any link in the chain is nil.
Here is some example
class Person {
var residence: Residence?
}
class Residence {
var numberOfRooms = 1
}
let john = Person()
if let roomCount = john.residence?.numberOfRooms {
println("John's residence has \(roomCount) room(s).")
} else {
println("Unable to retrieve the number of rooms.")
}
// prints "Unable to retrieve the number of rooms."
You can check the full article here.
We can use optional binding.
var x:Int?
if let y = x {
// x was not nil, and its value is now stored in y
}
else {
// x was nil
}
After lot of thinking and researching i have came up with the easiest way to unwrap an optional :
Create a new Swift File and name it UnwrapOperator.swift
Paste the following code in the file :
import Foundation
import UIKit
protocol OptionalType { init() }
extension String: OptionalType {}
extension Int: OptionalType {}
extension Int64: OptionalType {}
extension Float: OptionalType {}
extension Double: OptionalType {}
extension CGFloat: OptionalType {}
extension Bool: OptionalType {}
extension UIImage : OptionalType {}
extension IndexPath : OptionalType {}
extension NSNumber : OptionalType {}
extension Date : OptionalType {}
extension UIViewController : OptionalType {}
postfix operator *?
postfix func *?<T: OptionalType>( lhs: T?) -> T {
guard let validLhs = lhs else { return T() }
return validLhs
}
prefix operator /
prefix func /<T: OptionalType>( rhs: T?) -> T {
guard let validRhs = rhs else { return T() }
return validRhs
}
Now the above code has created 2 operator [One prefix and one postfix].
At the time of unwrapping you can use either of these operator before or after the optionals
The explanation is simple, the operators returns the constructor value if they get nil in variable else the contained value inside the variable.
Below is the example of usage :
var a_optional : String? = "abc"
var b_optional : Int? = 123
// before the usage of Operators
print(a_optional) --> Optional("abc")
print(b_optional) --> Optional(123)
// Prefix Operator Usage
print(/a_optional) --> "abc"
print(/b_optional) --> 123
// Postfix Operator Usage
print(a_optional*?) --> "abc"
print(b_optional*?) --> 123
Below is the example when variable contains nil :
var a_optional : String? = nil
var b_optional : Int? = nil
// before the usage of Operators
print(a_optional) --> nil
print(b_optional) --> nil
// Prefix Operator Usage
print(/a_optional) --> ""
print(/b_optional) --> 0
// Postfix Operator Usage
print(a_optional*?) --> ""
print(b_optional*?) --> 0
Now it is your choice which operator you use, both serve the same purpose.
Can someone explain me what is wrong with this statement.
var someString = "Welcome"
someString.append("!")
However this works when I replace the code with,
var someString = "Welcome"
let exclamationMark : Character = "!"
someString.append(exclamationMark)
Thanks in advance
In Swift, there is no character literal (such as 'c' in C-derived languages), there are only String literals.
Then, you have two functions defined on Strings: append, to append a single character, and extend, to append a whole String. So this works:
var someString = "Welcome"
someString.extend("!")
If you really want to use append, you can force a one-char String literal to be turned into a Character either by calling Character's constructor:
someString.append(Character("!"))
or by using a type conversion:
someString.append("!" as Character)
or by using a type annotation as you did with an extra variable:
let exclamationMark: Character = "!"
someString.append(exclamationMark)
String has 2 overloaded append(_:)
mutating func append(x: UnicodeScalar)
mutating func append(c: Character)
and both Character and UnicodeScalar conforms UnicodeScalarLiteralConvertible
enum Character : ExtendedGraphemeClusterLiteralConvertible, Equatable, Hashable, Comparable {
/// Create an instance initialized to `value`.
init(unicodeScalarLiteral value: Character)
}
struct UnicodeScalar : UnicodeScalarLiteralConvertible {
/// Create an instance initialized to `value`.
init(unicodeScalarLiteral value: UnicodeScalar)
}
"!" in this case is a UnicodeScalarLiteral. So, the compiler can not determine "!" is Character or UnicodeScalar, and which append(_:) method should be invoked. That's why you must specify it explicitly.
You can see: "!" can be a UnicodeScalar literal by this code:
struct MyScalar: UnicodeScalarLiteralConvertible {
init(unicodeScalarLiteral value: UnicodeScalar) {
println("unicode \(value)")
}
}
"!" as MyScalar // -> prints "unicode !"
I'm trying to use an Objective-C library which expects a NSDictionary as its return type. Within the NSDictionary, I can return values of any type, including blocks.
I cannot figure out if there is a way to write an analogous swift method that returns a Dictionary with a closure or a string as a possible value type.
I can't use AnyObject as the value type for the dictionary so this doesn't work:
Dictionary<String,AnyObject> = ["Key":{(value:AnyObject) -> String in return value.description]
I get a Does not conform to protocol error from the compiler regarding the closure and AnyObject.
Is there a higher level type or protocol that both closures and basic types adhere to that I can use as the value type in a Dictionary?
Your basic problem is that in Objective-C closures (aka blocks) are represented as NSObject (or more precisely are transparently converted to NSObjects) while in Swift there is no such mapping. This means that closures can not be directly stored in a Dictionary (short of using objective-c glue)
The closest I can come up with is something along the lines of wrapping the value in an enum:
enum DataType {
case AsString(String)
case AsClosure((AnyObject)->String)
}
var dict:Dictionary<String,DataType> = [
"string":DataType.AsString("value"),
"closure":DataType.AsClosure({(argument:AnyObject) -> String in
return "value"
}
)
]
Which is probably a better solution anyway, because this way you have an explicit typing associated with individual arguments instead of it being implicit using some sort of inflection.
Alternatively, you could only wrap the closure and use a dictionary of type Dictionary<String,Any>.
If you still need a workaround, here is one; usage looks like this:
var d : [String : AnyObject] = [:]
d["a"] = Blocks.voidBlockToId({ println("Doing something") })
d["b"] = "Some string"
d["c"] = Blocks.intBlockToId({ i in println("Called with integer: \(i)") })
Blocks.toIntBlock(d["c"])(1)
Blocks.toVoidBlock(d["a"])()
println(d["b"])
Output is:
Called with integer: 1
Doing something
Some string
The Blocks class is defined like this in Objective-C (with corresponding header and bridging header, I won't put those here):
typedef void(^VoidBlock)(void);
typedef void(^IntBlock)(int);
#implementation Blocks
+ (id) voidBlockToId: (VoidBlock) block { return block; }
+ (VoidBlock) toVoidBlock: (id) block { return (VoidBlock)block; }
+ (id) intBlockToId: (IntBlock) block { return block; }
+ (IntBlock) toIntBlock:(id)block { return (IntBlock)block; }
#end
You also need to add a new xyzBlockToId and toXyzBlock method for every new closure-type you want to use. It's pretty ugly, but it works.
There is another type, Any, that object, structs and primitives all conform to but functions do not. There is no general function type, but you can describe a function type as its arguments and return value like this:
Dictionary<String, (AnyObject) -> String>
Function Types
Could you use an NSMutableDictionary?
Alternatively, this seemed to work for me using your example:
1> import Foundation
2> var myDict: [String: (NSObject) -> String] = ["Key":{(value:NSObject) -> String in return value.description}]
myDict: [String : (NSObject) -> String] = {
[0] = {
key = "Key"
value =
}
}
3> myDict["Key"]!("Testing")
$R2: String = "Testing"
Hmm, maybe this Swift-Code doesn't really help, because you want to have heterogenous dictionaries.
It's also not possible to put closures into an NSDictionary, it seems (as a closure does not conform to AnyObject).
You could also roll your own higher type using an enum. You need the dictionary values to be either strings or functions which return strings, so define a type to represent that:
enum MyDictVal {
case ValString(String)
case ValFunc(AnyObject -> String)
}
Then, you can put it in a dictionary:
let d: Dictionary<String, MyDictVal> = [
"a": .ValString("a")
, "b": .ValFunc({ (value) in value.description })
]
Then you'll need to process the dictionary values using pattern matching:
switch d["b"] {
case .ValString(let s):
...
case .ValFunc(let f):
...
}
A more "generic" solution which should work with Any object, but shown with closures and function references. Drop it into a playground and try it out!
// Wrapper for sticking non-objects in NSDictionary instances
class ObjectWrapper {
let value: T
init(_ value: T) {
self.value = value
}
}
// convenience to downcast `as! ObjectWrapper` and return its value
func getValueFromObjectWrapper(a: AnyObject) -> T {
return (a as! ObjectWrapper).value
}
func wrappedObjectsInDictionary() -> NSDictionary {
var dict = NSMutableDictionary()
let appendToFoo: (String) -> String = NSString.stringByAppendingString("foo")
let firstChar: (String) -> Character = { $0[$0.startIndex] }
dict.setObject(ObjectWrapper(firstChar), forKey: "stringToChar")
dict.setObject(ObjectWrapper(appendToFoo), forKey: "stringTransformer")
return dict.copy() as! NSDictionary
}
let dict = wrappedObjectsInDictionary()
let appendToFoo: (String) -> String = getValueFromObjectWrapper(dict["stringTransformer"]!)
let strToChar: (String) -> Character = getValueFromObjectWrapper(dict["stringToChar"]!)
appendToFoo("bar") // "foobar"
strToChar("bar") // "b"