Parametrized unit tests in Swift - swift

Is there any way to use parameterized unit tests, similar to what you can achieve in .Net using NUnit framework.
[TestCase(12, 3, 4)]
[TestCase(12, 2, 6)]
[TestCase(12, 4, 3)]
public void DivideTest(int expectedResult, int a, int b)
{
Assert.AreEqual(expectedResult, a / b);
}
Using this kind of tests (vs non-parameterized ones) can give you bigger back for buck by allowing you to avoid writing series of almost identical unit tests differing only by parameter values.
I am looking for either XCTest-based solution or some other means to achieve it. Optimal solution should report each test case (parameter set) as a separate unit test in Xcode, so is it clear whether all or only some of the tests cases failed.

The best way to use parametrized is using the XCTestCase subclass's property defaultTestSuite. A clear example with division is the following:
import XCTest
class ParameterizedExampleTests: XCTestCase {
//properties to save the test cases
private var array: [Float]? = nil
private var expectedResult: Float? = nil
// This makes the magic: defaultTestSuite has the set of all the test methods in the current runtime
// so here we will create objects of ParameterizedExampleTests to call all the class' tests methodos
// with differents values to test
override open class var defaultTestSuite: XCTestSuite {
let testSuite = XCTestSuite(name: NSStringFromClass(self))
addTestsWithArray([12, 3], expectedResult: 4, toTestSuite: testSuite)
addTestsWithArray([12, 2], expectedResult: 6, toTestSuite: testSuite)
addTestsWithArray([12, 4], expectedResult: 3, toTestSuite: testSuite)
return testSuite
}
// This is just to create the new ParameterizedExampleTests instance to add it into testSuite
private class func addTestsWithArray(_ array: [Float], expectedResult: Float, toTestSuite testSuite: XCTestSuite) {
testInvocations.forEach { invocation in
let testCase = ParameterizedExampleTests(invocation: invocation)
testCase.array = array
testCase.expectedResult = expectedResult
testSuite.addTest(testCase)
}
}
// Normally this function is into production code (e.g. class, struct, etc).
func division(a: Float, b: Float) -> Float {
return a/b
}
func testDivision() {
XCTAssertEqual(self.expectedResult, division(a: array?[0] ?? 0, b: array?[1] ?? 0))
}
}

You function parameters are all over the place. I'm not sure if your function is doing multiplication or division. But here's one way you can do multiple test cases in a single test method.
Given this function:
func multiply(_ a: Int, _ b: Int) -> Int {
return a * b
}
You can have multiple test cases on it:
class MyTest: XCTestCase {
func testMultiply() {
let cases = [(4,3,12), (2,4,8), (3,5,10), (4,6,20)]
cases.forEach {
XCTAssertEqual(multiply($0, $1), $2)
}
}
}
The last two would fail and Xcode will tell you about them.

The best way to handle parameterized testing is to use XCTContext.runActivity. This allows to create a new activity with some name that will help you identify exactly which of the iterations failed. So for your division scenario:
func testDivision() {
let testCases = [
(a: 12, b: 3, result: 4),
(a: 12, b: 2, result: 6),
(a: 12, b: 6, result: 1),
(a: 12, b: 4, result: 3),
]
for (a, b, result) in testCases {
XCTContext.runActivity(named: "Testing dividing \(a) by \(b) to get result \(result)") { activity in
XCTAssertEqual(result, a/b)
}
}
}
Note that after running the above test, case no. 1, 2 and 4 will succeed while case no. 3 will fail. You can view exactly which test activity failed and which of the assertions caused faiure in test report:

