Execute closure from another method in an extension Swift - swift

I have a class that is a delegate to a custom modal view, therefore it has a method for when the modal has been dismissed. I am extending that class and in the extension I have a method that accepts a completion closure.
I can't write in the main implementation of the class or the modal's implementation - only the extension.
I want to execute the closure when the modal is dismissed, but I can't seem to figure it out on my own. Is it even possible?
Here is an example of what I want to do:
extension MyClass {
func method(completion: (Int) -> ()) {
// showing the modal
}
}
extension MyClass: ModalDelegate {
func modalDismissed() {
// here I want to execute the completion passed to method()
}
}

Assign the completion as a variable to a MyClass's property in method and call it in modalDismissed:
class MyClass {
var classCompletion: (() -> ())?
}
extension MyClass {
func method(completion: #escaping () -> ()) {
classCompletion = completion
}
}
extension MyClass: ModalDelegate {
func modalDismissed() {
classCompletion?()
}
}
Update: If you can't "write in the main implementation of the class", here's a method using static property. This is a hack and has many limitations but does the work. Otherwise without writing to the main implementation you can't do anything.
extension MyClass {
static var classCompletion: (() -> ())?
func method(completion: #escaping () -> ()) {
MyClass.classCompletion = completion
}
}
extension MyClass: ModalDelegate {
func modalDismissed() {
MyClass.classCompletion?()
}
}

Related

Swift: Assign a class method to a handler and handling weak self

