Closed msalmanST closed 7 years ago
Hello, @msalmanST Please, can you show example of your plist file?
This is my entry of assembly in plist.
ApplicationAssemblyObjc gets loaded by the code successfully but ApplicationAssembly is creating a runtime exception at file "TyphoonAssemblyBuilder+PlistProcessor.m" line number 28
@msalmanST Ok, all clear.
Please, can you read note for TyphoonClassFromString
function? Could this be useful for you?
Class TyphoonClassFromString(NSString *className)
{
if (TyphoonIsInvalidClassName(className)) {
return Nil;
}
Class clazz = NSClassFromString(className);
if (!clazz) {
clazz = NSClassFromString([TyphoonDefaultModuleName() stringByAppendingFormat:@".%@", className]);
}
if (!clazz) {
/**
Swift issue:
When calling property_getAttributes() for a Swift class that belongs in a different
module, the module name is *NOT* returned, therefore attempting to resolve the
Swift class via name wont work:
1. Foo.BarAssembly in Foo.framework
2. App.app includes Foo.framework and references Foo.BarAssembly in AppAssembly
import Foo
class AppAssembly: TyphonAssembly {
var barAssembly: Foo.BarAssembly?
}
3. property_getAttributes() called on `barAssembly` returns @T"BarAssembly" but
should return @T"Foo.BarAssembly"
4. NSClassforString("BarAssembly") returns nil because the App.app does not define
this class
Poor workaround, not the best, but no other way around it unless Apple fixes the objc reflection of
Swift classes there is no other way:
If we are unable to find the class in the top level project iterate all dynamic
frameworks and attempt to resolve the class name by appending the module name
This is somewhat brittle as we loose the namespacing modules give us (for example,
if 2 modules define the same class then which ever appears first in the list will
be used which might not be expected). In order for this to work, developers are required
to:
- have unique names of assemblies across modules
- frameworks bundle ids much match the following format: *.{Name} where Name is
the name of the module
*/
//Those class names will never be resolved, so no reason to try
if(!className || [className isEqual:@"?"] || [className isEqual:@""]) {
return nil;
}
clazz = TyphoonClassFromFrameworkString(className);
}
return clazz;
}
Ohhh, so I have to use my module name with the swift class in oder to access it. It works man (Y) thanks for pointing that comment, I missed that :).
Another quick question, I saw that on app launch all the methods written in the assembly gets called on app launch this means all the objects define in the assembly will get created with their dependencies at the app launch time, how I can make them lazy load, so that every object gets instantiate when any part of the app ask for that object and not before.
Hi @msalmanST
All methods on the assembly called called on startup, just so that Typhoon has a blue-print for each defined object. Then, only singletons are pre-instantiated. Typhoon, along with its assembly rules is then retained as a factory for emitting objects.
Hi,
So I have a legacy application which is written in objective-c, we are now adopting swift and currently we have a mix of objc and swift code.
I want to integrate the typhoon lib so I have added it as a pod. After that I create one test assembly in swift file like below. ( I try it with and without @objc directive)
@objc public class ApplicationAssembly: TyphoonAssembly {}
I have also added the entry in the plist file as required by the instantiation of assemblies. Now at runtime I am getting the below error.
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Can't resolve assembly for name ApplicationAssembly
.Please help me.