-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
172 changed files
with
13,986 additions
and
3 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
<plist version="1.0"> | ||
<dict> | ||
<key>IDEDidComputeMac32BitWarning</key> | ||
<true/> | ||
</dict> | ||
</plist> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
Pod::Spec.new do |spec| | ||
|
||
spec.name = 'CarbonCore' | ||
spec.version = '1.2.2' | ||
spec.license = { :type => 'MIT', :file => 'LICENSE' } | ||
spec.summary = 'Swift dependency injection framework for iOS' | ||
spec.homepage = 'https://github.com/baidu/CarbonGraph' | ||
spec.authors = { 'Baidu' => '[email protected]' } | ||
spec.source = { :git => 'https://github.com/baidu/CarbonGraph', :tag => spec.version } | ||
|
||
spec.swift_versions = ['5.2', '5.3', '5.4', '5.5'] | ||
spec.ios.deployment_target = '9.0' | ||
|
||
spec.source_files = 'CarbonCore/CarbonCore/**/*.swift' | ||
|
||
end |
Large diffs are not rendered by default.
Oops, something went wrong.
7 changes: 7 additions & 0 deletions
7
CarbonCore/CarbonCore.xcodeproj/project.xcworkspace/contents.xcworkspacedata
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
8 changes: 8 additions & 0 deletions
8
CarbonCore/CarbonCore.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
<plist version="1.0"> | ||
<dict> | ||
<key>IDEDidComputeMac32BitWarning</key> | ||
<true/> | ||
</dict> | ||
</plist> |
78 changes: 78 additions & 0 deletions
78
CarbonCore/CarbonCore.xcodeproj/xcshareddata/xcschemes/CarbonCore.xcscheme
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<Scheme | ||
LastUpgradeVersion = "1300" | ||
version = "1.3"> | ||
<BuildAction | ||
parallelizeBuildables = "YES" | ||
buildImplicitDependencies = "YES"> | ||
<BuildActionEntries> | ||
<BuildActionEntry | ||
buildForTesting = "YES" | ||
buildForRunning = "YES" | ||
buildForProfiling = "YES" | ||
buildForArchiving = "YES" | ||
buildForAnalyzing = "YES"> | ||
<BuildableReference | ||
BuildableIdentifier = "primary" | ||
BlueprintIdentifier = "A3E70366271EC18A00D1CAE5" | ||
BuildableName = "CarbonCore.framework" | ||
BlueprintName = "CarbonCore" | ||
ReferencedContainer = "container:CarbonCore.xcodeproj"> | ||
</BuildableReference> | ||
</BuildActionEntry> | ||
</BuildActionEntries> | ||
</BuildAction> | ||
<TestAction | ||
buildConfiguration = "Debug" | ||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" | ||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" | ||
shouldUseLaunchSchemeArgsEnv = "YES" | ||
codeCoverageEnabled = "YES"> | ||
<Testables> | ||
<TestableReference | ||
skipped = "NO"> | ||
<BuildableReference | ||
BuildableIdentifier = "primary" | ||
BlueprintIdentifier = "A3E70370271EC18B00D1CAE5" | ||
BuildableName = "CarbonCoreTests.xctest" | ||
BlueprintName = "CarbonCoreTests" | ||
ReferencedContainer = "container:CarbonCore.xcodeproj"> | ||
</BuildableReference> | ||
</TestableReference> | ||
</Testables> | ||
</TestAction> | ||
<LaunchAction | ||
buildConfiguration = "Debug" | ||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" | ||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" | ||
launchStyle = "0" | ||
useCustomWorkingDirectory = "NO" | ||
ignoresPersistentStateOnLaunch = "NO" | ||
debugDocumentVersioning = "YES" | ||
debugServiceExtension = "internal" | ||
allowLocationSimulation = "YES"> | ||
</LaunchAction> | ||
<ProfileAction | ||
buildConfiguration = "Release" | ||
shouldUseLaunchSchemeArgsEnv = "YES" | ||
savedToolIdentifier = "" | ||
useCustomWorkingDirectory = "NO" | ||
debugDocumentVersioning = "YES"> | ||
<MacroExpansion> | ||
<BuildableReference | ||
BuildableIdentifier = "primary" | ||
BlueprintIdentifier = "A3E70366271EC18A00D1CAE5" | ||
BuildableName = "CarbonCore.framework" | ||
BlueprintName = "CarbonCore" | ||
ReferencedContainer = "container:CarbonCore.xcodeproj"> | ||
</BuildableReference> | ||
</MacroExpansion> | ||
</ProfileAction> | ||
<AnalyzeAction | ||
buildConfiguration = "Debug"> | ||
</AnalyzeAction> | ||
<ArchiveAction | ||
buildConfiguration = "Release" | ||
revealArchiveInOrganizer = "YES"> | ||
</ArchiveAction> | ||
</Scheme> |
29 changes: 29 additions & 0 deletions
29
CarbonCore/CarbonCore/ApplicationContext/Application.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
// | ||
// Application.swift | ||
// CarbonCore | ||
// | ||
// Copyright (c) Baidu Inc. All rights reserved. | ||
// | ||
// This source code is licensed under the MIT license. | ||
// See LICENSE file in the project root for license information. | ||
// | ||
|
||
import UIKit | ||
|
||
/// Use Application instead of UIApplication in the main function to automatically create an application context | ||
/// with module scanning | ||
open class Application: UIApplication { | ||
|
||
/// Create a default application context | ||
/// - Returns: An application context with module scanning. | ||
open override class func makeApplicationContext() -> ApplicationContext { | ||
ApplicationContext(moduleScan: true) | ||
} | ||
|
||
/// Create application and trigger the creation of the context | ||
override public init() { | ||
super.init() | ||
_ = context | ||
} | ||
|
||
} |
223 changes: 223 additions & 0 deletions
223
CarbonCore/CarbonCore/ApplicationContext/ApplicationContext.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,223 @@ | ||
// | ||
// ApplicationContext.swift | ||
// CarbonCore | ||
// | ||
// Copyright (c) Baidu Inc. All rights reserved. | ||
// | ||
// This source code is licensed under the MIT license. | ||
// See LICENSE file in the project root for license information. | ||
// | ||
|
||
import UIKit | ||
|
||
/// Application context with configuration and module management | ||
@objc(CBNApplicationContext) public class ApplicationContext: ObjectContext { | ||
|
||
private var modules: [Module] = [] | ||
|
||
/// Classes collected according to strategy classes | ||
@objc public let scannedClasses: [AnyClass] | ||
|
||
/// Created by default strategy | ||
/// | ||
/// When there is an ApplicationContext with moduleScan enabled in the project, Configuration classes | ||
/// and ModuleDelegate classes inherited from the ``ScannableObject`` will be automatically | ||
/// registered. | ||
/// | ||
/// - SeeAlso: ``ScannableConfiguration``, ``ScannableModuleConfiguration`` | ||
/// | ||
/// - Parameters: | ||
/// - defaultScope: The default life cycle of objects in the context. | ||
/// - moduleScan: Whether to scan configuration classes according to the default | ||
/// ``ScannableObjectStrategy``. | ||
@objc public convenience init(defaultScope: ObjectScope = .default, | ||
moduleScan: Bool = false) { | ||
if moduleScan == true { | ||
self.init(defaultScope: defaultScope, | ||
strategies: [ScannableObjectStrategy()]) | ||
} else { | ||
self.init(defaultScope: defaultScope, strategies: []) | ||
} | ||
} | ||
|
||
/// Created by custom strategies | ||
/// - Parameter strategies: Scan configuration classes according to custom strategies. | ||
@objc public init(defaultScope: ObjectScope = .default, | ||
strategies: [ScannableStrategy]) { | ||
if !strategies.isEmpty { | ||
Scanner.scan(strategies: strategies) | ||
scannedClasses = strategies.flatMap {$0.types} | ||
} else { | ||
scannedClasses = [] | ||
} | ||
|
||
super.init(defaultScope: defaultScope) | ||
|
||
for anyClass in scannedClasses { | ||
// Directly using '$0 as? Configuration.Type' to determine | ||
// whether the class defined by ObjC implements the | ||
// configuration protocol will cause a crash on a | ||
// specific model. | ||
// | ||
// Known models: | ||
// * iPhone XR, MT122CH/A, A2108; iOS 15.0, 19A5297e | ||
let className = NSStringFromClass(anyClass) | ||
guard let safeClass = NSClassFromString(className) else { continue } | ||
|
||
if let delegateClass = safeClass as? ModuleDelegate.Type { | ||
register(delegate: delegateClass) | ||
} else if let configClass = safeClass as? Configuration.Type { | ||
register(configuration: configClass) | ||
} | ||
} | ||
registerNotifications() | ||
} | ||
|
||
/// Register module delegate | ||
/// | ||
/// If the delegate also implements the ``Configuration`` protocol, then the | ||
/// ``ObjectContext/register(configuration:)`` will also be called. | ||
/// | ||
/// - Note: It's not thread-safe, do not use it in a multi-threaded environment. | ||
/// | ||
/// - Parameter delegate: Class conforming to the ``ModuleDelegate`` protocol | ||
/// - Returns: Registered module | ||
@discardableResult | ||
@objc public func register(delegate: ModuleDelegate.Type) -> Module { | ||
if let configuration = delegate as? Configuration.Type { | ||
register(configuration: configuration) | ||
} | ||
let launchOptions = delegate.launchOptions?() | ||
let moduleLaunchOptions = ModuleLaunchOptions(delegateClass: delegate, | ||
items: launchOptions) | ||
let moduleClass = moduleLaunchOptions.moduleClass | ||
let module = moduleClass.init(launchOptions: moduleLaunchOptions) | ||
let index = modules.firstIndex(where: { | ||
$0.comparePriority(to: module) == .orderedDescending | ||
}) ?? modules.endIndex | ||
modules.insert(module, at: index) | ||
return module | ||
} | ||
|
||
/// Batch registration of ``ModuleDelegate`` | ||
/// | ||
/// Call the ``register(delegate:)`` for each ModuleDelegate type. | ||
/// | ||
/// - Note: It's not thread-safe, do not use it in a multi-threaded environment. | ||
/// - Parameter delegates: Classes conforming to the ModuleDelegate protocol | ||
/// - Returns: Registered ordered modules | ||
@discardableResult | ||
@objc public func register(delegates: [ModuleDelegate.Type]) -> [Module] { | ||
delegates.map { delegate in | ||
register(delegate: delegate) | ||
}.sorted { $0.comparePriority(to: $1) == .orderedDescending } | ||
} | ||
|
||
/// Load module | ||
/// | ||
/// Create the modue's delegate if not and call the ``ModuleDelegate/moduleDidFinishLaunching(_:)``. | ||
/// | ||
/// - Parameter module_: Module to be loaded | ||
/// - Returns: Whether the load is successful | ||
@discardableResult | ||
@objc public func load(module: Module) -> Bool { | ||
if module.delegate == nil { | ||
module.delegate = module.launchOptions.delegateClass.init() | ||
module.delegate?.moduleDidFinishLaunching?(module) | ||
return true | ||
} | ||
return false | ||
} | ||
|
||
/// Batch registration and loading ``ModuleDelegate`` | ||
/// | ||
/// Call the ``register(delegate:)`` and ``load(module:)`` for each | ||
/// ModuleDelegate type. | ||
/// | ||
/// - Note: It's not thread-safe, do not use it in a multi-threaded environment. | ||
/// - Parameter delegates: Classes conforming to the ModuleDelegate protocol | ||
@objc public func registerAndLoad(delegates: [ModuleDelegate.Type]) { | ||
for module in register(delegates: delegates) { | ||
load(module: module) | ||
} | ||
} | ||
|
||
private var launchOptions: [UIApplication.LaunchOptionsKey: Any]? | ||
private func registerNotifications() { | ||
NotificationCenter.default.addObserver( | ||
forName: UIApplication.didEnterBackgroundNotification, | ||
object: nil, | ||
queue: .main | ||
) { notification in | ||
for module in self.modules { | ||
module.delegate?.applicationDidEnterBackground?(notification.object as? UIApplication ?? UIApplication.shared) | ||
} | ||
} | ||
NotificationCenter.default.addObserver( | ||
forName: UIApplication.willEnterForegroundNotification, | ||
object: nil, | ||
queue: .main | ||
) { notification in | ||
for module in self.modules { | ||
module.delegate?.applicationWillEnterForeground?(notification.object as? UIApplication ?? UIApplication.shared) | ||
} | ||
} | ||
NotificationCenter.default.addObserver( | ||
forName: UIApplication.didFinishLaunchingNotification, | ||
object: nil, | ||
queue: .main | ||
) { notification in | ||
self.launchOptions = notification.userInfo as? [UIApplication.LaunchOptionsKey: Any] | ||
for module in self.modules { | ||
if module.launchOptions.lazyLoad == false { | ||
self.load(module: module) | ||
} | ||
} | ||
} | ||
NotificationCenter.default.addObserver( | ||
forName: UIApplication.didBecomeActiveNotification, | ||
object: nil, | ||
queue: .main | ||
) { notification in | ||
for module in self.modules { | ||
module.delegate?.applicationDidBecomeActive?(notification.object as? UIApplication ?? UIApplication.shared) | ||
} | ||
} | ||
NotificationCenter.default.addObserver( | ||
forName: UIApplication.willResignActiveNotification, | ||
object: nil, | ||
queue: .main | ||
) { notification in | ||
for module in self.modules { | ||
module.delegate?.applicationWillResignActive?(notification.object as? UIApplication ?? UIApplication.shared) | ||
} | ||
} | ||
NotificationCenter.default.addObserver( | ||
forName: UIApplication.didReceiveMemoryWarningNotification, | ||
object: nil, | ||
queue: .main | ||
) { notification in | ||
for module in self.modules { | ||
module.delegate?.moduleDidReceiveMemoryWarning?(module) | ||
} | ||
} | ||
NotificationCenter.default.addObserver( | ||
forName: UIApplication.willTerminateNotification, | ||
object: nil, | ||
queue: .main | ||
) { notification in | ||
for module in self.modules { | ||
module.delegate?.moduleWillTerminate?(module) | ||
} | ||
} | ||
NotificationCenter.default.addObserver( | ||
forName: UIApplication.significantTimeChangeNotification, | ||
object: nil, | ||
queue: .main | ||
) { notification in | ||
for module in self.modules { | ||
module.delegate?.applicationSignificantTimeChange?(notification.object as? UIApplication ?? UIApplication.shared) | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.