I just went memory-leak hunting in the app I am working on, and noticed that the following produces a memory leak:
class SubClass {
var didCloseHandler: (() -> Void)?
}
class MainClass {
var subClass = SubClass()
func setup {
subClass.didCloseHandler = self.didCloseSubClass
}
func didCloseSubClass() {
//
}
}
This produces a retain cycle, and for good reason - didCloseHandler captures MainClass strongly, and MainClass captures SubClass strongly.
My Question: Is there a way in Swift that allows me to assign a class method to a handler without a retain cycle?
And yes, I am aware that I can do this using subClass.didCloseHandler = { [weak self] self?.didCloseSubClass() }. I'm wondering, though, if it can be done without introducing a new closure.
make a weak reference of subClass in MainClass
If you don't have strong reference to SubClass instance somewhere else - you may try wrapper like this:
func WeakPointer<T: AnyObject>(_ object: T, _ method: #escaping (T) -> () -> Void) -> (() -> Void) {
return { [weak object] in
method(object!)()
}
}
Then use it like this:
func setup() {
subClass.didCloseHandler = WeakPointer(self, MainClass.didCloseSubClass)
}
If you don't need properties from MainClass instance in didCloseSubClass implementation - you can make this method static, which will also solve your problem.
If you have strong reference to SubClass instance somewhere else and it won't be deallocated immediately - weak var subClass will do, as was already mentioned.
EDIT:
I've come up with another idea. It may look a bit more complicated, but maybe it would help.
import Foundation
class SubClass {
#objc dynamic func didCloseHandler() {
print(#function)
}
deinit {
print(" \(self) deinit")
}
}
class MainClass {
var subClass = SubClass()
func setup() {
if let implementation = class_getMethodImplementation(MainClass.self, #selector(didCloseSubClass)),
let method = class_getInstanceMethod(SubClass.self, #selector(SubClass.didCloseHandler)) {
method_setImplementation(method, implementation)
}
}
#objc func didCloseSubClass() {
print(#function)
}
deinit {
print(" \(self) deinit")
}
}
You change closure for #objc dynamic method and set it's implementation to the one from MainClass in setup().

Assign Function to other class variable

Sorry for if this asked many times, I tried many solution none of the work for me. I am doing a very basic thing like this way.
class NotificationModel: NSObject {
var selector = (() -> Void).self
}
Other class.
class TestNotificationClass1 {
init() {
var model = NotificationModel.init()
model.selector = handleNotification //error is here
}
func handleNotification() -> Void {
print("handle function 1")
}
}
Error description: Cannot assign value of type '() -> Void' to type '(() -> Void).Type'
If you want selector to be able to hold any function with no parameters and no return value then change its declaration to:
var selector: (() -> Void)?
This also makes it optional. If you don't want it to be optional then you need to add an initializer to NotificationModel that takes the desired selector as a parameter as shown below:
class NotificationModel: NSObject {
var selector: (() -> Void)
init(selector: #escaping () -> Void) {
self.selector = selector
super.init()
}
}
class TestNotificationClass1 {
init() {
var model = NotificationModel(selector: handleNotification)
}
func handleNotification() -> Void {
print("handle function 1")
}
}

what is 'where self' in protocol extension

I saw so many examples with below format
extension Protocolname where Self: UIViewController
What is where Self in protocol extension. I couldn't find the documentation on this.
That syntax is: https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html#//apple_ref/doc/uid/TP40014097-CH25-ID521
Consider:
protocol Meh {
func doSomething()
}
// Extend protocol Meh, where `Self` is of type `UIViewController`
// func blah() will only exist for classes that inherit `UIViewController`.
// In fact, this entire extension only exists for `UIViewController` subclasses.
extension Meh where Self: UIViewController {
func blah() {
print("Blah")
}
func foo() {
print("Foo")
}
}
class Foo : UIViewController, Meh { //This compiles and since Foo is a `UIViewController` subclass, it has access to all of `Meh` extension functions and `Meh` itself. IE: `doSomething, blah, foo`.
func doSomething() {
print("Do Something")
}
}
class Obj : NSObject, Meh { //While this compiles, it won't have access to any of `Meh` extension functions. It only has access to `Meh.doSomething()`.
func doSomething() {
print("Do Something")
}
}
The below will give a compiler error because Obj doesn't have access to Meh extension functions.
let i = Obj()
i.blah()
But the below will work.
let j = Foo()
j.blah()
In other words, Meh.blah() is only available to classes that are of type UIViewController.
Here is an example which explains that what is the use of where self: UIViewController
protocol SBIdentifiable {
static var sbIdentifier: String { get }
}
extension SBIdentifiable where Self: UIViewController {
static var sbIdentifier: String {
return String(describing: self)
}
}
extension UIVieWcontroller: SBIdentifiable { }
class ViewController: UIViewController {
func loadView() {
/*Below line we are using the sbIdentifier which will return the
ViewController class name.
and same name we would mentioned inside ViewController
storyboard ID. So that we do not need to write the identifier everytime.
So here where Self: UIViewController means it will only conform the protocol of type UIViewController*/
let viewController = self.instantiateViewController(withIdentifier:
self.sbIdentifier) as? SomeBiewController
}
}
You can find the same example here: WWDC2015-408, (Highly recommend to watch it,it illustrates the reason)
And also, another similar example is Extensions with a Generic Where Clause
struct Stack<Element> {
var items = [Element]()
mutating func push(_ item: Element) {
items.append(item)
}
mutating func pop() -> Element {
return items.removeLast()
}
}
The where clause add a requirement to the extension, so that the extension adds the isTop(_:) method only when the items in the stack are equatable.
extension Stack where Element: Equatable {
func isTop(_ item: Element) -> Bool {
guard let topItem = items.last else {
return false
}
return topItem == item
}
}

Swift 3: Any way to declare a static class function to restrict closure type to Self?

I'm trying to create a static method on a generic class which takes in a closure as parameter and creates an instance of the class and passes it the closure. The catch is that I want to subclass this and ensure that the closure conforms to any subclass I use.
I know that you can use "Self" as a return type for a static method, but when I try to use it in the method header, I get the following error:
"'Self' is only available in a protocol or as the result of a method
in a class"
I'd like to do something like this:
class GenericClass: NSObject {
required override init() {
super.init()
}
static func createAndExecuteAsync(block: (Self) -> Void) {
DispatchQueue.global().async {
let instance = self.init()
block(instance)
}
}
}
class OtherClass: GenericClass {
// ...
}
Somewhere else...
OtherClass.createAndExecuteAsync { (instance: OtherClass) in
// Do stuff to instance
}
UPDATE:
Thanks to Hamish's solution in this post, I'm closer to a solution. I can use Self in the desired way if I first create a protocol for my generic class. However that forces me to make OtherClass final, which isn't desirable for my situation.
Without making OtherClass final, I get the following error:
Protocol 'GenericClass' requirement 'createAndExecuteAsync(block:)'
cannot be satisfied by a non-final class ('OtherClass') because it
uses 'Self' in a non-parameter, non-result type position.
Here's what it would look like:
protocol GenericClass {
init()
static func createAndExecuteAsync(block: #escaping (Self) -> Void)
}
extension GenericClass {
static func createAndExecuteAsync(block: #escaping (Self) -> Void) {
DispatchQueue.global().async {
let instance = self.init()
block(instance)
}
}
}
final class OtherClass : GenericClass {
var myProperty = 1
required init() { }
}
// Somewhere else...
OtherClass.createAndExecuteAsync { (instance) in
instance.myProperty = 2
}
Perhaps you could use a global generic function with a slightly different usage syntax.
for example:
func createAndExecuteAsync<T:GenericClass>(_ objectType:T.Type, _ block:#escaping (T) -> Void)
{
DispatchQueue.global().async
{
let instance = T.init()
block(instance)
}
}
createAndExecuteAsync(OtherClass.self){ $0.myProperty = 2 }
// instead of OtherClass.createAndExecuteAsync{ $0.myProperty = 2 }

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