How can one use XCTAssertNil with optional structs? - swift

Update 3/23/2016 I just tested my original sample code below and it all compiles fine in XCode 7.3. Looks like XCTAssertNil was updated along the way to take an expression of type () throws -> Any? Therefore this question and answer may be no longer needed (except for a while with older versions of the compiler.)
I'm writing my first unit tests in XCode with XCTest. I'm unsure how one can take advantage of XCTAssertNil as it seems to only compile when using certain types. It appears it will work with optionals made from classes and built-in primitives, but not structs. How would one go about using this method?
For structs the compiler gives the following error (assuming 'SimpleStruct' is the name of your type):
'SimpleStruct' is not identical to 'AnyObject'
Here's a simple test class to illustrate some of the types that compile okay and other's that don't.
import Cocoa
import XCTest
struct SimpleStruct {
}
class SimpleClass {
}
class Tests: XCTestCase {
func testl() {
var simpleStruct:SimpleStruct? = nil;
var simpleClass:SimpleClass? = nil;
var i:Int? = nil;
var s:String? = nil;
var tuple:(Int,String)? = nil;
XCTAssertNil(simpleStruct); // compile error
XCTAssertNil(simpleClass); // OK
XCTAssertNil(i); // OK
XCTAssertNil(s); // OK
XCTAssertNil(tuple); // compile error
}
}

