How to append a closure to another closure? - swift

So I have my first closure here:
var instructions: (() -> Void) = {
print("First")
}
instructions() /// prints "First"
Now I have another closure:
let additionalInstructions: (() -> Void) = {
print("Second")
}
additionalInstructions() /// prints "Second"
I want to "append" additionalInstructions to the end of instructions... is this possible? I tried making a new closure containing both of them, like this:
let finalInstructions: (() -> Void) = {
instructions()
additionalInstructions()
}
finalInstructions()
This prints
First
Second
But, when I replace instructions with finalInstructions, I get an EXC_BAD_ACCESS.
instructions = finalInstructions
instructions() /// error here
I think this is because closures are reference types, and some sort of loop happens when instructions contains itself. Is there a way to avoid the error? Making a new closure like finalInstructions, just as a container, also seems kind of clunky.

This is some interesting semantics I didn't expect, but what you're seeing is an infinite recursion, which crashes due to a stack overflow. You can confirm this by running this code in a project, where the debugger will catch the error. You'll see thousands of stackframes of the same closure being called.
It appears that the reference to instructions within your closure is capturing its new, self-referential value, rather than its previous value.
Your approach of using a new variable like finalInstructions is much better. Not only because it avoids this issue, but also because it's much more readable code.
Here's a simpler, more minimal demonstration of the problem:
var closure = { print("initial definition") }
closure() // prints "initial definition"
closure = {
print("second definition")
closure()
}
closure() // prints "second definition" repeatedly, until the stack overflows
FYI, I asked about this on the Swift forums: https://forums.swift.org/t/mutable-closures-can-capture-themselves/43228

It's easy to put them together. It's not easy to take them apart, like C#'s delegates are.
To do that, you'll need to maintain a bunch of junk like below. Better to use Combine, these days.
final class MultiClosureTestCase: XCTestCase {
func test_multiClosure() {
var x = 0
let closures: [EquatableClosure<()>] = [
.init { _ in x += 1 },
.init { _ in x += 2 }
]
let multiClosure = MultiClosure(closures)
multiClosure()
XCTAssertEqual(x, 3)
multiClosure -= closures.first!
multiClosure()
XCTAssertEqual(x, 5)
}
func test_setRemoval() {
let closure: EquatableClosure<()>! = .init { _ in }
let multiClosure = MultiClosure(closure)
XCTAssertNotEqual(multiClosure.closures, [])
XCTAssertNotEqual(closure.multiClosures, [])
multiClosure -= closure
XCTAssertEqual(multiClosure.closures, [])
XCTAssertEqual(closure.multiClosures, [])
}
func test_deallocation() {
var closure: EquatableClosure<()>! = .init { _ in }
var multiClosure: MultiClosure! = .init(closure)
XCTAssertNotEqual(multiClosure.closures, [])
closure = nil
XCTAssertEqual(multiClosure.closures, [])
closure = EquatableClosure { _ in }
multiClosure += closure
XCTAssertNotEqual(closure.multiClosures, [])
multiClosure = nil
XCTAssertEqual(closure.multiClosures, [])
}
}
/// Use this until Swift has unowned-referencing collections.
public final class UnownedReferencer<Reference: AnyObject>: HashableViaID {
public init(_ reference: Reference) {
self.reference = reference
}
public unowned let reference: Reference
}
/// Use this until Swift has weak-referencing collections.
public final class WeakReferencer<Reference: AnyObject>: HashableViaID {
public init(_ reference: Reference) {
self.reference = reference
}
public weak var reference: Reference?
}
/// Remove the first `UnownedReferencer` with this `reference`
public func -= <Reference: Equatable>(
set: inout Set< UnownedReferencer<Reference> >,
reference: Reference
) {
guard let referencer = ( set.first { $0.reference == reference} )
else { return }
set.remove(referencer)
}
/// Remove the first `WeakReferencer` with this `reference`
public func -= <Reference: Equatable>(
set: inout Set< WeakReferencer<Reference> >,
reference: Reference
) {
guard let referencer = ( set.first { $0.reference == reference } )
else { return }
set.remove(referencer)
}
/// A workaround for Swift not providing a way to remove closures
/// from a collection of closures.
///- Note: Designed for one-to-many events, hence no return value.
/// Returning a single value from multiple closures doesn't make sense.
public final class MultiClosure<Input>: Equatable {
public init(_ closures: EquatableClosure<Input>...) {
self += closures
}
public init<Closures: Sequence>(_ closures: Closures)
where Closures.Element == EquatableClosure<Input> {
self += closures
}
var closures: Set<
UnownedReferencer< EquatableClosure<Input> >
> = []
// MARK: deallocation
// We can't find self in `closures` without this.
fileprivate lazy var unownedSelf = UnownedReferencer(self)
// Even though this MultiClosure will be deallocated,
// its corresponding WeakReferencers won't be,
// unless we take this manual action or similar.
deinit {
for closure in closures {
closure.reference.multiClosures.remove(unownedSelf)
}
}
}
public extension MultiClosure {
/// Execute every closure
func callAsFunction(_ input: Input) {
for closure in closures {
closure.reference(input)
}
}
}
public extension MultiClosure where Input == () {
/// Execute every closure
func callAsFunction() {
self(())
}
}
/// A wrapper around a closure, for use with MultiClosures
public final class EquatableClosure<Input>: Equatable {
public init(_ closure: #escaping (Input) -> Void) {
self.closure = closure
}
/// Execute the closure
func callAsFunction(_ input: Input) {
closure(input)
}
private let closure: (Input) -> Void
// MARK: deallocation
var multiClosures: Set<
UnownedReferencer< MultiClosure<Input> >
> = []
// We can't find self in `multiClosures` without this.
fileprivate lazy var unownedSelf = UnownedReferencer(self)
deinit {
for multiClosure in multiClosures {
multiClosure.reference.closures.remove(unownedSelf)
}
}
}
/// Add `closure` to the set of closures that runs
/// when `multiClosure` does
public func += <Input>(
multiClosure: MultiClosure<Input>,
closure: EquatableClosure<Input>
) {
multiClosure.closures.formUnion([closure.unownedSelf])
closure.multiClosures.formUnion([multiClosure.unownedSelf])
}
/// Add `closures` to the set of closures that runs
/// when `multiClosure` does
public func += <
Input,
Closures: Sequence
>(
multiClosure: MultiClosure<Input>,
closures: Closures
)
where Closures.Element == EquatableClosure<Input> {
for closure in closures {
multiClosure += closure
}
}
/// Remove `closure` from the set of closures that runs
/// when `multiClosure` does
public func -= <Input>(
multiClosure: MultiClosure<Input>,
closure: EquatableClosure<Input>
) {
multiClosure.closures.remove(closure.unownedSelf)
closure.multiClosures.remove(multiClosure.unownedSelf)
}
/// An `Identifiable` instance that uses its `id` for equality and hashability.
public protocol HashableViaID: Hashable, Identifiable { }
// MARK: - Equatable
public extension HashableViaID {
static func == (equatable0: Self, equatable1: Self) -> Bool {
equatable0.id == equatable1.id
}
}
// MARK: - Hashable
public extension HashableViaID {
func hash(into hasher: inout Hasher) {
hasher.combine(id)
}
}
// MARK: - AnyObject
public extension Equatable where Self: AnyObject {
static func == (class0: Self, class1: Self) -> Bool {
class0 === class1
}
}

Related

How can I get a specific struct type returned?

I want to initialize the struct by receiving the "struct type"(?) by a specific logic as below.
As I abstracted the return value of the struct into MyProtocol had a declaration of init(), which seems a little awkward.
I'm not sure I can do this.
I'd like to get an undecided struct type returned, what should I do?
Is this for the best?
For your information, Opaque Type is not available because it needs to support iOS 13 or earlier.
protocol MyProtocol {
init() // Is this for the best?
}
struct AAA: MyProtocol {
var numberAAA: Int // Sample variable.
init() {
print("init AAA")
numberAAA = 100
}
}
struct BBB: MyProtocol {
var numberBBB: Int // Sample variable.
init() {
print("init BBB")
numberBBB = 200
}
}
class MyClass {
func mainLogic() {
let myStruct = randomStruct()
myStruct.init() // This is the reason init () declared in the MyProtocol.
}
func randomStruct() -> MyProtocol.Type {
if Bool.random() {
return AAA.self
} else {
return BBB.self
}
}
}
init() as a protocol requirement seems odd. No one is stopping you to do this and compiler should allow this, however I would consider making protocol based on some other requirement rather than just init().
Here's an attempt to do so -
protocol NumberOperation {
var number: Int { get set }
mutating func perform()
}
struct Incrementer: NumberOperation {
var number: Int
mutating func perform() {
number += 1
}
}
struct Decrementer: NumberOperation {
var number: Int
mutating func perform() {
number -= 1
}
}
struct Record<O: NumberOperation> {
public var operation: O
mutating func perform() {
operation.perform()
}
}
class MyClass {
func mainLogic() {
var record = getRecord(type: Incrementer.self)
record.perform()
}
func getRecord<O: NumberOperation>(type: O.Type) -> Record<O> {
if type == Incrementer.self {
return Record(operation: Incrementer(number: 1) as! O)
}
return Record(operation: Decrementer(number: 10) as! O)
}
}
This introduces a container type Record that holds/wraps our type based on the same protocol conformation. This does the same what you were doing, probably is easier to read/understand.

Weak reference implementing a (generic) protocol

I want to create an array of weak references implementing a protocol for observable functionality.
If possible this protocol should have an associated type, so I would not need to create identical ones for each type.
However in Swift 4 this does not seem to work, what I want is basically this:
protocol DelegateBase: AnyObject {
associatedtype Item
func onDataUpdated(data: [Item])
}
protocol Delegate : DelegateBase where Item == Int {
// Will have func onDataUpdated(data: [Int])
}
// T should be a class implementing Delegate, but cannot find a way to
// define T in a way that the Swift compiler accepts it
class WeakListener<T> {
weak var listener : T?
init(listener: T) {
self.listener = listener
}
}
class Implementation {
val listeners = [WeakListener<Delegate>]()
}
If I define everything as non-generic I can make it work, but I would like the convenience of not having to copy paste a concrete version of DelegateBase for each type I want to support.
// This works but is clunky
protocol DelegateA {
func onDataUpdated(data: [Int])
}
// DelegateB with type Double, DelegateC with type X
class WeakListenerA {
weak var listener : DelegateA?
init(listener: DelegateA) {
self.listener = listener
}
}
// WeakListenerB with type Double, WeakListenerC with type X
class ImplementationA {
val listeners = [WeakListenerA]()
}
// ImplementationB with type Double, ImplementationC with type X
EDIT: Intended usage
Basically I want to implement remote-backed repository where UIViewControllers can listen in on events happening inside the repository even though they aren't actively requesting data.
I want the listener to be generic, so I don't need to clone everything for each type. I want weak references since then no manual work is needed for managing them apart from adding listeners.
protocol DelegateBase: AnyObject {
associatedtype Item
func onDataModified(data: [Item])
func onDataRefreshed(data: [Item])
}
protocol IntDelegate : DelegateBase where Item == Int {
// Will have
//func onDataModified(data: [Int])
//func onDataRefreshed(data: [Int])
}
// Listener should implement the delegate T, that extends DelegateBase
// with a type
class WeakListener<T : DelegateBase> {
weak var listener : T?
init(listener: T) {
self.listener = listener
}
}
class IntRepository {
var listeners = [WeakListener<IntDelegate>]()
var data = [Int]()
func addListener(_ listener: IntDelegate /* UIViewController implementing IntDelegate*/) {
listeners.add(listener)
}
func add() {
// data is updated, notify weak listeners
data.append(1)
for listener in listeners {
listener.listener?.onDataModified(data: data)
}
}
func refresh() {
// data refreshed from a remote source
for listener in listeners {
listener.listener?.onDataRefreshed(data: data)
}
}
fileprivate func cleanupListeners() {
self.listeners = self.listeners.filter({$0.listener != nil})
}
// Singleton for example
fileprivate static var _instance: IntImplementation!
public class func shared() -> IntImplementation {
if _instance == nil {
_instance = IntImplementation()
}
return _instance!
}
}
class IntViewController: UIViewController, IntDelegate {
override func viewDidLoad() {
IntImplementation.shared().addListener(self)
}
func onDataModified(data: [Int]) {
// update UI
}
func onDataRefreshed(data: [Int]) {
// update UI
}
}
Because the DelegateBase (and by extension, the Delegate) protocol has an associated type (unlike DelegateA), you cannot use it as a type; you can only use some concrete type that conforms to it.
For what you're trying to do, you don't actually need the Delegate protocol. You seem to want a WeakListener generic with respect to Item type, which you can declare like so:
class WeakListener<T: DelegateBase> {
weak var listener : T?
init(listener: T) {
self.listener = listener
}
}
In other words, the above works with some concrete T type that conforms to DelegateBase.
Let's say you had such a concrete type for Int:
class ConcreteIntDelegateA: DelegateBase {
func onDataUpdated(data: [Int]) {
// ...
}
}
Then you could create a WeakListener for ConcreteIntDelegateA because it conforms to DelegateBase and further specifies that an Item is Int
let listener: WeakListener<ConcreteIntDelegateA>
So, it works for a concrete type, but you cannot do this for a protocol DelegateBase, because DelegateBase doesn't conform to DelegateBase (protocols don't conform to protocols, including themselves):
let listener: WeakListener<DelegateBase> // ERROR
This gives you the ability to create array of listeneres for a specific concrete type, e.g. [WeakListener<ConcreteIntDelegateA>] or [WeakListener<ConcreteIntDelegateB>], but not mixed, because these types are unrelated even though both ConcreteDelegateX conform to DelegateBase.
To get around it is to create a type-erased type, e.g. class AnyDelegate<Item>: DelegateBase, which takes a concrete type in its init:
class AnyDelegate<Item>: DelegateBase {
private let onDataUpdated: ([Item]) -> Void
init<C: DelegateBase>(_ c: C) where C.Item == Item {
self.sonDataUpdated = c.onDataUpdated(data:)
}
func onDataUpdated(data: [Item]) {
onDataUpdated(data)
}
}
let anyIntA = AnyDelegate(ConcreteIntDelegateA())
let anyIntB = AnyDelegate(ConcreteIntDelegateB())
let anyIntListeners: [WeakListener<AnyDelegate<Int>>] = [anyIntA, anyIntB]
What I ended up doing was just throwing away the DelegateBase. To provide some type conformance I created a generic base repository and enforce the delegate type during runtime when adding listeners
import UIKit
protocol IntDelegate : AnyObject {
func onDataModified(data: [Int])
func onDataRefreshed(data: [Int])
}
class WeakListener {
weak var listener : AnyObject?
init(listener: AnyObject) {
self.listener = listener
}
}
class RepositoryBase<T> {
private var _listeners = [WeakListener]()
var listeners: [T] {
get {
// Remove dead listeners
self._listeners = self._listeners.filter({($0.listener as? T) != nil})
return self._listeners.map({ $0.listener as! T })
}
}
func addListener(_ listener: AnyObject) {
assert(listener is T)
_listeners.append(WeakListener(listener: listener))
}
}
class IntRepository : RepositoryBase<IntDelegate> {
var data = [Int]()
func add() {
// data is updated, notify weak listeners
data.append(1)
for listener in self.listeners {
listener.onDataModified(data: data)
}
}
func refresh() {
// data refreshed from a remote source
for listener in self.listeners {
listener.onDataRefreshed(data: data)
}
}
// Singleton for example
fileprivate static var _instance: IntRepository!
public class func shared() -> IntRepository {
if _instance == nil {
_instance = IntRepository()
}
return _instance!
}
}
class IntViewController: IntDelegate {
func viewDidLoad() {
IntRepository.shared().addListener(self)
IntRepository.shared().add()
}
func onDataModified(data: [Int]) {
print("modified")
}
func onDataRefreshed(data: [Int]) {
print("refreshed")
}
}
IntViewController().viewDidLoad() // Prints "modified"

Generic protocol for observing changes in Swift 5

Trying hard to code in Swift 5 the Java example below.
Generally, I want to have an Observable protocol which will be adopted by multiple other protocols. I need these protocols to be types in functions' arguments, so that these functions can add additional observers.
In Java, it is very easy to do. The code prints out:
Observer 1 changed to 10
Observer 2 changed to 10
,
interface Observable<O> {
void addObserver(O observer);
}
interface Settings extends Observable<SettingsObserver> {
void setInterval(int interval);
}
interface SettingsObserver {
void intervalChanged(int interval);
}
class AppSettings implements Settings {
private List<SettingsObserver> observers = new ArrayList<>();
#Override public void addObserver(SettingsObserver observer) { observers.add(observer); }
#Override public void setInterval(int interval) { observers.forEach(observer -> observer.intervalChanged(interval)); }
}
class Observer1 implements SettingsObserver {
#Override public void intervalChanged(int interval) {
System.out.println("Observer 1 changed to " + interval);
}
}
class Observer2 implements SettingsObserver {
#Override public void intervalChanged(int interval) {
System.out.println("Observer 2 changed to " + interval);
}
}
class Main {
public static void main(String[] args) {
Observer1 observer1 = new Observer1();
Settings settings = new AppSettings();
settings.addObserver(observer1);
Main main = new Main();
main.run(settings);
}
void run(Settings settings) {
Observer2 observer2 = new Observer2();
settings.addObserver(observer2);
settings.setInterval(10);
}
}
While it's simple to create a generic wrapper to which you can add your own observables, there are two native solutions that you should use instead.
Notifications.
When value is changed, send a notification using NotificationCenter.default. Observers should listen to these notifications. Notification are a crucial part of the ecosystem:
class AppSettings {
enum Notifications {
static let intervalChanged = Notification.Name("AppSettingsIntervalChangedNotification")
}
var interval: TimeInterval = 0 {
didSet {
NotificationCenter.default.post(name: Notifications.intervalChanged, object: self)
}
}
}
let settings = AppSettings()
let observer = NotificationCenter.default.addObserver(
forName: AppSettings.Notifications.intervalChanged,
object: settings,
queue: nil
) { [weak settings] _ in
guard let settings = settings else { return }
print(settings.interval)
}
settings.interval = 10
Key-value observing (KVO)
If you inherit your objects from NSObject, you can simply add a direct observer to any Obj-C compatible value:
class AppSettings: NSObject {
#objc dynamic var interval: TimeInterval = 0
}
let settings = AppSettings()
let observer: NSKeyValueObservation = settings.observe(\.interval, options: .new) { _, change in
print(change.newValue)
}
settings.interval = 10
See https://developer.apple.com/documentation/swift/cocoa_design_patterns/using_key-value_observing_in_swift
Just for completeness a simple generic observer here:
class Observable<ValueType> {
typealias Observer = (ValueType) -> Void
var observers: [Observer] = []
var value: ValueType {
didSet {
for observer in observers {
observer(value)
}
}
}
init(_ defaultValue: ValueType) {
value = defaultValue
}
func addObserver(_ observer: #escaping Observer) {
observers.append(observer)
}
}
class AppSettings {
let interval: Observable<TimeInterval> = Observable(0)
}
let settings = AppSettings()
settings.interval.addObserver { interval in
print(interval)
}
settings.interval.value = 10
Note that all my observers are simple closures. The reason why Java uses objects as observers is mostly historical due to Java limitations. There is no need for Observable or Observer protocols in Swift.
Depending on your needs, you may be able to get by with property observers in Swift. It allows you to take action when a property is going to be changed or has changed. It is also less complicated than a full observerable type.
Here is Apple's example from the Swift manual:
class StepCounter {
var totalSteps: Int = 0 {
willSet(newTotalSteps) {
print("About to set totalSteps to \(newTotalSteps)")
}
didSet {
if totalSteps > oldValue {
print("Added \(totalSteps - oldValue) steps")
}
}
}
}
let stepCounter = StepCounter()
stepCounter.totalSteps = 200
// About to set totalSteps to 200
// Added 200 steps
stepCounter.totalSteps = 360
// About to set totalSteps to 360
// Added 160 steps
stepCounter.totalSteps = 896
// About to set totalSteps to 896
// Added 536 steps
You would want to use the didSet() function. You could also call another function within the observer.
You could also use the property observers to write a simple observable-like class if you do not want to use a framework such as RxSwift or Apple's new Combine.
Here is a simple example that just uses closures instead of classes:
class ClassToWatch {
typealias ObservingFunc = (ClassToWatch) -> Void
private var observers: [ObservingFunc] = []
func addObserver(_ closure: #escaping ObservingFunc) {
observers.append(closure)
}
private func valueChanged() {
observers.forEach { observer in
observer(self)
}
}
var value1: Int = 0 {
didSet {
valueChanged()
}
}
var value2: String = "" {
didSet {
valueChanged()
}
}
}
var myclass = ClassToWatch()
myclass.addObserver { object in
print("Observer 1: \(object.value1) \(object.value2)")
}
myclass.addObserver { object in
print("Observer 2: \(object.value1) \(object.value2)")
}
myclass.value1 = 3
myclass.value2 = "Test"
Your Java code could be directly translated into Swift code. Here is my translation, with some degree of "Swiftification":
protocol Observable {
associatedtype ObserverType
func addObserver(_ observer: ObserverType)
}
protocol Settings : Observable where ObserverType == SettingsObserver {
var interval: Int { get set }
}
protocol SettingsObserver {
func intervalDidChange(newValue: Int)
}
class Observer1 : SettingsObserver {
func intervalDidChange(newValue: Int) {
print("Observer 1 changed to \(newValue)")
}
}
class Observer2 : SettingsObserver {
func intervalDidChange(newValue: Int) {
print("Observer 2 changed to \(newValue)")
}
}
class AppSettings: Settings {
var interval: Int = 0 {
didSet {
observers.forEach { $0.intervalDidChange(newValue: interval) }
}
}
private var observers: [SettingsObserver] = []
func addObserver(_ observer: SettingsObserver) {
observers.append(observer)
}
}
let settings = AppSettings()
settings.addObserver(Observer1())
settings.addObserver(Observer2())
settings.interval = 10
Although Observable cannot be used as a parameter type, the protocols that derive from it that also specifies the associated type, can.
You could go one step further and make SettingsObserver a typealias of (Int) -> Void. This way you don't need all those different ObserverX classes.
typelias SettingsObserver = (Int) -> Void
The addObserver calls would then become:
settings.addObserver { print("Observer 1 changed to \($0)") }
settings.addObserver { print("Observer 2 changed to \($0)") }
And the call in didSet would change to:
observers.forEach { $0(interval) }
Also, I don't understand why Settings exist. Can't you just conform AppSettings directly to Observable? I mean, I know the idea of program to interface and all that, but IMO this is a bit too much...

