Swift: Capture inout parameter in closures that escape the called function - ios

I tried to write an "editor" class that could retain a reference to a property on a different object for later mutation. I first wrote the editor class to receive a closure for reading, and a closure for writing. This worked. I then tried to pass the parameter in question by (inout) reference, and then generate the getter / setter pair from that. This did not work. The Swift docs does say (paraphrasing) that Swift figures out when to copy, and when to not. I think I am up against unpredictability of that limitation, but thought I'd pose the question just the same.
Alternatively, is it possible to get a curried function for the individual getter and setter?
My code is:
class SomeModel : Printable {
var a:String
init(a:String) {
self.a = a
}
var description:String {
return "\(self.a)"
}
}
class Editor {
var getter:()-> String
var setter:(String)->()
init(getter:()-> String, setter:(String)->()) {
self.getter = getter
self.setter = setter
}
convenience init(inout bindTo:String) {
self.init(
getter:{ return bindTo },
setter: { v in bindTo = v })
}
func read() -> String {
return self.getter()
}
func write(value:String) {
self.setter(value)
}
}
func testBindTo() {
var readModel = SomeModel(a:"Did not capture by reference");
var bindForReading = Editor(bindTo: &readModel.a)
readModel.a = "captured by reference!"
println(bindForReading.read())
var writeModel = SomeModel(a:"Did not capture by reference");
var bindForWriting = Editor(bindTo: &writeModel.a)
bindForWriting.write("captured by reference")
println(writeModel)
}
testBindTo()
func testExplicitGetterSetter() {
var readModel = SomeModel(a:"Did not capture by reference");
var bindForReading = Editor(
getter: { readModel.a },
setter: { v in readModel.a = v })
readModel.a = "captured by reference!"
println(bindForReading.read())
var writeModel = SomeModel(a:"Did not capture by reference");
var bindForWriting = Editor(
getter: { writeModel.a },
setter: { v in writeModel.a = v })
bindForWriting.write("captured by reference")
println(writeModel)
}
testExplicitGetterSetter()
The results are:
Did not capture by reference
Did not capture by reference
captured by reference!
captured by reference
Thanks!

I don't think this is possible. And it shouldn't be possible, if you think about it, because it would be super unsafe.
Because closures can outlive the scope they were created in, captured variables must be stored with the block. But in order to be able to assign to the captured variable and share the state of that variable between the (one or more) block(s) that captured it and the original scope, the blocks cannot just capture the value of the variable (which would create independent copies of the variable), but capture a kind of "reference" to a shared copy. This means that assignable variables that are captured by blocks must be stored specially. In Objective-C, this is declared with __block. In Swift, this __block behavior is implicit.
However, in order for the block to modify an inout variable (potentially at a later time) as it is seen in the function caller's scope, that would mean that the passed variable in the caller's scope would also need to be stored in a way that can outlive the stack frame. But the caller function doesn't know this. All it knows from the type of the called function is that one of its parameters is inout; it doesn't know that the function plans to capture that inout variable in a block. So it doesn't know to prepare this __block storage for this passed variable.

It can be done as follows. )Notice that the closure and the inout param have the same lifespan.)
/// A class providing access to a resource with an inout parameter in an escaping closure.
class ProtectedResource<ValueType> {
private var protectedResourceArray = [ValueType]()
private var protectedResourceArrayLock = NSRecursiveLock()
private let opq = OperationQueue()
func performWithResource(block: #escaping (inout [ValueType]) -> ()) {
opq.addOperation { [weak self] in
guard let strongSelf = self else {
return
}
strongSelf.protectedResourceArrayLock.lock()
block(&strongSelf.protectedResourceArray)
strongSelf.protectedResourceArrayLock.unlock()
}
}
}
/// Some other class using that in out parameter.
func run() {
func updateArray(array: inout [String]) {
print("Performing on \(array)")
array.append("test")
}
protectedResource.performWithResource(block: updateArray)
protectedResource.performWithResource {
print("Performing on \($0)")
}
}

Related

