Posts

Post marked as solved
4 Replies
1.3k Views
Hi,I've got a few questions regarding a marketplace web platform, where users interact with music studios/producers.Would like to understand how is the following use-case* considered in terms of Apple transaction fee rules?The use-case:- User can access the platform website or use ios app (same credentials and content)- User downloads ios app (it's free)- User requests a service provided by a music studio or producer- Music studio/producer creates requested work (play instruments, hire musicians, etc)- Music studio/producer provides files digitally and requests payment- User has to make payment to access the download (this is distributed to the user email address and may be of a format only compatible with certain music software)- Payment is done through Stripe and is paid in full (except Stripe fees) to the music studio/producer- User can request amends (prior or post-payment)- User can use the music studio physicallyAs far as I understand these are not subject to Apple transaction fees. But this is a bit confusing becausemusic studios deliver their goods digitally and AFAIK Apple charges 30% for any digital good. I just can'tfind a way to explain that to the users and the service providers. How's that?Would appreciate some feedback, please!
Posted
by punkbit.
Last updated
.
Post not yet marked as solved
4 Replies
981 Views
(I've posted this originally on StackOverflow and answered it myself, but I don't have enough experience with Swift and SwiftUI and would like this to be review by someone more experienced, to avoid misleading other users [https://stackoverflow.com/questions/61903284/why-isnt-a-closure-in-state-array-property-triggering-state-change])A test view has @State showTitle, title and items where the title value text is controlled by a closure assigned to a CTA show title. When the showTitle state changes, the value presented in the body Content of test view changes accordingly: Text({ self.showTitle ? "Yes, showTitle!" : "No, showTitle!" }()) While the case where the closure is a value in the array items does not change. Why isn't the closure triggering the title state? NestedView(title: $0.title()) The complete source-code:struct test: View { @State var showTitle: Bool = true @State var title: String @State var items: [Foobar] var body: some View { VStack { Group { Text("Case 1") Text({ self.showTitle ? "Yes, showTitle!" : "No, showTitle!" }()) } Group { Text("Case 2") ForEach (self.items, id: \.id) { NestedView(title: $0.title()) } } Button("show title") { print("show title cb") self.showTitle.toggle() } }.onAppear { let data = ["hello", "world", "test"] for title in data { self.items.append(Foobar(title: { self.showTitle ? title : "n/a" })) } } } } struct NestedView: View { var title: String var body: some View { Text("\(title)") } }What's expected is that "Case 2" to have a similar side-effect we have in "Case 1" that should display "n/a" on showTitle toggle. Output demo: https://i.stack.imgur.com/YJVQu.gifMy conclusion:From what I understand, the reason why the initial code does not work is related to the showTitle property that is passed to the Array and holds a copy of the value (creates a unique copy of the data). I did think @State would make it controllable and mutable, and the closure would capture and store the reference (create a shared instance). In other words, to have had a reference, instead of a copied value! Feel free to correct me, if that's not the case, but that's what it looks like based on my analysis. With that being said, I kept the initial thought process, I still want to pass a closure to the Array and have the state changes propagated, cause side-effects, accordingly to any references to it! So, I've used the same pattern but instead of relying on a primitive type for showTitleBool, created a Class that conforms to the protocol ObservableObject: since Classes are reference types. So, let's have a look and see how this worked out:import SwiftUI class MyOption: ObservableObject { @Published var option: Bool = false } struct Foobar: Identifiable { var id: UUID = UUID() var title: () -> String init (title: @escaping () -> String) { self.title = title } } struct test: View { @EnvironmentObject var showTitle: MyOption @State var title: String @State var items: [Foobar] var body: some View { VStack { Group { Text("Case 1") Text(self.showTitle.option ? "Yes, showTitle!" : "No, showTitle!") } Group { Text("Case 2") ForEach (self.items, id: \.id) { NestedView(title: $0.title()) } } Button("show title") { print("show title cb") self.showTitle.option.toggle() print("self.showTitle.option: ", self.showTitle.option) } }.onAppear { let data = ["hello", "world", "test"] for title in data { self.items.append(Foobar(title: { self.showTitle.option ? title : "n/a" })) } } } } struct NestedView: View { var title: String var body: some View { Text("\(title)") } }The result as expected: https://i.stack.imgur.com/dAHjh.gifPlease share your knowledge,Thank you!
Posted
by punkbit.
Last updated
.
Post not yet marked as solved
0 Replies
1.2k Views
I've posted this issue originally at ( https://stackoverflow.com/questions/61830571/whats-causing-swiftui-nested-view-items-jumpy-animation-after-the-initial-drawi ), where I describe an issue that I've encountered why developing a list of progress state animations for audio players.You can find the issue by following the steps:- Add player- Add player- Add player- Stop All (*the animations played well this far)- Play All (*same issue as previously documented)- Add player (*the tail player animation works fine)// SwiftUIPlayground import SwiftUI struct PlayerLoopView: View { @ObservedObject var player: MyPlayer var body: some View { ZStack { Circle() .stroke(style: StrokeStyle(lineWidth: 10.0)) .foregroundColor(Color.purple) .opacity(0.3) .overlay( Circle() .trim( from: 0, to: player.isPlaying ? 1.0 : 0.0 ) .stroke( style: StrokeStyle(lineWidth: 10.0, lineCap: .round, lineJoin: .round) ) .animation( player.isPlaying ? Animation .linear(duration: player.duration) .repeatForever(autoreverses: false) : .none ) .rotationEffect(Angle(degrees: -90)) .foregroundColor(Color.purple) ) } .frame(width: 100, height: 100) .padding() } } struct PlayersProgressView: View { @ObservedObject var engine = Engine() var body: some View { NavigationView { VStack { ForEach(self.engine.players) { player in HStack { Text("Player") PlayerLoopView(player: player) } } } .navigationBarItems(trailing: VStack { Button("Add Player") { self.engine.addPlayer() } Button("Play All") { self.engine.playAll() } Button("Stop All") { self.engine.stopAll() } }.padding() ) } } } class MyPlayer: ObservableObject, Identifiable { var id = UUID() @Published var isPlaying: Bool = false var duration: Double = 1 func play() { self.isPlaying = true } func stop() { self.isPlaying = false } } class Engine: ObservableObject { @Published var players = [MyPlayer]() func addPlayer() { let player = MyPlayer() players.append(player) DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) { player.isPlaying = true } } func stopAll() { self.players.forEach { $0.stop() } } func playAll() { self.players.forEach { $0.play() } } } struct PlayersProgressView_Previews: PreviewProvider { static var previews: some View { PlayersProgressView() } }
Posted
by punkbit.
Last updated
.
Post not yet marked as solved
1 Replies
428 Views
I want to load a local file in the playground. Started by adding it to the "resources" directory of "navigator".To make sure I get the correct full path, I did a drag and drop to the source-code and got the complete string path.This doesn't seem to be the correct way of doing it. The error I got is:Playground execution terminated: An error was thrown and was not caught:Error Domain=NSCocoaErrorDomain Code=264 "The file “click.wav” couldn’t be opened because the text encoding of its contents can’t be determined." UserInfo={NSFilePath=/foobar/click.wav}Here's the source:let url = URL(fileURLWithPath: "/foobar/click.wav")Have in mind that for brevity used `foobar` in the file path.The library I'd like to pass the variable expects a `URL`!
Posted
by punkbit.
Last updated
.
Post not yet marked as solved
4 Replies
1.2k Views
Hi,I'd like to know if there are any good patterns to follow for state management in SwiftUI?A quick google search returns me a few approaches on Redux like architecture but given the Combine framework and likes such as the ObservableObject + EnvironmentObject, which seems closer to what Context API in Reactjs represents for most cases, it might be unnecessary. Ideally, I'd like to find ways in the SwiftUI world to help me assess the app performance, which could help me find patterns or architectures to solve state management in my applications, so any tips or advice in these regards will be extremely beneficial for me to learn if you don't mind sharing! Meanwhile, I find that I can look into redrawing to identify occurrences but wonder about other approaches that might be more suitable or can provide better insight, let's look at my cavemen, not the best example and a bit of a pseudo-code: // My ObservableObject class Hunter: ObservableObject { @Published var name = "Fred Flinston" @Published var gun = "Rock" ... } // CaveView struct CaveView: View { @EnvironmentObject var hunter: Hunter var body: some View { print("[DEBUG] redraw happend!") ... } } // Main view struct HunterLand: View { // @EnvironmentObject var hunter: Hunter var body: some View { // print("[DEBUG] redraw happend!") VStack { CaveView() ... } } }The Main View represented above as HunterLand has a nested view that is subscribed to the Hunter ObservableObject instance (resolved in the sceneDelegate); The Main View has nested views and only the CaveView will be affected by any observable changes. The commented out parts is to expose that if it also subscribed the redrawing would happen twice in principle. It's my understanding that the diff algorithm for SwiftUI probably takes care of a lot of stuff for us, but would be nice to know how to verify how it performs when developing and making architecture choices to better improve the app experience or any good reads or best practices in this regard.Thank you!
Posted
by punkbit.
Last updated
.