https://kotlinlang.org logo
r

Robert Munro

10/10/2022, 12:04 PM
i have a sealed class in mu kotlin usecase but the types arent available in iOS - just wondering if there is anything i have to do to get the sealed subclasses to be generated (compiler flag or something?). The module is
domainKmm
Copy code
class LoginUseCase {
sealed class State {
    object Initial : State()
    object StartAuthorization : State()
    object AuthorizationTokenReceived : State()
    object AccessTokenReceived : State()
    object SuppliersLoading : State()
    data class SuppliersLoaded(val suppliers: List<Supplier>) : State()
    data class ConfirmSupplierChange(val chosenSupplier: Supplier, val currentSupplier: Supplier) : State()
    data class SupplierLoadError(val e: Throwable) : State()
    object NoSupplier : State()
    data class LoggedInSuccess(val isNewSupplier: Boolean) : State()
}
}
So i can use
DomainKmmLoginUseCase
and
DomainKmmLoginUseCase.State
but i cant use
DomainKmmLoginUseCase.State.Initial
I cant find any declaration of things like
Initial
or
StartAuthorization
in the generated iOS header file. is there any guidance on using sealed classes in iOS? i've seen they dont really map to swift well - but havent been able to find any usage examples.
🐛 1
stupid question?
n

novikau

10/11/2022, 10:07 AM
If
Initial
is not declared as
internal
it should be generated as
DomainKmmLoginUseCase.StateInitial
(without a dot between
State
and
Initial
) in the iOS header file. But you're right, the sealed classes are mapped to swift as regular classes, so you will loose the restricted class hierarchy of the sealed classes when you work with these classes in swift.
r

Robert Munro

10/11/2022, 11:55 AM
so i just get
DomainKmmLoginUseCase.State
with no subclasses. I get all the member `fun`s of
LoginUseCase
- so for some reason its not generating the children of the sealed
State
class. I'm on 1.6.20.
n

novikau

10/11/2022, 12:39 PM
so i just get
DomainKmmLoginUseCase.State
with no subclasses.
for
Initial
class (a subclass of
State
sealed class) you should use
DomainKmmLoginUseCase.StateInitial
. At least this is how I see it is generated in my case for the nested classes of a 3d level. I'm on 1.7.0, so maybe something has been changed in the latest updates.
r

Robert Munro

10/11/2022, 1:05 PM
yes so
DomainKmmLoginUseCase.StateInitial
doesn't get generated for me.
I updated to 1.7.20 but classes still not generating.
n

novikau

10/11/2022, 2:07 PM
You said that the outer class is called
LoginUseCase
where does
DomainKmmLoginUseCase
come from?
r

Robert Munro

10/11/2022, 2:42 PM
That is the generated classname
so in kotlin its
LoginUseCase
swift its
DomainKmmLoginUseCase
n

novikau

10/11/2022, 2:56 PM
I don't know. It looks like you have some tricky build configuration because I added a class from the snippet above to my kmm module and here is what I have in the generated header:
Copy code
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("LoginUseCase")))
@interface CSCLoginUseCase : CSCBase
- (instancetype)init __attribute__((swift_name("init()"))) __attribute__((objc_designated_initializer));
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
@end;

__attribute__((swift_name("LoginUseCase.State")))
@interface CSCLoginUseCaseState : CSCBase
@end;

__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("LoginUseCase.StateInitial")))
@interface CSCLoginUseCaseStateInitial : CSCLoginUseCaseState
+ (instancetype)alloc __attribute__((unavailable));
+ (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((unavailable));
+ (instancetype)initial __attribute__((swift_name("init()")));
@property (class, readonly, getter=shared) CSCLoginUseCaseStateInitial *shared __attribute__((swift_name("shared")));
@end;
So there is a module prefix in the generated class name, but only for Objective C. For swift there is a different name defined (without a prefix) and I can access the kotlin classes from swift code by this name.
r

Robert Munro

10/11/2022, 4:49 PM
yeah I'm not sure what i could have done to make it have differently - there are a few modules in the project - possibly something is getting messed up since its included through another module (
domainKmm
is included via
sharedKmm
- as there classes are created via Koin). I omitted the methods in the class above for brevity. This is what i get though..
Copy code
__attribute__((objc_subclassing_restricted))
__attribute__((swift_name("DomainKmmLoginUseCase")))
@interface SharedKmmDomainKmmLoginUseCase : SharedKmmBase
- (instancetype)initWithAuthStateManager:(id<SharedKmmDomainKmmIAuthStateManager>)authStateManager authChecks:(id<SharedKmmDomainKmmUserAuthorizationChecker>)authChecks jwtTokenParser:(SharedKmmDomainKmmJwtTokenParser *)jwtTokenParser userMapper:(SharedKmmDomainKmmUserMapper *)userMapper prefs:(SharedKmmDomainKmmAppPreferences *)prefs analytics:(SharedKmmDomainKmmAnalytics *)analytics supplierApiGatewayRepository:(id<SharedKmmDomainKmmSupplierApiRepository>)supplierApiGatewayRepository newLoggedInUserUseCase:(SharedKmmDomainKmmNewLoggedInUserUseCase *)newLoggedInUserUseCase networkErrorBus:(id<SharedKmmDomainKmmINetworkErrorBus>)networkErrorBus __attribute__((swift_name("init(authStateManager:authChecks:jwtTokenParser:userMapper:prefs:analytics:supplierApiGatewayRepository:newLoggedInUserUseCase:networkErrorBus:)"))) __attribute__((objc_designated_initializer));
- (SharedKmmDomainKmmLoginUseCaseState *)_getState __attribute__((swift_name("_getState()")));
possibly if i include
domainKmm
directly it might work - I guess that would be a bug tho. not sure.
OK! i moved
LoginUseCase
to the
sharedKmm
module and the sealed classes generate OK. Does this seem like a bug?
n

novikau

10/11/2022, 6:57 PM
As for me it seems like a bug. Try to look for a similar issue in the JetBrains' bug tracker or report them a bug
43 Views