Optional cast to protocol's associated type is failing (returning nil)

I have a protocol in my open source library (link in-case code samples aren't enough).
Said protocol has two associated types, one for a function "send" type, and one for a "return type" defined like so:
/// A protocol which can be adopted to define a function that can be performed on any given camera
public protocol CameraFunction {
/// An associated type which is taken as an input when calling this function on a `Camera` instance
associatedtype SendType
/// An associated type which is returned from the camera when calling this function on the `Camera`
associatedtype ReturnType
/// The enum representation of this given function
var function: _CameraFunction { get }
}
In a function implementation (performFunction declared on another protocol):
func performFunction<T>(_ function: T, payload: T.SendType?, callback: #escaping ((Error?, T.ReturnType?) -> Void)) where T : CameraFunction {
switch function.function {
case .getEvent:
let packet = Packet.commandRequestPacket(code: .getAllDevicePropData, arguments: [0], transactionId: ptpIPClient?.getNextTransactionId() ?? 0)
ptpIPClient?.awaitDataFor(transactionId: packet.transactionId, callback: { (dataResult) in
switch dataResult {
case .success(let data):
guard let numberOfProperties = data.data[qWord: 0] else { return }
var offset: UInt = UInt(MemoryLayout<QWord>.size)
var properties: [PTPDeviceProperty] = []
for _ in 0..<numberOfProperties {
guard let property = data.data.getDeviceProperty(at: offset) else { break }
properties.append(property)
offset += property.length
}
let event = CameraEvent(sonyDeviceProperties: properties)
callback(nil, event as? T.ReturnType)
case .failure(let error):
callback(error, nil)
}
})
ptpIPClient?.sendCommandRequestPacket(packet, callback: nil)
I create a CameraEvent object and attempt to downcast (unsure if that's the correct terminology) to T.ReturnType. At the point that is called, event is non-nil, however casting it to T.ReturnType gives a nil result even though it should match!
Event.get (.getEvent) is defined like so:
/// Functions for interacting with the event API on the camera
public struct Event: CameraFunction {
public var function: _CameraFunction
public typealias SendType = Bool
public typealias ReturnType = CameraEvent
/// Gets the current event
public static let get = Event(function: .getEvent)
}
It's important to note as well that another implementation of the second protocol I talk about (The one defining the performFunction function) successfully does very similar logic and I don't get nil back! There must be something I'm doing wrong here, but I have no idea what it could be!
Screenshots in case that helps!
Calling the protocol's function
Implementation of the protocol's function
This was... just the debugger being a pile of rubbish! Decided to add in a print statement to make absolutely sure it was nil. Turns out that wasn't the case! Prints fine, but lldb seems to think it's nil for whatever reason.

Calling async function in lazy var property

Is there a way to call an async function from a lazy or computed property?
struct Item {
lazy var name: String = {
API.requestThing({ (string: String) in // Xcode didn't like this
return string // this would not work here
})
}()
}
class API {
class func requestThing(completion: String -> Void) {
completion("string")
}
}
Your completion handler in API.requestThing returns a String, yet it is supposed to have no return value:
(completion: String -> Void)
I got this to work:
struct Item {
lazy var name: String = {
API.requestThing({ (string: String) in
return string
})
}()
}
class API {
class func requestThing(completion: String -> String) -> String {
return completion("string")
}
}
There is no good reason to use "lazy" in this case. lazy is for initialization. Just create a normal func and pass a completion handler.
First, requestThing returns () (ie void) and not String. So the type of the following expression is also () and not String:
API.requestThing { string in
return string
}
Second, the call to requestThing is asynchronous, so even if you defined name as a lazy var, the call to the var body function is still synchronousand will return immediately.
So if you can transform name into a function like this:
func name(completion: String -> ()) {
API.requestThing { string in
completion(string)
}
}
// Later you call it in this way
myItem.name { name in
// use the value of name
}
If in addition you want to cache the retrieved value you can modify Item to a class and use the following code
class Item {
private var nameValue: String?
func name(completion: String -> ()) {
if let value = nameValue {
// return cached value
return completion(value)
} else {
// request value
API.requestThing { string in
// cache retrieved value
self.nameValue = string
// return retrieved value
completion(string)
}
}
}
}
There's probably no compelling reason to do this, but the following approach seems to be reasonable:
Instead having a variable of type String - we sometimes require a "Future" of that thing, e.g. Future<String>. A future represents the eventual result of an asynchronous operation - that is exactly what's given in your question.
The future itself is a "normal" variable and can be lazy evaluated, too. It just doesn't yet have its eventual value. That means, the underlying task will only be started when explicitly requested (e.g. lazily). From a design or architectural point of view, this may make sense.
func fetchString() -> Future<String> { ... }
lazy var name: Future<String> = fetchString()
Later in your code, you obtain the variable as follows:
item.name.map { string in
print(string)
}
If this is the first access to the lazy property, it will start the underlying asynchronous operation which calculates the string. Then, when the variable is available, the mapping function as provided in the map function will be called with the variable as an argument - possibly some time later, too.
Otherwise (if this is not the first access), it will just provide the string in the parameter when it is available, possibly immediately.
Since operations may fail, a "Future" also provides means to handle this:
item.name.map { string in
print(string)
}.onFailure { error in
print("Error: \(error)")
}
See also: https://en.wikipedia.org/wiki/Futures_and_promises
There are implementations for Futures in Swift and Objective-C, also often called "Promise".

Initialiser Inheritance confusion

I am trying to build some mocking infrastructure, I want to be able to return a stubbed value and count the times the value was accessed. I have something simple like this:
class BasicMock<T> {
var callsCount = 0
private let backing: T
var result: T {
callsCount++
return backing
}
init(result: T) {
self.backing = result
}
}
class MockTimeDefinitionSerialiser: BasicMock<[String: [AnyObject]]>, TimeDefinitionSerialiserProtocol {
func serialiseTravelTime(travelTime: JSSTravelTime) -> [String: AnyObject] {
return result
}
}
However trying to build it:
let mockTimeDefinitionSerialiser = MockTimeDefinitionSerialiser(result: ["": ""])
Emits the error 'MockTimeDefinitionSerialiser' cannot be constructed because it has no accessible initialisers
My interpretation of the Swift docs is that I should automatically inherit the initialiser as I have set all stored properties.
What am I doing wrong?
Please remove any unnecessary code when asking a question. I was able to reduce your problem to this:
class Base<T> {
init(t: T) {}
}
class Sub: Base<Int> {}
Sub(t: 0) // error: 'Sub' cannot be constructed because it has no accessible initialisers
It seems like even though you specified the T in the subclass, the compiler cannot infer what the initialiser uses for T. I couldn't find a way to get the initialiser to be inherited, you'd have to use a workaround:
class Sub: Base<Int> {
override init(t: Int) {
super.init(t: t)
}
}

What is "self" used for in Swift?

I am new to Swift and I'm wondering what self is used for and why.
I have seen it in classes and structures but I really don't find them essential nor necessary to even mention them in my code. What are they used for and why? In what situations it's necessary to use it?
I have been reading lots of questions and answers for this question but none of them fully answers my questions and they always tend to compare it with this as in Java, with which I'm not familiar whatsoever.
Yes it is the same as this in Java and self in Objective-C, but with Swift, self is only required when you call a property or method from a closure or to differentiate property names inside your code, such as initializers. So you can use almost all of your class components safely without using self unless you are making the call from a closure.
“The self Property Every instance of a type has an implicit property
called self, which is exactly equivalent to the instance itself. You
use the self property to refer to the current instance within its
own instance methods.
The increment() method in the example above could have been written
like this:
func increment() {
self.count += 1
}
In practice, you don’t need to write self in your code very often.
If you don’t explicitly write self, Swift assumes that you are
referring to a property or method of the current instance whenever you
use a known property or method name within a method. This assumption
is demonstrated by the use of count (rather than self.count)
inside the three instance methods for Counter.
The main exception to this rule occurs when a parameter name for an
instance method has the same name as a property of that instance. In
this situation, the parameter name takes precedence, and it becomes
necessary to refer to the property in a more qualified way. You use
the self property to distinguish between the parameter name and the
property name.
Here, self disambiguates between a method parameter called x and
an instance property that is also called x:”
Excerpt From: Apple Inc. “The Swift Programming Language (Swift 2 Prerelease).”
This is how Ray Wenderlich recommends the use of self in Swift for their tutorials:
Use of Self
For conciseness, avoid using self since Swift does not require it to access an object's properties or invoke its methods.
Use self when required to differentiate between property names and arguments in initializers, and when referencing properties in closure expressions as required by the compiler:
class BoardLocation {
let row: Int, column: Int
init(row: Int, column: Int) {
self.row = row
self.column = column
let closure = {
println(self.row)
}
}
}
And this is GitHub's recommendations on self for their applications:
Only explicitly refer to self when required
When accessing properties or methods on self, leave the reference to self implicit by default:
private class History {
var events: [Event]
func rewrite() {
events = []
}
}
Only include the explicit keyword when required by the language — for example, in a closure, or when parameter names conflict:
extension History {
init(events: [Event]) {
self.events = events
}
var whenVictorious: () -> () {
return {
self.rewrite()
}
}
}
Rationale: This makes the capturing semantics of self stand out more in closures, and avoids verbosity elsewhere.
You will also use self a lot when creating your extensions, example:
extension Int {
func square() -> Int {
return self * self
}
// note: when adding mutating in front of it we don't need to specify the return type
// and instead of "return " whatever
// we have to use "self = " whatever
mutating func squareMe() {
self = self * self
}
}
let x = 3
let y = x.square()
println(x) // 3
printlx(y) // 9
now let's say you want to change the var result itself
you have to use the mutating func to make change itself
var z = 3
println(z) // 3
now let's mutate it
z.squareMe()
println(z) // 9
// now let's see another example using strings :
extension String {
func x(times:Int) -> String {
var result = ""
if times > 0 {
for index in 1...times{
result += self
}
return result
}
return ""
}
// note: when adding mutating in front of it we don't need to specify the return type
// and instead of "return " whatever
// we have to use "self = " whatever
mutating func replicateMe(times:Int){
if times > 1 {
let myString = self
for index in 1...times-1{
self = self + myString
}
} else {
if times != 1 {
self = ""
}
}
}
}
var myString1 = "Abc"
let myString2 = myString1.x(2)
println(myString1) // "Abc"
println(myString2) // "AbcAbc"
now let's change myString1
myString1.replicateMe(3)
println(myString1) // "AbcAbcAbc"
In what situations it's necessary to use it
It is necessary to use it only when the name of a local variable overshadows the name of a property.
However, as a matter of style (and readability), I always use it:
I use it with property names, because otherwise I am left wondering what this variable is (since it is neither locally declared nor an incoming parameter).
I use it as the receiver of function (method) calls, in order to differentiate such methods from top-level or local functions.
This is why we need self.
When we define a class, like:
class MyClass {
func myMethod()
}
We are creating a "Class Object". Yes, Class is an object too.
Then no matter how many instances are created using the class, all instances will have a reference pointer to its Class Object.
You can imagine that all instance methods defined by the Class are in the Class Object, and there will be only one copy of them.
That means all instances created using the Class are sharing the same method.
Now imagine you are the myMethod in the Class Object, and because you are shared for all instances, you must have a way to tell which instance you are working on.
When someone says instance1.myMethod(), it means "Hi! myMethod, please do your work and instance1 is the object you are working on".
To reference the object that the caller sent to you, use self.
“In practice, you don’t need to write self in your code very often. If
you don’t explicitly write self, Swift assumes that you are referring
to a property or method of the current instance whenever you use a
known property or method name within a method.”
Excerpt From: Apple Inc. “The Swift Programming Language.” iBooks.
https://itun.es/tw/jEUH0.l
The reserved word self in Swift is similar to this but it's not the same as in Java or JavaScript.
As #Dave Gomez correctly quoted:
Every instance of a type has an implicit property called self, which is exactly equivalent to the instance itself.
Here lies one of the main differences, because:
"Every instance" in Swift (at least for now) is almost every-thing.
In Java, for example, you can only use the word this inside an instance scope, in Swift you can use it almost every-where.
Here are a few examples:
//Example 1:
var x="foo"
x.self="bar".self//compiles and run
//Example 2:
print.self(x);//compiles and run
//Example 3:
func myOther(self otherSelf:Person){}
myOther(self: personObject);//compiles and run
//Example 4:
class Foo{
var bar=""
init(){
self.addSome()//this would be the same in Java
}
func addSome(){
//But definitely not this:
self.self.bar.self.self="some".self.self
}
}
//Guess what - also compiles and run...
let f=Foo()
print(f.bar)
See : Why 'self.self' compiles and run in swift for more information.
I arrived at this question while searching for self as a class function, which looks like this: Int.self, String.self, or YourClass.self
Previously, as near as I can tell, only Dmitri Pavlutin's answer touches on this, when he said:
When self is accessed in a type method (static func or class func), it refers to the actual type (rather than an instance).
When self is used this way, it actually returns what in Swift is called a Metatype. You can read the Swift documentation page on Types for more information.
There is also an article with more details about using and understanding metatypes called "What's .self, .Type and .Protocol? Understanding Swift Metatypes" on swiftrocks.com.
"How to use correctly 'self' keyword in Swift" explains self in detail.
self is a property on the instance that refers to itself. It's used to access class, structure and enumeration instance within methods.
When self is accessed in a type method like static func or class func, it refers to the actual type rather than an instance.
Swift allows omitting self when you want to access instances properties.
When a method parameter has the same name as an instance property, you have to explicitly use self.myVariable = myVariable to make a distinction.
Notice that method parameters have a priority over instance properties.
I'm a total noob at coding in general - and whilst these answers are great, from the perspective of a total noob who just wants it answered as practically as possible without all these difficult words and concepts, here's my Super Noob dumbed down version:
'self' is used because the coding application doesn't know which variable to use if you type the variable in the scope of your functions. It's all about the scope and making it clear which variable you're using if some other variable has the same name. Scope is the area inside the curly {} brackets. so for example:
{ scope1 {scope2} }
Here you don't need to use self:
class example {
private var exampleVar = “this is the class scope variable”
func x() {
//You don't have to use self here
print(exampleVar)
}
}
Here you do need to use self:
class example {
private var exampleVar = “this is the class scope variable”
func x(_ exampleVar: String) {
//It would be confusing which exampleVar is used here so you should use self
print(exampleVar)
print(self.exampleVar)
}
}
There's also this situation:
class example {
private var exampleVar = “this is the class scope variable”
func x() {
randomMethod { _ in
//This is not the class scope here, so we need to use self here.
//You will be flagged during build time of this if you don't use self.
print(self.exampleValue)
}
}
}
self is a property on the instance that refers to itself. It's used to access the class, structure and enumeration instance within methods.
When a method parameter has the same name as an instance property, you have to explicitly use self.myVariable = myVariable to make a distinction.
Notice that method parameters have a priority over instance properties.
struct Weather {
let windSpeed: Int
let chanceOfRain: Int
init(windSpeed: Int, chanceOfRain: Int) {
self.windSpeed = windSpeed
self.chanceOfRain = chanceOfRain
}
func isDayForWalk() -> Bool {
let comfortableWindSpeed = 5
let acceptableChanceOfRain = 30
return self.windSpeed <= comfortableWindSpeed
&& self.chanceOfRain <= acceptableChanceOfRain
}
}
// A nice day for a walk
let niceWeather = Weather(windSpeed: 4, chanceOfRain: 25)
print(niceWeather.isDayForWalk()) // => true
I have an elegant case for using self in Swift. I use it in blocks like this:
class MyBase {
private var baseValue: Int = 100
var block: ((Int)->())? = nil
func baseMethod(anotherValue: Int) {
guard let b = block else { return }
b(baseValue + anotherValue)
}
...
}
class MyClass {
init()
{
// Define base class block.
// This may hold self in block causing memory leaks
// if self is a strong reference
block = {
// indicate self is a weak reference
[weak self] (para) in
// guaranty self existence
guard let this = self else {return}
let value = this.value1 + para
// this call passes value to other obj's method
this.obj.method(value)
return
}
}
func callBaseBlock(otherValue: Int) {
baseMethod(otherValue)
}
private var value1: Int = 1 // ini value
private var obj: OtherClass // another class with method defined
...
...
}
This way, I guarantee that there will be no strong references to self in the block. The syntax is very clear. I use this way to prevent memory leaks.

Trigger lazy initializer again in Swift by setting property to nil

I want a lazily-initialized property whose initializer I can invoke again if I set the property to nil.
If I define my property this way:
lazy var object = { /*init code*/ }()
...and later invoke the property, the initializer is triggered once. However, if I set object to nil later in my program, the initializer is not invoked again. How can I do that in Swift?
I looked into computed properties but they don't actually store values, so whenever I invoke the variable, the computation or initialization always occurs. I want to compute only whenever the property is nil.
The lazy property initializer is responsible of initializing the property the first time it is accessed in read mode. Setting to nil has no effect on the initialization status - it's just a valid value the property stores.
You can mimic a lazy initialization with 3 properties:
a private initializer, implemented as a computed property (or a closure if you prefer)
a private backing property, storing the actual value
a non private property, which is the one you actually use in your code
The code looks like this:
class MyClass {
private var _myPropInitializer: Int {
return 5
}
private var _myProp: Int?
var myProp: Int? {
get {
if self._myProp == nil {
self._myProp = self._myPropInitializer
}
return _myProp!
}
set {
_myProp = newValue
}
}
}
the initializer property returns a computed value for the variable when it needs to be initialized, which is the 5 integer in the above example
myProp is an optional integer (to be able to store a nil):
on set, it will store the new value in the _myProp property
on get, if _myProp is nil, it invokes the initializer, assigning it to _myProp, and it returns its value
If you want to reuse that pattern, it's better to put everything in a class:
class Lazy<T> {
private let _initializer: () -> T
private var _value: T?
var value: T? {
get {
if self._value == nil {
self._value = self._initializer()
}
return self._value
}
set {
self._value = newValue
}
}
required init(initializer: () -> T) {
self._initializer = initializer
}
}
Note: a struct is not usable because setting a property inside a property getter is not allowed, whereas in a class it is.
Then you can use it as follows:
class MyTestClass {
var lazyProp: Lazy<Int>
init() {
self.lazyProp = Lazy( { return 5 } )
}
}
Some tests in playground:
var x = MyTestClass()
x.lazyProp.value // Prints {Some 5}
x.lazyProp.value = nil
x.lazyProp._value // Prints nil
x.lazyProp.value // Prints {Some 5}
The downside is that you have to access to the actual property as x.lazyProp.value and not as x.lazyProp.
Here's a lazy pattern I use when your object can only ever be nil or a computed value. It requires only 2 properties:
var todayPredicate: NSPredicate! {
set {
guard newValue == nil else {return} // could throw here if required
self._todayPredicateLazyBacker = nil
}
get {
guard self._todayPredicateLazyBacker == nil else {return self. _todayPredicateLazyBacker}
// construct your today predicate
let predicate = ...
self._todayPredicateLazyBacker = predicate
return self._todayPredicateLazyBacker
}
}
private var _todayPredicateLazyBacker: NSPredicate?
todayPredicate is constructed only once when it is read for the first time (lazy).
So why would you ever want to set todayPredicate to nil? In this example you are probably observing for the day changing because todayPredicate must always represent today. In your observer code you would simply do this, for example...
self.todayPredicate = nil
self.loadEvents()

Resources