I rather like #DariusV's solution. However, it doesn't handle well when I the developer execute the test method directly from Xcode's sidebar. That's a dealbreaker for me.
What I wound up doing I think is rather slick.
I declare a Dictionary of testValues (probs need a better name for that) as an instance computed property of my XCTestCase subclass. Then, I define a Dictionary literal of inputs keying expected outputs. My example tests a function that acts on Int, so I define testValues like so:
static var testRange: ClosedRange<Int> { 0...100 }
var testValues: [Int: Int] {
let range = Self.testRange
return [
// Lower extreme
Int.min: range.lowerBound,
// Lower bound
range.lowerBound - 1: range.lowerBound,
range.lowerBound : range.lowerBound,
range.lowerBound + 1: range.lowerBound + 1,
// Middle
25: 25,
50: 50,
75: 75,
// Upper bound
range.upperBound - 1: range.upperBound - 1,
range.upperBound : range.upperBound,
range.upperBound + 1: range.upperBound,
// Upper extreme
Int.max: range.upperBound
]
}
Here, I very easily declare my edge and boundary cases. A more semantic way of accomplishing the same might be to use an array of tuples, but Swift's dictionary literal syntax is thin enough, and I know what this does. 😊
Now, in my test method, I have a simple for loop.
/// The property wrapper I'm testing. This could be anything, but this works for example.
#Clamped(testRange) var number = 50
func testClamping() {
let initial = number
for (input, expected) in testValues {
// Call the code I'm testing. (Computed properties act on assignment)
number = input
XCTAssertEqual(number, expected, "{number = \(input)}: `number` should be \(expected)")
// Reset after each iteration.
number = initial
}
}
Now to run for each parameter, I simply invoke XCTests in any of Xcode's normal ways, or any other way that works with Linux (I assume). No need to run every test class to get this one's parameterizedness.
Isn't that pretty? I just covered every boundary value and equivalence class in only a few lines of DRY code!
As for identifying failing cases, each invocation runs through an XCTAssert function, which as per Xcode's convention will only throw a message at you if there's something wrong that you need to think about. These show up in the sidebar, but similar messages tend to blend together. My message string here identifies the failing input and its resulting output, fixing the blending-togetherness, and making my testing flow a sane piece of cherry apple pie. (You may format yours any way you like, bumpkin! Whatever blesses your sanity.)
Delicious.
TL;DR
An adaptation of #Code Different's answer: Use a dictionary of inputs and outputs, and run with a for loop. 😄

#Code Different's answer is legit. Here's other two options, or rather workarounds:
Property Based Testing
You could use a tool like Fox to perform generative testing, where the test framework will generate many input sets for the behaviour you want to test and run them for you.
More on this approach:
http://www.pivotaltracker.com/community/tracker-blog/generative-testing
http://blog.jessitron.com/2013/04/property-based-testing-what-is-it.html
BDD Shared Examples
If you like the BDD style and are using a test framework that supports them, you could use shared examples.
Using Quick it would look like:
class MultiplySharedExamplesConfiguration: QuickConfiguration {
override class func configure(configuration: Configuration) {
sharedExamples("something edible") { (sharedExampleContext: SharedExampleContext) in
it("multiplies two numbers") {
let a = sharedExampleContext()["a"]
let b = sharedExampleContext()["b"]
let expectedResult = sharedExampleContext()["b"]
expect(multiply(a, b)) == expectedResult
}
}
}
}
class MultiplicationSpec: QuickSpec {
override func spec() {
itBehavesLike("it multiplies two numbers") { ["a": 2, "b": 3, "result": 6] }
itBehavesLike("it multiplies two numbers") { ["a": 2, "b": 4, "result": 8] }
itBehavesLike("it multiplies two numbers") { ["a": 3, "b": 3, "result": 9] }
}
}
To be honest this option is: 1) a lot of work, 2) a misuse of the shared example technique, as you are not using them to test behaviour shared by multiple classes but rather to parametrise the test. But as I said at the start, this is a more of a workaround.

