swift class declared inside method can not reach method? - swift

I am using XCTest and declaring classes inside the TestMethod as a means of Mocking a class. However, It seems that the class is unable to call a method outside of its declaration. how do I fix this?
class MyTestCase : XCTestCase {
func testExample() {
class Bar { // <-- the class declared inside a function
func Barkly() {
foo(); // <-- apparently this produces a compile error.
}
}
}
func foo() { //<-- this is the method I am trying to call
println("hello world")
}
}

Related

Swift Quick framework memory leak

I'm using Quick to test my Swift code.
However, I think it doesn't release objects defined in describe scope:
class MyClass {
deinit {
print(self, #function)
}
}
final class MyClassSpec: QuickSpec {
override func spec() {
describe("") {
let foo = MyClass()
it("") {
print(foo)
expect(true).to(beTrue())
}
}
}
}
I don't see any output from print inside deinit, and a debug breakpoint inside the deinit does not get catched.
If I move foo inside it, the deinit is called.
Is this a bug in Quick, or is it normal for deinit not to be called in a test suite?
Apparently the code I wrote was not only retaining the object but was also an anti-pattern.
Even a plain old XCTestCase retains an object:
class MyClass {
deinit {
print(self, #function)
}
}
final class MyClassTest: XCTestCase {
let foo = MyClass()
func testMyClass() {
print(foo)
XCTAssert(true)
}
}
deinit is not called for foo.
This is due to a nature of XCTestCase—it never really gets deinited.
So one should always use setUp & tearDown to manage everything (or more accurately, objects with reference semantics).
I believe this directly translates to QuickSpec as well, so I should always use beforeEach & afterEach in order to manage the objects.
To "fix" the problem, I should test like:
final class MyClassSpec: QuickSpec {
override func spec() {
describe("") {
let foo: MyClass!
beforeEach { foo = MyClass() }
afterEach { foo = nil }
it("") {
print(foo)
expect(true).to(beTrue())
}
}
}
}

Unable to invoke optional function on a protocol when inheriting from a generic class

If a subclass implements an optional function, calling the function on the protocol works as expected. Namely it'll call the child's method even though it's not implemented in the parent.
When we introduce generics to the parent class, this behavior stops working.
Here's a playground showing the problem...
import UIKit
#objc
protocol MyProtocol {
#objc optional func foo()
}
// MARK: - Works
class Parent: MyProtocol { }
class Child: Parent {
func foo() { print("Child.foo()") }
}
(Child() as MyProtocol).foo?()
// ✅ Outputs `Child.foo()`
// MARK: - Broken
class BrokenParent<T>: MyProtocol { }
class BrokenChild: BrokenParent<String> {
func foo() { print("BrokenChild.foo()") }
}
(BrokenChild() as MyProtocol).foo?()
// ❌ Bug: does not output anything
Why does this happen, and what workarounds are there to fix it?
Xcode 11.4.1
Not sure why it happens, but I suspect that the #objc protocol causes the Objective-C runtime to be used to dispatch the event, and Swift has some behind the scenes code to make the simple case work (and omitted the more complicated inheritance+generic case). I could totally be wrong on this though, and would love to learn the real reason.
Here are two snippets that can be added to the same playground that show the workarounds available, namely (1) implementing the method in the parent class, or (2) using the #objc keyword on the method name.
// MARK: - Fixed 1
class FixedParent1<T>: MyProtocol {
open func foo() {}
}
class FixedChild1: FixedParent1<String> {
override func foo() { print("FixedChild1.foo()") }
}
(FixedChild1() as MyProtocol).foo?()
// ✅ Outputs `FixedChild1.foo()`
// MARK: - Fixed 2
class FixedParent2<T>: MyProtocol {}
class FixedChild2: FixedParent2<String> {
#objc func foo() { print("FixedChild2.foo()") }
}
(FixedChild2() as MyProtocol).foo?()
// ✅ Outputs `FixedChild2.foo()`
Just add '#objc' to your func:
#objc func foo() { print("BrokenChild.foo()") }

swift: How can I override a public method in superclass to be a private method in subclass

I have a super class
class Father {
public func doSomething() {
}
}
I want this child class to be
class Child: Father {
private override func doSomething() {
}
}
but Xcode says that
Overriding instance method must be as accessible as the declaration it
overrides
so, how can I override a public method in superclass be a private method in subclass
THANK YOU
You can't because that would violate the Liskov Substitution Principle.
Essentially, any code that can operate on an instance of a superclass must also be able to operate on an instance of your subclass.
So, if some other class has a method
class Unrelated {
func operateOnAThing(_ someThing:Father) {
someThing.doSomething()
}
}
then it still has to work when you do the following:
let aChild = Child()
unrelatedInstance.operateOnAThing(aChild)
If the doSomething method had more restrictive access in the Child class then you would get a runtime error. To prevent this, you cannot make access more restrictive in a subclass.
You can achieve that by marking the public method as unavailable using the #available attribute. Then, call the method using super in the private method.
Example:
class Father {
public func doSomething() {
print("doSomething privatly")
}
}
class Child: Father {
#available (*, unavailable)
override func doSomething() {
}
fileprivate func internal_doSomething() {
super.doSomething()
}
}
Child().internal_doSomething()
Child().doSomething() //'doSomething()' has been explicitly marked unavailable
(Tested using Swift 4.0!)

Swift: overriding typealias inside subclass

So I was thinking about a custom pattern in my project, but I can't get it to work. The main idea is to change the typealias on every subclass to get access to the subclass specific interface.
protocol InstanceInterface: class {
typealias Interface
var interface: Interface { get }
}
// Baseclass
protocol FirstClassInterface: class { /* nothing here for the example */ }
class FirstClass: InstanceInterface, FirstClassInterface {
typealias Interface = FirstClassInterface
var interface: Interface { return self }
}
// Subclass
protocol SecondClassInterface: FirstClassInterface {
func foo()
}
class SecondClass: FirstClass, SecondClassInterface {
typealias Interface = SecondClassInterface // <--- This does nothing :(
func foo() { print("hello world") } // Swift 2.0 here
}
// Lets say I want to call foo trough the interface
let test = SecondClass()
test.interface.foo() // 'Interface' does not have a member named 'foo'
Is there something I'm doing wrong or do I misunderstand some Swift concepts here?! I do need to subclass here to not to implement everything from super class' protocols over and over again. Is my little pattern even possible? I'd appreciate any help. :)
Would something like this work for your purposes?
class MyClass<T> {
}
class MySubclass1: MyClass<String> {
}
class MySubclass2: MyClass<Int> {
}
Unfortunately there is no good workaround for this problem.
The main idea to override the typealias would work in this case but consider the following:
protocol TakeAndGet {
typealias T
func take(value: T)
func get() -> T
}
class FirstClass: TakeAndGet {
typealias T = FirstClass
var property = 0
func take(value: T) {
value.property = 4
}
func get() -> T {
return FirstClass()
}
}
class SecondClass: FirstClass {
typealias T = SecondClass
var property2 = "hello"
}
If the typealias of the SecondClass overrides the other one the take method would work since it takes a subclass which can be treated as the superclass. But the get method cannot implicitly convert FirstClass to SecondClass. Therefore it is not possible to override a typealias.
Now if we want to override the get function with get() -> SecondClass it wouldn't work since it has not the same signature as the one in the superclass. In addition we inherit the get method which results in an ambiguous use:
SecondClass().get() // which type gets returned? SecondClass or FirstClass
So you have to try a different approach.

Swift - class method which must be overridden by subclass

Is there a standard way to make a "pure virtual function" in Swift, ie. one that must be overridden by every subclass, and which, if it is not, causes a compile time error?
You have two options:
1. Use a Protocol
Define the superclass as a Protocol instead of a Class
Pro: Compile time check for if each "subclass" (not an actual subclass) implements the required method(s)
Con: The "superclass" (protocol) cannot implement methods or properties
2. Assert in the super version of the method
Example:
class SuperClass {
func someFunc() {
fatalError("Must Override")
}
}
class Subclass : SuperClass {
override func someFunc() {
}
}
Pro: Can implement methods and properties in superclass
Con: No compile time check
The following allows to inherit from a class and also to have the protocol's compile time check :)
protocol ViewControllerProtocol {
func setupViews()
func setupConstraints()
}
typealias ViewController = ViewControllerClass & ViewControllerProtocol
class ViewControllerClass : UIViewController {
override func viewDidLoad() {
self.setup()
}
func setup() {
guard let controller = self as? ViewController else {
return
}
controller.setupViews()
controller.setupConstraints()
}
//.... and implement methods related to UIViewController at will
}
class SubClass : ViewController {
//-- in case these aren't here... an error will be presented
func setupViews() { ... }
func setupConstraints() { ... }
}
There isn't any support for abstract class/ virtual functions, but you could probably use a protocol for most cases:
protocol SomeProtocol {
func someMethod()
}
class SomeClass: SomeProtocol {
func someMethod() {}
}
If SomeClass doesn't implement someMethod, you'll get this compile time error:
error: type 'SomeClass' does not conform to protocol 'SomeProtocol'
Another workaround, if you don't have too many "virtual" methods, is to have the subclass pass the "implementations" into the base class constructor as function objects:
class MyVirtual {
// 'Implementation' provided by subclass
let fooImpl: (() -> String)
// Delegates to 'implementation' provided by subclass
func foo() -> String {
return fooImpl()
}
init(fooImpl: (() -> String)) {
self.fooImpl = fooImpl
}
}
class MyImpl: MyVirtual {
// 'Implementation' for super.foo()
func myFoo() -> String {
return "I am foo"
}
init() {
// pass the 'implementation' to the superclass
super.init(myFoo)
}
}
You can use protocol vs assertion as suggested in answer here by drewag.
However, example for the protocol is missing. I am covering here,
Protocol
protocol SomeProtocol {
func someMethod()
}
class SomeClass: SomeProtocol {
func someMethod() {}
}
Now every subclasses are required to implement the protocol which is checked in compile time. If SomeClass doesn't implement someMethod, you'll get this compile time error:
error: type 'SomeClass' does not conform to protocol 'SomeProtocol'
Note: this only works for the topmost class that implements the protocol. Any subclasses can blithely ignore the protocol requirements. – as commented by memmons
Assertion
class SuperClass {
func someFunc() {
fatalError("Must Override")
}
}
class Subclass : SuperClass {
override func someFunc() {
}
}
However, assertion will work only in runtime.
This is what I usually do, to causes the compile-time error :
class SuperClass {}
protocol SuperClassProtocol {
func someFunc()
}
typealias SuperClassType = SuperClass & SuperClassProtocol
class Subclass: SuperClassType {
func someFunc() {
// ...
}
}
You can achieve it by passing function into initializer.
For example
open class SuperClass {
private let abstractFunction: () -> Void
public init(abstractFunction: #escaping () -> Void) {
self.abstractFunction = abstractFunction
}
public func foo() {
// ...
abstractFunction()
}
}
public class SubClass: SuperClass {
public init() {
super.init(
abstractFunction: {
print("my implementation")
}
)
}
}
You can extend it by passing self as the parameter:
open class SuperClass {
private let abstractFunction: (SuperClass) -> Void
public init(abstractFunction: #escaping (SuperClass) -> Void) {
self.abstractFunction = abstractFunction
}
public func foo() {
// ...
abstractFunction(self)
}
}
public class SubClass: SuperClass {
public init() {
super.init(
abstractFunction: {
(_self: SuperClass) in
let _self: SubClass = _self as! SubClass
print("my implementation")
}
)
}
}
Pro:
Compile time check for if each subclassimplements the required method(s)
Can implement methods and properties in superclass
Note that you can't pass self to the function so you won't get memory leak.
Con:
It's not the prettiest code
You can't use it for the classes with required init
Being new to iOS development, I'm not entirely sure when this was implemented, but one way to get the best of both worlds is to implement an extension for a protocol:
protocol ThingsToDo {
func doThingOne()
}
extension ThingsToDo {
func doThingTwo() { /* Define code here */}
}
class Person: ThingsToDo {
func doThingOne() {
// Already defined in extension
doThingTwo()
// Rest of code
}
}
The extension is what allows you to have the default value for a function while the function in the regular protocol still provides a compile time error if not defined