Posts by Alexbbrown@hachyderm.io
 (DIR) Post #APyRNT2S4zWHog4EHg by Alexbbrown@hachyderm.io
       2022-11-25T07:27:54Z
       
       0 likes, 0 repeats
       
       📖 An actor is a new kind of storage in swift, joining `class` and `struct` as a way to store and share structured data and behaviour.In particular, most methods (funcs) in an actor are implicitly async.  From the perspective of the caller, they asynchronously return a value.  actor MyActor {   func compute() -> Int {    return 6 * 7    }}func(a: MyActor) {  Task {    // this call might take a while, so we 'await'.    let answer = await a.compute()   }}
       
 (DIR) Post #APyRNUWcYJFKQXBpwm by Alexbbrown@hachyderm.io
       2022-11-25T07:27:55Z
       
       0 likes, 0 repeats
       
       An async function represents delayed work. When it does eventually return, it returns *all at once*.But some data doesn't arrive like that - it returns a little at a time - eg:* downloading a large file in small bits* instant message replies from your buddy* photos of world cup goals as they happen.In Swift #Concurrency we transmit values like this as as `AsyncStream` or other types which conform to `protocol AsyncSequences`https://developer.apple.com/documentation/swift/asyncstream/
       
 (DIR) Post #APyRNVY4kO0JbKsVqy by Alexbbrown@hachyderm.io
       2022-11-25T07:27:56Z
       
       0 likes, 0 repeats
       
       The very best thing about AsyncSequences is that there is a really easy and familiar way to use them in code:It's the humble `for` loop…for try await goalPhoto in footballGoals() {  displayInWindow(goalPhoto)}with the keyword `await` added to recognise that your code might have to wait a long time…⏱️… until the next message arrives (come ON you football guys, score already ⚽️…🥅 )Tech Note: await can cause code to switch threads or be rentrant.Now watch this:https://developer.apple.com/wwdc21/10058
       
 (DIR) Post #APyRNWRjPSWWNwuxbU by Alexbbrown@hachyderm.io
       2022-11-25T07:27:56Z
       
       0 likes, 0 repeats
       
       But `AsyncSequence` values can be hard to construct.And actors have subtle requirements which make this harder - like `Sendable`As you learn more, I'm sure you will find many ways to get and create AsyncSequences, including getting them from other APIs, and writing your own.But for the moment I want to show you just one quick way that works.  It may not be the optimal way, and might not work for all uses, but you can try it out
       
 (DIR) Post #APyRNXCAcnfchye2zI by Alexbbrown@hachyderm.io
       2022-11-25T07:27:57Z
       
       0 likes, 0 repeats
       
       AsyncSequence is Apple's simpler, funner successor to another great technology called #Combine.The API is almost identical, and this means you can easily create AsyncSequences from existing Combine Publishers.So that's how my example works:1. Create a sample Combine Publisher of Integers (Int)2. Erase it to`some Publisher<Int, Never>` (actually this step is automatic)3. Convert it to AsyncThrowingPublisher4. return it from the actor as AsyncThrowingPublisher<some Publisher<Int, Never>>
       
 (DIR) Post #APyRNY57KVcfSOLvdI by Alexbbrown@hachyderm.io
       2022-11-25T07:28:00Z
       
       0 likes, 0 repeats
       
       actor MyActor {  func numbers() -> AsyncThrowingPublisher<some Publisher<Int, Never>> {    (1...10) // an array      .publisher // combine publisher      .drip(every: 0.5) // same but slower      .values // a AsyncSequence (actually AsyncThrowingPublisher)  }}call it like this:do {  for try await value in await anActor.numbers() {    self.numbers += [value]  }    } catch {  self.numbers += [-1]}note that 'await' is required twice, once for the actor, and once for the sequence!
       
 (DIR) Post #APyRNYtSJLt9yVu85w by Alexbbrown@hachyderm.io
       2022-11-25T07:28:02Z
       
       0 likes, 0 repeats
       
       You might be asking : how can I use this?But luckily, there's loads of great ways to make a combine Publisher that you already have access to.Notifications in Notification Center: https://developer.apple.com/documentation/combine/routing-notifications-to-combine-subscribersTimers: https://developer.apple.com/documentation/combine/replacing-foundation-timers-with-timer-publishersKVO: https://developer.apple.com/documentation/combine/performing-key-value-observing-with-combineFetching Data from a Internet URL: https://developer.apple.com/documentation/foundation/urlsession/processing_url_session_data_task_results_with_combine/
       
 (DIR) Post #APyRNZgNNT1KQEnCLY by Alexbbrown@hachyderm.io
       2022-11-25T07:28:03Z
       
       0 likes, 0 repeats
       
       Future steps:As you get better at using Actors with SwiftUI, you may find other AsyncStreams and AsyncSequences that aren't based on combine.You'll need to tweak your approach a bit.  Sadly, it's not as easy as writingsome AsyncSequence<Int> // this does not workBut you can access the actual type of the Sequence and return that.  You'll need to play around a bit, and that's outside the scope of this article.Good luck!
       
 (DIR) Post #APyRNba4JtACJFrBnE by Alexbbrown@hachyderm.io
       2022-11-25T07:28:04Z
       
       0 likes, 0 repeats
       
       Note: The rules on Sendable types are quickly evolving in Swift.  I tested this example in Swift Playgrounds 4.2.1 and didn't get any compiler warnings.However, you might get warnings in Xcode with the same code.  If so, sorry.  Let me know and I'll take a look if I get time.
       
 (DIR) Post #APyRNcFtoMckOzQazg by Alexbbrown@hachyderm.io
       2022-11-25T07:28:05Z
       
       0 likes, 0 repeats
       
       You should now have everything you need to try it out for yourself.  For the source code, check out the ALT Text for the images in the first post.  It's not quite clear to me the best way to add code to Toots.  LMK what you would prefer in future.I'd like to get code examples
       
 (DIR) Post #AV12JT3Y1xZnXa3KKG by Alexbbrown@hachyderm.io
       2023-04-25T16:15:27Z
       
       0 likes, 0 repeats
       
       @EU_Commission you designed a new search engine? Or a new rule for search engines?
       
 (DIR) Post #AWcQfkef8Z1Ai7PIlk by Alexbbrown@hachyderm.io
       2023-06-12T15:07:52Z
       
       0 likes, 0 repeats
       
       @noim the challenges of fetching data and managing data seem distinct to me.You can likely transition your combine code with only moderate pain to newer AsyncStream, and replace "sink" with await or for await.Can you share more details?
       
 (DIR) Post #AWcsUA8PNLe4yaaBsW by Alexbbrown@hachyderm.io
       2023-06-12T20:19:20Z
       
       0 likes, 0 repeats
       
       @noim combine is great for what you describe, but async await is awesome at this stuff: easier to write, read and reason about, and you done need the result type at all; "throws" is all you need for error handling.
       
 (DIR) Post #AWcsmy34XGC4zh3ORU by Alexbbrown@hachyderm.io
       2023-06-12T20:22:54Z
       
       0 likes, 0 repeats
       
       @noim if you watch the new wwdc videos from 2023 you will see that in ios17 combine is no longer a load bearing component of swiftUI.That won't prevent you from using combine code you have already written however, so if your code already work you can leave or as is, or gradually migrate to the new systems.
       
 (DIR) Post #AWeNa9RO9xlCIakwng by Alexbbrown@hachyderm.io
       2023-06-13T13:42:40Z
       
       0 likes, 0 repeats
       
       @noimHere's three videos to watch.  If you have the developer app you can also read the transcripts which might work with low bandwidthdiscover observation in swiftUIhttps://developer.apple.com/wwdc23/10149Meet async / await https://developer.apple.com/wwdc21/10132Use async/await with url session https://developer.apple.com/wwdc21/10095
       
 (DIR) Post #AWhUn4GA14xl9EUSQq by Alexbbrown@hachyderm.io
       2023-06-15T01:47:28Z
       
       0 likes, 0 repeats
       
       @noim if you have some UI appear for the life of the operation, eg a progress bar, modal sheet or cancel button, attach a .task { } to it.If the view is dismissed the code in the .task will be sent a Task.cancel. It's straightforward to monitor that; if you have a for await loop doing the work it even happens automatically for most async streams you can read.  Otherwise you can call try Task.checkCancellation in the loop or after a return from other async work.https://developer.apple.com/documentation/swift/task/checkcancellation()
       
 (DIR) Post #AWhfqr9vlT1dAhaML2 by Alexbbrown@hachyderm.io
       2023-06-15T03:51:31Z
       
       0 likes, 0 repeats
       
       @noim sure, but if the button creates a state that enables a view you can use the lifetime of the view to drive the lifetime of the response.struct MyView: View {  @State var started = false  var body: some View {     if !started {       Button("start") {          started = true       }    } else {       Button("cancel") {         started = false       }       .task {          defer {             started = false          }          try await doWorkUntilCancelled()       }} }
       
 (DIR) Post #AZ9wFxFZIqp9NdexCS by Alexbbrown@hachyderm.io
       2023-08-27T14:51:20Z
       
       0 likes, 0 repeats
       
       @fuxoft @obfusk you've earned a nice fat block
       
 (DIR) Post #Ahx7nu44DNGwDLWm4O by Alexbbrown@hachyderm.io
       2024-04-10T19:23:58Z
       
       0 likes, 0 repeats
       
       @Migueldeicaza tell me what you have working
       
 (DIR) Post #Ahx7nvpxcnB1iAwXMO by Alexbbrown@hachyderm.io
       2024-04-10T20:03:55Z
       
       0 likes, 0 repeats
       
       @Migueldeicaza in terms of bringing non-project content into an out of Godot