Delegating to another initializer from a closure - swift

I'm looking at ways to create a DispatchData instance out of a Data instance. I started with a static function:
static func dispatchData(fromData data: Data) -> DispatchData {
return data.withUnsafeBytes { (typedPtr: UnsafePointer<UInt8>) -> DispatchData in
let bufferPtr = UnsafeRawBufferPointer(start: UnsafeRawPointer(typedPtr), count: data.count)
return DispatchData(bytes: bufferPtr)
}
}
This works fine (and is coincidentally very similar to this answer). I then decided I'd like to add this as an initializer to DispatchData in an extension and wrote:
private extension DispatchData {
init(data: Data) {
data.withUnsafeBytes { (typedPtr: UnsafePointer<UInt8>) in // 1
let bufferPtr = UnsafeRawBufferPointer(start: UnsafeRawPointer(typedPtr), count: data.count)
self.init(bytes: bufferPtr)
}
}
}
At this, the compiler balked on the line marked // 1:
Variable 'self.__wrapped' captured by a closure before being initialized
It makes sense — the compiler doesn't want self to be captured before I've delegated to init(bytes: UnsafeRawBufferPointer), since stored variables — like __wrapped, in this case — aren't yet initialized. But I can't see another way to get the UnsafeRawBufferPointer; I can't return it from data.withUnsafeBytes, per the documentation:
Warning
The byte pointer argument should not be stored and used outside of the lifetime of the call to the closure.
I know I can just go back to using a static function to achieve what I want, but I'd prefer it if there were a way to add this initializer. Is there a way to make this initializer work as intended?

The problem with your extension is that although the compiler knows you're passing the closure as non-escaping argument to withUnsafeBytes(_:); it doesn't have any guarantee that it will be called once and only once (which is required for initialisation).
One simple solution is to, rather than chain to another initialiser, just construct a new instance of DispatchData yourself, and then assign this to self, thus completing initialisation:
import Foundation
private extension DispatchData {
init(data: Data) {
self = data.withUnsafeBytes { (typedPtr: UnsafePointer<UInt8>) in
DispatchData(bytes:
UnsafeRawBufferPointer(start: typedPtr, count: data.count)
)
}
}
}
Note also that there's an implicit conversion from UnsafePointer<UInt8> to UnsafeRawPointer? when passing it as an argument; so we don't need to wrap it in an initialiser call.
And in Swift 5, withUnsafeBytes gives you a UnsafeRawBufferPointer directly:
private extension DispatchData {
init(data: Data) {
self = data.withUnsafeBytes(DispatchData.init)
}
}

Related

How does the encoded data end up in the Encoder, when it has no mutating functions?

