The following is written as Swift dependencies
OC library, no namespace
Key points of componentization - agreement
Personally think
For example, the registration of URL routes means passing on the agreed information. As a service.
Lotusoot contains service calls, short chain registration and calls
The following focuses on service calls, short links are a little bit
Scene
project has two dependencies: A (protocol) and B (the implementer of the protocol, providing services)
project reference A, know the protocol information
project does not reference B, project knows nothing about B
In this way, the project removes B and compiles faster
B depends on A, references A, implements A's protocol and provides services
Calling the service
// Get the key let lotus = s() // kv obtains an example of providing services let accountModule: AccountLotus = (lotus: lotus) as! AccountLotus // Call service (username: "zhoulingyu", password: "wow") { (error) in print(error ?? "1234") }
Step 3: Calling the service is very simple
Step 2 is very exciting, making full use of the static features of Swift compile time
The protocol method is determined at compile time
Several parameters are required, and what type of parameters can generally be used explicitly
Don't see a parameter dictionary, ah, what's this
// Step 2. Take from below// Key-value pair, value is the object that provides the servicevar lotusootMap: Dictionary = Dictionary<String, Any>()
Step 1: Get the key
Here is the protocol name as key
// Use generics to describe// Agreement, transfer the agreement namepublic extension String { init<Subject>(_ instance: Subject) { (describing: instance) } } /// Quickly get strings with Subjectpublic func s<Subject>(_ instance: Subject) -> String { return String(instance) }
Register Service
1. Project does not have import B (providing services). How to use the function of B?
public static func registerAll(serviceMap: Dictionary<String, String>) { for (lotus, lotusootName) in serviceMap { // lotus, protocol name // lotusootName, package name. Class name let classStringName = lotusootName // Reflect, produce class // The class that provides services must be a subclass of NSObject and has an init method (this is a convention) let classType = NSClassFromString(classStringName) as? if let type = classType { // Generate the corresponding instance and force it to comply with the agreement, let lotusoot = () register(lotusoot: lotusoot, lotusName: lotus) } } }
2. Here we use python script to register. The information is obtained during compilation. Protocol name: package name. Class name
By agreement, mark
// @NameSpace(ZLYAccountModule) // @Lotusoot(AccountLotusoot) // @Lotus(AccountLotus) class AccountLotusoot: NSObject, AccountLotus {}
Python scripts find out marks, integrate, and put them inplist
In the file
1, script entry
lotusootSuffix = 'Lotusoot' length = len() if length != 3 and length != 4: print 'parameter error' os._exit(1) if length == 4: lotusootSuffix = [3] lotusootFiles = findLotusoots(scanPath, lotusootSuffix + '.swift') else: // Go here lotusootFiles = findAmbiguityLotusoots(scanPath)
Go through every swift file
def findAmbiguityLotusoots(path): list = [] for root, subFolders, files in (path): # Ignore 'Target Support Files' and '' // No processing is required if 'Target Support Files' in subFolders: ('Target Support Files') // No processing is required, if '' in subFolders: ('') // Every file for f in files: // Every Swift file if ('.swift'): // Get the tag configuration tup = getLotusootConfig((root, f)) if tup[0] and tup[1] and tup[2]: // All three are satisfied, and the file path is added (f) return list
Scan every line,
Get the configuration, the package name and namespace you see above
@NameSpace(ZLYAccountModule)
The class name seen above
@Lotusoot(AccountLotusoot)
The key (protocol name) seen above
@Lotus(AccountLotus)
def getLotusootConfig(file): lotus = '' lotusoot = '' namespace = '' // Flip through every line of the file for line in open(file): // The key seen above if getLotus(line): lotus = getLotus(line) // The class name seen above if getLotusoot(line): lotusoot = getLotusoot(line) // The package name, namespace seen above if getNameSpace(line): namespace = getNameSpace(line) return (lotus, lotusoot, namespace)
... There are many more,
Logic is to get the configuration and write a plist
When running, start
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [ : Any]? = nil) -> Bool { () return true }
Registration means reading the plist just written as a dictionary of [Protocol name: package name.class name],
@objc public static func registerAll() { let lotusPlistPath = (forResource: "Lotusoot", ofType: "plist") if let lotusPlistPath = lotusPlistPath { let map = NSDictionary(contentsOfFile: lotusPlistPath) registerAll(serviceMap: map as! Dictionary<String, String>) } }
Echoing the above
Dynamic ideas
Enter the dynamic idea and register KV dynamically (Protocol name: Service library name. Class name)
There is an impression above, just know the scene
Writing a long text,
How to reflect my 10 years of work experience?
No, insist on getting the word count
1. Project gets the key (protocol name), yes
2. project gets all dependency information
With MachO you can
3. project gets the name of the service class
Make sure module B's class name = key (protocol) + Cls
MachO
Get the names of all dependency libraries, each + "." + key (Protocol) + Cls=MachO
Get the names of all dependency libraries, each + "." + module B's class name
Then, see if it can be instantiated.
Can be instantiated, just OK
After trying it, it cannot be instantiated, so it will be an error
Probably depend on B, not added
It may depend on B's class name, and it was written incorrectly
project gets the name of the service class, elegant
Make sure module B's class name = key (protocol) + Cls,
Hard code is not good
Rely on A (to put protocol), add a protocol
public protocol Maid{ var name: String{ get } }
In module B, there must be a class called key (protocol) + C
This category, comply withMaid
protocol.
Through the protocol attribute, return the name of the service class in B
class AccountLotusC: NSObject, Maid{ var name: String{ return String(reflecting: ) } }
This process is more consistent with the design of the modular utilization protocol above.
The agreement is to implement the service module of the agreement.
There must be a key + C class
Name of the service class
Hard coded, relatively minor
Code implementation
1. MachO obtains namespace
import MachO lazy var moduleNames: [String] = { () -> [String] in // Find the project name and remove it later let mainNameTmp = NSStringFromClass() guard let mainName = (separatedBy: ".").first else{ fatalError("emptyMainProject") } var result = [String]() let cnt = _dyld_image_count() // Process all packages, system, and user's for i in 0..<cnt{ if let tmp = _dyld_get_image_name(i){ let name = String(validatingUTF8: tmp) // System, don't worry if let candidate = name, ("/Users"){ if let tmp = (separatedBy: "/").last{ // Remove project if tmp != mainName{ // Get user dependencies (tmp) } } } } } return result }()
The above, the emulator is OK, I haven't tried it in real machine (no development certificate at hand)
2. Verification of package name + class name
@objc public static func lotusoot(lotus: String) -> Any? { // It has been cached if let val = [lotus]{ return val } else{ var i = 0 let names = let cnt = // traversal, user package while i < cnt{ // As agreed, try to create assistants let classType = NSClassFromString(names[i] + "." + lotus + "C") as? if let type = classType { // Instantiation, helper class let assist = () if let maid = assist as? Maid{ // Get the name of the service class that module B let classType = NSClassFromString() as? if let type = classType { // Instantiate the service class of module B let lotusoot = () register(lotusoot: lotusoot, lotusName: lotus) } // The default is a module and a service class. // Exclude user classes that have been used (at: i) break } } i+=1 } if let val = [lotus]{ return val } else{ fatalError("name Module of" + lotus) } } }
GitHub repo
This is the end of this article about the dynamic ideas of the application of iOS Lotusoot modular tools. For more related iOS Lotusoot modular content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!