Update 3/23/2016 Updated for XCode 7.3 (however if you see my edit to the question, it would appear this workaround is no longer needed)
Here is a workaround. I created my own generic function:
func AssertNil<T>(#autoclosure expression: () -> T?, message: String = "",
file: StaticString = #file, line: UInt = #line) {
if (expression() != nil) {
XCTFail(message, file:file, line:line)
}
}
Doesn't seem like this should be necessary. Is this just a result of XCTest originally targeting Objective-C and not being updated/bridged enough for Swift yet?
Edit: I've done enough research to see that AnyObject can be used to represent any class but not structs. However, that then doesn't explain why the code in my original post compiles for Int types and String types. (I read somewhere else that Xcode may auto convert these to NSNumber and NSString for you which might explain why. See http://www.scottlogic.com/blog/2014/09/24/swift-anyobject.html and http://www.drewag.me/posts/swift-s-weird-handling-of-basic-value-types-and-anyobject. I'll try removing my import of Cocoa which imports Foundation to see what happens)
Edit2: XCTest also imports Foundation so I can't test what I wanted to. I could create my own methods and test this. For now, I assume that the auto-conversions are what are allowing the int and string optionals to compile. Seems like XCTest isn't quite ready for prime time with Swift.
Update 8/13/2015: Edited the function to be compatible with XCode 7 beta

Related

Why does my code work on Playgrounds but not CoderPad?

I have a very simple func in Xcode playgrounds which works when I run it. But when i try to run the same code in CoderPad it gives me the following error Solution.swift:18:1: warning: result of call to 'isPalindrome(word:)' is unused
isPalindrome(word:"racecar")
Here is the code
import Foundation
func isPalindrome(word: String) -> Bool{
var oddCharacters: Set<Character> = []
for char in word {
if oddCharacters.contains(char){
oddCharacters.remove(char)
}else{
oddCharacters.insert(char)
}
}
return oddCharacters.count <= 1
}
isPalindrome(word:"racecar")
I really do not understand why this is happening.
Try this:
import Foundation
func isPalindrome(word: String) -> Bool{
var oddCharacters: Set<Character> = []
for char in word {
if oddCharacters.contains(char){
oddCharacters.remove(char)
}else{
oddCharacters.insert(char)
}
}
return oddCharacters.count <= 1
}
print(isPalindrome(word:"racecar"))
all you had to do was print it, hope this helped
That means, that the "left-hand-side" result of the call to your function isPalindrome(word: "racecar") is unused ("wasted").
It seems that for a debugging, testing, try-out environment like a Playground it's just okay to find out the result of this call (true) without storing it inside a variable. However, when doing that in other development environments, the compiler will be complaining about that. I can give you four options that would prevent the error from being thrown, just to give you a better idea of why the compiler is complaining:
If you want to use it in your further code below, just store the result and change your calling line to let isPalindrome = isPalindrome(word: "racecar"). But if you don't use it, the compiler will give you a warning again saying that you're never using your isPalindrome variable... --> Option 2
If you don't need the result, you can also just say: _ = isPalindrome(word: "racecar"). That will explicitly tell the compiler "bro, it's okay if the result is just ignored". It wouldn't make much sense for this function, though.
You can add the #discardableResult keyword prior to your function declaration, so it would say: #discardableResult func isPalindrome(word: String) -> Bool { ... That would kinda just silence your thrown error and like option 2 just tell the compiler that it's okay to just ignore the result of this function.
Just use the result in any way like:
if isPalindrome(word: "racecar") {
// do something
} else {
// do something else
}
// or
print("racecar is a palindrome: \(isPalindrome(word: "racecar")")
and everything will just be fine. I hope that helps you!

Why can't NSSpeechsynthesier's class method availableVoices be bridged to a Swift array of strings?

In Apple's Working with Cocoa Frameworks it reads as if the Foundation and Swift Foundation frameworks work together through bridging. However, I noticed that while attempting to use NSSpeechSynthesizer's class method availableVoices() it allows me to received an returned array of NSStrings but not Strings.
This compiles and runs just fine:
let voices = NSSpeechSynthesizer.availableVoices as [NSString]
print(voices)
However this won't compile:
let voicesTwo = NSSpeechSynthesizer.availableVoices as [String]
Why wouldn't this work if the voiceName documentation shows that VoiceName is a string property?
I see the term 'rawValue' in the VoiceName documentation so is the reasoning having anything to do with this being some sort of an enum?
It looks like NSSpeechSynthesizer.VoiceName is an Enum with a rawValue of String. That is not the same thing as being a string.
Try using
NSSpeechSynthesizer.availableVoices.map { $0.rawValue }

Is it Possible To Set Up Implicit Conversion from NSError to Custom Error in Swift?

Reading the following from NSHipster got me wondering about NSError and if something could be set up so that NSError implicitly converts to a custom error type.
I created the following:
protocol NSErrorConvertible {
init(error: NSError)
}
and this
struct CustomError: NSErrorConvertible {
var message: String
var code: String?
init(error: NSError) {
code = String(error.code)
message = error.localizedDescription
}
}
However, I don't see anything that would make implicit conversion happen.
I know such a feature exists in C++ with a one argument constructor. Is there something available like that in Swift using protocols or something else?
No. Swift generally avoids implicit conversions by design. They even took out the tools we used to use to implement it (__conversion) because it creates a lot of headaches, both for the compiler and by injecting subtle bugs. It is very common that implicit conversion introduces small differences that matter. It is often important that the programmer consider these things and not fall back on magic. This has been a long source of bugs in C and C++.
If you add an _ before the error (so the label isn't required) then explicit conversion is trivial:
init(_ error: NSError) { ... }
...
CustomError(error)
See also Does Swift support implicit conversion?

Syntactic Sugar Struct Reference in Swift?

In c++, one can introduce an alias reference as follows:
StructType & alias = lengthyExpresionThatEvaluatesToStuctType;
alias.anAttribute = value; // modify "anAttribute" on the original struct
Is there a similar syntactic sugar for manipulating a (value typed) struct in Swift?
Update 1: For example: Let say the struct is contained in a dictionary of kind [String:StructType], and that I like to modify several attributes in the the struct myDict["hello"]. I could make a temporary copy of that entry. Modify the copy, and then copy the temporary struct back to the dictionary, as follows:
var temp = myDict["hello"]!
temp.anAttribute = 1
temp.anotherAttribute = "hej"
myDict["hello"] = temp
However, if my function has several exit points I would have to write myDict["hello"] = temp before each exit point, and it would therefore be more convinient if I could just introduce and alias (reference) for myDict["hello"] , as follows:
var & alias = myDict["hello"]! // how to do this in swift ???
alias.anAttribute = 1
alias.anotherAttribute = "hej"
Update 2: Before down- or close- voting this question: Please look at Building Better Apps with Value Types in swift (from WWWDC15)!! Value type is an important feature of Swift! As you may know, Swift has borrowed several features from C++, and value types are maybe the most important feature of C++ (when C++ is compared to Java and such languages). When it comes to value types, C++ has some syntactic sugar, and my questions is: Does Swift have a similar sugar hidden in its language?. I am sure Swift will have, eventually... Please, do not close-vote this question if you do not understand it!
I have just read Deitel's book on Swift. While I'am not an expert (yet) I am not completely novel. I am trying to use Swift as efficient as possible!
Swift doesn't allow reference semantics to value types generally speaking, except when used as function parameters declared inout. You can pass a reference to the struct to a function that works on an inout version (I believe, citation needed, that this is implemented as a copy-write, not as a memory reference). You can also capture variables in nested functions for similar semantics. In both cases you can return early from the mutating function, while still guaranteeing appropriate assignment. Here is a sample playground that I ran in Xcode 6.3.2 and Xcode 7-beta1:
//: Playground - noun: a place where people can play
import Foundation
var str = "Hello, playground"
struct Foo {
var value: Int
}
var d = ["nine": Foo(value: 9), "ten": Foo(value: 10)]
func doStuff(key: String) {
let myNewValue = Int(arc4random())
func doMutation(inout temp: Foo) {
temp.value = myNewValue
}
if d[key] != nil {
doMutation(&d[key]!)
}
}
doStuff("nine")
d // d["nine"] has changed... unless you're really lucky
// alternate approach without using inout
func doStuff2(key: String) {
if var temp = d[key] {
func updateValues() {
temp.value = Int(arc4random())
}
updateValues()
d[key] = temp
}
}
doStuff2("ten")
d // d["ten"] has changed
You don't have to make the doMutation function nested in your outer function, I just did that to demonstrate the you can capture values like myNewValue from the surrounding function, which might make implementation easier. updateValues, however, must be nested because it captures temp.
Despite the fact that this works, based on your sample code, I think that using a class here (possibly a final class if you are concerned about performance) is really more idiomatic imperative-flavored Swift.
You can, if you really want to, get a raw pointer using the standard library function withUnsafeMutablePointer. You can probably also chuck the value into an inner class that only has a single member. There are also functional-flavored approaches that might mitigate the early-return issue.

Differentiating Between a Struct and a Class in Swift

I know why I would use a struct as opposed to a class, but how could I best tell which is being used by an API I'm using?
Obviously looking at the header file (or hopefully documentation) should make it immediately obvious. I am wondering if there is a way to know if the object I am using is a struct or class on face value though?
You can’t inherit from other structures or types. Classes have the ability to inherit functions, variables, and constants from parent classes.
In swift structs are value types while classes are reference types. Working with value types can make your code less error prone.
When you make a copy of a reference type variable, both variables are referring to the same object in memory. A change to one of the variables will change the other.
when you make a copy of a value type variable, the complete variable is copied to a new place in memory. A change to one of the copies will not change the other. If the copying of an object is cheap, it is far safer to make a copy than it is to share memory.
Auto completion in Xcode knows the type of type:
I'm not sure what you mean by "face-value". You can test to see if an object is an instance of a class by getting it's MirrorType using reflect and checking for the MirrorType's objectIdentifier property, like this:
struct TestStruct { }
class TestClass { }
let testStruct = TestStruct()
let testClass = TestClass()
if let x = reflect(testStruct).objectIdentifier {
println("I am a class...")
} else {
println("I am not a class...") // prints "I am not a class..."
}
if let x = reflect(testClass).objectIdentifier {
println("I am a class...") // prints "I am a class..."
} else {
println("I am not a class...")
}
This answer may be outdated with the upcoming release of Swift 1.2 (I do not have the new xCode beta so I can't say for sure), which I understand has better object introspection, but this does do the trick.