I am trying to code a custom Coder and I am having trouble understanding something, particularly about the Encoder part.
The Encoder is only required to have three functions and two variables :
struct MyEncoder : Encoder {
public var codingPath : [CodingKey]
public var userInfo : [CodingUserInfoKey : Any]
public func container<Key>(keyedBy type: Key.Type -> KeyedEncodingContainer<Key> where Key : CodingKey {}
public func unkeyedContainer() -> UnkeyedEncodingContainer {}
public func singleValueContainer() -> SingleValueEncodingContainer {}
}
You will notice, none of them are mutating. They all return something and that's it.
The containers themselves, to generalise, have sub functions to encode specific types into themselves :
struct MySingleValueContainer : SingleValueEncodingContainer {
var codingPath: [CodingKey]
mutating func encode(_ value : someType) throws {}
/// etc with a lot of different types
}
If a user wants to customise how their class is encoded, they may do this :
func encode(to: Encoder) throws {}
And here is my problem ! The encoder persists after the call to encode(to: Encoder) but it does not mutate so how does the encoded data end up inside it ? Reading the JSON Encoder's source I can see that their containers have a variable containing an Encoder, which is passed down. But it should be copy-on-write as everything else in Swift, which means the data shouldn't be able to make its way back up the chain !
Is the Encoder somehow secretly passed as a reference instead of as a value ? That seems like the only logical conclusion but it seems very weird to me... If not, what is going on ?
I have also taken a look at this question and its answer, and although they have helped me they display the same behaviour of magically bringing data up the chain, except it passes down a custom type instead of the Encoder itself.
Is the Encoder somehow secretly passed as a reference instead of as a value?
Close, but not quite. JSONEncoder and its underlying containers are relatively thin veneer interfaces for reference-based storage. In the swift-corelibs-foundation implementation used on non-Darwin platforms, this is done using RefArray and RefObject to store keyed objects; on Darwin platforms, the same is done using NSMutableArray and NSMutableDictionary. It's these reference objects that are passed around and shared, so while the individual Encoders and containers can be passed around, they're writing to shared storage.
But it should be copy-on-write as everything else in Swift, which means the data shouldn't be able to make its way back up the chain!
One more note on this: all of the relevant types internal to this implementation are all classes (e.g. JSONEncoderImpl in swift-corelibs-foundation, _JSONEncoder on Darwin), which means that they wouldn't be copy-on-write, but rather, passed by reference anyway.
Regarding your edit: this is the same approach that the linked answer uses with its fileprivate final class Data — it's that class which is shared between all of the internal types and passed around.
JSONEncoder.encode uses JSONEncoderImpl as the concrete implementation of Encoder (source):
open func encode<T: Encodable>(_ value: T) throws -> Data {
let value: JSONValue = try encodeAsJSONValue(value)
...
}
func encodeAsJSONValue<T: Encodable>(_ value: T) throws -> JSONValue {
let encoder = JSONEncoderImpl(options: self.options, codingPath: [])
guard let topLevel = try encoder.wrapEncodable(value, for: nil) else {
...
}
return topLevel
}
wrapEncodable would then eventually call encode(to: Encoder) on your Codable type with self as the argument.
Is the Encoder somehow secretly passed as a reference instead of as a value ?
Notice that JSONEncoderImpl is a class, so there is nothing "secret" about this at all. The encoder is passed as a reference in this particular case.
In general though, the Encoder implementation could also be a struct, and be passed by value. After all, all it needs to do is to provide mutable containers into which data can be encoded. As long as you have a class somewhere down the line, it is possible to "seemingly" mutate a struct without mutating or making the struct a var. Consider:
private class Bar {
var magic: Int = -1
}
struct Foo: CustomStringConvertible {
private let bar = Bar()
var description: String { "\(bar.magic)" }
func magicallyMutateMyself() {
bar.magic = Int.random(in: 0..<100)
}
}
let foo = Foo()
print(foo) // -1
foo.magicallyMutateMyself()
print(foo) // some other number

How to return value from a closure in a Struct in Swift?

I'm retrieving data from a website.
Networking works well. Data is parsed correctly from JSON.
A couple of references - In this struct:
Replies is the datamodel for the JSON
PrepareQuestions is a func which performs the parsing (I have it in an extension of the same Struct)
I'd like to have an object within this struct (downloadedData - 'Replies' is the struct with the datamodel) containing all the information downloaded, but I incur into an error due to "self being an immutable capture". Any suggestions? Thank you!
struct QuestionsManager {
var downloadedData:Replies?
func useData() {
manageQuestions(url: K.urlForRetreival, numberOfQuestions: K.numberOfSquares) { [self] (replies, error) in
if let replies = replies {
DispatchQueue.main.async {
downloadedData = replies // Here I got the error
}
}
}
}
func manageQuestions(url: String, numberOfQuestions: String, myCompletion: #escaping (Replies?, Error?)->()) {
let generatedUrl = URL(string: url + numberOfQuestions)!
let urlSession = URLSession(configuration: .default)
let task = urlSession.dataTask(with: generatedUrl) { (data, response, error) in
if error == nil {
if let fetchedData = data {
let fetchedProcessedData = prepareQuestions(data: fetchedData)
myCompletion(fetchedProcessedData, nil)
return
}
} else {
myCompletion(nil, error)
return
}
}
task.resume()
}
}
You're seeing this error because the closure captures an immutable self.
Just like primitive types (e.g. Int), structs are value-types, and Swift is built with the notion of immutability of value-types.
In other words, if you had let questionManager = QuestionManager(), you'd expect questionManager not to change. Even if it was a var, it can only mutate via direct action by the caller, e.g. questionManager.doMutatingFunc().
But, if a closure was allowed to capture self, it could modify itself at some later point. This is not allowed.
This simplest (only?) way to fix this is to turn QuestionManager into a class:
class QuestionManager {
// ...
}
struct is a value type. For value types, only methods explicitly
marked as mutating can modify the properties of self, so this is not
possible within a computed property.
If you change struct to be a class then your code compiles without
problems.
Structs are value types which means they are copied when they are
passed around.So if you change a copy you are changing only that copy,
not the original and not any other copies which might be around.If
your struct is immutable then all automatic copies resulting from
being passed by value will be the same.If you want to change it you
have to consciously do it by creating a new instance of the struct
with the modified data.
From https://stackoverflow.com/a/49253452/11734662

Difference between T and Self in generic methods

I’m writing a protocol called JSONDataInitializable, which will enable values to be initialized from Data that contains JSON using JSONDecoder.
Since it’s not possible to explicitly use generics within initializers, I declared a universal, type-agnostic helper method in a protocol extension, which the initializer later calls.
However, I came up with not one, but two ways to write such a method.
(1):
private static func initialize<T: JSONDataInitializable>(from jsonData: Data) throws -> T {
return try JSONDecoder().decode(T.self, from: jsonData)
}
(2):
private static func initialize(from jsonData: Data) throws -> Self {
return try JSONDecoder().decode(Self.self, from: jsonData)
}
Could you explain the difference between these methods? They both seem to produce the same result.
The only visible difference is the protocol conformance part in the first variant. However, the methods are declared in a protocol extension and therefore only available to types which conform to the protocol.
UPD
Here’s the complete protocol declaration:
protocol JSONDataInitializable: Decodable {
init?(from jsonData: Data)
}
extension JSONDataInitializable {
init?(from jsonData: Data) {
do {
self = try Self.initialize(from: jsonData)
} catch {
print(error)
return nil
}
}
// (1)
private static func initialize<T: JSONDataInitializable>(from jsonData: Data) throws -> T {
return try JSONDecoder().decode(T.self, from: jsonData)
}
// ⬆⬆⬆
// OR
// ⬇⬇⬇
// (2)
private static func initialize(from jsonData: Data) throws -> Self {
return try JSONDecoder().decode(Self.self, from: jsonData)
}
}
Let’s say we have a struct called User that’s Decodable. We need to initialize values of User from JSON (stored as Data). With the protocol, initialization works like that:
// Protocol conformance declaration
extension User: JSONDataInitializable { }
// JSON stored as Data
let networkData = ...
// Initialization
let john = User(from: networkData)
Your second implementation, using Self is the one that matches your requirements. You want to create an initializer in a protocol, which you can call on the type you want to initialize. Self in protocol functions refers to the type that you call the specific method on.
On the other hand, the generic implementation would allow you to initialize any types conforming to the protocol, but in your init(from:) method you assign the return value to self, so the generic type parameter T will be inferred as Self. This makes it unnecessary to make the method generic, since on a specific type, T will always be Self.

Closure cannot implicitly capture self parameter. Swift

I've got an error "Closure cannot implicitly capture self parameter". Tell me please how it fix?
struct RepoJson {
...
static func get(url: String, completion: #escaping (RepoJson!) -> ()) {
...
}
}
struct UsersJson {
var repo: RepoJson!
init() throws {
RepoJson.get(url: rep["url"] as! String) { (results:RepoJson?) in
self.repo = results //error here
}
}
}
It's because you're using struct. Since structs are value, they are copied (with COW-CopyOnWrite) inside the closure for your usage. It's obvious now that copied properties are copied by "let" hence you can not change them. If you want to change local variables with callback you have to use class. And beware to capture self weakly ([weak self] in) to avoid retain-cycles.

"Closure cannot implicitly capture a mutating self parameter" - after updating to Swift 3 [duplicate]

I am using Firebase to observe event and then setting an image inside completion handler
FirebaseRef.observeSingleEvent(of: .value, with: { (snapshot) in
if let _ = snapshot.value as? NSNull {
self.img = UIImage(named:"Some-image")!
} else {
self.img = UIImage(named: "some-other-image")!
}
})
However I am getting this error
Closure cannot implicitly capture a mutating self parameter
I am not sure what this error is about and searching for solutions hasn't helped
The short version
The type owning your call to FirebaseRef.observeSingleEvent(of:with:) is most likely a value type (a struct?), in which case a mutating context may not explicitly capture self in an #escaping closure.
The simple solution is to update your owning type to a reference once (class).
The longer version
The observeSingleEvent(of:with:) method of Firebase is declared as follows
func observeSingleEvent(of eventType: FIRDataEventType,
with block: #escaping (FIRDataSnapshot) -> Void)
The block closure is marked with the #escaping parameter attribute, which means it may escape the body of its function, and even the lifetime of self (in your context). Using this knowledge, we construct a more minimal example which we may analyze:
struct Foo {
private func bar(with block: #escaping () -> ()) { block() }
mutating func bax() {
bar { print(self) } // this closure may outlive 'self'
/* error: closure cannot implicitly capture a
mutating self parameter */
}
}
Now, the error message becomes more telling, and we turn to the following evolution proposal was implemented in Swift 3:
SE-0035: Limiting inout capture to #noescape contexts
Stating [emphasis mine]:
Capturing an inout parameter, including self in a mutating
method, becomes an error in an escapable closure literal, unless the
capture is made explicit (and thereby immutable).
Now, this is a key point. For a value type (e.g. struct), which I believe is also the case for the type that owns the call to observeSingleEvent(...) in your example, such an explicit capture is not possible, afaik (since we are working with a value type, and not a reference one).
The simplest solution to this issue would be making the type owning the observeSingleEvent(...) a reference type, e.g. a class, rather than a struct:
class Foo {
init() {}
private func bar(with block: #escaping () -> ()) { block() }
func bax() {
bar { print(self) }
}
}
Just beware that this will capture self by a strong reference; depending on your context (I haven't used Firebase myself, so I wouldn't know), you might want to explicitly capture self weakly, e.g.
FirebaseRef.observeSingleEvent(of: .value, with: { [weak self] (snapshot) in ...
Sync Solution
If you need to mutate a value type (struct) in a closure, that may only work synchronously, but not for async calls, if you write it like this:
struct Banana {
var isPeeled = false
mutating func peel() {
var result = self
SomeService.synchronousClosure { foo in
result.isPeeled = foo.peelingSuccess
}
self = result
}
}
You cannot otherwise capture a "mutating self" with value types except by providing a mutable (hence var) copy.
Why not Async?
The reason this does not work in async contexts is: you can still mutate result without compiler error, but you cannot assign the mutated result back to self. Still, there'll be no error, but self will never change because the method (peel()) exits before the closure is even dispatched.
To circumvent this, you may try to change your code to change the async call to synchronous execution by waiting for it to finish. While technically possible, this probably defeats the purpose of the async API you're interacting with, and you'd be better off changing your approach.
Changing struct to class is a technically sound option, but doesn't address the real problem. In our example, now being a class Banana, its property can be changed asynchronously who-knows-when. That will cause trouble because it's hard to understand. You're better off writing an API handler outside the model itself and upon finished execution fetch and change the model object. Without more context, it is hard to give a fitting example. (I assume this is model code because self.img is mutated in the OP's code.)
Adding "async anti-corruption" objects may help
I'm thinking about something among the lines of this:
a BananaNetworkRequestHandler executes requests asynchronously and then reports the resulting BananaPeelingResult back to a BananaStore
The BananaStore then takes the appropriate Banana from its inside by looking for peelingResult.bananaID
Having found an object with banana.bananaID == peelingResult.bananaID, it then sets banana.isPeeled = peelingResult.isPeeled,
finally replacing the original object with the mutated instance.
You see, from the quest to find a simple fix it can become quite involved easily, especially if the necessary changes include changing the architecture of the app.
If someone is stumbling upon this page (from search) and you are defining a protocol / protocol extension, then it might help if you declare your protocol as class bound. Like this:
protocol MyProtocol: class {
...
}
You can try this! I hope to help you.
struct Mutating {
var name = "Sen Wang"
mutating func changeName(com : #escaping () -> Void) {
var muating = self {
didSet {
print("didSet")
self = muating
}
}
execute {
DispatchQueue.global(qos: .background).asyncAfter(deadline: .now() + 15, execute: {
muating.name = "Wang Sen"
com()
})
}
}
func execute(with closure: #escaping () -> ()) { closure() }
}
var m = Mutating()
print(m.name) /// Sen Wang
m.changeName {
print(m.name) /// Wang Sen
}
Another solution is to explicitly capture self (since in my case, I was in a mutating function of a protocol extension so I couldn't easily specify that this was a reference type).
So instead of this:
functionWithClosure(completion: { _ in
self.property = newValue
})
I have this:
var closureSelf = self
functionWithClosure(completion: { _ in
closureSelf.property = newValue
})
Which seems to have silenced the warning.
Note this does not work for value types so if self is a value type you need to be using a reference type wrapper in order for this solution to work.