Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UIStateKs not synchronized with UIState class #97

Open
aleksey-ho opened this issue Jul 3, 2024 · 4 comments
Open

UIStateKs not synchronized with UIState class #97

aleksey-ho opened this issue Jul 3, 2024 · 4 comments

Comments

@aleksey-ho
Copy link

I have this code that works in debug environment, but crashes in testflight.

    private val _purchaseResult = MutableStateFlow<UIState<UserPremium>>(UIState.Empty)
    val purchaseResult = _purchaseResult.cStateFlow()

in BasePurchaiseScreen.swift:

struct BasePurchaiseScreen<Content> : View where Content : View {
  @StateObject var vm = PurchaseVM()
...
extension PurchaseVM {
  var purchaseResultBind: UIStateKs<UserPremium> {
    get {
      return self.state(
        \.purchaseResult,
         equals: { $0 === $1 },
         mapper: { UIStateKs($0) }
      )
    }
  }
}

It did work, but somehow it started crashing when I call vm.purchaseResultBind with error:

Crashed: com.apple.main-thread
EXC_BREAKPOINT 0x00000001a0ab58c0
0 libswiftCore.dylib 0x398c0 assertionFailure(:_:file:line🎏) + 264
1 myapp 0x7c850 MPLPurchaseVM.purchaseResultBind.getter + 80 (BasePurchaiseScreen.swift:80)
2 myapp 0x7bb48 closure #1 in BasePurchaiseScreen.body.getter + 42 (BasePurchaiseScreen.swift:42)
3 SwiftUI 0x181e58 OUTLINED_FUNCTION_1147 + 1244
4 myapp 0x7b35c BasePurchaiseScreen.body.getter + 53 (BasePurchaiseScreen.swift:53)
5 myapp 0x7cad8 protocol witness for View.body.getter in conformance BasePurchaiseScreen + 4366256856 (:4366256856)
6 SwiftUI 0x202528 dynamic_cast_existential_0_superclass_conditional + 24428
7 SwiftUI 0x24d738 -[UIScrollView(SwiftUI) _swiftui_adjustsContentInsetWhenScrollDisabled] + 31980
8 SwiftUI 0x24b3bc -[UIScrollView(SwiftUI) _swiftui_adjustsContentInsetWhenScrollDisabled] + 22896
9 SwiftUI 0x1fdb30 dynamic_cast_existential_0_superclass_conditional + 5492
10 AttributeGraph 0x9010 AG::Graph::UpdateStack::update() + 512
11 AttributeGraph 0x8bfc AG::Graph::update_attribute(AG::data::ptrAG::Node, unsigned int) + 424
12 AttributeGraph 0x2cc0 AG::Graph::input_value_ref_slow(AG::data::ptrAG::Node, AG::AttributeID, unsigned int, unsigned int, AGSwiftMetadata const*, unsigned char&, long) + 720
....

I also found "MultiPlatformLibrarySwift/myapp_shared.swift:37: Fatal error: UIStateKs not synchronized with UIState class" message in logs from generated UIStateKs.

Any idea to fix this crash?

@Alex009
Copy link
Member

Alex009 commented Jul 3, 2024

your generated swift code outdated. in kotlin source you have some new cases in sealed, but in swift code this cases not used yet

@aleksey-ho
Copy link
Author

@Alex009, Hi, Thank you for quick reply! Here's my sealed class UIState and UserPremium used in MutableStateFlow<UIState>(UIState.Empty)

sealed class UIState<out T> {
    object Loading : UIState<Nothing>()
    object Empty : UIState<Nothing>()
    data class Data<T>(val value: T) : UIState<T>()
    data class Error(val throwable: Throwable) : UIState<Nothing>()
}

data class UserPremium(val isActive: Boolean, val state: SubscriptionState)

enum class SubscriptionState {
    AVAILABLE, BILLING_ISSUE, CANCELLED, ERROR
}

and generated UIStateKs:

public enum UIStateKs<T : AnyObject> {

  case data(UIStateData<T>)
  case empty
  case error(UIStateError)
  case loading

  public var sealed: UIState<T> {
    switch self {
    case .data(let obj):
      return obj as MultiPlatformLibrary.UIState<T>
    case .empty:
      return MultiPlatformLibrary.UIStateEmpty() as! MultiPlatformLibrary.UIState<T>
    case .error(let obj):
      return obj as! MultiPlatformLibrary.UIState<T>
    case .loading:
      return MultiPlatformLibrary.UIStateLoading() as! MultiPlatformLibrary.UIState<T>
    }
  }

  public init(_ obj: UIState<T>) {
    if let obj = obj as? MultiPlatformLibrary.UIStateData<T> {
      self = .data(obj)
    } else if obj is MultiPlatformLibrary.UIStateEmpty {
      self = .empty
    } else if let obj = obj as? MultiPlatformLibrary.UIStateError {
      self = .error(obj)
    } else if obj is MultiPlatformLibrary.UIStateLoading {
      self = .loading
    } else {
      fatalError("UIStateKs not synchronized with UIState class")
    }
  }

}

is there anything I need to change? I's not clear for me why is it working on simulator but not in festflight build

@Alex009
Copy link
Member

Alex009 commented Jul 3, 2024

strange. what value you have in UIState<T> when fatalError throws?

@aleksey-ho
Copy link
Author

Unfortunately, I can't get the value in debug environment. It crashes only in testflight build
Снимок экрана 2024-07-03 в 11 33 47

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants