I have a little bit misunderstanding how to use -(void) in swift correctly. Whenever I have tried to write a code using -(Void) but I am getting an error "Expected declaration" or sometimes "Binary operator '-' cannot be applied to operands of type 'UIFont' and '(Void).Type'".
Why is this happening? What is the right way to use this functionality correctly in swift?
{
- (Void)keyboardWillShow { //>> showing me the error "Binary operator '-' cannot be applied to operands of type 'UIFont' and '(Void).Type'"
// Animate the current view out of the way
if (self.view.frame.origin.y >= 0)
{
[self setViewMovedUp:YES];
}
else if (self.view.frame.origin.y < 0)
{
[self setViewMovedUp:NO];
}
}
}
Thanks
It sounds like you're trying to declare a function with no return value. In Swift this is done as:
func thisFunction() {
..
}
You can return nil value like below code:
func myFunc(myVar: String) -> ()? {
print(myVar)
return nil
}
var c = myFunc("Hello")
print(c) // nil
but Swift Function always return default value nil if not declared. like below code:
func myFunc(myVar: String) {
print(myVar)
return
}
var c = myFunc("Hello")
print(c) // ()
Related
I have a class where I have an extension to check equality but on test, the equality crashes.
here's my code
extension LPItemAction {
public override func isEqual(_ other: Any?) -> Bool {
if (other as? LPItemAction) == self {
return true
} else if !(other is LPItemAction) {
return false
} else {
let otherAction = other as? LPItemAction
return hash == otherAction?.hash
}
}
}
and my test case is like this
func testIsEqualSelf() {
// Given
let action = LPItemAction()
action.type = .account
// When
let equal = action.isEqual(action)
// Then
XCTAssertTrue(equal)
}
I got a crash with error Thread 1: EXC_BAD_ACCESS (code=2, address=0x16e747fc0)
Since this is obviously a NSObject, you are probably right to override isEqual. There are some rules though.
You cannot use ==. This operator invokes the Equality protocol, which, on NSObject is implemented using isEqual, therefore you end up with infinite recursion.
Another thing is that using hash to compare equality is just wrong.
// test type first
guard let otherAction = other as? LPItemAction else {
return false
}
// test reference equality
if self === otherAction {
return true
}
// test equality of all properties
return type === otherAction.type
I've made extension
extension Optional where Wrapped == [Any] {
var isNilOrEmpty: Bool {
get {
if let array = self {
return array.count == 0
} else {
return false
}
}
}
}
Then I try to use it like this
if fetchedResults.fetchedObjects.isNilOrEmpty { ... }
I'm getting error
'[Task]?' is not convertible to 'Optional<[Any]>'
But, by specification
Any can represent an instance of any type at all, including function types.
What is my mistake here?
Task is subclass of NSManagedObject if it matters.
Well, [Task] and [Any] are two different types, and Wrapped == [Any] won't work.
Proper way would be to limit Wrapped by protocol, not specific type.
extension Optional where Wrapped: Collection {
var isNilOrEmpty: Bool {
get { // `get` can be omitted here, btw
if let collection = self {
return collection.isEmpty // Prefer `isEmpty` over `.count == 0`
} else {
return true // If it's `nil` it should return `true` too
}
}
}
}
I've got an NSViewController extension that iterates through all its descendant child view controllers looking for the first view controller that passes a particular test (specified by a user-defined block):
extension NSViewController {
func descendantViewControllerPassingTest(test: (viewController: NSViewController) -> Bool) -> NSViewController? {
var retval: NSViewController?
for childViewController in childViewControllers {
if test(viewController: childViewController) {
retval = childViewController
} else if let descendantViewController = viewController.descendantViewControllerPassingTest(test) {
retval = descendantViewController
}
if retval != nil { break }
}
return retval
}
}
Ninety-nine percent of the time my tests consist of a simple type-check...
contentViewController.descendantViewControllerPassingTest {$0 is OutlineViewController}
...so I'd like to create a short convenience extension that does this:
extension NSViewController {
func descendantViewControllerMatchingType(type: WHAT_HERE?) {
return descendantViewControllerPassingTest({ $0 is WHAT_HERE? })
}
}
But I can't work out what type my parameter type should be. I've tried AnyClass and AnyObject but the compiler informs me that these aren't types:
Closures is what I'd use. Pass in your object to the closure with a return type of BOOL. Use the closure to match your descendant recursively.
I'm trying to do the equivalent in Objective-C:
if (causeStr != nil) {
...
}
I would get a compiler error if do this:
if !(let myString = causeStr) {
}
So I'm left with this:
if let myString = causeStr {
} else {
// ... do something
}
Is there a more-elegant way to do this?
Yes, there's a more elegant way, and coincidentally it's the same as in obj-c:
if myString == nil {
...
}
Note: Your 1st snippet of code should be:
if (causeStr == nil) {
...
}
otherwise it means I misunderstood your question...
Is there any equivalent to check for throwing exceptions in swift language Unit tests?
For example I Have a class:
class Square : NSObject{
let sideLength: Int
init(sideLength: Int) {
assert(sideLength >= 0, "Wrong initialization of Square class with below zero side length")
self.sideLength = sideLength
super.init()
}
}
and Test to check it work. In objective C I can write test method like this:
- (void)testInitializationWithWrongSideLengthThrowsExceptions{
XCTAssertThrows([[Shape alloc] initWithSideLength: -50], "Should throw exceptions on wrong side values initialisations");
}
What is Swift equal technic?
If you add the following three files to your tests:
// ThrowsToBool.h
#import <Foundation/Foundation.h>
/// A 'pure' closure; has no arguments, returns nothing.
typedef void (^VoidBlock)(void);
/// Returns: true if the block throws an `NSException`, otherwise false
BOOL throwsToBool(VoidBlock block);
// ThrowsToBool.m
#import "ThrowsToBool.h"
BOOL throwsToBool(VoidBlock const block) {
#try {
block();
}
#catch (NSException * const notUsed) {
return YES;
}
return NO;
}
// xxxTests-Bridging-Header.h
#import "ThrowsToBool.h"
Then you can write:
XCTAssert(throwsToBool {
// test code that throws an NSException
})
But it doesn't work for assert or precondition :(
PS I got the idea from: http://modocache.io/xctest-the-good-parts
I think the assert()-function should only be used for debug-purposes. Not only because of the following statement from Apple's Swift-Book (https://itun.es/de/jEUH0.l):
„Assertions cause your app to terminate and are not a substitute for designing your code in such a way that invalid conditions are unlikely to arise.“
Thats why I would solve this as follows:
import Cocoa
import XCTest
class Square
{
let sideLength: Int
init(_ sideLength: Int)
{
self.sideLength = sideLength >= 0 ? sideLength : 0
}
}
class SquareTests: XCTestCase
{
override func setUp() { super.setUp() }
override func tearDown() { super.tearDown() }
func testMySquareSideLength() {
let square1 = Square(1);
XCTAssert(square1.sideLength == 1, "Sidelength should be 1")
let square2 = Square(-1);
XCTAssert(square2.sideLength >= 0, "Sidelength should be not negative")
}
}
let tester = SquareTests()
tester.testMySquareSideLength()
There is no equivalent to XCTAssertThrows in swift. For now you can't use a native function, but there is a solution with some objective-c help. You can use Quick, or only Nimble. Or to make your own assert function - see this article - http://modocache.io/xctest-the-good-parts - Potential Improvement #2: Add XCTAssertThrows to Swift
the best way is add a bridge I think.
please look at https://gist.github.com/akolov/8894408226dab48d3021
it works for me.
correct way in Swift 2:
class Square : NSObject{
let sideLength: Int
init(sideLength: Int) throws { // throwable initializer
guard sideLength >= 0 else { // use guard statement
throw ...// your custom error type
}
self.sideLength = sideLength
super.init()
}
}
and testing:
func testInitThrows() {
do {
_ = try Square(sideLength: -1) // or without parameter name depending on Swift version
XCTFail()
} catch ... { // your custom error type
} catch {
XCTFail()
}
}