Could not infer generic parameter when calling protocol static method

Using a Playground and given these definitions:
import Foundation
protocol MoneyTrakObject {
var key: String { get set }
init()
}
extension MoneyTrakObject {
static func objectFromDB<T: MoneyTrakObject>(for key: String, queue: DispatchQueue? = nil, completion: #escaping (T) -> Void) -> String? {
// after data is retrieved, call completion closure
let valueObject = T()
completion(valueObject)
return "dbToken"
}
}
protocol Transaction: MoneyTrakObject {
var amount: Int { get set }
}
struct BasicTransaction: Transaction {
var key = UUID().uuidString
var amount = 0
init() {}
}
struct RecurringTransaction: Transaction {
var key = UUID().uuidString
var amount = 0
init() {}
}
I would expect that I could do this:
let token1 = BasicTransaction.objectFromDB(for: "") { (transaction) in
// use transaction
}
let token2 = RecurringTransaction.objectFromDB(for: "") { (transaction) in
// use transaction
}
However I get the Generic parameter 'T' could not be inferred error when calling the static method and I'm not sure why.
I do not see why you need the generic constraint. If you change the extension of your protocol to this:
extension MoneyTrakObject {
static func objectFromDB(for key: String, queue: DispatchQueue? = nil, completion: #escaping (Self) -> Void) -> String? {
// after data is retrieved, call completion closure
let valueObject = Self()
completion(valueObject)
return "dbToken"
}
}
Your code compiles just fine. Self is a placeholder for the actually implementing type.
Well... the only place where T is used is inside the completion handler argument. When you write this:
let token1 = BasicTransaction.objectFromDB(for: "") { (transaction) in
// use transaction
}
The compiler has no idea what type transaction is and hence cannot specialize the generic function. Provide some type info like this:
let token1 = BasicTransaction.objectFromDB(for: "") { (transaction: Transaction) in
// use transaction
}
let token2 = BasicTransaction.objectFromDB(for: "") { (transaction: BasicTransaction) in
// use transaction
}

Is self captured within a nested function

With closures I usually append [weak self] onto my capture list and then do a null check on self:
func myInstanceMethod()
{
let myClosure =
{
[weak self] (result : Bool) in
if let this = self
{
this.anotherInstanceMethod()
}
}
functionExpectingClosure(myClosure)
}
How do I perform the null check on self if I'm using a nested function in lieu of a closure (or is the check even necessary...or is it even good practice to use a nested function like this) i.e.
func myInstanceMethod()
{
func nestedFunction(result : Bool)
{
anotherInstanceMethod()
}
functionExpectingClosure(nestedFunction)
}
Unfortunately, only Closures have "Capture List" feature like [weak self]. For nested functions, You have to use normal weak or unowned variables.
func myInstanceMethod() {
weak var _self = self
func nestedFunction(result : Bool) {
_self?.anotherInstanceMethod()
}
functionExpectingClosure(nestedFunction)
}
Does not seem to be the case anymore. This is valid in swift 4.1:
class Foo {
var increment = 0
func bar() {
func method1() {
DispatchQueue.main.async(execute: {
method2()
})
}
func method2() {
otherMethod()
increment += 1
}
method1()
}
func otherMethod() {
}
}
The question remains: How is self captured ?