The asserts all seem to throw, so perhaps something like this will work for you:
typealias Division = (dividend: Int, divisor: Int, quotient: Int)
func testDivisions() {
XCTAssertNoThrow(try divisionTest((12, 3, 4)))
XCTAssertNoThrow(try divisionTest((12, 2, 6)))
XCTAssertNoThrow(try divisionTest((12, 4, 3)))
}
private func divisionTest(_ division: Division) throws {
XCTAssertEqual(division.dividend / division.divisor, division.quotient)
}
If one fails, the entire function will fail. If more granularity is required, every case can be split up into an individual function.

We found that this solution How to Dynamically add XCTestCase offers us the flexibility we need. Being able to dynamically add tests, pass arguments to tests, and display the dynamic test names in the test report.
Another option is to checkout XCTestPlan in XCode. There's an informative video from WWDC about it.

Related

cannot convert value of type [Int] to specified type 'Int' [duplicate]

In The Swift Programming Language, it says:
Functions can also take a variable number of arguments, collecting them into an array.
func sumOf(numbers: Int...) -> Int {
...
}
When I call such a function with a comma-separated list of numbers (`sumOf(1, 2, 3, 4), they are made available as an array inside the function.
Question: what if I already have an array of numbers that I want to pass to this function?
let numbers = [1, 2, 3, 4]
sumOf(numbers)
This fails with a compiler error, “Could not find an overload for '__conversion' that accepts the supplied arguments”. Is there a way to turn an existing array into a list of elements that I can pass to a variadic function?
Splatting is not in the language yet, as confirmed by the devs. Workaround for now is to use an overload or wait if you cannot add overloads.
Here's a work around that I found. I know it's not exactly what you want, but it seems to be working.
Step 1: Declare the function you'd like with an array instead of variadic arguments:
func sumOf(numbers: [Int]) -> Int {
var total = 0
for i in numbers {
total += i
}
return total
}
Step 2: Call this from within your variadic function:
func sumOf(numbers: Int...) -> Int {
return sumOf(numbers)
}
Step 3: Call Either Way:
var variadicSum = sumOf(1, 2, 3, 4, 5)
var arraySum = sumOf([1, 2, 3, 4, 5])
It seems strange, but it is working in my tests. Let me know if this causes unforeseen problems for anyone. Swift seems to be able to separate the difference between the two calls with the same function name.
Also, with this method if Apple updates the language as #manojid's answer suggests, you'll only need to update these functions. Otherwise, you'll have to go through and do a lot of renaming.
You can cast the function:
typealias Function = [Int] -> Int
let sumOfArray = unsafeBitCast(sumOf, Function.self)
sumOfArray([1, 2, 3])
You can use a helper function as such:
func sumOf (numbers : [Int]) -> Int { return numbers.reduce(0, combine: +) }
func sumOf (numbers : Int...) -> Int { return sumOf (numbers) }
I did this (Wrapper + Identity Mapping):
func addBarButtonItems(types: REWEBarButtonItemType...) {
addBarButtonItems(types: types.map { $0 })
}
func addBarButtonItems(types: [REWEBarButtonItemType]) {
// actual implementation
}
I know this response does not answer your exact question, but I feel its worth noting. I too was starting to play with Swift and immediately ran into a similar question. Manojlds answer is better for your question, I agree, but again, another workaround I came up with. I do happen to like Logan's better too.
In my case I just wanted to pass an array:
func sumOf(numbers: Array<Int>) -> Int {
var sum = 0
for number in numbers {
sum += number
}
return sum
}
var someNums = [8,7,2,9,12]
sumOf(someNums)
sumOf([10, 15, 20])
Just wanted to share, in case anyone else was thinking like me. Most of the time I would prefer pass the array like this, but I don't think the "Swiftly" yet. :)
Swift 5
This is an approach with #dynamicCallable feature that allows to avoid overloading or unsafeBitCast but you should make a specific struct to call:
#dynamicCallable
struct SumOf {
func dynamicallyCall(withArguments args: [Int]) -> Int {
return args.reduce(0, +)
}
}
let sum = SumOf()
// Use a dynamic method call.
sum(1, 2, 3) // 6
// Call the underlying method directly.
sum.dynamicallyCall(withArguments: [1, 2, 3]) // 6

Swift - Unit testing private variables and methods

I'm trying to test a class but I'm kind of confused as to what to test. Here is the class I want to unit test:
class CalculatorBrain {
private var accumulator = 0.0
func setOperand(operand: Double) {
accumulator = operand
}
var result: Double {
return accumulator
}
private var operations: Dictionary<String, Operation> = [
"=" : .Equals,
"π" : .Constant(M_PI),
"e" : .Constant(M_E),
"±" : .UnaryOperation({ (op1: Double) -> Double in return -op1 }),
"√" : .UnaryOperation(sqrt ),
"cos": .UnaryOperation(cos),
"+" : .BinaryOperation({ (op1: Double, op2: Double) -> Double in return op1 + op2 }),
"−" : .BinaryOperation({ (op1: Double, op2: Double) -> Double in return op1 - op2 }),
"×" : .BinaryOperation({ (op1: Double, op2: Double) -> Double in return op1 * op2 }),
"Ă·" : .BinaryOperation({ (op1: Double, op2: Double) -> Double in return op1 / op2 })
]
private enum Operation {
case Constant(Double)
case UnaryOperation((Double) -> Double)
case BinaryOperation((Double, Double) -> Double)
case Equals
}
func performOperation(symbol: String) {
if let operation = operations[symbol] {
switch operation {
case .Constant(let value):
accumulator = value
case .UnaryOperation(let function):
accumulator = function(accumulator)
case .BinaryOperation(let function):
executePendingBinaryOperation()
pendingBinaryOperation = PendingBinaryOperationInfo(binaryOperation: function, firstOperand: accumulator)
case .Equals:
executePendingBinaryOperation()
}
}
}
private var pendingBinaryOperation: PendingBinaryOperationInfo?
private struct PendingBinaryOperationInfo {
var binaryOperation: (Double, Double) -> Double
var firstOperand: Double
}
private func executePendingBinaryOperation() {
if let pending = pendingBinaryOperation {
accumulator = pending.binaryOperation(pending.firstOperand, accumulator)
pendingBinaryOperation = nil
}
}
}
For the code above, what would be good tests.
Is it worth testing every single operation (+, -, *, /, etc) in the dictionary operations?
Is it worth testing the private methods?
You can't test private methods in Swift using #testable. You can only test methods marked either internal or public. As the docs say:
Note: #testable provides access only for “internal” functions;
“private” declarations are not visible outside of their file even when
using #testable.
Read more here
Unit testing should be considered black box testing, which means you don't care about the internals of the unit you test. You are mainly interested to see what's the unit output based on the inputs you give it in the unit test.
Now, by outputs we can assert on several things:
the result of a method
the state of the object after acting on it,
the interaction with the dependencies the object has
In all cases, we are interested only about the public interface, since that's the one that communicates with the rest of the world.
Private stuff don't need to have unit tests simply because any private item is indirectly used by a public one. The trick is to write enough tests that exercise the public members so that the private ones are fully covered.
Also, one important thing to keep in mind is that unit testing should validate the unit specifications, and not its implementation. Validating implementation details adds a tight coupling between the unit testing code and the tested code, which has a big disadvantage: if the tested implementation detail changes, then it's likely that the unit test will need to be changed also.
Writing unit tests in a black box manner means that you'll be able to refactor all the code in those units without worrying that by also having to change the tests you risk into introducing bugs in the unit testing code. Unreliable unit tests are sometimes worse than a lack of tests, as tests that give false positives are likely to hide actual bugs in your code.
Although I agree with not testing private stuff, and I'd rather prefer to test just public interface, sometimes I've needed to test something inside a class that was hidden (like a complex state machine). For these cases what you can do is:
import Foundation
public class Test {
internal func testInternal() -> Int {
return 1
}
public func testPublic() -> Int {
return 2
}
// we can't test this!
private func testPrivate() -> Int {
return 3
}
}
// won't ship with production code thanks to #if DEBUG
// add a good comment with "WHY this is needed 😉"
#if DEBUG
extension Test {
public func exposePrivate() -> Int {
return self.testPrivate()
}
}
#endif
Then you can do this:
import XCTest
#testable import TestTests
class TestTestsTests: XCTestCase {
func testExample() {
let sut = Test()
XCTAssertEqual(1, sut.testInternal())
}
func testPrivateExample() {
let sut = Test()
XCTAssertEqual(3, sut.exposePrivate())
}
}
I understand perfectly that this is a hack. But knowing this trick can save your bacon in the future or not. Do not abuse this trick.
Diego's answer is clever but it is possible to go further.
Go into your project editor and define a new Testing Configuration by duplicating the Debug configuration.
Edit your scheme's Test action so that the build configuration is Testing.
Now edit your test target's build settings to define an additional Active Compilation Conditions value for the Testing configuration, "TESTING".
Now you can say #if TESTING, as distinct from mere DEBUG.
I use this, for example, to declare initializers that only a test can see.
Short answer is you can't. Private parts can't be tested.
However, I don't think "you shouldn't" is a valid answer. I used to think in this way, but real life scenarios are more complicated than we would expect. At some point, I need to write a FileScanner class as part of a framework, which conforms to a Scanner protocol that only has a scan(filename: String) function. Of course FileScanner.scan(filename: String) needs to be public, but how about the functions that support scan?
As I mentioned in a comment above, I want to:
keep the interface as clean as possible, and
limit access level as private as possible
Which means I don't want to expose other functions that are not used by other classes. I really hope there's a #testable modifier at function level (works like #discardable etc) but since it's not really there in Swift, we unfortunately only have 2 options:
Write unit tests for scan only, which is suggested by most people. This requires a lot of input files in the unit test bundle (not necessarily Target, as I'm using SPM only without Xcode, and it's just a Tests directory), and is hard to create specific cases for individual functions. Depends on how complex scan is, it's not really a good approach.
Expose private other functions. I ended up with this approach, and make a convention, that if a function doesn't have any modifier, we assume it's internal and can be used by other files in the same bundle (Target), just not public. But if we specifically mark it as internal func etc, it means we just want to make it #testable and it should never be used by other classes in the same bundle.
So, my conclusion is that even you can't test private methods and properties in Swift yet, I consider it as a limitation of Swift but not an invalid use case.
I found this link which is saying something similar with Cristik.
Basically, you are asking the wrong question, you should not be seeking to test the class/functions marked with "private".
I think actually don’t need to test of private members.
But if you want to use to private members(properties & methods) at UnitTest, there is a way that use Protocol.
Protocol PrivateTestable {
associatedtype PrivateTestCase
var privateTestCase: PrivateTestCase {get}
}
And try to extension the protocol in same file (target class file).
extension CalculatorBrain: PrivateTestable {
struct PrivateTestCase {
private let target: CalculatorBrain
var pendingBinaryOperation: PendingBinaryOperationInfo? {
return target.pendingBinaryOperation
}
init(target: CalculatorBrain) {
self.target = target
}
}
var privateTestable: PrivateTestCase {
return PrivateTestCase(target: self)
}
}
Then you can use pendingBinaryOperation in UnitTest
class CalculatorBrainTest: XCTestCase {
func testPendingBinaryOperation() {
let brain = CalculatorBrain()
XCTAssertNotNil(brain.privateTestCase.pendingBinaryOperation)
}
}
If you really want to get a private field in tests, you can use the Mirror class:
let testClass = CalculatorBrain()
let mirror = Mirror(reflecting: testClass)
func extract<T>(variable name: StaticString, mirror: Mirror?) -> T? {
guard let mirror = mirror else {
return nil
}
guard let descendant = mirror.descendant("\(name)") as? T
else {
return extract(variable: name, mirror: mirror)
}
return descendant
}
let result: Dictionary<String, Any>? = extract(variable: "operations", mirror: mirror)
print(result!)
For example, I made an extension of the class to check the output result
extension CalculatorBrain {
var test: Any {
operations
}
}
print("")
print(testClass.test)
As a result, I got this:
Mirror
["−": __lldb_expr_24.CalculatorBrain.Operation.BinaryOperation((Function)),
"√": __lldb_expr_24.CalculatorBrain.Operation.UnaryOperation((Function)),
"+": __lldb_expr_24.CalculatorBrain.Operation.BinaryOperation((Function)),
"Ă·": __lldb_expr_24.CalculatorBrain.Operation.BinaryOperation((Function)),
"e": __lldb_expr_24.CalculatorBrain.Operation.Constant(2.718281828459045),
"π": __lldb_expr_24.CalculatorBrain.Operation.Constant(3.141592653589793),
"cos": __lldb_expr_24.CalculatorBrain.Operation.UnaryOperation((Function)),
"=": __lldb_expr_24.CalculatorBrain.Operation.Equals,
"±": __lldb_expr_24.CalculatorBrain.Operation.UnaryOperation((Function)),
"×": __lldb_expr_24.CalculatorBrain.Operation.BinaryOperation((Function))]
Extension
["×": __lldb_expr_24.CalculatorBrain.Operation.BinaryOperation((Function)),
"Ă·": __lldb_expr_24.CalculatorBrain.Operation.BinaryOperation((Function)),
"√": __lldb_expr_24.CalculatorBrain.Operation.UnaryOperation((Function)),
"=": __lldb_expr_24.CalculatorBrain.Operation.Equals,
"−": __lldb_expr_24.CalculatorBrain.Operation.BinaryOperation((Function)),
"±": __lldb_expr_24.CalculatorBrain.Operation.UnaryOperation((Function)),
"e": __lldb_expr_24.CalculatorBrain.Operation.Constant(2.718281828459045),
"cos": __lldb_expr_24.CalculatorBrain.Operation.UnaryOperation((Function)),
"π": __lldb_expr_24.CalculatorBrain.Operation.Constant(3.141592653589793),
"+": __lldb_expr_24.CalculatorBrain.Operation.BinaryOperation((Function))]
Private methods will not be tested (at least I do not know how to do this without changing the main code)

Array of tuples as argument - types look the same but aren't [duplicate]

In The Swift Programming Language, it says:
Functions can also take a variable number of arguments, collecting them into an array.
func sumOf(numbers: Int...) -> Int {
...
}
When I call such a function with a comma-separated list of numbers (`sumOf(1, 2, 3, 4), they are made available as an array inside the function.
Question: what if I already have an array of numbers that I want to pass to this function?
let numbers = [1, 2, 3, 4]
sumOf(numbers)
This fails with a compiler error, “Could not find an overload for '__conversion' that accepts the supplied arguments”. Is there a way to turn an existing array into a list of elements that I can pass to a variadic function?
Splatting is not in the language yet, as confirmed by the devs. Workaround for now is to use an overload or wait if you cannot add overloads.
Here's a work around that I found. I know it's not exactly what you want, but it seems to be working.
Step 1: Declare the function you'd like with an array instead of variadic arguments:
func sumOf(numbers: [Int]) -> Int {
var total = 0
for i in numbers {
total += i
}
return total
}
Step 2: Call this from within your variadic function:
func sumOf(numbers: Int...) -> Int {
return sumOf(numbers)
}
Step 3: Call Either Way:
var variadicSum = sumOf(1, 2, 3, 4, 5)
var arraySum = sumOf([1, 2, 3, 4, 5])
It seems strange, but it is working in my tests. Let me know if this causes unforeseen problems for anyone. Swift seems to be able to separate the difference between the two calls with the same function name.
Also, with this method if Apple updates the language as #manojid's answer suggests, you'll only need to update these functions. Otherwise, you'll have to go through and do a lot of renaming.
You can cast the function:
typealias Function = [Int] -> Int
let sumOfArray = unsafeBitCast(sumOf, Function.self)
sumOfArray([1, 2, 3])
You can use a helper function as such:
func sumOf (numbers : [Int]) -> Int { return numbers.reduce(0, combine: +) }
func sumOf (numbers : Int...) -> Int { return sumOf (numbers) }
I did this (Wrapper + Identity Mapping):
func addBarButtonItems(types: REWEBarButtonItemType...) {
addBarButtonItems(types: types.map { $0 })
}
func addBarButtonItems(types: [REWEBarButtonItemType]) {
// actual implementation
}
I know this response does not answer your exact question, but I feel its worth noting. I too was starting to play with Swift and immediately ran into a similar question. Manojlds answer is better for your question, I agree, but again, another workaround I came up with. I do happen to like Logan's better too.
In my case I just wanted to pass an array:
func sumOf(numbers: Array<Int>) -> Int {
var sum = 0
for number in numbers {
sum += number
}
return sum
}
var someNums = [8,7,2,9,12]
sumOf(someNums)
sumOf([10, 15, 20])
Just wanted to share, in case anyone else was thinking like me. Most of the time I would prefer pass the array like this, but I don't think the "Swiftly" yet. :)
Swift 5
This is an approach with #dynamicCallable feature that allows to avoid overloading or unsafeBitCast but you should make a specific struct to call:
#dynamicCallable
struct SumOf {
func dynamicallyCall(withArguments args: [Int]) -> Int {
return args.reduce(0, +)
}
}
let sum = SumOf()
// Use a dynamic method call.
sum(1, 2, 3) // 6
// Call the underlying method directly.
sum.dynamicallyCall(withArguments: [1, 2, 3]) // 6

Java-like Iterator in Swift

How to iterate array without using position (index) i and for/for in loop?
var a = [1, 2, 3]
for var i = 0; i < a.count; i++ {
//
}
for item in a {
//
}
A SequenceType (which CollectionType, and thus all Swift collections including array, conform to) is pretty simple. It requires you provide a generate() function that returns a type conforming to GeneratorType.
GeneratorType in turn only needs to provide one method: a next() that returns each element until the elements are exhausted. It returns an optional, returning nil after the last element is returned. This makes them pretty similar to Java iterators, only with next and hasNext combined into one via use of optionals.
Swift’s for
in is really syntactic sugar for a combination of getting a generator and then repeatedly calling next on it:
let a = [1, 2, 3]
for i in a { print(i) }
// is equivalent to:
var g = a.generate()
// the generator, being stateful, must be declared with var
while let i = g.next() { print(i) }
If using generators like this, take note of the comment above the definition of GeneratorType in the std lib doc:
Encapsulates iteration state and interface for iteration over a
sequence.
Note: While it is safe to copy a generator, advancing one
copy may invalidate the others.
Since writing a generator for a collection often involves a lot of boiler plate, there is a helper type, IndexingGenerator, that can be used. This implements a generator that starts at startIndex, and returns the value at that index and increments the index each time. A generate() that returns an IndexingGenerator is provided as the default implementation for CollectionType, which means if this is good enough for your purposes, you don’t need to implement generate when implementing a collection:
struct Bitfield: CollectionType {
let data: UInt
var startIndex: UInt { return 0 }
var endIndex: UInt { return UInt(sizeofValue(data)*8) }
subscript(idx: UInt) -> Bit {
return (data >> idx) & 1 == 0
? Bit.Zero : Bit.One
}
// no need to implement generate()
}
This default was added in Swift 2.0. Prior to that, you had to provide a minimal generator that just returned an IndexingGenerator(self).
You can do it using IndexingGenerator:
var a = [1, 2, 3]
var generator = a.generate()
while let item = generator.next() {
//
}
P. S. I created and answered my own question because I did not find anything when tried to figure out how to use Java-like iterators in Swift.
It could be done with the help of IteratorProtocol.
let a = [1, 2, 3]
var aIterator = a.makeIterator()
while let aItem = aIterator.next() {
// do something with array item
}
More on IteratorProtocol in Apple's documentation here
if you use Java 8 you can use streams.
As an example:
List<User> olderUsers = users.stream().filter(u -> u.age > 30).collect(Collectors.toList());

Passing an array to a function with variable number of args in Swift

In The Swift Programming Language, it says:
Functions can also take a variable number of arguments, collecting them into an array.
func sumOf(numbers: Int...) -> Int {
...
}
When I call such a function with a comma-separated list of numbers (`sumOf(1, 2, 3, 4), they are made available as an array inside the function.
Question: what if I already have an array of numbers that I want to pass to this function?
let numbers = [1, 2, 3, 4]
sumOf(numbers)
This fails with a compiler error, “Could not find an overload for '__conversion' that accepts the supplied arguments”. Is there a way to turn an existing array into a list of elements that I can pass to a variadic function?
Splatting is not in the language yet, as confirmed by the devs. Workaround for now is to use an overload or wait if you cannot add overloads.
Here's a work around that I found. I know it's not exactly what you want, but it seems to be working.
Step 1: Declare the function you'd like with an array instead of variadic arguments:
func sumOf(numbers: [Int]) -> Int {
var total = 0
for i in numbers {
total += i
}
return total
}
Step 2: Call this from within your variadic function:
func sumOf(numbers: Int...) -> Int {
return sumOf(numbers)
}
Step 3: Call Either Way:
var variadicSum = sumOf(1, 2, 3, 4, 5)
var arraySum = sumOf([1, 2, 3, 4, 5])
It seems strange, but it is working in my tests. Let me know if this causes unforeseen problems for anyone. Swift seems to be able to separate the difference between the two calls with the same function name.
Also, with this method if Apple updates the language as #manojid's answer suggests, you'll only need to update these functions. Otherwise, you'll have to go through and do a lot of renaming.
You can cast the function:
typealias Function = [Int] -> Int
let sumOfArray = unsafeBitCast(sumOf, Function.self)
sumOfArray([1, 2, 3])
You can use a helper function as such:
func sumOf (numbers : [Int]) -> Int { return numbers.reduce(0, combine: +) }
func sumOf (numbers : Int...) -> Int { return sumOf (numbers) }
I did this (Wrapper + Identity Mapping):
func addBarButtonItems(types: REWEBarButtonItemType...) {
addBarButtonItems(types: types.map { $0 })
}
func addBarButtonItems(types: [REWEBarButtonItemType]) {
// actual implementation
}
I know this response does not answer your exact question, but I feel its worth noting. I too was starting to play with Swift and immediately ran into a similar question. Manojlds answer is better for your question, I agree, but again, another workaround I came up with. I do happen to like Logan's better too.
In my case I just wanted to pass an array:
func sumOf(numbers: Array<Int>) -> Int {
var sum = 0
for number in numbers {
sum += number
}
return sum
}
var someNums = [8,7,2,9,12]
sumOf(someNums)
sumOf([10, 15, 20])
Just wanted to share, in case anyone else was thinking like me. Most of the time I would prefer pass the array like this, but I don't think the "Swiftly" yet. :)
Swift 5
This is an approach with #dynamicCallable feature that allows to avoid overloading or unsafeBitCast but you should make a specific struct to call:
#dynamicCallable
struct SumOf {
func dynamicallyCall(withArguments args: [Int]) -> Int {
return args.reduce(0, +)
}
}
let sum = SumOf()
// Use a dynamic method call.
sum(1, 2, 3) // 6
// Call the underlying method directly.
sum.dynamicallyCall(withArguments: [1, 2, 3]) // 6