Commit 703cc9e0 ilCode

Alamofire、R.swift、CocoaLumberjack

1 个父辈 97db6cee
正在显示 87 个修改的文件 包含 4749 行增加212 行删除
......@@ -7,23 +7,91 @@
objects = {
/* Begin PBXBuildFile section */
42F3CE39682BAB273520A375 /* Pods_AoleiSports.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F63DEFD57EAA7FD3A430F57E /* Pods_AoleiSports.framework */; };
5E9A19EC2C0EAC0200321AC5 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E9A19EB2C0EAC0200321AC5 /* AppDelegate.swift */; };
5E9A19EE2C0EAC0200321AC5 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E9A19ED2C0EAC0200321AC5 /* SceneDelegate.swift */; };
5E9A19F02C0EAC0200321AC5 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E9A19EF2C0EAC0200321AC5 /* ViewController.swift */; };
5E9A19F32C0EAC0200321AC5 /* Base in Resources */ = {isa = PBXBuildFile; fileRef = 5E9A19F22C0EAC0200321AC5 /* Base */; };
5E9A19F52C0EAC0300321AC5 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5E9A19F42C0EAC0300321AC5 /* Assets.xcassets */; };
5E9A19F82C0EAC0300321AC5 /* Base in Resources */ = {isa = PBXBuildFile; fileRef = 5E9A19F72C0EAC0300321AC5 /* Base */; };
5E9A1A052C0EAF7600321AC5 /* goal.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 5E9A19FF2C0EAF7600321AC5 /* goal.mp3 */; };
5E9A1A062C0EAF7600321AC5 /* launch_bg.png in Resources */ = {isa = PBXBuildFile; fileRef = 5E9A1A002C0EAF7600321AC5 /* launch_bg.png */; };
5E9A1A072C0EAF7600321AC5 /* launch_foot.png in Resources */ = {isa = PBXBuildFile; fileRef = 5E9A1A012C0EAF7600321AC5 /* launch_foot.png */; };
5E9A1A082C0EAF7600321AC5 /* red.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 5E9A1A022C0EAF7600321AC5 /* red.mp3 */; };
5E9A1A092C0EAF7600321AC5 /* yellow.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 5E9A1A032C0EAF7600321AC5 /* yellow.mp3 */; };
5E9A1A112C0EB74300321AC5 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5E9A19F62C0EAC0300321AC5 /* LaunchScreen.storyboard */; };
5E9A1A262C0EF51600321AC5 /* Bundle+GKExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E9A1A132C0EF51600321AC5 /* Bundle+GKExtension.swift */; };
5E9A1A272C0EF51600321AC5 /* GKBaseAnimatedTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E9A1A142C0EF51600321AC5 /* GKBaseAnimatedTransition.swift */; };
5E9A1A282C0EF51600321AC5 /* GKNavigationBarConfigure.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E9A1A152C0EF51600321AC5 /* GKNavigationBarConfigure.swift */; };
5E9A1A292C0EF51600321AC5 /* GKNavigationBarDefine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E9A1A162C0EF51600321AC5 /* GKNavigationBarDefine.swift */; };
5E9A1A2A2C0EF51600321AC5 /* GKNavigationBarSwift.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 5E9A1A172C0EF51600321AC5 /* GKNavigationBarSwift.bundle */; };
5E9A1A2B2C0EF51600321AC5 /* GKNavigationBarSwift.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E9A1A192C0EF51600321AC5 /* GKNavigationBarSwift.swift */; };
5E9A1A2C2C0EF51600321AC5 /* GKNavigationInteractiveTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E9A1A1A2C0EF51600321AC5 /* GKNavigationInteractiveTransition.swift */; };
5E9A1A2D2C0EF51600321AC5 /* GKPopAnimatedTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E9A1A1B2C0EF51600321AC5 /* GKPopAnimatedTransition.swift */; };
5E9A1A2E2C0EF51600321AC5 /* GKPushAnimatedTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E9A1A1C2C0EF51600321AC5 /* GKPushAnimatedTransition.swift */; };
5E9A1A2F2C0EF51600321AC5 /* UIBarButtonItem+GKExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E9A1A1D2C0EF51600321AC5 /* UIBarButtonItem+GKExtension.swift */; };
5E9A1A302C0EF51600321AC5 /* UIImage+GKExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E9A1A1E2C0EF51600321AC5 /* UIImage+GKExtension.swift */; };
5E9A1A312C0EF51600321AC5 /* UINavigationController+GKExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E9A1A1F2C0EF51600321AC5 /* UINavigationController+GKExtension.swift */; };
5E9A1A322C0EF51600321AC5 /* UINavigationController+GKGesture.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E9A1A202C0EF51600321AC5 /* UINavigationController+GKGesture.swift */; };
5E9A1A332C0EF51600321AC5 /* UINavigationItem+GKExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E9A1A212C0EF51600321AC5 /* UINavigationItem+GKExtension.swift */; };
5E9A1A342C0EF51600321AC5 /* UIScrollView+GKExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E9A1A222C0EF51600321AC5 /* UIScrollView+GKExtension.swift */; };
5E9A1A352C0EF51600321AC5 /* UIViewController+GKExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E9A1A232C0EF51600321AC5 /* UIViewController+GKExtension.swift */; };
5E9A1A362C0EF51600321AC5 /* UIViewController+GKGesture.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E9A1A242C0EF51600321AC5 /* UIViewController+GKGesture.swift */; };
5E9A1A392C0EFF4000321AC5 /* UIWindow+Ext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E9A1A382C0EFF4000321AC5 /* UIWindow+Ext.swift */; };
5E9A1A3C2C0F00AD00321AC5 /* ImportTools.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E9A1A3B2C0F00AD00321AC5 /* ImportTools.swift */; };
5E9A1A3E2C0F043100321AC5 /* RootController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E9A1A3D2C0F043100321AC5 /* RootController.swift */; };
5E9A1A402C0F04CC00321AC5 /* HomeController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E9A1A3F2C0F04CC00321AC5 /* HomeController.swift */; };
5E9A1A422C0F04DB00321AC5 /* ProfileController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E9A1A412C0F04DB00321AC5 /* ProfileController.swift */; };
5E9A1A482C0F0DC400321AC5 /* AsBaseController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E9A1A472C0F0DC400321AC5 /* AsBaseController.swift */; };
5E9A1A4A2C0F13BF00321AC5 /* UIColor+Ext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E9A1A492C0F13BF00321AC5 /* UIColor+Ext.swift */; };
5E9A1A4C2C0F144200321AC5 /* ColorTools.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E9A1A4B2C0F144200321AC5 /* ColorTools.swift */; };
5E9A1A4E2C0F1A2E00321AC5 /* FontTools.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E9A1A4D2C0F1A2E00321AC5 /* FontTools.swift */; };
5E9A1A502C0F1F5200321AC5 /* R.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E9A1A4F2C0F1F5200321AC5 /* R.generated.swift */; };
5E9A1A522C0F205A00321AC5 /* LeagueController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E9A1A512C0F205A00321AC5 /* LeagueController.swift */; };
5EA670622C104D2800CEEA01 /* LoggerTools.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5EA670612C104D2800CEEA01 /* LoggerTools.swift */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
0F08FB0AC554BD156228E35A /* Pods-AoleiSports.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AoleiSports.debug.xcconfig"; path = "Target Support Files/Pods-AoleiSports/Pods-AoleiSports.debug.xcconfig"; sourceTree = "<group>"; };
5E9A19E82C0EAC0200321AC5 /* AoleiSports.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AoleiSports.app; sourceTree = BUILT_PRODUCTS_DIR; };
5E9A19EB2C0EAC0200321AC5 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
5E9A19ED2C0EAC0200321AC5 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
5E9A19EF2C0EAC0200321AC5 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
5E9A19F22C0EAC0200321AC5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
5E9A19F42C0EAC0300321AC5 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
5E9A19F72C0EAC0300321AC5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
5E9A19F92C0EAC0300321AC5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
5E9A19FF2C0EAF7600321AC5 /* goal.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = goal.mp3; sourceTree = "<group>"; };
5E9A1A002C0EAF7600321AC5 /* launch_bg.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = launch_bg.png; sourceTree = "<group>"; };
5E9A1A012C0EAF7600321AC5 /* launch_foot.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = launch_foot.png; sourceTree = "<group>"; };
5E9A1A022C0EAF7600321AC5 /* red.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = red.mp3; sourceTree = "<group>"; };
5E9A1A032C0EAF7600321AC5 /* yellow.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = yellow.mp3; sourceTree = "<group>"; };
5E9A1A0F2C0EB68800321AC5 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/LaunchScreen.strings; sourceTree = "<group>"; };
5E9A1A132C0EF51600321AC5 /* Bundle+GKExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Bundle+GKExtension.swift"; sourceTree = "<group>"; };
5E9A1A142C0EF51600321AC5 /* GKBaseAnimatedTransition.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GKBaseAnimatedTransition.swift; sourceTree = "<group>"; };
5E9A1A152C0EF51600321AC5 /* GKNavigationBarConfigure.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GKNavigationBarConfigure.swift; sourceTree = "<group>"; };
5E9A1A162C0EF51600321AC5 /* GKNavigationBarDefine.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GKNavigationBarDefine.swift; sourceTree = "<group>"; };
5E9A1A172C0EF51600321AC5 /* GKNavigationBarSwift.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = GKNavigationBarSwift.bundle; sourceTree = "<group>"; };
5E9A1A182C0EF51600321AC5 /* GKNavigationBarSwift.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GKNavigationBarSwift.h; sourceTree = "<group>"; };
5E9A1A192C0EF51600321AC5 /* GKNavigationBarSwift.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GKNavigationBarSwift.swift; sourceTree = "<group>"; };
5E9A1A1A2C0EF51600321AC5 /* GKNavigationInteractiveTransition.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GKNavigationInteractiveTransition.swift; sourceTree = "<group>"; };
5E9A1A1B2C0EF51600321AC5 /* GKPopAnimatedTransition.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GKPopAnimatedTransition.swift; sourceTree = "<group>"; };
5E9A1A1C2C0EF51600321AC5 /* GKPushAnimatedTransition.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GKPushAnimatedTransition.swift; sourceTree = "<group>"; };
5E9A1A1D2C0EF51600321AC5 /* UIBarButtonItem+GKExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIBarButtonItem+GKExtension.swift"; sourceTree = "<group>"; };
5E9A1A1E2C0EF51600321AC5 /* UIImage+GKExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImage+GKExtension.swift"; sourceTree = "<group>"; };
5E9A1A1F2C0EF51600321AC5 /* UINavigationController+GKExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UINavigationController+GKExtension.swift"; sourceTree = "<group>"; };
5E9A1A202C0EF51600321AC5 /* UINavigationController+GKGesture.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UINavigationController+GKGesture.swift"; sourceTree = "<group>"; };
5E9A1A212C0EF51600321AC5 /* UINavigationItem+GKExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UINavigationItem+GKExtension.swift"; sourceTree = "<group>"; };
5E9A1A222C0EF51600321AC5 /* UIScrollView+GKExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIScrollView+GKExtension.swift"; sourceTree = "<group>"; };
5E9A1A232C0EF51600321AC5 /* UIViewController+GKExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIViewController+GKExtension.swift"; sourceTree = "<group>"; };
5E9A1A242C0EF51600321AC5 /* UIViewController+GKGesture.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIViewController+GKGesture.swift"; sourceTree = "<group>"; };
5E9A1A382C0EFF4000321AC5 /* UIWindow+Ext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIWindow+Ext.swift"; sourceTree = "<group>"; };
5E9A1A3B2C0F00AD00321AC5 /* ImportTools.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImportTools.swift; sourceTree = "<group>"; };
5E9A1A3D2C0F043100321AC5 /* RootController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootController.swift; sourceTree = "<group>"; };
5E9A1A3F2C0F04CC00321AC5 /* HomeController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeController.swift; sourceTree = "<group>"; };
5E9A1A412C0F04DB00321AC5 /* ProfileController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileController.swift; sourceTree = "<group>"; };
5E9A1A472C0F0DC400321AC5 /* AsBaseController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsBaseController.swift; sourceTree = "<group>"; };
5E9A1A492C0F13BF00321AC5 /* UIColor+Ext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+Ext.swift"; sourceTree = "<group>"; };
5E9A1A4B2C0F144200321AC5 /* ColorTools.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorTools.swift; sourceTree = "<group>"; };
5E9A1A4D2C0F1A2E00321AC5 /* FontTools.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FontTools.swift; sourceTree = "<group>"; };
5E9A1A4F2C0F1F5200321AC5 /* R.generated.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = R.generated.swift; sourceTree = SOURCE_ROOT; };
5E9A1A512C0F205A00321AC5 /* LeagueController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LeagueController.swift; sourceTree = "<group>"; };
5EA670612C104D2800CEEA01 /* LoggerTools.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoggerTools.swift; sourceTree = "<group>"; };
EA8E48B8C50E8D94161797C6 /* Pods-AoleiSports.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AoleiSports.release.xcconfig"; path = "Target Support Files/Pods-AoleiSports/Pods-AoleiSports.release.xcconfig"; sourceTree = "<group>"; };
F63DEFD57EAA7FD3A430F57E /* Pods_AoleiSports.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_AoleiSports.framework; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
......@@ -31,17 +99,29 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
42F3CE39682BAB273520A375 /* Pods_AoleiSports.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
19A2F39F75F2BDE4A03CC92C /* Pods */ = {
isa = PBXGroup;
children = (
0F08FB0AC554BD156228E35A /* Pods-AoleiSports.debug.xcconfig */,
EA8E48B8C50E8D94161797C6 /* Pods-AoleiSports.release.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
};
5E9A19DF2C0EAC0200321AC5 = {
isa = PBXGroup;
children = (
5E9A19EA2C0EAC0200321AC5 /* AoleiSports */,
5E9A19E92C0EAC0200321AC5 /* Products */,
19A2F39F75F2BDE4A03CC92C /* Pods */,
C05EA2A76F80BD312DE7A52C /* Frameworks */,
);
sourceTree = "<group>";
};
......@@ -56,15 +136,119 @@
5E9A19EA2C0EAC0200321AC5 /* AoleiSports */ = {
isa = PBXGroup;
children = (
5E9A19EB2C0EAC0200321AC5 /* AppDelegate.swift */,
5E9A19ED2C0EAC0200321AC5 /* SceneDelegate.swift */,
5E9A19EF2C0EAC0200321AC5 /* ViewController.swift */,
5E9A19F12C0EAC0200321AC5 /* Main.storyboard */,
5E9A1A0B2C0EAFDC00321AC5 /* Src */,
5E9A1A042C0EAF7600321AC5 /* Res */,
5E9A1A0A2C0EAFAE00321AC5 /* Config */,
);
path = AoleiSports;
sourceTree = "<group>";
};
5E9A1A042C0EAF7600321AC5 /* Res */ = {
isa = PBXGroup;
children = (
5E9A19FF2C0EAF7600321AC5 /* goal.mp3 */,
5E9A1A002C0EAF7600321AC5 /* launch_bg.png */,
5E9A1A012C0EAF7600321AC5 /* launch_foot.png */,
5E9A1A022C0EAF7600321AC5 /* red.mp3 */,
5E9A1A032C0EAF7600321AC5 /* yellow.mp3 */,
5E9A19F42C0EAC0300321AC5 /* Assets.xcassets */,
5E9A19F62C0EAC0300321AC5 /* LaunchScreen.storyboard */,
);
path = Res;
sourceTree = "<group>";
};
5E9A1A0A2C0EAFAE00321AC5 /* Config */ = {
isa = PBXGroup;
children = (
5E9A19F92C0EAC0300321AC5 /* Info.plist */,
);
path = AoleiSports;
path = Config;
sourceTree = "<group>";
};
5E9A1A0B2C0EAFDC00321AC5 /* Src */ = {
isa = PBXGroup;
children = (
5E9A1A462C0F0D9E00321AC5 /* Base */,
5E9A1A3A2C0F00A000321AC5 /* Utils */,
5E9A1A372C0EFF0C00321AC5 /* Ext */,
5E9A1A122C0EF4E200321AC5 /* Vendors */,
5E9A19EB2C0EAC0200321AC5 /* AppDelegate.swift */,
5E9A19F62C0EAC0300321AC5 /* LaunchScreen.storyboard */,
5E9A1A3D2C0F043100321AC5 /* RootController.swift */,
5E9A1A3F2C0F04CC00321AC5 /* HomeController.swift */,
5E9A1A412C0F04DB00321AC5 /* ProfileController.swift */,
5E9A1A512C0F205A00321AC5 /* LeagueController.swift */,
);
path = Src;
sourceTree = "<group>";
};
5E9A1A122C0EF4E200321AC5 /* Vendors */ = {
isa = PBXGroup;
children = (
5E9A1A252C0EF51600321AC5 /* GKNavigationBarSwift */,
);
path = Vendors;
sourceTree = "<group>";
};
5E9A1A252C0EF51600321AC5 /* GKNavigationBarSwift */ = {
isa = PBXGroup;
children = (
5E9A1A132C0EF51600321AC5 /* Bundle+GKExtension.swift */,
5E9A1A142C0EF51600321AC5 /* GKBaseAnimatedTransition.swift */,
5E9A1A152C0EF51600321AC5 /* GKNavigationBarConfigure.swift */,
5E9A1A162C0EF51600321AC5 /* GKNavigationBarDefine.swift */,
5E9A1A172C0EF51600321AC5 /* GKNavigationBarSwift.bundle */,
5E9A1A182C0EF51600321AC5 /* GKNavigationBarSwift.h */,
5E9A1A192C0EF51600321AC5 /* GKNavigationBarSwift.swift */,
5E9A1A1A2C0EF51600321AC5 /* GKNavigationInteractiveTransition.swift */,
5E9A1A1B2C0EF51600321AC5 /* GKPopAnimatedTransition.swift */,
5E9A1A1C2C0EF51600321AC5 /* GKPushAnimatedTransition.swift */,
5E9A1A1D2C0EF51600321AC5 /* UIBarButtonItem+GKExtension.swift */,
5E9A1A1E2C0EF51600321AC5 /* UIImage+GKExtension.swift */,
5E9A1A1F2C0EF51600321AC5 /* UINavigationController+GKExtension.swift */,
5E9A1A202C0EF51600321AC5 /* UINavigationController+GKGesture.swift */,
5E9A1A212C0EF51600321AC5 /* UINavigationItem+GKExtension.swift */,
5E9A1A222C0EF51600321AC5 /* UIScrollView+GKExtension.swift */,
5E9A1A232C0EF51600321AC5 /* UIViewController+GKExtension.swift */,
5E9A1A242C0EF51600321AC5 /* UIViewController+GKGesture.swift */,
);
path = GKNavigationBarSwift;
sourceTree = "<group>";
};
5E9A1A372C0EFF0C00321AC5 /* Ext */ = {
isa = PBXGroup;
children = (
5E9A1A492C0F13BF00321AC5 /* UIColor+Ext.swift */,
5E9A1A382C0EFF4000321AC5 /* UIWindow+Ext.swift */,
);
path = Ext;
sourceTree = "<group>";
};
5E9A1A3A2C0F00A000321AC5 /* Utils */ = {
isa = PBXGroup;
children = (
5E9A1A4F2C0F1F5200321AC5 /* R.generated.swift */,
5E9A1A3B2C0F00AD00321AC5 /* ImportTools.swift */,
5E9A1A4B2C0F144200321AC5 /* ColorTools.swift */,
5E9A1A4D2C0F1A2E00321AC5 /* FontTools.swift */,
5EA670612C104D2800CEEA01 /* LoggerTools.swift */,
);
path = Utils;
sourceTree = "<group>";
};
5E9A1A462C0F0D9E00321AC5 /* Base */ = {
isa = PBXGroup;
children = (
5E9A1A472C0F0DC400321AC5 /* AsBaseController.swift */,
);
path = Base;
sourceTree = "<group>";
};
C05EA2A76F80BD312DE7A52C /* Frameworks */ = {
isa = PBXGroup;
children = (
F63DEFD57EAA7FD3A430F57E /* Pods_AoleiSports.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
/* End PBXGroup section */
......@@ -74,9 +258,12 @@
isa = PBXNativeTarget;
buildConfigurationList = 5E9A19FC2C0EAC0300321AC5 /* Build configuration list for PBXNativeTarget "AoleiSports" */;
buildPhases = (
69924A559A2CC4F444E3D152 /* [CP] Check Pods Manifest.lock */,
5E9A1A432C0F08CD00321AC5 /* ShellScript */,
5E9A19E42C0EAC0200321AC5 /* Sources */,
5E9A19E52C0EAC0200321AC5 /* Frameworks */,
5E9A19E62C0EAC0200321AC5 /* Resources */,
79CA6586F866F3CDFA07AF07 /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
......@@ -125,40 +312,125 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
5E9A1A112C0EB74300321AC5 /* LaunchScreen.storyboard in Resources */,
5E9A1A072C0EAF7600321AC5 /* launch_foot.png in Resources */,
5E9A19F52C0EAC0300321AC5 /* Assets.xcassets in Resources */,
5E9A19F82C0EAC0300321AC5 /* Base in Resources */,
5E9A19F32C0EAC0200321AC5 /* Base in Resources */,
5E9A1A052C0EAF7600321AC5 /* goal.mp3 in Resources */,
5E9A1A2A2C0EF51600321AC5 /* GKNavigationBarSwift.bundle in Resources */,
5E9A1A082C0EAF7600321AC5 /* red.mp3 in Resources */,
5E9A1A092C0EAF7600321AC5 /* yellow.mp3 in Resources */,
5E9A1A062C0EAF7600321AC5 /* launch_bg.png in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
5E9A1A432C0F08CD00321AC5 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
);
outputFileListPaths = (
);
outputPaths = (
$SRCROOT/R.generated.swift,
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"$PODS_ROOT/R.swift/rswift\" generate \"$SRCROOT/R.generated.swift\"\n";
};
69924A559A2CC4F444E3D152 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-AoleiSports-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
79CA6586F866F3CDFA07AF07 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-AoleiSports/Pods-AoleiSports-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-AoleiSports/Pods-AoleiSports-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-AoleiSports/Pods-AoleiSports-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
5E9A19E42C0EAC0200321AC5 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
5E9A19F02C0EAC0200321AC5 /* ViewController.swift in Sources */,
5E9A1A522C0F205A00321AC5 /* LeagueController.swift in Sources */,
5E9A1A282C0EF51600321AC5 /* GKNavigationBarConfigure.swift in Sources */,
5E9A1A342C0EF51600321AC5 /* UIScrollView+GKExtension.swift in Sources */,
5E9A1A402C0F04CC00321AC5 /* HomeController.swift in Sources */,
5E9A1A2B2C0EF51600321AC5 /* GKNavigationBarSwift.swift in Sources */,
5E9A1A2C2C0EF51600321AC5 /* GKNavigationInteractiveTransition.swift in Sources */,
5E9A1A3E2C0F043100321AC5 /* RootController.swift in Sources */,
5E9A1A332C0EF51600321AC5 /* UINavigationItem+GKExtension.swift in Sources */,
5E9A1A4A2C0F13BF00321AC5 /* UIColor+Ext.swift in Sources */,
5E9A1A362C0EF51600321AC5 /* UIViewController+GKGesture.swift in Sources */,
5E9A1A4C2C0F144200321AC5 /* ColorTools.swift in Sources */,
5E9A1A482C0F0DC400321AC5 /* AsBaseController.swift in Sources */,
5E9A1A422C0F04DB00321AC5 /* ProfileController.swift in Sources */,
5E9A1A352C0EF51600321AC5 /* UIViewController+GKExtension.swift in Sources */,
5E9A1A2F2C0EF51600321AC5 /* UIBarButtonItem+GKExtension.swift in Sources */,
5EA670622C104D2800CEEA01 /* LoggerTools.swift in Sources */,
5E9A1A312C0EF51600321AC5 /* UINavigationController+GKExtension.swift in Sources */,
5E9A1A3C2C0F00AD00321AC5 /* ImportTools.swift in Sources */,
5E9A19EC2C0EAC0200321AC5 /* AppDelegate.swift in Sources */,
5E9A19EE2C0EAC0200321AC5 /* SceneDelegate.swift in Sources */,
5E9A1A392C0EFF4000321AC5 /* UIWindow+Ext.swift in Sources */,
5E9A1A292C0EF51600321AC5 /* GKNavigationBarDefine.swift in Sources */,
5E9A1A4E2C0F1A2E00321AC5 /* FontTools.swift in Sources */,
5E9A1A502C0F1F5200321AC5 /* R.generated.swift in Sources */,
5E9A1A272C0EF51600321AC5 /* GKBaseAnimatedTransition.swift in Sources */,
5E9A1A322C0EF51600321AC5 /* UINavigationController+GKGesture.swift in Sources */,
5E9A1A2D2C0EF51600321AC5 /* GKPopAnimatedTransition.swift in Sources */,
5E9A1A262C0EF51600321AC5 /* Bundle+GKExtension.swift in Sources */,
5E9A1A2E2C0EF51600321AC5 /* GKPushAnimatedTransition.swift in Sources */,
5E9A1A302C0EF51600321AC5 /* UIImage+GKExtension.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
5E9A19F12C0EAC0200321AC5 /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
5E9A19F22C0EAC0200321AC5 /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
5E9A19F62C0EAC0300321AC5 /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
5E9A19F72C0EAC0300321AC5 /* Base */,
5E9A1A0F2C0EB68800321AC5 /* en */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
......@@ -203,7 +475,7 @@
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu17;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
......@@ -218,7 +490,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 17.5;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
......@@ -266,7 +538,7 @@
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
GCC_C_LANGUAGE_STANDARD = gnu17;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
......@@ -275,7 +547,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 17.5;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
......@@ -287,6 +559,7 @@
};
5E9A19FD2C0EAC0300321AC5 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 0F08FB0AC554BD156228E35A /* Pods-AoleiSports.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
......@@ -294,27 +567,33 @@
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = L275Z886SW;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = AoleiSports/Info.plist;
INFOPLIST_FILE = AoleiSports/Config/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "傲雷体育";
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
INFOPLIST_KEY_UIMainStoryboardFile = Main;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen.storyboard;
INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.aolei.sports.AoleiSports;
PRODUCT_BUNDLE_IDENTIFIER = com.aolei.sports;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TARGETED_DEVICE_FAMILY = 1;
};
name = Debug;
};
5E9A19FE2C0EAC0300321AC5 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = EA8E48B8C50E8D94161797C6 /* Pods-AoleiSports.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
......@@ -322,22 +601,27 @@
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = L275Z886SW;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = AoleiSports/Info.plist;
INFOPLIST_FILE = AoleiSports/Config/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "傲雷体育";
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
INFOPLIST_KEY_UIMainStoryboardFile = Main;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen.storyboard;
INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.aolei.sports.AoleiSports;
PRODUCT_BUNDLE_IDENTIFIER = com.aolei.sports;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TARGETED_DEVICE_FAMILY = 1;
};
name = Release;
};
......
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1540"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES"
buildArchitectures = "Automatic">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "5E9A19E72C0EAC0200321AC5"
BuildableName = "AoleiSports.app"
BlueprintName = "AoleiSports"
ReferencedContainer = "container:AoleiSports.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
</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">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "5E9A19E72C0EAC0200321AC5"
BuildableName = "AoleiSports.app"
BlueprintName = "AoleiSports"
ReferencedContainer = "container:AoleiSports.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<EnvironmentVariables>
<EnvironmentVariable
key = "IDEPreferLogStreaming"
value = "YES"
isEnabled = "YES">
</EnvironmentVariable>
</EnvironmentVariables>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "5E9A19E72C0EAC0200321AC5"
BuildableName = "AoleiSports.app"
BlueprintName = "AoleiSports"
ReferencedContainer = "container:AoleiSports.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
......@@ -7,7 +7,15 @@
<key>AoleiSports.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>0</integer>
<integer>4</integer>
</dict>
</dict>
<key>SuppressBuildableAutocreation</key>
<dict>
<key>5E9A19E72C0EAC0200321AC5</key>
<dict>
<key>primary</key>
<true/>
</dict>
</dict>
</dict>
......
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:AoleiSports.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>
<?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>
//
// AppDelegate.swift
// AoleiSports
//
// Created by ilCode on 2024/6/4.
//
import UIKit
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
}
// MARK: UISceneSession Lifecycle
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
// Called when a new scene session is being created.
// Use this method to select a configuration to create the new scene with.
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
// Called when the user discards a scene session.
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}
}
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
</document>
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="ViewController" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>
<?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>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
</dict>
</plist>
<?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>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneConfigurationName</key>
<string>Default Configuration</string>
<key>UISceneDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
<key>UISceneStoryboardFile</key>
<string>Main</string>
</dict>
</array>
</dict>
</dict>
</dict>
</plist>
{
"images" : [
{
"filename" : "app_logo.png",
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
......
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "match_filter.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "match_filter@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "match_filter@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "match_filter.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "match_filter@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "match_filter@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "home.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "home@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "home@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "home_selected.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "home_selected@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "home_selected@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "profile.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "profile@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "profile@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "profile_selected.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "profile_selected@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "profile_selected@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
此文件类型无法预览
此文件类型无法预览
此文件类型无法预览
//
// SceneDelegate.swift
// AoleiSports
//
// Created by ilCode on 2024/6/4.
//
import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
guard let _ = (scene as? UIWindowScene) else { return }
}
func sceneDidDisconnect(_ scene: UIScene) {
// Called as the scene is being released by the system.
// This occurs shortly after the scene enters the background, or when its session is discarded.
// Release any resources associated with this scene that can be re-created the next time the scene connects.
// The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
}
func sceneDidBecomeActive(_ scene: UIScene) {
// Called when the scene has moved from an inactive state to an active state.
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
}
func sceneWillResignActive(_ scene: UIScene) {
// Called when the scene will move from an active state to an inactive state.
// This may occur due to temporary interruptions (ex. an incoming phone call).
}
func sceneWillEnterForeground(_ scene: UIScene) {
// Called as the scene transitions from the background to the foreground.
// Use this method to undo the changes made on entering the background.
}
func sceneDidEnterBackground(_ scene: UIScene) {
// Called as the scene transitions from the foreground to the background.
// Use this method to save data, release shared resources, and store enough scene-specific state information
// to restore the scene back to its current state.
}
}
//
// AppDelegate.swift
// AoleiSports
//
// Created by ilCode on 2024/6/4.
//
import UIKit
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
Thread.sleep(forTimeInterval: 3)
initLogger()
initNaviBar()
initWindow()
return true
}
}
extension AppDelegate {
private func initLogger() {
// 使用默认的OS Logger
DDLog.add(DDOSLogger.sharedInstance)
// 使用File Logger
let fileLogger = DDFileLogger()
fileLogger.rollingFrequency = 60 * 60 * 24
fileLogger.logFileManager.maximumNumberOfLogFiles = 7
DDLog.add(fileLogger)
// 创建并设置自定义的 LogFormatter
let customFormatter = CustomLogFormatter()
if let osLogger = DDLog.allLoggers.first(where: { $0 is DDOSLogger }) as? DDOSLogger {
osLogger.logFormatter = customFormatter
}
// 设置远程日志记录器
// if let remoteLoggingURL = URL(string: "https://your-remote-server.com/logs") {
// let remoteLogger = RemoteLogger(remoteLoggingURL: remoteLoggingURL)
// DDLog.add(remoteLogger)
// }
}
private func initNaviBar() {
GKConfigure.setupCustom {
// 导航栏背景色
$0.backgroundColor = kWhite
// 导航栏标题颜色
$0.titleColor = kMainTitleColor
// 导航栏标题字体
$0.titleFont = kBoldFontSize(18)
// 导航栏返回按钮样式
$0.backStyle = .black
// 状态栏样式
$0.statusBarStyle = .darkContent
// 导航栏左右item间距
$0.gk_navItemLeftSpace = 10
$0.gk_navItemRightSpace = 10
// 是否恢复系统导航
$0.gk_restoreSystemNavBar = true
// 缩放配置
$0.gk_scaleX = 0.90
$0.gk_scaleY = 0.92
// 开启全局UIScrollView处理
$0.gk_openScrollViewGestureHandle = true
}
}
private func initWindow() {
window = UIWindow.init(frame: UIScreen.main.bounds)
window?.backgroundColor = .white
let rootVC = RootController()
window?.rootViewController = rootVC
window?.makeKeyAndVisible()
/*
let infoDic = Bundle.main.infoDictionary
print(infoDic!["HOST_URL"]!)
let path = Bundle.main.path(forResource: "Info", ofType: "plist")
let dict = NSDictionary(contentsOfFile: path!)
print(dict!["HOST_URL"]!)
*/
}
}
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<device id="retina6_12" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22685"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="launch_bg.png" translatesAutoresizingMaskIntoConstraints="NO" id="3SD-Jb-IZc">
<rect key="frame" x="0.0" y="0.0" width="393" height="818"/>
</imageView>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="launch_foot.png" translatesAutoresizingMaskIntoConstraints="NO" id="LaA-Gs-P7Z">
<rect key="frame" x="0.0" y="723" width="393" height="60"/>
<constraints>
<constraint firstAttribute="height" constant="60" id="Osa-eN-FKw"/>
</constraints>
</imageView>
</subviews>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstItem="LaA-Gs-P7Z" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" id="Djh-AB-Mpx"/>
<constraint firstItem="3SD-Jb-IZc" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" id="NW9-ez-QqS"/>
<constraint firstItem="6Tk-OE-BBY" firstAttribute="trailing" secondItem="LaA-Gs-P7Z" secondAttribute="trailing" id="X8B-h3-rty"/>
<constraint firstItem="6Tk-OE-BBY" firstAttribute="trailing" secondItem="3SD-Jb-IZc" secondAttribute="trailing" id="e9h-JN-jgi"/>
<constraint firstItem="6Tk-OE-BBY" firstAttribute="bottom" secondItem="LaA-Gs-P7Z" secondAttribute="bottom" constant="35" id="gg5-Jn-FBt"/>
<constraint firstItem="6Tk-OE-BBY" firstAttribute="bottom" secondItem="3SD-Jb-IZc" secondAttribute="bottom" id="hAF-oa-ilP"/>
<constraint firstItem="3SD-Jb-IZc" firstAttribute="top" secondItem="Ze5-6b-2t3" secondAttribute="top" id="mhm-9E-QgK"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
<resources>
<image name="launch_bg.png" width="750" height="1334"/>
<image name="launch_foot.png" width="344" height="108"/>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
</resources>
</document>
//
// AsBaseController.swift
// AoleiSports
//
// Created by ilCode on 2024/6/4.
//
import UIKit
class AsBaseController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = kMainBgColor
}
}
//
// UIColor+Ext.swift
// AoleiSports
//
// Created by ilCode on 2024/6/4.
//
import UIKit
extension UIColor {
/// 传入一个16进制的字符串,返回该16进制代表的颜色(默认alpha位1)
///
/// - Parameter hexString: 代表颜色的16进制字符串
/// - Returns: 该16进制表示的颜色
static func colorWith(hexString: String) -> UIColor {
return UIColor.colorWith(hexString: hexString, alpha: 1.0)
}
/// 传入一个16进制的字符串,返回该16进制代表的颜色
///
/// - Parameter hexString: 代表颜色的16进制字符串,支持@“#123456”、 @“0X123456”、 @“123456”三种格式
/// - alpha: 颜色的透明度
/// - Returns: 该16进制表示的颜色
static func colorWith(hexString: String, alpha: CGFloat) -> UIColor {
// 删除字符串中的空格并转换为大写
var cString = hexString.trimmingCharacters(in: .whitespacesAndNewlines).uppercased()
// 如果是0x或#开头的,去除前缀
if cString.hasPrefix("0X") {
cString.removeFirst(2)
} else if cString.hasPrefix("#") {
cString.removeFirst()
}
// 字符串应该是6或8个字符
guard cString.count == 6 || cString.count == 8 else {
print("colorWithHexString 错误!")
return UIColor.clear
}
// 将十六进制字符串转换为RGB组件
var r: UInt32 = 0, g: UInt32 = 0, b: UInt32 = 0
// 如果包含alpha值,则先解析alpha
var alphaComponent: CGFloat = 1.0
if cString.count == 8 {
let alphaString = String(cString.prefix(2))
if let alphaValue = UInt32(alphaString, radix: 16) {
alphaComponent = CGFloat(alphaValue) / 255.0
cString.removeFirst(2)
} else {
print("无效的alpha值")
return UIColor.clear
}
}
// 解析RGB值
if let rValue = UInt32(String(cString.prefix(2)), radix: 16),
let gValue = UInt32(String(cString.dropFirst(2).prefix(2)), radix: 16),
let bValue = UInt32(String(cString.dropFirst(4).prefix(2)), radix: 16) {
r = rValue
g = gValue
b = bValue
} else {
print("无效的RGB值")
return UIColor.clear
}
// 创建UIColor实例
return UIColor(red: CGFloat(r) / 255.0, green: CGFloat(g) / 255.0, blue: CGFloat(b) / 255.0, alpha: alphaComponent)
}
convenience init(r: CGFloat, g: CGFloat, b: CGFloat, alpha: CGFloat = 1.0) {
self.init(red: r/255.0, green: g/255.0, blue: b/255.0, alpha: alpha)
}
}
//
// UIWindow+Ext.swift
// AoleiSports
//
// Created by ilCode on 2024/6/4.
//
import UIKit
extension UIWindow {
static var isLandscape: Bool {
if #available(iOS 13.0, *) {
return UIApplication.shared.windows
.first?
.windowScene?
.interfaceOrientation
.isLandscape ?? false
} else {
return UIApplication.shared.statusBarOrientation.isLandscape
}
}
}
//
// HomeController.swift
// AoleiSports
//
// Created by ilCode on 2024/6/4.
//
import UIKit
class HomeController: AsBaseController {
lazy var filterItem: UIBarButtonItem = {
let btn = UIButton()
btn.frame = CGRect(x: 0, y: 0, width: 44, height: 44)
btn.addTarget(self, action: #selector(filterAction), for: .touchUpInside)
btn.setTitle("筛选", for: .normal)
btn.setTitleColor(kMainTitleColor, for: .normal)
btn.titleLabel?.font = kFontSize(14)
btn.imageEdgeInsets = UIEdgeInsets(top: 0, left: -5, bottom: 0, right: 0)
btn.setImage(R.image.match_filter(), for: .normal)
return UIBarButtonItem(customView: btn)
}()
lazy var setItem: UIBarButtonItem = {
let btn = UIButton()
btn.frame = CGRect(x: 0, y: 0, width: 44, height: 44)
btn.addTarget(self, action: #selector(setAction), for: .touchUpInside)
btn.setImage(R.image.match_setting(), for: .normal)
return UIBarButtonItem(customView: btn)
}()
override func viewDidLoad() {
super.viewDidLoad()
gk_navTitle = "赛事比分"
gk_navLeftBarButtonItem = filterItem
gk_navRightBarButtonItem = setItem
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
DDLogVerbose("Verbose")
DDLogDebug("Debug")
DDLogInfo("Info")
DDLogWarn("Warn")
DDLogError("Error")
}
}
extension HomeController {
@objc private func filterAction() {
let leagueVC = LeagueController()
navigationController?.pushViewController(leagueVC, animated: true)
}
@objc private func setAction() {
}
}
//
// LeagueController.swift
// AoleiSports
//
// Created by ilCode on 2024/6/4.
//
import UIKit
class LeagueController: AsBaseController {
override func viewDidLoad() {
super.viewDidLoad()
gk_navTitle = "赛事筛选"
}
}
//
// ViewController.swift
// ProfileController.swift
// AoleiSports
//
// Created by ilCode on 2024/6/4.
......@@ -7,13 +7,11 @@
import UIKit
class ViewController: UIViewController {
class ProfileController: AsBaseController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}
}
//
// RootController.swift
// AoleiSports
//
// Created by ilCode on 2024/6/4.
//
import UIKit
//MARK: - life
class RootController: UITabBarController {
private var curIndex: Int = 0
private lazy var tabBarItemViews = [UIView]()
override func viewDidLoad() {
super.viewDidLoad()
// 设置tabbar背景色 && 隐藏tabbar分割线
tabBar.backgroundImage = UIImage()
tabBar.shadowImage = UIImage()
tabBar.backgroundColor = kWhite
// 设置tabbar选中及未选中的文字颜色
tabBar.tintColor = kMasterColor
tabBar.unselectedItemTintColor = kSubTitleColor
addController(rootVC: HomeController(), title: "赛事比分", image: R.image.home(), selectedImage: R.image.home_selected())
addController(rootVC: ProfileController(), title: "我的", image: R.image.profile(), selectedImage: R.image.profile_selected())
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// 保存tabBarItemView
for tabBarItemView in tabBar.subviews {
if tabBarItemView.isKind(of: NSClassFromString("UITabBarButton")!) {
tabBarItemViews.append(tabBarItemView)
}
}
}
}
//MARK: - UITabBarDelegate
extension RootController {
override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
guard let itemIndex = tabBar.items?.firstIndex(of: item),
itemIndex != curIndex else { return }
zoomAnimate(itemViews: tabBarItemViews, index: itemIndex)
curIndex = itemIndex
}
}
//MARK: - Private
extension RootController {
/// 添加缩放动画
/// - Parameters:
/// - itemViews: itemViews
/// - index: index
private func zoomAnimate(itemViews: [UIView], index: Int) {
guard itemViews.count > 0 else { return }
let zoomAni = CABasicAnimation(keyPath: "transform.scale")
zoomAni.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
zoomAni.duration = 0.2;
zoomAni.repeatCount = 1;
zoomAni.autoreverses = true;
zoomAni.fromValue = 0.9
zoomAni.toValue = 1.1
itemViews[index].layer.add(zoomAni, forKey: nil)
}
/// 添加子控制器
/// - Parameters:
/// - rootVC: rootVC
/// - title: title
/// - image: image
/// - selectedImage: selectedImage
private func addController(rootVC: UIViewController, title: String, image: UIImage?, selectedImage: UIImage?) {
let navi = UINavigationController(rootVC: rootVC)
navi.tabBarItem = UITabBarItem(title: title, image: image, selectedImage: selectedImage)
navi.tabBarItem.image = navi.tabBarItem.image?.withRenderingMode(.alwaysOriginal)
navi.tabBarItem.selectedImage = navi.tabBarItem.selectedImage?.withRenderingMode(.alwaysOriginal)
addChild(navi)
}
}
//
// ColorTools.swift
// AoleiSports
//
// Created by ilCode on 2024/6/4.
//
import UIKit
func kHexColor(_ HexString: String) ->UIColor {
return UIColor.colorWith(hexString: HexString)
}
func kHexColorA(_ HexString: String,_ a: CGFloat) ->UIColor {
return UIColor.colorWith(hexString: HexString, alpha: a)
}
let kWhite = UIColor.white
/// 主色调
let kMasterColor = kHexColor("DA2323")
/// 主title颜色
let kMainTitleColor = kHexColor("333333")
/// 子title颜色
let kSubTitleColor = kHexColor("AAAAAA")
/// 主背景色
let kMainBgColor = kHexColor("EFEFEF")
//
// FontTools.swift
// AoleiSports
//
// Created by ilCode on 2024/6/4.
//
import UIKit
// 字体 字号
func kFontSize(_ size: CGFloat) -> UIFont {
return UIFont.systemFont(ofSize: size)
}
func kBoldFontSize(_ size: CGFloat) -> UIFont {
return UIFont.boldSystemFont(ofSize: size)
}
//
// ImportTools.swift
// AoleiSports
//
// Created by ilCode on 2024/6/4.
//
@_exported import CocoaLumberjack
//
// LoggerTools.swift
// AoleiSports
//
// Created by ilCode on 2024/6/5.
//
import Foundation
// 自定义日志输出格式
class CustomLogFormatter: NSObject, DDLogFormatter {
let dateFormatter: DateFormatter
override init() {
dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss.SSS"
super.init()
}
func format(message logMessage: DDLogMessage) -> String? {
let _ = dateFormatter.string(from: logMessage.timestamp)
let logLevel: String
switch logMessage.flag {
case .error:
logLevel = "❗️[ERROR]"
case .warning:
logLevel = "⚠️[WARN]"
case .info:
logLevel = "ℹ️[INFO]"
case .debug:
logLevel = "🐞[DEBUG]"
case .verbose:
logLevel = "🔍[VERBOSE]"
default:
logLevel = "[UNKNOWN]"
}
return "\(logLevel) [\(logMessage.fileName) \(logMessage.function ?? ""):\(logMessage.line)]: \(logMessage.message)"
}
}
// 将日志存储到远程服务器
class RemoteLogger: DDAbstractLogger {
private let remoteLoggingURL: URL
init(remoteLoggingURL: URL) {
self.remoteLoggingURL = remoteLoggingURL
super.init()
}
override func log(message logMessage: DDLogMessage) {
let formattedMessage = format(logMessage: logMessage)
sendLogToServer(formattedMessage)
}
private func format(logMessage: DDLogMessage) -> String {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss.SSS"
let dateAndTime = dateFormatter.string(from: logMessage.timestamp)
let logLevel: String
switch logMessage.flag {
case .error: logLevel = "ERROR"
case .warning: logLevel = "WARNING"
case .info: logLevel = "INFO"
case .debug: logLevel = "DEBUG"
case .verbose: logLevel = "VERBOSE"
default: logLevel = "UNKNOWN"
}
return "\(dateAndTime) \(logLevel) [\(logMessage.fileName) \(logMessage.function ?? ""):\(logMessage.line)]: \(logMessage.message)"
}
private func sendLogToServer(_ message: String) {
var request = URLRequest(url: remoteLoggingURL)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: ["log": message], options: [])
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Failed to send log to server: \(error)")
} else {
print("Successfully sent log to server")
}
}
task.resume()
}
}
//
// Bundle+GKExtension.swift
// GKNavigationBarSwift
//
// Created by QuintGao on 2023/7/21.
//
import Foundation
extension Bundle {
static var gk_bundle: Bundle? {
normalModule ?? spmModule
}
private static var normalModule: Bundle? = {
let bundleName = "GKNavigationBarSwift"
var candidates = [
// Bundle should be present here when the package is linked into an App.
Bundle.main.resourceURL,
// Bundle should be present here when the package is linked into a framework.
Bundle(for: GKNavigationBarConfigure.self).resourceURL,
// For command-line tools.
Bundle.main.bundleURL,
]
#if SWIFT_PACKAGE
// For SWIFT_PACKAGE.
candidates.append(Bundle.module.bundleURL)
#endif
for candidate in candidates {
let bundlePath = candidate?.appendingPathComponent(bundleName + ".bundle")
if let bundle = bundlePath.flatMap(Bundle.init(url:)) {
return bundle
}
}
return nil
}()
private static var spmModule: Bundle? = {
let bundleName = "GKNavigationBarSwift_GKNavigationBarSwift"
let candidates = [
// Bundle should be present here when the package is linked into an App.
Bundle.main.resourceURL,
// Bundle should be present here when the package is linked into a framework.
Bundle(for: GKNavigationBarConfigure.self).resourceURL,
// For command-line tools.
Bundle.main.bundleURL,
]
for candidate in candidates {
let bundlePath = candidate?.appendingPathComponent(bundleName + ".bundle")
if let bundle = bundlePath.flatMap(Bundle.init(url:)) {
return bundle
}
}
return nil
}()
}
//
// GKBaseAnimatedTransition.swift
// GKNavigationBarSwift
//
// Created by QuintGao on 2020/3/24.
// Copyright © 2020 QuintGao. All rights reserved.
//
import UIKit
open class GKBaseAnimatedTransition: NSObject {
open var isScale = false
open var shadowView: UIView!
open var transitionContext: UIViewControllerContextTransitioning!
open var containerView: UIView!
open var fromViewController: UIViewController!
open var toViewController: UIViewController!
open var isHideTabBar = false
open class func transition(with scale: Bool) -> GKBaseAnimatedTransition {
return self.init(scale: scale)
}
required public init(scale: Bool) {
self.isScale = scale
}
}
extension GKBaseAnimatedTransition: UIViewControllerAnimatedTransitioning {
// MARK - UIViewControllerAnimatedTransitioning
open func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return TimeInterval(UINavigationController.hideShowBarDuration)
}
open func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let containerView = transitionContext.containerView
let fromVC = transitionContext.viewController(forKey: .from)
let toVC = transitionContext.viewController(forKey: .to)
self.containerView = containerView
self.fromViewController = fromVC
self.toViewController = toVC
self.transitionContext = transitionContext
animateTransition()
}
public func animationDuration() -> TimeInterval {
return self.transitionDuration(using: self.transitionContext)
}
@objc open func animateTransition() {
// SubClass Implementation
}
public func completeTransition() {
guard let transitionContext = self.transitionContext else { return }
transitionContext .completeTransition(!transitionContext.transitionWasCancelled)
}
}
extension UIViewController {
fileprivate struct AssociatedKeys {
static var defCaptureImage: Void?
}
public var gk_captureImage: UIImage? {
get {
guard let obj = gk_getAssociatedObject(self, &AssociatedKeys.defCaptureImage) else { return nil }
return obj as? UIImage
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.defCaptureImage, newValue)
}
}
}
//
// GKNavigationBarConfigure.swift
// GKNavigationBarSwift
//
// Created by QuintGao on 2020/3/24.
// Copyright © 2020 QuintGao. All rights reserved.
//
import UIKit
public let GKConfigure = GKNavigationBarConfigure.shared
// 配置类宏定义
open class GKNavigationBarConfigure : NSObject {
/// 导航栏背景色
open var backgroundColor: UIColor?
/// 导航栏背景图片,默认nil,优先级高于backgroundColor
open var backgroundImage: UIImage?
/// 暗黑模式下的背景图片,默认nil,优先级高于backgroundColor
open var darkBackgroundImage: UIImage?
/// 导航栏分割线颜色,默认nil,使用系统颜色
open var lineColor: UIColor?
/// 导航栏分割线图片,默认nil,优先级高于lineColor
open var lineImage: UIImage?
/// 暗黑模式下的分割线图片,默认nil,优先级高于lineColor
open var darkLineImage: UIImage?
/// 导航栏分割线是否隐藏,默认NO
open var lineHidden: Bool = false
/// 导航栏标题颜色,默认黑色
open var titleColor: UIColor?
/// 导航栏标题字体,默认系统字体17
open var titleFont: UIFont?
/// 返回按钮图片,默认nil,优先级高于backStyle
open var backImage: UIImage?
/// 暗黑模式下的返回图片,mornil,优先级高于backStyle
open var darkBackImage: UIImage?
/// backStyle为GKNavigationBarBackStyle.black时对应的图片,默认btn_back_black
open var blackBackImage: UIImage?
/// backStyle为GKNavigationBarBackStyle.white时对应的图片,默认btn_black_white
open var whiteBackImage: UIImage?
/// 返回按钮样式
open var backStyle: GKNavigationBarBackStyle = .none
/// 是否禁止导航栏左右item间距调整,默认是NO
/// 1.4.0版本之后,只对带有GKNavigationBar的控制器有效
open var gk_disableFixSpace: Bool = false
/// 是否开启普通控制器的导航栏item间距调整,只能在对应的控制器中开启
open var gk_openSystemFixSpace: Bool = false
/// 导航栏左侧按钮距屏幕左边间距,默认是0,可自行调整
open var gk_navItemLeftSpace: CGFloat = 0.0
/// 导航栏右侧按钮距屏幕右边间距,默认是0,可自行调整
open var gk_navItemRightSpace: CGFloat = 0.0
/// 是否隐藏状态栏,默认NO
open var statusBarHidden: Bool = false
/// 状态栏类型,默认UIStatusBarStyleDefault
open var statusBarStyle: UIStatusBarStyle = .default
/// 用于恢复系统导航栏的显示,默认NO
open var gk_restoreSystemNavBar: Bool = false
/// 快速滑动时的灵敏度,默认0.7
open var gk_snapMovementSensitivity: CGFloat = 0.7
/// 左滑push过渡临界值,默认0.3,大于此值完成push操作
open var gk_pushTransitionCriticalValue: CGFloat = 0.3
/// 右滑pop过渡临界值,默认0.5,大于此值完成pop操作
open var gk_popTransitionCriticalValue: CGFloat = 0.5
/// 控制x、y轴的缩放程度,默认(0.95,0.97)
open var gk_scaleX: CGFloat = 0.95
open var gk_scaleY: CGFloat = 0.97
/// 需要屏蔽手势处理的VC,默认nil,支持UIViewController和String
open var shiledGuestureVCs: [Any]?
/// 全局开启UIScrollView手势处理,默认false
/// 如果设置为YES,可在单个UIScrollView中通过gk_openGestureHandle关闭
open var gk_openScrollViewGestureHandle: Bool = false
/// 设置push时是否隐藏tabbar,默认NO
open var gk_hidesBottomBarWhenPushed: Bool = false
/// 导航栏左右间距,内部使用
open var disableFixSpace: Bool = false
open var navItemLeftSpace: CGFloat = 0
open var navItemRightSpace: CGFloat = 0
/// 单例,设置一次全局使用
public static let shared: GKNavigationBarConfigure = {
let instance = GKNavigationBarConfigure()
// setup code
return instance
}()
private static let awake: Void = {
UIViewController.gkAwake()
UINavigationController.gkChildAwake()
UINavigationItem.gkAwake()
NSObject.gkObjectAwake()
UIScrollView.gkAwake()
UIViewController.gkGestureAwake()
UINavigationController.gkGestureChildAwake()
}()
/// 设置默认配置
open func setupDefault() {
GKNavigationBarConfigure.awake
backgroundColor = .white
titleColor = .black
titleFont = UIFont.boldSystemFont(ofSize: 17.0)
blackBackImage = UIImage.gk_image(with: "btn_back_black")
whiteBackImage = UIImage.gk_image(with: "btn_back_white")
backStyle = .black
gk_disableFixSpace = false
gk_navItemLeftSpace = 0
gk_navItemRightSpace = 0
navItemLeftSpace = 0
navItemRightSpace = 0
statusBarHidden = false
statusBarStyle = .default
gk_snapMovementSensitivity = 0.7
gk_pushTransitionCriticalValue = 0.3
gk_popTransitionCriticalValue = 0.5
gk_scaleX = 0.95
gk_scaleY = 0.97
}
open func awake() {
GKNavigationBarConfigure.awake
}
/// 设置自定义配置,此方法只需调用一次
/// @param block 配置回调
open func setupCustom(_ block: @escaping (GKNavigationBarConfigure) -> Void) {
setupDefault()
block(self)
disableFixSpace = gk_disableFixSpace
navItemLeftSpace = gk_navItemLeftSpace
navItemRightSpace = gk_navItemRightSpace
}
/// 更新配置
/// @param block 配置回调
open func update(_ block: @escaping (GKNavigationBarConfigure) -> Void) {
block(self)
}
open func visibleViewController() -> UIViewController? {
return GKDevice.keyWindow()?.rootViewController?.gk_findCurrentViewController(true)
}
/// 获取当前item修复间距
open func gk_fixedSpace() -> CGFloat {
// 经测试发现iPhone 12,iPhone 12 Pro,iPhone 14 Pro默认导航栏间距是16,需要单独处理
if GKDevice.is61InchScreenAndiPhone12Later || GKDevice.is61InchScreenAndiPhone14Pro { return 16 }
return GKDevice.width > 375.0 ? 20 : 16
}
open func fixNavItemSpaceDisabled() -> Bool {
return self.gk_disableFixSpace && !self.gk_openSystemFixSpace
}
// 内部方法
open func isVelocityInsensitivity(_ velocity: CGFloat) -> Bool {
return (abs(velocity) - (1000.0 * (1 - self.gk_snapMovementSensitivity))) > 0;
}
/// 获取某个view的截图
open func getCapture(with view: UIView) -> UIImage? {
if view.bounds.size.width <= 0 || view.bounds.size.height <= 0 { return nil }
UIGraphicsBeginImageContextWithOptions(view.bounds.size, false, UIScreen.main.scale)
view.drawHierarchy(in: view.bounds, afterScreenUpdates: false)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}
}
open class GKDevice {
public static let deviceModel: String = {
if isSimulator, let identifier = ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] {
return identifier
}
var systemInfo = utsname()
uname(&systemInfo)
let machineMirror = Mirror(reflecting: systemInfo.machine)
let identifier = machineMirror.children.reduce("") { identifier, element in
guard let value = element.value as? Int8, value != 0 else { return identifier }
return identifier + String(UnicodeScalar(UInt8(value)))
}
return identifier
}()
public static func isZoomedMode() -> Bool {
if !isIPhone { return false }
let nativeScale = UIScreen.main.nativeScale
var scale = UIScreen.main.scale
// 对于所有的Plus系列iPhone,屏幕物理像素低于软件层面的渲染像素,不管标准模式还是放大模式,nativeScale均小于scale,所以需要特殊处理才能准确区分放大模式
let shouldBeDownsampledDevice = __CGSizeEqualToSize(UIScreen.main.nativeBounds.size, CGSize(width: 1080, height: 1920))
if shouldBeDownsampledDevice {
scale /= 1.15
}
return nativeScale > scale
}
public static let isIPad: Bool = {
return UIDevice.current.userInterfaceIdiom == .pad
}()
public static let isIPod: Bool = {
let model = UIDevice.current.model as NSString
return model.range(of: "iPod touch").location != NSNotFound
}()
public static let isIPhone: Bool = {
let model = UIDevice.current.model as NSString
return model.range(of: "iPhone").location != NSNotFound
}()
public static let isSimulator: Bool = {
#if targetEnvironment(simulator)
return true
#else
return false
#endif
}()
public static let isMac: Bool = {
#if IOS14_SDK_ALLOWED
if #available(iOS 14.0, *) {
return ProcessInfo.processInfo.isiOSAppOnMac || ProcessInfo.processInfo.isMacCatalystApp
}
#endif
if #available(iOS 13.0, *) {
return ProcessInfo.processInfo.isMacCatalystApp
}
return false
}()
/// 带物理凹槽的刘海屏或使用 Home Indicator 类型的设备
public static let isNotchedScreen: Bool = {
if #available(iOS 11.0, *) {
var window = keyWindow()
if window == nil {
// keyWindow还没有创建时,通过创建临时window获取安全区域
window = UIWindow(frame: UIScreen.main.bounds)
if window!.safeAreaInsets.bottom <= 0 {
let viewController = UIViewController()
window?.rootViewController = viewController
}
}
if window!.safeAreaInsets.bottom > 0 {
return true
}
} else {
return false
}
return false
}()
/// 将屏幕分为普通和紧凑两种,这个方法用于判断普通屏幕(也即大屏幕)
public static func isRegularScreen() -> Bool {
return isIPad || (!isZoomedMode() && (is67InchScreenAndiPhone14ProMax || is67InchScreen || is65InchScreen || is61InchScreen || is55InchScreen))
}
/// 是否是横屏
public static func isLandScape() -> Bool {
if #available(iOS 13.0, *) {
// 在 iOS 13 及更高版本中,使用 traitCollection
guard let window = UIApplication.shared.windows.first(where: { $0.isKeyWindow }) else {
// 如果没有找到 key window,则返回 false
return false
}
let horizontalSizeClass = window.traitCollection.horizontalSizeClass
// 横屏时,horizontalSizeClass 通常是 .regular
return horizontalSizeClass == .regular
} else {
// 在 iOS 12 及更早版本中,使用已弃用的 statusBarOrientation
return UIApplication.shared.statusBarOrientation.isLandscape
}
}
public static func statusBarNavBarHeight() -> CGFloat {
return statusBarFrame().size.height + navBarHeight()
}
public static func navBarHeight() -> CGFloat {
if isIPad {
if let version = version, version >= 12.0 {
return 50
}else {
return 44
}
}else {
if isLandScape() {
return isRegularScreen() ? 44 : 32
}else {
return 44
}
}
}
public static func navBarHeightNonFullScreen() -> CGFloat {
return 56
}
public static func tabBarHeight() -> CGFloat {
var tabBarHeight: CGFloat = 0
if isIPad {
if isNotchedScreen {
tabBarHeight = 65
}else {
if let version = version, version >= 12.0 {
tabBarHeight = 50
}else {
tabBarHeight = 49
}
}
}else {
if isLandScape() {
if isRegularScreen() {
tabBarHeight = 49
}else {
tabBarHeight = 32
}
}else {
tabBarHeight = 49
}
tabBarHeight += safeAreaInsertsForDeviceWithNotch().bottom
}
return tabBarHeight
}
public static func safeAreaInsets() -> UIEdgeInsets {
var safeAreaInsets = UIEdgeInsets.zero
if #available(iOS 11.0, *) {
var window = keyWindow()
if window == nil {
// keyWindow还没有创建时,通过创建临时window获取安全区域
window = UIWindow(frame: UIScreen.main.bounds)
if window!.safeAreaInsets.bottom <= 0 {
let viewController = UIViewController()
window?.rootViewController = viewController
}
}
safeAreaInsets = window!.safeAreaInsets
}
return safeAreaInsets
}
public static func statusBarFrame() -> CGRect {
var statusBarFrame = CGRect.zero
if #available(iOS 13.0, *) {
statusBarFrame = keyWindow()?.windowScene?.statusBarManager?.statusBarFrame ?? .zero
}
if statusBarFrame == .zero {
let statusBarH = isNotchedScreen ? 44 : 20
statusBarFrame = CGRect(x: 0, y: 0, width: Int(UIScreen.main.bounds.size.width), height: statusBarH)
}
return statusBarFrame
}
public static func keyWindow() -> UIWindow? {
var window: UIWindow?
if #available(iOS 13.0, *) {
window = UIApplication.shared.connectedScenes
.filter({$0.activationState == .foregroundActive})
.map({$0 as? UIWindowScene})
.compactMap({$0})
.first?.windows
.filter({$0.isKeyWindow}).first
}
if window == nil {
window = UIApplication.shared.delegate?.window ?? nil
}
return window
}
public static func safeAreaInsertsForDeviceWithNotch() -> UIEdgeInsets {
if !isNotchedScreen {
return .zero
}
if isIPad {
return UIEdgeInsets(top: 24, left: 0, bottom: 20, right: 0)
}
let dict = [
// iPhone 14
"iPhone14,7": [UIInterfaceOrientation.portrait: UIEdgeInsets(top: 47, left: 0, bottom: 34, right: 0),
UIInterfaceOrientation.landscapeLeft: UIEdgeInsets(top: 0, left: 47, bottom: 21, right: 47)],
"iPhone14,7-Zoom": [UIInterfaceOrientation.portrait: UIEdgeInsets(top: 48, left: 0, bottom: 28, right: 0),
UIInterfaceOrientation.landscapeLeft: UIEdgeInsets(top: 0, left: 48, bottom: 21, right: 48)],
// iPhone 14 Plus
"iPhone14,8": [UIInterfaceOrientation.portrait: UIEdgeInsets(top: 47, left: 0, bottom: 34, right: 0),
UIInterfaceOrientation.landscapeLeft: UIEdgeInsets(top: 0, left: 47, bottom: 21, right: 47)],
"iPhone14,8-Zoom": [UIInterfaceOrientation.portrait: UIEdgeInsets(top: 41, left: 0, bottom: 30, right: 0),
UIInterfaceOrientation.landscapeLeft: UIEdgeInsets(top: 0, left: 41, bottom: 21, right: 41)],
// iPhone 14 Pro
"iPhone15,2": [UIInterfaceOrientation.portrait: UIEdgeInsets(top: 59, left: 0, bottom: 34, right: 0),
UIInterfaceOrientation.landscapeLeft: UIEdgeInsets(top: 0, left: 59, bottom: 21, right: 59)],
"iPhone15,2-Zoom": [UIInterfaceOrientation.portrait: UIEdgeInsets(top: 48, left: 0, bottom: 28, right: 0),
UIInterfaceOrientation.landscapeLeft: UIEdgeInsets(top: 0, left: 48, bottom: 21, right: 48)],
// iPhone 14 Pro Max
"iPhone15,3": [UIInterfaceOrientation.portrait: UIEdgeInsets(top: 59, left: 0, bottom: 34, right: 0),
UIInterfaceOrientation.landscapeLeft: UIEdgeInsets(top: 0, left: 59, bottom: 21, right: 59)],
"iPhone15,3-Zoom": [UIInterfaceOrientation.portrait: UIEdgeInsets(top: 51, left: 0, bottom: 31, right: 0),
UIInterfaceOrientation.landscapeLeft: UIEdgeInsets(top: 0, left: 51, bottom: 21, right: 51)],
// iPhone 13 mini
"iPhone14,4": [UIInterfaceOrientation.portrait : UIEdgeInsets(top: 50, left: 0, bottom: 34, right: 0),
UIInterfaceOrientation.landscapeLeft: UIEdgeInsets(top: 0, left: 50, bottom: 21, right: 50)],
"iPhone14,4-Zoom": [UIInterfaceOrientation.portrait: UIEdgeInsets(top: 43, left: 0, bottom: 29, right: 0),
UIInterfaceOrientation.landscapeLeft: UIEdgeInsets(top: 0, left: 43, bottom: 21, right: 43)],
// iPhone 13
"iPhone14,5": [UIInterfaceOrientation.portrait: UIEdgeInsets(top: 47, left: 0, bottom: 34, right: 0),
UIInterfaceOrientation.landscapeLeft: UIEdgeInsets(top: 0, left: 47, bottom: 21, right: 47)],
"iPhone14,5-Zoom": [UIInterfaceOrientation.portrait: UIEdgeInsets(top: 39, left: 0, bottom: 28, right: 0),
UIInterfaceOrientation.landscapeLeft: UIEdgeInsets(top: 0, left: 39, bottom: 2, right: 39)],
// iPhone 13 Pro
"iPhone14,2": [UIInterfaceOrientation.portrait: UIEdgeInsets(top: 47, left: 0, bottom: 34, right: 0),
UIInterfaceOrientation.landscapeLeft: UIEdgeInsets(top: 0, left: 47, bottom: 21, right: 47)],
"iPhone14,2-Zoom": [UIInterfaceOrientation.portrait: UIEdgeInsets(top: 39, left: 0, bottom: 28, right: 0),
UIInterfaceOrientation.landscapeLeft: UIEdgeInsets(top: 0, left: 39, bottom: 21, right: 39)],
// iPhone 13 Pro Max
"iPhone14,3": [UIInterfaceOrientation.portrait: UIEdgeInsets(top: 47, left: 0, bottom: 34, right: 0),
UIInterfaceOrientation.landscapeLeft: UIEdgeInsets(top: 0, left: 47, bottom: 21, right: 47)],
"iPhone14,3-Zoom": [UIInterfaceOrientation.portrait: UIEdgeInsets(top: 41, left: 0, bottom: 29 + 2.0 / 3.0, right: 0),
UIInterfaceOrientation.landscapeLeft: UIEdgeInsets(top: 0, left: 41, bottom: 21, right: 41)],
// iPhone 12 mini
"iPhone13,1": [UIInterfaceOrientation.portrait: UIEdgeInsets(top: 50, left: 0, bottom: 34, right: 0),
UIInterfaceOrientation.landscapeLeft: UIEdgeInsets(top: 0, left: 50, bottom: 21, right: 50)],
"iPhone13,1-Zoom": [.portrait: UIEdgeInsets(top: 43, left: 0, bottom: 29, right: 0),
.landscapeLeft: UIEdgeInsets(top: 0, left: 43, bottom: 21, right: 43)],
// iPhone 12
"iPhone13,2": [.portrait: UIEdgeInsets(top: 47, left: 0, bottom: 34, right: 0),
.landscapeLeft: UIEdgeInsets(top: 0, left: 47, bottom: 21, right: 47)],
"iPhone13,2-Zoom": [.portrait: UIEdgeInsets(top: 39, left: 0, bottom: 28, right: 0),
.landscapeLeft: UIEdgeInsets(top: 0, left: 39, bottom: 21, right: 39)],
// iPhone 12 Pro
"iPhone13,3": [.portrait: UIEdgeInsets(top: 47, left: 0, bottom: 34, right: 0),
.landscapeLeft: UIEdgeInsets(top: 0, left: 47, bottom: 21, right: 47)],
"iPhone13,3-Zoom": [.portrait: UIEdgeInsets(top: 39, left: 0, bottom: 28, right: 0),
.landscapeLeft: UIEdgeInsets(top: 0, left: 39, bottom: 21, right: 39)],
// iPhone 12 Pro Max
"iPhone13,4": [.portrait: UIEdgeInsets(top: 47, left: 0, bottom: 34, right: 0),
.landscapeLeft: UIEdgeInsets(top: 0, left: 47, bottom: 21, right: 47)],
"iPhone13,4-Zoom": [.portrait: UIEdgeInsets(top: 41, left: 0, bottom: 29 + 2.0 / 3.0, right: 0),
.landscapeLeft: UIEdgeInsets(top: 0, left: 41, bottom: 21, right: 41)],
// iPhone 11
"iPhone12,1": [.portrait: UIEdgeInsets(top: 48, left: 0, bottom: 34, right: 0),
.landscapeLeft: UIEdgeInsets(top: 0, left: 48, bottom: 21, right: 48)],
"iPhone12,1-Zoom": [.portrait: UIEdgeInsets(top: 44, left: 0, bottom: 31, right: 0),
.landscapeLeft: UIEdgeInsets(top: 0, left: 44, bottom: 21, right: 44)],
// iPhone 11 Pro Max
"iPhone12,5": [.portrait: UIEdgeInsets(top: 44, left: 0, bottom: 34, right: 0),
.landscapeLeft: UIEdgeInsets(top: 0, left: 44, bottom: 21, right: 44)],
"iPhone12,5-Zoom": [.portrait: UIEdgeInsets(top: 40, left: 0, bottom: 30 + 2.0 / 3.0, right: 0),
.landscapeLeft: UIEdgeInsets(top: 0, left: 40, bottom: 21, right: 40)]
]
var deviceKey = deviceModel
if dict[deviceKey] == nil {
deviceKey = "iPhone15,2" // 默认按最新的机型处理,因为新出的设备肯定更大概率与上一代设备相似
}
if isZoomedMode() {
deviceKey = deviceKey + "-Zoom"
}
var orientationKey = UIInterfaceOrientation.unknown
let value = dict[deviceKey]
var insets = value![orientationKey]!
if (UIWindow.isLandscape) {
orientationKey = .landscapeLeft
insets = UIEdgeInsets(top: insets.top, left: insets.right, bottom: insets.bottom, right: insets.left)
} else {
orientationKey = .portrait
insets = UIEdgeInsets(top: insets.bottom, left: insets.left, bottom: insets.top, right: insets.right)
}
return insets
}
}
extension GKDevice {
public static let version: Double? = {
return Double(UIDevice.current.systemVersion)
}()
public static let width: CGFloat = {
min(UIScreen.main.bounds.size.width, UIScreen.main.bounds.size.height)
}()
public static let height: CGFloat = {
max(UIScreen.main.bounds.size.width, UIScreen.main.bounds.size.height)
}()
// MARK - Screen
/// iPhone 14 Pro Max
public static let is67InchScreenAndiPhone14ProMax: Bool = {
return width == _67InchAndiPhone14ProMax.width && height == _67InchAndiPhone14ProMax.height
}()
/// iPhone 12 Pro Max
public static let is67InchScreen: Bool = {
return width == _67Inch.width && height == _67Inch.height
}()
/// iPhone XS Max / 11 Pro Max
public static let is65InchScreen: Bool = {
// 由于 iPhone XS Max、iPhone 11 Pro Max 这两款机型和 iPhone XR 的屏幕宽高是一致的,我们通过机器的 Identifier 加以区别
return (width == _65Inch.width && height == _65Inch.height && (deviceModel == "iPhone11,4" || deviceModel == "iPhone11,6" || deviceModel == "iPhone12,5"))
}()
/// iPhone 14 Pro
public static let is61InchScreenAndiPhone14Pro: Bool = {
return width == _61InchAndiPhone14Pro.width && height == _61InchAndiPhone14Pro.height
}()
/// iPhone 12 / 12 Pro
public static let is61InchScreenAndiPhone12Later: Bool = {
return width == _61InchAndiPhone12Later.width && height == _61InchAndiPhone12Later.height
}()
/// iPhone XR / 11
public static let is61InchScreen: Bool = {
return (width == _61Inch.width && height == _61Inch.height && (deviceModel == "iPhone11,8" || deviceModel == "iPhone12,1"))
}()
/// iPhone X / XS / 11 Pro
public static let is58InchScreen: Bool = {
// iPhone XS 和 iPhone X 的物理尺寸是一致的,因此无需比较机器 Identifier
return width == _58Inch.width && height == _58Inch.height
}()
/// iPhone 6,6s,7,8 Plus
public static let is55InchScreen: Bool = {
return width == _55Inch.width && height == _55Inch.height
}()
/// iPhone 12 mini
public static let is54InchScreen: Bool = {
return width == _54Inch.width && height == _54Inch.height
}()
/// iPhone 6,6s,7,8,SE2
public static let is47InchScreen: Bool = {
return width == _47Inch.width && height == _47Inch.height
}()
/// iPhone 5,5s,5c,SE
public static let is40InchScreen: Bool = {
return width == _40Inch.width && height == _40Inch.height
}()
/// iPhone 4
public static let is35InchScreen: Bool = {
return width == _35Inch.width && height == _35Inch.height
}()
public static let _67InchAndiPhone14ProMax: CGSize = {
return CGSize(width: 430, height: 932)
}()
public static let _67Inch: CGSize = {
return CGSize(width: 428, height: 926)
}()
public static let _65Inch: CGSize = {
return CGSize(width: 414, height: 896)
}()
public static let _61InchAndiPhone14Pro: CGSize = {
return CGSize(width: 393, height: 852)
}()
public static let _61InchAndiPhone12Later: CGSize = {
return CGSize(width: 390, height: 844)
}()
public static let _61Inch: CGSize = {
return CGSize(width: 414, height: 896)
}()
public static let _58Inch: CGSize = {
return CGSize(width: 375, height: 812)
}()
public static let _55Inch: CGSize = {
return CGSize(width: 414, height: 736)
}()
public static let _54Inch: CGSize = {
return CGSize(width: 375, height: 812)
}()
public static let _47Inch: CGSize = {
return CGSize(width: 375, height: 667)
}()
public static let _40Inch: CGSize = {
return CGSize(width: 320, height: 568)
}()
public static let _35Inch: CGSize = {
return CGSize(width: 320, height: 480)
}()
}
//
// GKNavigationBarDefine.swift
// GKNavigationBarSwift
//
// Created by QuintGao on 2020/3/24.
// Copyright © 2020 QuintGao. All rights reserved.
//
import UIKit
/// 导航栏间距,用于不同控制器之间的间距
public let GKNavigationBarItemSpace: CGFloat = -1.0
public enum GKNavigationBarBackStyle {
case none
case black
case white
}
public func gk_swizzled_instanceMethod(_ prefix: String, oldClass: Swift.AnyClass!, oldSelector: String, newClass: Swift.AnyClass) {
let newSelector = prefix + "_" + oldSelector;
let originalSelector = NSSelectorFromString(oldSelector)
let swizzledSelector = NSSelectorFromString(newSelector)
let originalMethod = class_getInstanceMethod(oldClass, originalSelector)
let swizzledMethod = class_getInstanceMethod(newClass, swizzledSelector)
let isAdd = class_addMethod(oldClass, originalSelector, method_getImplementation(swizzledMethod!), method_getTypeEncoding(swizzledMethod!))
if isAdd {
class_replaceMethod(newClass, swizzledSelector, method_getImplementation(originalMethod!), method_getTypeEncoding(originalMethod!))
}else {
method_exchangeImplementations(originalMethod!, swizzledMethod!)
}
}
public func gk_getAssociatedObject(_ object: Any, _ key: UnsafeRawPointer) -> Any? {
return objc_getAssociatedObject(object, key)
}
public func gk_setAssociatedObject(_ object: Any, _ key: UnsafeRawPointer, _ value: Any?) {
objc_setAssociatedObject(object, key, value, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
// 定义Awake协议,让需要重新系统方法的类实现该协议
public protocol GKObjectAwakeProtocol: AnyObject {
static func gkObjectAwake()
}
public protocol GKAwakeProtocol: AnyObject {
static func gkAwake()
}
public protocol GKChildAwakeProtocol: AnyObject {
static func gkChildAwake()
}
public protocol GKGestureAwakeProtocol: AnyObject {
static func gkGestureAwake()
}
public protocol GKGestureChildAwakeProtocol: AnyObject {
static func gkGestureChildAwake()
}
// MARK: - Swizzling会改变全局状态,所以用DispatchQueue.once来确保无论多少线程都只会被执行一次
extension DispatchQueue {
private static var onceTracker = [String]()
// Executes a block of code, associated with a unique token, only once. The code is thread safe and will only execute the code once even in the presence of multithreaded calls.
public class func once(token: String, block: () -> Void) {
// 保证被 objc_sync_enter 和 objc_sync_exit 包裹的代码可以有序同步地执行
objc_sync_enter(self)
defer { // 作用域结束后执行defer中的代码
objc_sync_exit(self)
}
if onceTracker.contains(token) {
return
}
onceTracker.append(token)
block()
}
}
//
// GKNavigationBarSwift.h
// GKNavigationBarSwift
//
// Created by QuintGao on 2020/4/11.
// Copyright © 2020 QuintGao. All rights reserved.
//
#import <Foundation/Foundation.h>
//! Project version number for GKNavigationBarSwift.
FOUNDATION_EXPORT double GKNavigationBarSwiftVersionNumber;
//! Project version string for GKNavigationBarSwift.
FOUNDATION_EXPORT const unsigned char GKNavigationBarSwiftVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <GKNavigationBarSwift/PublicHeader.h>
//
// GKNavigationBarSwift.swift
// GKNavigationBarSwift
//
// Created by QuintGao on 2020/3/25.
// Copyright © 2020 QuintGao. All rights reserved.
// Custom navigation bar
import UIKit
open class GKNavigationBar: UINavigationBar {
/// 当前所在的控制器是否隐藏状态栏
public var gk_statusBarHidden: Bool = false
/// 导航栏透明度
public var gk_navBarBackgroundAlpha: CGFloat = 1 {
willSet {
for obj in self.subviews {
if let cls = NSClassFromString("_UIBarBackground") {
if #available(iOS 10.0, *), obj.isKind(of: cls) {
DispatchQueue.main.async {
if obj.alpha != newValue {
obj.alpha = newValue
}
}
}else {
if let navBarBackgroundCls = NSClassFromString("_UINavigationBarBackground") {
if obj.isKind(of: navBarBackgroundCls) {
DispatchQueue.main.async {
if obj.alpha != newValue {
obj.alpha = newValue
}
}
}
}
}
}
}
let isClipsToBounds = (newValue == 0.0)
if self.clipsToBounds != isClipsToBounds {
self.clipsToBounds = isClipsToBounds
}
}
}
/// 导航栏分割线是否隐藏
public var gk_navLineHidden: Bool = false
/// 是否是非全屏控制器
public var gk_nonFullScreen: Bool = false
public override init(frame: CGRect) {
super.init(frame:frame)
self.gk_navBarBackgroundAlpha = 1.0
}
required public init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
open override func layoutSubviews() {
super.layoutSubviews()
/// 适配iOS11及以上,遍历所有子控件,向下移动状态栏高度
if #available(iOS 11.0, *) {
for obj in self.subviews {
if let cls = NSClassFromString("_UIBarBackground") {
if obj.isKind(of: cls) {
var frame = obj.frame
frame.size.height = self.frame.size.height
obj.frame = frame
}else {
let navBarHNFS = GKDevice.navBarHeightNonFullScreen()
let navBarH = GKDevice.navBarHeight()
var frame = obj.frame
frame.origin.y = self.frame.size.height - (self.gk_nonFullScreen ? navBarHNFS : navBarH)
obj.frame = frame
}
}
}
}
// 重新设置透明度
let alpha = self.gk_navBarBackgroundAlpha
self.gk_navBarBackgroundAlpha = alpha
// 分割线处理
self.gk_navLineHideOrShow()
}
fileprivate func gk_navLineHideOrShow() {
guard let backgroundView = self.subviews.first else { return }
for view in backgroundView.subviews {
if view.frame.size.height > 0 && view.frame.size.height <= 1.0 {
view.isHidden = self.gk_navLineHidden
}
}
}
}
// 实现touches方法,防止其实现父试图的touches方法
extension GKNavigationBar {
open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
}
open override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
}
open override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
}
open override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
}
}
//
// GKNavigationInteractiveTransition.swift
// GKNavigationBarSwift
//
// Created by QuintGao on 2020/11/27.
// Copyright © 2020 QuintGao. All rights reserved.
//
import UIKit
class GKNavigationInteractiveTransition: NSObject {
var isGesturePush: Bool = false
var pushTransition: UIPercentDrivenInteractiveTransition?
var popTransition: UIPercentDrivenInteractiveTransition?
weak var navigationController: UINavigationController!
weak var visibleVC: UIViewController?
var systemTarget: Any?
var systemAction: Selector?
// MARK: - 滑动手势处理
@objc public func panGestureAction(_ gesture: UIPanGestureRecognizer) {
// 进度
guard let width = gesture.view?.bounds.size.width else { return }
if width == 0 { return }
var progress = gesture.translation(in: gesture.view).x / width
let velocity = gesture.velocity(in: gesture.view)
// 在手势开始的时候判断是push操作还是pop操作
if gesture.state == .began {
self.isGesturePush = velocity.x < 0 ? true : false
self.visibleVC = self.navigationController.visibleViewController
}
// push时progress < 0 需要做处理
if self.isGesturePush {
progress = -progress
}
progress = min(1.0, max(0.0, progress))
if gesture.state == .began {
if self.isGesturePush { // push
if self.navigationController.gk_openScrollLeftPush {
if let visibleVC = self.visibleVC {
if visibleVC.gk_pushDelegate != nil {
self.pushTransition = UIPercentDrivenInteractiveTransition()
visibleVC.gk_pushDelegate?.pushToNextViewController?()
}
}
}
pushScrollBegan()
}else { // pop
if self.navigationController.gk_transitionScale {
self.popTransition = UIPercentDrivenInteractiveTransition()
self.navigationController.popViewController(animated: true)
}else {
if let visibleVC = self.visibleVC {
if visibleVC.gk_systemGestureHandleDisabled {
var shouldPop = visibleVC.navigationShouldPop()
let selector = NSSelectorFromString("navigationShouldPopOnGesture")
if visibleVC.responds(to: selector) {
if visibleVC.perform(selector) != nil {
shouldPop = true
}else {
shouldPop = false
}
}
if shouldPop {
self.popTransition = UIPercentDrivenInteractiveTransition()
self.navigationController.popViewController(animated: true)
}
}
}
}
popScrollBegan()
}
}else if gesture.state == .changed {
if self.isGesturePush {
if self.pushTransition != nil {
self.pushTransition?.update(progress)
}
pushScrollUpdate(progress: progress)
}else {
if self.popTransition != nil {
self.popTransition?.update(progress)
}
popScrollUpdate(progress: progress)
}
}else if gesture.state == .ended || gesture.state == .cancelled {
if self.isGesturePush {
var pushFinished: Bool = progress > 0.5
if self.pushTransition != nil {
if GKConfigure.isVelocityInsensitivity(velocity.x) && velocity.x < 0 {
pushFinished = true
self.pushTransition?.finish()
}else {
if progress > GKConfigure.gk_pushTransitionCriticalValue {
pushFinished = true
self.pushTransition?.finish()
}else {
pushFinished = false
self.pushTransition?.cancel()
}
}
}
pushScrollEnded(finished: pushFinished)
}else {
var popFinished: Bool = progress > 0.5
if self.popTransition != nil {
if GKConfigure.isVelocityInsensitivity(velocity.x) && velocity.x > 0 {
popFinished = true
self.popTransition?.finish()
}else {
if progress > GKConfigure.gk_popTransitionCriticalValue {
popFinished = true
self.popTransition?.finish()
}else {
popFinished = false
self.popTransition?.cancel()
}
}
}
popScrollEnded(finished: popFinished)
}
self.pushTransition = nil
self.popTransition = nil
self.visibleVC = nil
self.isGesturePush = false
}
}
func pushScrollBegan() {
if let visibleVC = self.visibleVC {
visibleVC.gk_pushDelegate?.viewControllerPushScrollBegan?()
}
}
func pushScrollUpdate(progress: CGFloat) {
if let visibleVC = self.visibleVC {
visibleVC.gk_pushDelegate?.viewControllerPushScrollUpdate?(progress: progress)
}
}
func pushScrollEnded(finished: Bool) {
if let visibleVC = self.visibleVC {
visibleVC.gk_pushDelegate?.viewControllerPushScrollEnded?(finished: finished)
}
}
func popScrollBegan() {
if let visibleVC = self.visibleVC {
visibleVC.gk_popDelegate?.viewControllerPopScrollBegan?()
}
}
func popScrollUpdate(progress: CGFloat) {
if let visibleVC = self.visibleVC {
visibleVC.gk_popDelegate?.viewControllerPopScrollUpdate?(progress: progress)
}
}
func popScrollEnded(finished: Bool) {
if let visibleVC = self.visibleVC {
visibleVC.gk_popDelegate?.viewControllerPopScrollEnded?(finished: finished)
}
}
}
extension GKNavigationInteractiveTransition: UINavigationControllerDelegate {
func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationController.Operation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
if fromVC.gk_pushTransition != nil && operation == .push {
return fromVC.gk_pushTransition
}
if fromVC.gk_popTransition != nil && operation == .pop {
return fromVC.gk_popTransition
}
let isScale = self.navigationController.gk_transitionScale
if (isScale || self.pushTransition != nil) && operation == .push {
return GKPushAnimatedTransition(scale: isScale)
}
if (isScale || self.popTransition != nil) && operation == .pop {
return GKPopAnimatedTransition(scale: isScale)
}
return nil
}
func navigationController(_ navigationController: UINavigationController, interactionControllerFor animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
if self.pushTransition != nil && animationController.isKind(of: GKPushAnimatedTransition.self) {
return self.pushTransition
}
if self.popTransition != nil && animationController.isKind(of: GKPopAnimatedTransition.self) {
return self.popTransition
}
return nil
}
}
extension GKNavigationInteractiveTransition: UIGestureRecognizerDelegate {
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
// 不是UIPanGestureRecognizer,不作处理
if gestureRecognizer.isKind(of: UIPanGestureRecognizer.self) == false {
return true
}
// 转为UIPanGestureRecognizer
let panGesture = gestureRecognizer as! UIPanGestureRecognizer
// 如果没有visibleViewController,不作处理
guard let visibleVC = self.navigationController.visibleViewController else {
return true
}
// 当前VC禁止滑动返回
if visibleVC.gk_interactivePopDisabled {
return false
}
// 根据transition判断是左滑还是右滑
let transition = panGesture.translation(in: gestureRecognizer.view)
// 如果开启缩放,则移除系统处理
if self.navigationController.gk_transitionScale {
gestureRecognizer.removeTarget(self.systemTarget, action: self.systemAction)
}
if transition.x < 0 { // 左滑
// 开启了左滑push并设置了代理
if self.navigationController.gk_openScrollLeftPush && visibleVC.gk_pushDelegate != nil {
gestureRecognizer.removeTarget(self.systemTarget, action: self.systemAction)
}else {
return false
}
}else if (transition.x > 0) { // 右滑
if !visibleVC.gk_systemGestureHandleDisabled {
var shouldPop = visibleVC.navigationShouldPop()
let selector = NSSelectorFromString("navigationShouldPopOnGesture")
if visibleVC.responds(to: selector) {
if visibleVC.perform(selector) != nil {
shouldPop = true
}else {
shouldPop = false
}
}
if shouldPop == false { return false }
}
// 解决根控制器右滑时出现的卡死情况
if self.navigationController.viewControllers.count <= 1 { return false }
// 忽略超出手势区域
let beginningLocation = gestureRecognizer.location(in: gestureRecognizer.view)
let maxAllowDistance = visibleVC.gk_maxPopDistance
if maxAllowDistance > 0 && beginningLocation.x > maxAllowDistance { return false }
}else {
if visibleVC.gk_fullScreenPopDisabled {
// 修复边缘侧滑返回失效的bug
if self.navigationController.viewControllers.count <= 1 {
return false
}
}else {
// 修复全屏返回手势上下滑动时可能导致的卡死情况
return false
}
}
// 忽略导航控制器正在做转场动画
if self.navigationController.value(forKey: "_isTransitioning") as? Bool == true { return false }
return true
}
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
// 获取当前显示的VC
guard let visibleVC = navigationController.visibleViewController else { return false }
let selector = NSSelectorFromString("popGestureRecognizer:shouldRecognizeSimultaneouslyWith:")
if visibleVC.responds(to: selector) {
if visibleVC.perform(selector, with: gestureRecognizer, with: otherGestureRecognizer) != nil {
return true
}else {
return false
}
}
return false
}
}
//
// GKPopAnimatedTransition.swift
// GKNavigationBarSwift
//
// Created by QuintGao on 2020/3/24.
// Copyright © 2020 QuintGao. All rights reserved.
//
import UIKit
open class GKPopAnimatedTransition: GKBaseAnimatedTransition {
public override func animateTransition() {
// 是否隐藏tabBar
self.isHideTabBar = (self.toViewController.tabBarController != nil) && (self.fromViewController.hidesBottomBarWhenPushed == true) && (self.toViewController.gk_captureImage != nil)
if (self.toViewController.navigationController?.children.first != self.toViewController) {
self.isHideTabBar = false
}
let tabBar = self.toViewController.tabBarController?.tabBar
if (tabBar == nil) {
self.isHideTabBar = false
}
let screenW = self.containerView.bounds.size.width
let screenH = self.containerView.bounds.size.height
let toView = UIView(frame: self.containerView.bounds)
var captureView: UIView? = nil
toView.addSubview(self.toViewController.view)
if self.isHideTabBar {
captureView = UIImageView(image: self.toViewController.gk_captureImage!)
var frame = tabBar!.frame
frame.origin.x = 0
captureView?.frame = frame
toView.addSubview(captureView!)
tabBar?.isHidden = true
}
if self.isScale {
self.shadowView = UIView(frame: CGRect(x: 0, y: 0, width: screenW, height: screenH))
self.shadowView.backgroundColor = UIColor.black.withAlphaComponent(0.6)
toView.addSubview(self.shadowView)
toView.transform = CGAffineTransform(scaleX: GKConfigure.gk_scaleX, y: GKConfigure.gk_scaleY)
}else {
var frame = toView.frame
frame.origin.x = -0.3 * frame.size.width
toView.frame = frame
}
self.containerView.insertSubview(toView, belowSubview: self.fromViewController.view)
self.fromViewController.view.layer.shadowColor = UIColor.black.cgColor
self.fromViewController.view.layer.shadowOpacity = 0.15
self.fromViewController.view.layer.shadowRadius = 3.0
UIView.animate(withDuration: animationDuration(), animations: {
self.fromViewController.view.frame = CGRect(x: screenW, y: 0, width: screenW, height: screenH)
if self.isScale {
self.shadowView.backgroundColor = UIColor.black.withAlphaComponent(0)
toView.transform = .identity
}else {
var frame = toView.frame
frame.origin.x = 0
toView.frame = frame
}
}) { (finished) in
if self.isHideTabBar {
self.toViewController.gk_captureImage = nil
if (self.transitionContext.transitionWasCancelled) {
self.toViewController.view.removeFromSuperview()
}else {
self.containerView.addSubview(self.toViewController.view)
}
toView.transform = .identity
toView.removeFromSuperview()
if (captureView != nil) {
captureView?.removeFromSuperview()
captureView = nil
}
if (self.toViewController.navigationController?.children.count == 1) {
tabBar?.isHidden = false
}
}
if self.isScale {
self.shadowView.removeFromSuperview()
}
self.completeTransition()
}
}
}
//
// GKPushAnimatedTransition.swift
// GKNavigationBarSwift
//
// Created by QuintGao on 2020/3/24.
// Copyright © 2020 QuintGao. All rights reserved.
//
import UIKit
open class GKPushAnimatedTransition: GKBaseAnimatedTransition {
public override func animateTransition() {
// 解决UITabBarController左滑push时的显示问题
self.isHideTabBar = (self.fromViewController.tabBarController != nil) && (self.toViewController.hidesBottomBarWhenPushed == true)
let tabBar = self.fromViewController.tabBarController?.tabBar
if (tabBar == nil) {
self.isHideTabBar = false
}
// tabBar位置不对或隐藏
if (tabBar?.frame.origin.x != 0 || tabBar?.isHidden == true) {
self.isHideTabBar = false
}
// 非根控制器
if (self.fromViewController.navigationController?.children.first != self.fromViewController) {
self.isHideTabBar = false
}
let screenW = self.containerView.bounds.size.width
let screenH = self.containerView.bounds.size.height
let fromView = UIView(frame: self.containerView.bounds)
fromView.addSubview(fromViewController.view)
var captureView: UIView? = nil
if self.isHideTabBar {
// 截取tabBar
let captureImage = GKConfigure.getCapture(with: tabBar!)
self.fromViewController.gk_captureImage = captureImage
captureView = UIImageView(image: captureImage)
var frame = tabBar!.frame;
frame.origin.x = 0
captureView?.frame = frame
fromView.addSubview(captureView!)
tabBar?.isHidden = true
}
if self.isScale {
self.shadowView = UIView(frame: CGRect(x: 0, y: 0, width: screenW, height: screenH))
self.shadowView.backgroundColor = UIColor.black.withAlphaComponent(0)
fromView.addSubview(self.shadowView)
fromView.transform = .identity
}
self.containerView.addSubview(fromView)
// 设置toViewController
self.toViewController.view.frame = CGRect(x: screenW, y: 0, width: screenW, height: screenH)
self.toViewController.view.layer.shadowColor = UIColor.black.cgColor
self.toViewController.view.layer.shadowOpacity = 0.15
self.toViewController.view.layer.shadowRadius = 3.0
self.containerView.addSubview(self.toViewController.view)
UIView.animate(withDuration: animationDuration(), animations: {
if self.isScale {
self.shadowView.backgroundColor = UIColor.black.withAlphaComponent(0.6)
fromView.transform = CGAffineTransform(scaleX: GKConfigure.gk_scaleX, y: GKConfigure.gk_scaleY)
}else {
var frame = fromView.frame
frame.origin.x = -0.3 * frame.size.width
fromView.frame = frame
}
self.toViewController.view.frame = CGRect(x: 0, y: 0, width: screenW, height: screenH)
}) { (finished) in
if self.isHideTabBar {
if (self.transitionContext.transitionWasCancelled) {
self.containerView.addSubview(self.fromViewController.view)
}else {
self.fromViewController.view.removeFromSuperview()
}
fromView.transform = .identity
fromView.removeFromSuperview()
if (captureView != nil) {
captureView?.removeFromSuperview()
captureView = nil
}
}
if self.isScale {
self.shadowView.removeFromSuperview()
}
self.completeTransition()
}
}
}
//
// UIBarButtonItem+GKExtension.swift
// GKNavigationBarSwift
//
// Created by QuintGao on 2020/3/25.
// Copyright © 2020 QuintGao. All rights reserved.
//
import UIKit
extension UIBarButtonItem {
public class func gk_item(title: String?, target: Any, action: Selector) -> UIBarButtonItem {
gk_item(title: title, image: nil, target: target, action: action)
}
public class func gk_item(title: String?, font: UIFont?, target: Any, action: Selector) -> UIBarButtonItem {
gk_item(title: title, color: nil, font: font, target: target, action: action)
}
public class func gk_item(title: String?, color: UIColor?, target: Any, action: Selector) -> UIBarButtonItem {
gk_item(title: title, color: color, font: nil, target: target, action: action)
}
public class func gk_item(title: String?, color: UIColor?, font: UIFont?, target: Any, action: Selector) -> UIBarButtonItem {
gk_item(title: title, titleColor: color, font: font, image: nil, imageColor: nil, highLightImage: nil, target: target, action: action)
}
public class func gk_item(image: UIImage?, target: Any, action: Selector) -> UIBarButtonItem {
gk_item(title: nil, image: image, target: target, action: action)
}
public class func gk_item(image: UIImage?, color: UIColor?, target: Any, action: Selector) -> UIBarButtonItem {
gk_item(title: nil, titleColor: nil, font: nil, image: image, imageColor: color, highLightImage: nil, target: target, action: action)
}
public class func gk_item(image: UIImage?, highLightImage: UIImage?, target: Any, action: Selector) -> UIBarButtonItem {
gk_item(title: nil, titleColor: nil, font: nil, image: image, imageColor: nil, highLightImage: highLightImage, target: target, action: action)
}
public class func gk_item(title: String?, image: UIImage?, target: Any, action: Selector) -> UIBarButtonItem {
gk_item(title: title, titleColor: nil, font: nil, image: image, imageColor: nil, highLightImage: nil, target: target, action: action)
}
public class func gk_item(title: String?, titleColor: UIColor?, font: UIFont?, image: UIImage?, imageColor: UIColor?, highLightImage: UIImage?, target: Any, action: Selector) -> UIBarButtonItem {
let button = UIButton()
if let title = title {
button.setTitle(title, for: .normal)
}
if let titleColor = titleColor {
button.setTitleColor(titleColor, for: .normal)
}
if let font = font {
button.titleLabel?.font = font
}
var buttonImage = image
if let image = image, let imageColor = imageColor {
buttonImage = UIImage.gk_change(with: image, color: imageColor)
}
if let buttonImage = buttonImage {
button.setImage(buttonImage, for: .normal)
}
if let highLightImage = highLightImage {
button.setImage(highLightImage, for: .highlighted)
}
button.sizeToFit()
if button.bounds.size.width < 44.0 {
button.bounds = CGRect(x: 0, y: 0, width: 44.0, height: 44.0)
}
button.addTarget(target, action: action, for: .touchUpInside)
return UIBarButtonItem(customView: button)
}
}
//
// UIImage+GKExtension.swift
// GKNavigationBarSwift
//
// Created by QuintGao on 2020/3/25.
// Copyright © 2020 QuintGao. All rights reserved.
//
import UIKit
extension UIImage {
public class func gk_image(with name: String) -> UIImage? {
var image: UIImage?
if let bundle = Bundle.gk_bundle {
image = UIImage(named: name, in: bundle, compatibleWith: nil)
}
if image == nil {
image = UIImage(named: name)
}
return image
}
public class func gk_image(with color: UIColor) -> UIImage? {
return self.gk_image(with: color, size: CGSize(width: 1, height: 1))
}
public class func gk_image(with color: UIColor, size: CGSize) -> UIImage? {
if size.width <= 0 || size.height <= 0 { return nil }
let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
UIGraphicsBeginImageContext(size)
guard let context = UIGraphicsGetCurrentContext() else { return nil }
context.setFillColor(color.cgColor)
context.fill(rect)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}
public class func gk_change(with image: UIImage?, color: UIColor) -> UIImage? {
guard let image = image else { return nil }
if image.size.width <= 0 || image.size.height <= 0 { return nil }
let drawRect = CGRectMake(0, 0, image.size.width, image.size.height)
UIGraphicsBeginImageContextWithOptions(image.size, false, image.scale)
guard let context = UIGraphicsGetCurrentContext() else { return nil }
context.setBlendMode(.normal)
context.clip(to: drawRect, mask: image.cgImage!)
color.setFill()
context.fill(drawRect)
guard let resultImage = UIGraphicsGetImageFromCurrentImageContext() else { return nil }
UIGraphicsEndImageContext()
return resultImage
}
}
//
// UINavigationController+GKExtension.swift
// GKNavigationBarSwift
//
// Created by QuintGao on 2020/3/25.
// Copyright © 2020 QuintGao. All rights reserved.
//
import UIKit
extension UINavigationController: GKChildAwakeProtocol {
// MARK: - 重新系统方法
private static let onceToken = UUID().uuidString
public static func gkChildAwake() {
DispatchQueue.once(token: onceToken) {
gk_swizzled_instanceMethod("gkNav", oldClass: self, oldSelector: "pushViewController:animated:", newClass: self)
}
}
@objc func gkNav_pushViewController(_ viewController: UIViewController, animated: Bool) {
if self.gk_openSystemNavHandle {
self.isNavigationBarHidden = true
}
gkNav_pushViewController(viewController, animated: animated)
}
}
extension UINavigationController {
fileprivate struct AssociatedKeys {
static var gkOpenSystemNavHandle: Void?
static var gkHideNavigationBar: Void?
}
public var gk_openSystemNavHandle: Bool {
get {
guard let obj = gk_getAssociatedObject(self, &AssociatedKeys.gkOpenSystemNavHandle) as? Bool else { return false }
return obj
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkOpenSystemNavHandle, newValue)
}
}
public var gk_hideNavigationBar: Bool {
get {
guard let obj = gk_getAssociatedObject(self, &AssociatedKeys.gkHideNavigationBar) as? Bool else { return false }
return obj
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkHideNavigationBar, newValue)
}
}
}
//
// UINavigationController+GKGesture.swift
// GKNavigationBarSwift
//
// Created by QuintGao on 2022/3/18.
// Copyright © 2022 QuintGao. All rights reserved.
//
import UIKit
extension UINavigationController {
// 创建便利构造函数为UINavigationcontroller增加初始化方法
public convenience init(rootVC: UIViewController) {
self.init()
gk_openGestureHandle = true
gk_transitionScale = false
pushViewController(rootVC, animated: true)
}
public convenience init(rootVC: UIViewController, scale: Bool) {
self.init()
gk_openGestureHandle = true
gk_transitionScale = scale
pushViewController(rootVC, animated: true)
}
}
extension UINavigationController: GKGestureChildAwakeProtocol {
// MARK: - 重新系统方法
private static let onceToken = UUID().uuidString
public static func gkGestureChildAwake() {
DispatchQueue.once(token: onceToken) {
let oriSels = ["viewDidLoad",
"pushViewController:animated:",
"navigationBar:shouldPopItem:"
]
for oriSel in oriSels {
gk_swizzled_instanceMethod("gkNavGesture", oldClass: self, oldSelector: oriSel, newClass: self)
}
}
}
@objc func gkNavGesture_viewDidLoad() {
if self.gk_openGestureHandle {
if self.isKind(of: UIImagePickerController.self) {
return
}
if self.isKind(of: UIVideoEditorController.self) {
return
}
// 设置背景色
self.view.backgroundColor = UIColor.black
// 设置代理
self.delegate = self.interactiveTransition
self.interactivePopGestureRecognizer?.isEnabled = false
// 注册控制器属性改变通知
NotificationCenter.default.addObserver(self, selector: #selector(propertyChangeNotification(_:)), name: GKViewControllerPropertyChanged, object: nil)
}
gkNavGesture_viewDidLoad()
}
@objc func gkNavGesture_pushViewController(_ viewController: UIViewController, animated: Bool) {
if self.children.count > 0 {
let rootVC = self.children.first!
// 获取tabbar截图
if viewController.gk_systemGestureHandleDisabled && rootVC.gk_captureImage == nil {
rootVC.gk_captureImage = GKConfigure.getCapture(with: rootVC.view.window ?? rootVC.view)
}
// 设置push时是否隐藏tabbar
if GKConfigure.gk_hidesBottomBarWhenPushed && rootVC != viewController {
viewController.hidesBottomBarWhenPushed = true
}
}
gkNavGesture_pushViewController(viewController, animated: animated)
}
// source:https://github.com/onegray/UIViewController-BackButtonHandler
@objc func gkNavGesture_navigationBar(_ navigationBar: UINavigationBar, shouldPopItem: UINavigationItem) -> Bool {
if self.viewControllers.count < navigationBar.items?.count ?? 0 {
return true
}
var shouldPop = self.topViewController?.navigationShouldPop()
let selector = NSSelectorFromString("navigationShouldPopOnClick")
if let vc = self.topViewController, vc.responds(to: selector) {
if vc.perform(selector) != nil {
shouldPop = true
}else {
shouldPop = false
}
}
if shouldPop == true {
DispatchQueue.main.async { [self] in
popViewController(animated: true)
}
}else {
// Workaround for iOS7.1. Thanks to @boliva - http://stackoverflow.com/posts/comments/34452906
for subview in navigationBar.subviews {
if 0.0 < subview.alpha && subview.alpha < 1.0 {
UIView.animate(withDuration: 0.25) {
subview.alpha = 1.0
}
}
}
}
return false
}
@objc func propertyChangeNotification(_ notify: Notification) {
guard let obj = notify.object as? [String: Any] else { return }
let vc: UIViewController = obj["viewController"] as! UIViewController
// 不处理导航控制器和tabbar控制器
if vc.isKind(of: UINavigationController.self) { return }
if vc.isKind(of: UITabBarController.self) { return }
if vc.navigationController == nil { return }
if vc.navigationController != self { return }
// 修复非导航控制器子类时出现的问题
if vc.parent != self { return }
var exist = false
if let shiledVCs = GKConfigure.shiledGuestureVCs {
for obj in shiledVCs {
if obj is UIViewController.Type {
if vc.isKind(of: obj as! UIViewController.Type) {
exist = true
}
}else if obj is String {
if let cls = NSStringFromClass(vc.classForCoder).components(separatedBy: ".").last, let str = obj as? String {
if cls == str {
exist = true
}else if cls.contains(str) {
exist = true
}
}
}
}
}
if exist { return }
// 手势处理
if vc.gk_interactivePopDisabled { // 禁止滑动
self.view.removeGestureRecognizer(self.screenPanGesture)
self.view.removeGestureRecognizer(self.panGesture)
}else if vc.gk_fullScreenPopDisabled { // 禁止全屏滑动,支持边缘滑动
self.view.removeGestureRecognizer(self.panGesture)
self.view.addGestureRecognizer(self.screenPanGesture)
if vc.gk_systemGestureHandleDisabled {
self.screenPanGesture.removeTarget(self.systemTarget, action: self.systemAction)
}else {
self.screenPanGesture.addTarget(self.systemTarget!, action: self.systemAction)
}
}else { // 支持全屏滑动
self.view.removeGestureRecognizer(self.screenPanGesture)
self.view.addGestureRecognizer(self.panGesture)
if vc.gk_systemGestureHandleDisabled {
self.panGesture.removeTarget(self.systemTarget, action: self.systemAction)
}else {
self.panGesture.addTarget(self.systemTarget!, action: self.systemAction)
}
}
}
}
extension UINavigationController {
fileprivate struct AssociatedKeys {
static var gkTransitionScale: Void?
static var gkOpenScrollLeftPush: Void?
static var gkOpenGestureHandle: Void?
static var screenPanGesture: Void?
static var panGesture: Void?
static var transition: Void?
}
public var gk_transitionScale: Bool {
get {
guard let obj = gk_getAssociatedObject(self, &AssociatedKeys.gkTransitionScale) as? Bool else { return false }
return obj
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkTransitionScale, newValue)
}
}
public var gk_openScrollLeftPush: Bool {
get {
guard let obj = gk_getAssociatedObject(self, &AssociatedKeys.gkOpenScrollLeftPush) as? Bool else { return false }
return obj
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkOpenScrollLeftPush, newValue)
}
}
fileprivate var gk_openGestureHandle: Bool {
get {
guard let obj = gk_getAssociatedObject(self, &AssociatedKeys.gkOpenGestureHandle) as? Bool else { return false }
return obj
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkOpenGestureHandle, newValue)
}
}
var screenPanGesture: UIScreenEdgePanGestureRecognizer {
get {
var panGesture = gk_getAssociatedObject(self, &AssociatedKeys.screenPanGesture) as? UIScreenEdgePanGestureRecognizer
if panGesture == nil {
panGesture = UIScreenEdgePanGestureRecognizer(target: self.interactiveTransition, action:#selector(self.interactiveTransition.panGestureAction(_:)))
panGesture?.edges = .left
panGesture?.delegate = self.interactiveTransition
gk_setAssociatedObject(self, &AssociatedKeys.screenPanGesture, panGesture)
}
return panGesture!
}
}
var panGesture: UIPanGestureRecognizer {
get {
var panGesture = gk_getAssociatedObject(self, &AssociatedKeys.panGesture) as? UIPanGestureRecognizer
if panGesture == nil {
panGesture = UIPanGestureRecognizer(target: self.interactiveTransition, action: #selector(self.interactiveTransition.panGestureAction(_:)))
panGesture?.maximumNumberOfTouches = 1
panGesture?.delegate = self.interactiveTransition
gk_setAssociatedObject(self, &AssociatedKeys.panGesture, panGesture)
}
return panGesture!
}
}
var interactiveTransition: GKNavigationInteractiveTransition {
get {
var transition = gk_getAssociatedObject(self, &AssociatedKeys.transition) as? GKNavigationInteractiveTransition
if transition == nil {
transition = GKNavigationInteractiveTransition()
transition?.navigationController = self
transition?.systemTarget = self.systemTarget
transition?.systemAction = self.systemAction
gk_setAssociatedObject(self, &AssociatedKeys.transition, transition)
}
return transition!
}
}
var systemTarget: Any? {
get {
let internalTargets = self.interactivePopGestureRecognizer?.value(forKey: "targets") as? [AnyObject]
let internamTarget = internalTargets?.first?.value(forKey: "target")
return internamTarget
}
}
var systemAction: Selector {
return NSSelectorFromString("handleNavigationTransition:")
}
}
extension UINavigationController {
open override var childForStatusBarHidden: UIViewController? {
return topViewController
}
open override var childForStatusBarStyle: UIViewController? {
return topViewController
}
}
//
// UINavigationItem+GKExtension.swift
// GKNavigationBarSwift
//
// Created by QuintGao on 2020/3/25.
// Copyright © 2020 QuintGao. All rights reserved.
//
import UIKit
extension UINavigationItem: GKAwakeProtocol {
// MARK: - 重新系统方法
private static let onceToken = UUID().uuidString
@objc public static func gkAwake() {
DispatchQueue.once(token: onceToken) {
if #available(iOS 11.0, *) {} else {
let oriSels = ["setLeftBarButtonItem:animated:",
"setLeftBarButtonItems:animated:",
"setRightBarButtonItem:animated:",
"setRightBarButtonItems:animated:"]
for oriSel in oriSels {
gk_swizzled_instanceMethod("gk", oldClass: self, oldSelector: oriSel, newClass: self)
}
}
}
}
@objc func gk_setLeftBarButtonItem(_ item: UIBarButtonItem?, animated: Bool) {
if !GKConfigure.fixNavItemSpaceDisabled() && item != nil { // 存在按钮且需要调节
self.setLeftBarButtonItems([item!], animated: animated)
}else { // 不存在按钮或者不需要调节
self.setLeftBarButtonItems(nil, animated: false)
self.gk_setLeftBarButtonItem(item, animated: animated)
}
}
@objc func gk_setLeftBarButtonItems(_ items: [UIBarButtonItem]?, animated: Bool) {
guard var leftItems = items else { return }
if !GKConfigure.fixNavItemSpaceDisabled() && leftItems.count > 0 {
let firstItem = leftItems.first!
let width = GKConfigure.gk_navItemLeftSpace - GKConfigure.gk_fixedSpace()
if firstItem.width == width {
self.gk_setLeftBarButtonItems(leftItems, animated: animated)
}else {
leftItems.insert(fixedSpace(width), at: 0)
self.gk_setLeftBarButtonItems(leftItems, animated: animated)
}
}else {
self.gk_setLeftBarButtonItems(leftItems, animated: animated)
}
}
@objc func gk_setRightBarButtonItem(_ item: UIBarButtonItem?, animated: Bool) {
if !GKConfigure.fixNavItemSpaceDisabled() && item != nil {
self.setRightBarButtonItems([item!], animated: animated)
}else {
self.setRightBarButtonItems(nil, animated: false)
self.gk_setRightBarButtonItem(item, animated: animated)
}
}
@objc func gk_setRightBarButtonItems(_ items: [UIBarButtonItem]?, animated: Bool) {
guard var rightItems = items else { return }
if !GKConfigure.fixNavItemSpaceDisabled() && rightItems.count > 0 {
let firstItem = rightItems.first!
let width = GKConfigure.gk_navItemRightSpace - GKConfigure.gk_fixedSpace()
if firstItem.width == width {
self.gk_setRightBarButtonItems(items, animated: animated)
}else {
rightItems.insert(fixedSpace(width), at: 0)
self.gk_setRightBarButtonItems(rightItems, animated: animated)
}
}else {
self.gk_setRightBarButtonItems(rightItems, animated: animated);
}
}
fileprivate func fixedSpace(_ width: CGFloat) -> UIBarButtonItem {
let fixedItem = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil)
fixedItem.width = width
return fixedItem
}
}
extension NSObject: GKObjectAwakeProtocol {
// MARK: - 重新系统方法
private static let onceToken = UUID().uuidString
public static func gkObjectAwake() {
DispatchQueue.once(token: onceToken) {
if #available(iOS 11.0, *) {
let oriSels = ["_UINavigationBarContentView": "layoutSubviews", "_UINavigationBarContentViewLayout": "_updateMarginConstraints"]
for (cls, sel) in oriSels {
gk_swizzled_instanceMethod("gk", oldClass: NSClassFromString(cls), oldSelector: sel, newClass: NSObject.self)
}
}
}
}
@objc func gk_layoutSubviews() {
gk_layoutSubviews()
if GKConfigure.fixNavItemSpaceDisabled() { return }
if let cls = NSClassFromString("_UINavigationBarContentView") {
if !self.isMember(of: cls) { return }
guard let layout = self.value(forKey: "_layout") as? NSObject else { return }
let selector = NSSelectorFromString("_updateMarginConstraints")
if layout.responds(to: selector) {
layout.perform(selector)
}
}
}
@objc func gk__updateMarginConstraints() {
gk__updateMarginConstraints()
if GKConfigure.fixNavItemSpaceDisabled() { return }
if let cls = NSClassFromString("_UINavigationBarContentViewLayout") {
if !self.isMember(of: cls) { return }
gk_adjustLeadingBarConstraints()
gk_adjustTrailingBarConstraints()
}
}
fileprivate func gk_adjustLeadingBarConstraints() {
if GKConfigure.fixNavItemSpaceDisabled() { return }
let leadingBarConstrainst: [NSLayoutConstraint]? = self.value(forKey: "_leadingBarConstraints") as? [NSLayoutConstraint]
if leadingBarConstrainst == nil { return }
let constant = GKConfigure.gk_navItemLeftSpace - GKConfigure.gk_fixedSpace()
for constraint in leadingBarConstrainst! {
if constraint.firstAttribute == .leading && constraint.secondAttribute == .leading {
constraint.constant = constant
}
}
}
fileprivate func gk_adjustTrailingBarConstraints() {
if GKConfigure.fixNavItemSpaceDisabled() { return }
let trailingBarConstraints: [NSLayoutConstraint]? = self.value(forKey: "_trailingBarConstraints") as? [NSLayoutConstraint]
if trailingBarConstraints == nil { return }
let constant = GKConfigure.gk_fixedSpace() - GKConfigure.gk_navItemRightSpace
for constraint in trailingBarConstraints! {
if constraint.firstAttribute == .trailing && constraint.secondAttribute == .trailing {
constraint.constant = constant
}
}
}
}
//
// UIScrollView+GKExtension.swift
// GKNavigationBarSwift
//
// Created by QuintGao on 2020/3/25.
// Copyright © 2020 QuintGao. All rights reserved.
//
import UIKit
extension UIScrollView: GKAwakeProtocol {
fileprivate struct AssociatedKeys {
static var gkOpenGestureHandle: Void?
}
/// 是否开启UIScrollView左滑返回手势处理,默认NO
public var gk_openGestureHandle: Bool {
get {
guard let obj = gk_getAssociatedObject(self, &AssociatedKeys.gkOpenGestureHandle) as? Bool else { return false }
return obj
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkOpenGestureHandle, newValue)
}
}
// MARK: - 重新系统方法
private static let onceToken = UUID().uuidString
@objc public static func gkAwake() {
DispatchQueue.once(token: onceToken) {
let oriSels = ["willMoveToSuperview:"]
for oriSel in oriSels {
gk_swizzled_instanceMethod("gkGesture", oldClass: self, oldSelector: oriSel, newClass: self)
}
}
}
@objc func gkGesture_willMove(toSuperview newSuperview: UIView?) {
if (newSuperview != nil), GKConfigure.gk_openScrollViewGestureHandle {
self.gk_openGestureHandle = true
}
gkGesture_willMove(toSuperview: newSuperview)
}
}
extension UIScrollView {
open override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
if !self.gk_openGestureHandle {
return true
}
if self.panBack(gesture: gestureRecognizer) {
return false
}
return true
}
fileprivate func panBack(gesture: UIGestureRecognizer) -> Bool {
if gesture == self.panGestureRecognizer {
let point = self.panGestureRecognizer.translation(in: self)
let state = gesture.state
// 设置手势滑动的位置距离屏幕左边的区域
let locationDistance = UIScreen.main.bounds.size.width
if state == .began || state == .possible {
let location = gesture.location(in: self)
if point.x > 0 && location.x < locationDistance && contentOffset.x <= 0 {
return true
}
}
}
return false
}
}
//
// UIViewController+GKExtension.swift
// GKNavigationBarSwift
//
// Created by QuintGao on 2020/3/25.
// Copyright © 2020 QuintGao. All rights reserved.
//
import UIKit
extension UIViewController: GKAwakeProtocol {
fileprivate struct AssociatedKeys {
static var gkNavBarAlpha: Void?
static var gkNavBarInit: Void?
static var gkNavBarAdded: Void?
static var gkNavigationBar: Void?
static var gkNavigationItem: Void?
static var gkStatusBarHidden: Void?
static var gkStatusBarStyle: Void?
static var gkBackImage: Void?
static var gkDarkBackImage: Void?
static var gkBlackBackImage: Void?
static var gkWhiteBackImage: Void?
static var gkBackStyle: Void?
static var gkNavBackgroundColor: Void?
static var gkNavBackgroundImage: Void?
static var gkDarkNavBackgroundImage: Void?
static var gkNavShadowColor: Void?
static var gkNavShadowImage: Void?
static var gkDarkNavShadowImage: Void?
static var gkNavLineHidden: Void?
static var gkNavTitle: Void?
static var gkNavTitleView: Void?
static var gkNavTitleColor: Void?
static var gkNavTitleFont: Void?
static var gkNavLeftBarButtonItem: Void?
static var gkNavLeftBarButtonItems: Void?
static var gkNavRightBarButtonItem: Void?
static var gkNavRightBarButtonItems: Void?
static var gkDisableFixNavItemSpace: Void?
static var gkOpenFixNavItemSpace: Void?
static var gkNavItemLeftSpace: Void?
static var gkNavItemRightSpace: Void?
}
public var gk_navBarAlpha: CGFloat {
get {
guard let obj = gk_getAssociatedObject(self, &AssociatedKeys.gkNavBarAlpha) as? CGFloat else { return 1 }
return obj
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkNavBarAlpha, newValue)
self.gk_navigationBar.gk_navBarBackgroundAlpha = newValue
}
}
fileprivate var gk_navBarInit: Bool {
get {
guard let isInit = gk_getAssociatedObject(self, &AssociatedKeys.gkNavBarInit) as? Bool else { return false }
return isInit
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkNavBarInit, newValue)
}
}
fileprivate var gk_navBarAdded: Bool {
get {
guard let added = gk_getAssociatedObject(self, &AssociatedKeys.gkNavBarAdded) as? Bool else { return false }
return added
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkNavBarAdded, newValue)
}
}
public var gk_navigationBar: GKNavigationBar {
get {
var navigationBar = gk_getAssociatedObject(self, &AssociatedKeys.gkNavigationBar) as? GKNavigationBar
if navigationBar == nil {
navigationBar = GKNavigationBar()
self.gk_navBarInit = true
self.gk_navigationBar = navigationBar!
}
if self.isViewLoaded && !self.gk_navBarAdded {
self.view.addSubview(navigationBar!)
self.gk_navBarAdded = true
}
return navigationBar!
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkNavigationBar, newValue)
self.gk_disableFixNavItemSpace = GKConfigure.disableFixSpace
self.gk_openFixNavItemSpace = true
setupNavBarAppearance()
setupNavBarFrame()
}
}
public var gk_navigationItem: UINavigationItem {
get {
var item = gk_getAssociatedObject(self, &AssociatedKeys.gkNavigationItem) as? UINavigationItem
if item == nil {
item = UINavigationItem()
self.gk_navigationItem = item!
}
return item!
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkNavigationItem, newValue)
self.gk_navigationBar.items = [newValue]
}
}
public var gk_statusBarHidden: Bool {
get {
guard let isHidden = gk_getAssociatedObject(self, &AssociatedKeys.gkStatusBarHidden) as? Bool else { return false }
return isHidden
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkStatusBarHidden, newValue)
setNeedsStatusBarAppearanceUpdate()
}
}
public var gk_statusBarStyle: UIStatusBarStyle {
get {
guard let style = gk_getAssociatedObject(self, &AssociatedKeys.gkStatusBarStyle) as? UIStatusBarStyle else { return GKConfigure.statusBarStyle }
return style
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkStatusBarStyle, newValue)
setNeedsStatusBarAppearanceUpdate()
}
}
public var gk_backImage: UIImage? {
get {
return gk_getAssociatedObject(self, &AssociatedKeys.gkBackImage) as? UIImage
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkBackImage, newValue)
setBackItemImage(image: newValue)
}
}
public var gk_darkBackImage: UIImage? {
get {
return gk_getAssociatedObject(self, &AssociatedKeys.gkDarkBackImage) as? UIImage
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkDarkBackImage, newValue)
if #available(iOS 12.0, *) {
if traitCollection.userInterfaceStyle == .dark {
setBackItemImage(image: newValue)
}
}
}
}
public var gk_blackBackImage: UIImage? {
get {
guard let obj = gk_getAssociatedObject(self, &AssociatedKeys.gkBlackBackImage) else { return GKConfigure.blackBackImage }
return obj as? UIImage
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkBlackBackImage, newValue)
setBackItemImage(image: newValue)
}
}
public var gk_whiteBackImage: UIImage? {
get {
guard let obj = gk_getAssociatedObject(self, &AssociatedKeys.gkWhiteBackImage) else { return GKConfigure.whiteBackImage }
return obj as? UIImage
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkWhiteBackImage, newValue)
setBackItemImage(image: newValue)
}
}
public var gk_backStyle: GKNavigationBarBackStyle {
get {
guard let style = gk_getAssociatedObject(self, &AssociatedKeys.gkBackStyle) as? GKNavigationBarBackStyle else { return .none }
return style
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkBackStyle, newValue)
setBackItemImage(image: self.gk_backImage)
}
}
public var gk_navBackgroundColor: UIColor? {
get {
return gk_getAssociatedObject(self, &AssociatedKeys.gkNavBackgroundColor) as? UIColor
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkNavBackgroundColor, newValue)
setNavBackground(newValue)
}
}
public var gk_navBackgroundImage: UIImage? {
get {
return gk_getAssociatedObject(self, &AssociatedKeys.gkNavBackgroundImage) as? UIImage
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkNavBackgroundImage, newValue)
setNavBackground(newValue)
}
}
public var gk_darkNavBackgroundImage: UIImage? {
get {
return gk_getAssociatedObject(self, &AssociatedKeys.gkDarkNavBackgroundImage) as? UIImage
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkDarkNavBackgroundImage, newValue)
if #available(iOS 12.0, *) {
if traitCollection.userInterfaceStyle == .dark {
setNavBackground(newValue)
}
}
}
}
public var gk_navShadowColor: UIColor? {
get {
return gk_getAssociatedObject(self, &AssociatedKeys.gkNavShadowColor) as? UIColor
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkNavShadowColor, newValue)
setNavShadow(newValue)
}
}
public var gk_navShadowImage: UIImage? {
get {
return gk_getAssociatedObject(self, &AssociatedKeys.gkNavShadowImage) as? UIImage
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkNavShadowImage, newValue)
setNavShadow(newValue)
}
}
public var gk_darkNavShadowImage: UIImage? {
get {
return gk_getAssociatedObject(self, &AssociatedKeys.gkDarkNavShadowImage) as? UIImage
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkDarkNavShadowImage, newValue)
if #available(iOS 12.0, *) {
if traitCollection.userInterfaceStyle == .dark {
setNavShadow(newValue)
}
}
}
}
public var gk_navLineHidden: Bool {
get {
guard let obj = gk_getAssociatedObject(self, &AssociatedKeys.gkNavLineHidden) as? Bool else { return false }
return obj
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkNavLineHidden, newValue)
self.gk_navigationBar.gk_navLineHidden = newValue
if #available(iOS 11.0, *) {
var shadowImage: UIImage?
if newValue {
shadowImage = UIImage()
}else if self.gk_navShadowImage != nil {
shadowImage = self.gk_navShadowImage
}else if self.gk_navShadowColor != nil {
shadowImage = UIImage.gk_change(with: UIImage.gk_image(with: "nav_line"), color: self.gk_navShadowColor!)
}
setNavShadow(shadowImage, color: nil)
}
self.gk_navigationBar.layoutSubviews()
}
}
public var gk_navTitle: String? {
get {
return gk_getAssociatedObject(self, &AssociatedKeys.gkNavTitle) as? String
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkNavTitle, newValue)
self.gk_navigationItem.title = newValue
}
}
public var gk_navTitleView: UIView? {
get {
return gk_getAssociatedObject(self, &AssociatedKeys.gkNavTitleView) as? UIView
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkNavTitleView, newValue)
self.gk_navigationItem.titleView = newValue
}
}
public var gk_navTitleColor: UIColor? {
get {
return gk_getAssociatedObject(self, &AssociatedKeys.gkNavTitleColor) as? UIColor
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkNavTitleColor, newValue)
setNavTitle(newValue)
}
}
public var gk_navTitleFont: UIFont? {
get {
return gk_getAssociatedObject(self, &AssociatedKeys.gkNavTitleFont) as? UIFont
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkNavTitleFont, newValue)
setNavTitle(newValue)
}
}
public var gk_navLeftBarButtonItem: UIBarButtonItem? {
get {
return gk_getAssociatedObject(self, &AssociatedKeys.gkNavLeftBarButtonItem) as? UIBarButtonItem
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkNavLeftBarButtonItem, newValue)
self.gk_navigationItem.leftBarButtonItem = newValue
}
}
public var gk_navLeftBarButtonItems: [UIBarButtonItem]? {
get {
return gk_getAssociatedObject(self, &AssociatedKeys.gkNavLeftBarButtonItems) as? [UIBarButtonItem]
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkNavLeftBarButtonItems, newValue)
self.gk_navigationItem.leftBarButtonItems = newValue
}
}
public var gk_navRightBarButtonItem: UIBarButtonItem? {
get {
return gk_getAssociatedObject(self, &AssociatedKeys.gkNavRightBarButtonItem) as? UIBarButtonItem
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkNavRightBarButtonItem, newValue)
self.gk_navigationItem.rightBarButtonItem = newValue
}
}
public var gk_navRightBarButtonItems: [UIBarButtonItem]? {
get {
return gk_getAssociatedObject(self, &AssociatedKeys.gkNavRightBarButtonItems) as? [UIBarButtonItem]
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkNavRightBarButtonItems, newValue)
self.gk_navigationItem.rightBarButtonItems = newValue
}
}
public var gk_disableFixNavItemSpace: Bool {
get {
guard let obj = gk_getAssociatedObject(self, &AssociatedKeys.gkDisableFixNavItemSpace) as? Bool else { return false }
return obj
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkDisableFixNavItemSpace, newValue)
if GKConfigure.gk_disableFixSpace == newValue { return }
GKConfigure.update { configure in
configure.gk_disableFixSpace = newValue
}
}
}
public var gk_openFixNavItemSpace: Bool {
get {
guard let obj = gk_getAssociatedObject(self, &AssociatedKeys.gkOpenFixNavItemSpace) as? Bool else { return false }
return obj
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkOpenFixNavItemSpace, newValue)
if GKConfigure.gk_openSystemFixSpace == newValue { return }
GKConfigure.update { configure in
configure.gk_openSystemFixSpace = newValue
}
}
}
public var gk_navItemLeftSpace: CGFloat {
get {
guard let obj = gk_getAssociatedObject(self, &AssociatedKeys.gkNavItemLeftSpace) as? CGFloat else { return GKNavigationBarItemSpace }
return obj
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkNavItemLeftSpace, newValue)
if newValue == GKNavigationBarItemSpace { return }
GKConfigure.update { (configure) in
configure.gk_navItemLeftSpace = newValue
}
}
}
public var gk_navItemRightSpace: CGFloat {
get {
guard let obj = gk_getAssociatedObject(self, &AssociatedKeys.gkNavItemRightSpace) as? CGFloat else { return GKNavigationBarItemSpace }
return obj
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkNavItemRightSpace, newValue)
if newValue == GKNavigationBarItemSpace { return }
GKConfigure.update { (configure) in
configure.gk_navItemRightSpace = newValue
}
}
}
}
extension UIViewController {
// MARK: - 重新系统方法
private static let onceToken = UUID().uuidString
@objc public static func gkAwake() {
DispatchQueue.once(token: onceToken) {
let oriSels = ["viewDidLoad",
"viewWillAppear:",
"viewDidAppear:",
"viewWillLayoutSubviews",
"traitCollectionDidChange:"]
for oriSel in oriSels {
gk_swizzled_instanceMethod("gk", oldClass: self, oldSelector: oriSel, newClass: self)
}
}
}
@objc func gk_viewDidLoad() {
// 设置默认状态
if let nav = self.navigationController, nav == self.parent {
self.gk_disableFixNavItemSpace = true
self.gk_openFixNavItemSpace = false
}
if shouldHandleNavBar() {
// 设置默认导航栏间距
self.gk_navItemLeftSpace = GKNavigationBarItemSpace
self.gk_navItemRightSpace = GKNavigationBarItemSpace
}
// 如果是根控制器,取消返回按钮
if let nav = self.navigationController, nav.children.count <= 1 {
if !self.gk_navBarInit { return }
self.gk_navLeftBarButtonItem = nil
}
gk_viewDidLoad()
}
@objc func gk_viewWillAppear(_ animated: Bool) {
if self.isKind(of: UINavigationController.self) { return }
if self.isKind(of: UITabBarController.self) { return }
if self.isKind(of: UIImagePickerController.self) { return }
if self.isKind(of: UIVideoEditorController.self) { return }
if self.isKind(of: UIAlertController.self) { return }
if NSStringFromClass(self.classForCoder).components(separatedBy: ".").last == "PUPhotoPickerHostViewController" { return }
if self.navigationController == nil { return }
if self.gk_navBarInit {
let disableFixNavItemSpace = self.gk_disableFixNavItemSpace
let openFixNavItemSpace = self.gk_openFixNavItemSpace
self.gk_disableFixNavItemSpace = disableFixNavItemSpace
self.gk_openFixNavItemSpace = openFixNavItemSpace
// 隐藏系统导航栏
if self.navigationController?.gk_openSystemNavHandle == false {
hiddenSystemNavBar()
}
// 将自定义的导航栏放置顶层
if !self.gk_navigationBar.isHidden {
self.view.bringSubviewToFront(self.gk_navigationBar)
}
}else {
if let nav = self.navigationController, nav == self.parent, !nav.isNavigationBarHidden, !isNonFullScreen() {
self.gk_disableFixNavItemSpace = self.gk_disableFixNavItemSpace
self.gk_openFixNavItemSpace = self.gk_openFixNavItemSpace
}
restoreSystemNavBar()
}
// 当创建了gk_navigationBar或者父控制器是导航控制器的时候才去调整导航栏间距
if self.shouldFixItemSpace() {
// 每次控制器出现的时候重置导航栏间距
if self.gk_navItemLeftSpace == GKNavigationBarItemSpace {
self.gk_navItemLeftSpace = GKConfigure.navItemLeftSpace
}else {
GKConfigure.update { configure in
configure.gk_navItemLeftSpace = self.gk_navItemLeftSpace
}
}
if self.gk_navItemRightSpace == GKNavigationBarItemSpace {
self.gk_navItemRightSpace = GKConfigure.navItemRightSpace
}else {
GKConfigure.update { configure in
configure.gk_navItemRightSpace = self.gk_navItemRightSpace
}
}
}
gk_viewWillAppear(animated)
}
@objc func gk_viewDidAppear(_ animated: Bool) {
if self.gk_navBarInit {
hiddenSystemNavBar()
}else {
restoreSystemNavBar()
}
gk_viewDidAppear(animated)
}
@objc func gk_viewWillLayoutSubviews() {
if self.gk_navBarInit {
setupNavBarFrame()
}
gk_viewWillLayoutSubviews()
}
@objc func gk_traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
if #available(iOS 13.0, *) {
if self.traitCollection.hasDifferentColorAppearance(comparedTo: previousTraitCollection) {
if self.isKind(of: UINavigationController.self) { return }
if self.isKind(of: UITabBarController.self) { return }
if !self.gk_navBarInit { return }
// 非根控制器重新设置返回按钮
var isRootVC = false
if let nav = self.navigationController, nav.children.first == self {
isRootVC = true
}
if !isRootVC && self.gk_backImage != nil && self.gk_navLeftBarButtonItem == nil && self.gk_navLeftBarButtonItems == nil {
setBackItemImage(image: self.gk_backImage)
}
// 重新设置导航栏背景颜色
if self.gk_navBackgroundImage != nil {
setNavBackground(self.gk_navBackgroundImage)
}else {
setNavBackground(self.gk_navBackgroundColor)
}
// 重新设置分割线颜色
if self.gk_navShadowImage != nil {
setNavShadow(self.gk_navShadowImage)
}else {
setNavShadow(self.gk_navShadowColor)
}
}
}
gk_traitCollectionDidChange(previousTraitCollection)
}
// MARK: - Public Funtions
public func showNavLine() {
self.gk_navLineHidden = false
}
public func hideNavLine() {
self.gk_navLineHidden = true
}
public func refreshNavBarFrame() {
self.setupNavBarFrame()
}
@objc open func backItemClick(_ sender: Any) {
var shouldPop = navigationShouldPop()
let selector = NSSelectorFromString("navigationShouldPopOnClick")
if self.responds(to: selector) {
if self.perform(selector) != nil {
shouldPop = true
}else {
shouldPop = false
}
}
if shouldPop {
self.navigationController?.popViewController(animated: true)
}
}
public func gk_findCurrentViewController(_ isRoot: Bool) -> UIViewController? {
if canFindPresented(self.presentedViewController) {
return self.presentedViewController?.gk_findCurrentViewController(false)
}
if self.isKind(of: UITabBarController.self) {
let tabbarVC = self as! UITabBarController
return tabbarVC.selectedViewController?.gk_findCurrentViewController(false)
}
if self.isKind(of: UINavigationController.self) {
let navVC = self as! UINavigationController
return navVC.topViewController?.gk_findCurrentViewController(false)
}
if self.children.count > 0 {
if self.children.count == 1 && isRoot {
return self.children.first?.gk_findCurrentViewController(false)
}else {
var currentVC: UIViewController? = self
for obj in self.children {
if obj.isViewLoaded {
let point = obj.view.convert(CGPoint.zero, to: nil)
let windowSize = obj.view.window?.bounds.size ?? .zero
// 是否全屏显示
let isFullScreenShow = !obj.view.isHidden && obj.view.alpha > 0.01 && __CGPointEqualToPoint(point, .zero) && __CGSizeEqualToSize(obj.view.bounds.size, windowSize)
// 判断类型
let isStopFindController = obj.isKind(of: UINavigationController.self) || obj.isKind(of: UITabBarController.self)
if isFullScreenShow && isStopFindController {
currentVC = obj.gk_findCurrentViewController(false)
break
}
}
}
return currentVC
}
}else if self.responds(to: NSSelectorFromString("contentViewController")) {
let tempVC = self.perform(NSSelectorFromString("contentViewController")).retain().takeRetainedValue() as? UIViewController
if tempVC != nil {
return tempVC?.gk_findCurrentViewController(false)
}
}
return self
}
fileprivate func canFindPresented(_ viewController: UIViewController?) -> Bool {
guard let vc = viewController else { return false }
if vc.isKind(of: UIAlertController.self) {
return false
}
if NSStringFromClass(self.classForCoder) == "_UIContextMenuActionsOnlyViewController" {
return false
}
return true
}
// MARK: - Private Functions
fileprivate func shouldHandleNavBar() -> Bool {
if self.gk_navBarInit {
return true
}
if self.isKind(of: UITabBarController.self) {
return false
}
if let vc = self.parent, vc.isKind(of: UINavigationController.self) {
return true
}
return false
}
fileprivate func shouldFixItemSpace() -> Bool {
if self.gk_navBarInit {
if self.isKind(of: UINavigationController.self) {
return false
}
if self.isKind(of: UITabBarController.self) {
return false
}
if self.navigationController == nil {
return false
}
if let parent = self.parent, !parent.isKind(of: UINavigationController.self) {
return false
}
return true
}
return self.gk_openFixNavItemSpace
}
fileprivate func hiddenSystemNavBar() {
if let nav = self.navigationController, nav.isNavigationBarHidden == false {
nav.gk_hideNavigationBar = true
nav.isNavigationBarHidden = true
}
}
fileprivate func restoreSystemNavBar() {
if GKConfigure.gk_restoreSystemNavBar && self.shouldHandleNavBar() {
if let nav = self.navigationController, nav.isNavigationBarHidden, nav.gk_hideNavigationBar {
nav.isNavigationBarHidden = false
}
}
}
fileprivate func setupNavBarAppearance() {
// 设置默认背景
if self.gk_navBackgroundImage == nil {
self.gk_navBackgroundImage = GKConfigure.backgroundImage
}
if self.gk_darkNavBackgroundImage == nil {
self.gk_darkNavBackgroundImage = GKConfigure.darkBackgroundImage
}
if self.gk_navBackgroundColor == nil && self.gk_navBackgroundImage == nil {
self.gk_navBackgroundColor = GKConfigure.backgroundColor
}
// 设置分割线
if self.gk_navShadowImage == nil {
self.gk_navShadowImage = GKConfigure.lineImage
}
if self.gk_darkNavShadowImage == nil {
self.gk_darkNavShadowImage = GKConfigure.darkLineImage
}
if self.gk_navShadowColor == nil && self.gk_navShadowImage == nil {
self.gk_navShadowColor = GKConfigure.lineColor
}
// 设置分割线是否隐藏
if self.gk_navLineHidden == false && GKConfigure.lineHidden == true {
self.gk_navLineHidden = GKConfigure.lineHidden
}
// 设置默认标题字体
if self.gk_navTitleFont == nil {
self.gk_navTitleFont = GKConfigure.titleFont
}
// 设置默认标题颜色
if self.gk_navTitleColor == nil {
self.gk_navTitleColor = GKConfigure.titleColor
}
// 设置默认返回按钮图片
if self.gk_backImage == nil {
self.gk_backImage = GKConfigure.backImage
}
if self.gk_darkBackImage == nil {
self.gk_darkBackImage = GKConfigure.darkBackImage
}
// 设置默认返回样式
if self.gk_backStyle == .none {
self.gk_backStyle = GKConfigure.backStyle
}
self.gk_navTitle = nil
}
fileprivate func setupNavBarFrame() {
let isNonFullScreen = isNonFullScreen()
var navBarH: CGFloat = 0.0
let gkNavBarHNFS = GKDevice.navBarHeightNonFullScreen()
let gkNavBarH = GKDevice.navBarHeight()
let gkStatusBarH = GKDevice.statusBarFrame().size.height
let gkStatusBarNavBarH = gkStatusBarH + gkNavBarH
if GKDevice.isIPad { // iPad
if isNonFullScreen {
navBarH = gkNavBarHNFS
self.gk_navigationBar.gk_nonFullScreen = true
}else {
navBarH = self.gk_statusBarHidden ? gkNavBarH : gkStatusBarNavBarH
}
}else if GKDevice.isLandScape() { // 横屏不显示状态栏,没有非全屏模式
navBarH = gkNavBarH
}else {
if isNonFullScreen {
navBarH = gkNavBarHNFS
self.gk_navigationBar.gk_nonFullScreen = true
}else {
if GKDevice.isNotchedScreen { // 刘海屏手机
// iPhone 14 Pro 状态栏高度与安全区域高度不一致,这里改为使用状态栏高度
var topH = GKDevice.statusBarFrame().height
if topH == 0 { topH = GKDevice.safeAreaInsets().top }
navBarH = topH + gkNavBarH
}else {
navBarH = self.gk_statusBarHidden ? gkNavBarH : gkStatusBarNavBarH
}
}
}
self.gk_navigationBar.frame = CGRect(x: 0, y: 0, width: self.view.bounds.width, height: navBarH)
self.gk_navigationBar.gk_statusBarHidden = self.gk_statusBarHidden
self.gk_navigationBar.layoutSubviews()
}
fileprivate func isNonFullScreen() -> Bool {
var isNonFullScreen = false
var viewW = self.view.bounds.width
var viewH = self.view.bounds.height
if self.isViewLoaded {
var parentVC = self
// 找到最上层的父控制器
while (parentVC.parent != nil) {
parentVC = parentVC.parent!
}
viewW = parentVC.view.frame.size.width
viewH = parentVC.view.frame.size.height
if viewW == 0 || viewH == 0 {
return false
}
// 如果是通过present方式弹出且高度小于屏幕高度,则认为是非全屏
var window = view.window
if window == nil {
window = GKDevice.keyWindow()
}
isNonFullScreen = (self.presentingViewController != nil) && viewH < window?.bounds.height ?? 0
}
return isNonFullScreen
}
fileprivate func setBackItemImage(image: UIImage?) {
if self.gk_navBarInit == false { return }
// 根控制器不作处理
guard let count = self.navigationController?.children.count else { return }
if (count <= 1) {
self.gk_navLeftBarButtonItem = nil
return
}
var backImage = image
if #available(iOS 12.0, *) {
if self.traitCollection.userInterfaceStyle == .dark, self.gk_darkBackImage != nil {
backImage = self.gk_darkBackImage
}
}
if backImage == nil {
if self.gk_backStyle != .none {
backImage = self.gk_backStyle == .black ? self.gk_blackBackImage : self.gk_whiteBackImage
}
}else {
if self.gk_backStyle == .none {
backImage = nil
}
}
if backImage == nil { return }
self.gk_navigationItem.leftBarButtonItem = UIBarButtonItem.gk_item(image: backImage, target: self, action: #selector(backItemClick(_:)))
}
fileprivate func setNavBackground(_ image: UIImage?) {
guard var image = image else { return }
if #available(iOS 12.0, *) {
if traitCollection.userInterfaceStyle == .dark, gk_darkNavBackgroundImage != nil {
image = gk_darkNavBackgroundImage!
}
}
setNavBackground(image, color: nil)
}
fileprivate func setNavBackground(_ color: UIColor?) {
guard let color = color else { return }
setNavBackground(nil, color: color)
}
fileprivate func setNavShadow(_ image: UIImage?) {
guard var image = image else { return }
if #available(iOS 12.0, *) {
if traitCollection.userInterfaceStyle == .dark, gk_darkNavShadowImage != nil {
image = gk_darkNavShadowImage!
}
}
setNavShadow(image, color: nil)
}
fileprivate func setNavShadow(_ color: UIColor?) {
guard let color = color else { return }
setNavShadow(nil, color: color)
}
fileprivate func setNavTitle(_ color: UIColor?) {
guard let color = color else { return }
var attr = [NSAttributedString.Key: AnyObject]()
attr[.foregroundColor] = color
if gk_navTitleFont != nil {
attr[.font] = gk_navTitleFont
}
setNavTitle(attr)
}
fileprivate func setNavTitle(_ font: UIFont?) {
guard let font = font else { return }
var attr = [NSAttributedString.Key: Any]()
if gk_navTitleColor != nil {
attr[.foregroundColor] = gk_navTitleColor
}
attr[.font] = font
setNavTitle(attr)
}
fileprivate func setNavBackground(_ image: UIImage?, color: UIColor?) {
if #available(iOS 13.0, *) {
let appearance = gk_navigationBar.standardAppearance
let shadowColor = appearance.shadowColor
let shadowImage = appearance.shadowImage
appearance.configureWithTransparentBackground()
appearance.backgroundImage = image
appearance.backgroundColor = color
appearance.shadowColor = shadowColor
appearance.shadowImage = shadowImage
gk_navigationBar.standardAppearance = appearance
gk_navigationBar.scrollEdgeAppearance = appearance
}else {
var bgImage = image
if bgImage == nil, let color = color {
bgImage = UIImage.gk_image(with: color)
}
gk_navigationBar.setBackgroundImage(bgImage, for: .default)
}
}
fileprivate func setNavShadow(_ image: UIImage?, color: UIColor?) {
if #available(iOS 13.0, *) {
let appearance = gk_navigationBar.standardAppearance
let backgroundColor = appearance.backgroundColor
let backgroundImage = appearance.backgroundImage
appearance.configureWithTransparentBackground()
appearance.shadowImage = image
appearance.shadowColor = color
appearance.backgroundColor = backgroundColor
appearance.backgroundImage = backgroundImage
gk_navigationBar.standardAppearance = appearance
gk_navigationBar.scrollEdgeAppearance = appearance
}else {
var shadowImage = image
if shadowImage == nil, let color = color {
shadowImage = UIImage.gk_change(with: UIImage.gk_image(with: "nav_line"), color: color)
}
gk_navigationBar.shadowImage = shadowImage
}
}
fileprivate func setNavTitle(_ attr: [NSAttributedString.Key: Any]) {
if #available(iOS 13, *) {
let appearance = gk_navigationBar.standardAppearance
appearance.titleTextAttributes = attr
gk_navigationBar.standardAppearance = appearance
gk_navigationBar.scrollEdgeAppearance = appearance
}else {
gk_navigationBar.titleTextAttributes = attr
}
}
}
//
// UIViewController+GKGesture.swift
// GKNavigationBarSwift
//
// Created by QuintGao on 2022/3/18.
// Copyright © 2022 QuintGao. All rights reserved.
//
import UIKit
// 左滑push代理
@objc public protocol GKViewControllerPushDelegate: NSObjectProtocol {
/// 左滑push,在这里创建将要push的控制器
@objc optional func pushToNextViewController()
/// push手势滑动开始
@objc optional func viewControllerPushScrollBegan()
/// push手势滑动进度更新
/// - Parameter progress: 进度(0-1)
@objc optional func viewControllerPushScrollUpdate(progress: CGFloat)
/// push手势滑动结束
/// - Parameter finished: 是否完成push操作(true:push成功 false:push取消)
@objc optional func viewControllerPushScrollEnded(finished: Bool)
}
// 右滑pop代理
@objc public protocol GKViewControllerPopDelegate: NSObjectProtocol {
/// pop手势滑动开始
@objc optional func viewControllerPopScrollBegan()
/// pop手势滑动进度更新
/// - Parameter progress: 进度(0-1)
@objc optional func viewControllerPopScrollUpdate(progress: CGFloat)
/// pop手势滑动结束
/// - Parameter finished: 是否完成pop操作(true:pop成功 false:pop取消)
@objc optional func viewControllerPopScrollEnded(finished: Bool)
}
// 返回拦截
@objc public protocol GKGesturePopHandlerProtocol: NSObjectProtocol {
/// 是否可以返回,包括点击返回和手势返回,默认YES
@objc func navigationShouldPop() -> Bool
/// 是否可以手势返回
@objc optional func navigationShouldPopOnGesture() -> Bool
/// 是否可以点击返回
@objc optional func navigationShouldPopOnClick() -> Bool
/// 返回手势冲突处理,当返回手势与其他手势冲突如:WKWebView中的手势,可实现以下方法返回YES,让返回手势与其他手势共存来解决手势冲突
@objc optional func popGestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool
}
public let GKViewControllerPropertyChanged = NSNotification.Name(rawValue: "GKViewControllerPropertyChanged")
extension UIViewController: GKGestureAwakeProtocol {
// MARK: - 重新系统方法
private static let onceToken = UUID().uuidString
@objc public static func gkGestureAwake() {
DispatchQueue.once(token: onceToken) {
let oriSels = ["viewWillAppear:",
"viewDidAppear:",
"viewDidDisappear:"]
for oriSel in oriSels {
gk_swizzled_instanceMethod("gkGesture", oldClass: self, oldSelector: oriSel, newClass: self)
}
}
}
@objc func gkGesture_viewWillAppear(_ animated: Bool) {
if self.hasPushDelegate {
self.gk_pushDelegate = self as? GKViewControllerPushDelegate
self.hasPushDelegate = false
}
if self.hasPopDelegate {
self.gk_popDelegate = self as? GKViewControllerPopDelegate
self.hasPopDelegate = false
}
gkGesture_viewWillAppear(animated)
}
@objc func gkGesture_viewDidAppear(_ animated: Bool) {
postPropertyChangeNotification()
gkGesture_viewDidAppear(animated)
}
@objc func gkGesture_viewDidDisappear(_ animated: Bool) {
if let delegate = self.gk_pushDelegate as? NSObject, delegate == self {
self.hasPushDelegate = true
}
if let delegate = self.gk_popDelegate as? NSObject, delegate == self {
self.hasPopDelegate = true
}
// 这两个代理系统不会自动回收,所以要做下处理
self.gk_pushDelegate = nil;
self.gk_popDelegate = nil;
gkGesture_viewDidDisappear(animated)
}
fileprivate func postPropertyChangeNotification() {
NotificationCenter.default.post(name: GKViewControllerPropertyChanged, object: ["viewController": self])
}
}
extension UIViewController {
fileprivate struct AssociatedKeys {
static var gkInteractivePopDisabled: Void?
static var gkFullScreenPopDisabled: Void?
static var gkSystemGestureHandleDisabled: Void?
static var gkMaxPopDistance: Void?
static var gkPushDelegate: Void?
static var gkPopDelegate: Void?
static var gkPushTransition: Void?
static var gkPopTransition: Void?
static var hasPushDelegate: Void?
static var hasPopDelegate: Void?
}
public var gk_interactivePopDisabled: Bool {
get {
guard let obj = gk_getAssociatedObject(self, &AssociatedKeys.gkInteractivePopDisabled) as? Bool else { return false }
return obj
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkInteractivePopDisabled, newValue)
postPropertyChangeNotification()
}
}
public var gk_fullScreenPopDisabled: Bool {
get {
guard let obj = gk_getAssociatedObject(self, &AssociatedKeys.gkFullScreenPopDisabled) as? Bool else { return false }
return obj
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkFullScreenPopDisabled, newValue)
postPropertyChangeNotification()
}
}
public var gk_systemGestureHandleDisabled: Bool {
get {
guard let obj = gk_getAssociatedObject(self, &AssociatedKeys.gkSystemGestureHandleDisabled) as? Bool else { return false }
return obj
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkSystemGestureHandleDisabled, newValue)
postPropertyChangeNotification()
}
}
public var gk_maxPopDistance: CGFloat {
get {
guard let obj = gk_getAssociatedObject(self, &AssociatedKeys.gkMaxPopDistance) as? CGFloat else { return 0 }
return obj
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkMaxPopDistance, newValue)
postPropertyChangeNotification()
}
}
public var gk_pushDelegate: GKViewControllerPushDelegate? {
get {
return gk_getAssociatedObject(self, &AssociatedKeys.gkPushDelegate) as? GKViewControllerPushDelegate
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkPushDelegate, newValue)
}
}
public var gk_popDelegate: GKViewControllerPopDelegate? {
get {
return gk_getAssociatedObject(self, &AssociatedKeys.gkPopDelegate) as? GKViewControllerPopDelegate
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkPopDelegate, newValue)
}
}
public var gk_pushTransition: UIViewControllerAnimatedTransitioning? {
get {
return gk_getAssociatedObject(self, &AssociatedKeys.gkPushTransition) as? UIViewControllerAnimatedTransitioning
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkPushTransition, newValue)
}
}
public var gk_popTransition: UIViewControllerAnimatedTransitioning? {
get {
return gk_getAssociatedObject(self, &AssociatedKeys.gkPopTransition) as? UIViewControllerAnimatedTransitioning
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.gkPopTransition, newValue)
}
}
fileprivate var hasPushDelegate: Bool {
get {
guard let obj = gk_getAssociatedObject(self, &AssociatedKeys.hasPushDelegate) as? Bool else { return false }
return obj
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.hasPushDelegate, newValue)
}
}
fileprivate var hasPopDelegate: Bool {
get {
guard let obj = gk_getAssociatedObject(self, &AssociatedKeys.hasPopDelegate) as? Bool else { return false }
return obj
}
set {
gk_setAssociatedObject(self, &AssociatedKeys.hasPopDelegate, newValue)
}
}
}
extension UIViewController: GKGesturePopHandlerProtocol {
open func navigationShouldPop() -> Bool {
return true
}
}
platform :ios, '13.0'
target 'AoleiSports' do
use_frameworks!
pod 'Alamofire', '~> 5.9.1'
pod 'R.swift', '~> 7.3.2'
pod 'CocoaLumberjack/Swift'
end
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
if config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'].to_f < 13.0
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.0'
end
end
end
end
PODS:
- Alamofire (5.9.1)
- CocoaLumberjack/Core (3.8.5)
- CocoaLumberjack/Swift (3.8.5):
- CocoaLumberjack/Core
- R.swift (7.3.2)
DEPENDENCIES:
- Alamofire (~> 5.9.1)
- CocoaLumberjack/Swift
- R.swift (~> 7.3.2)
SPEC REPOS:
trunk:
- Alamofire
- CocoaLumberjack
- R.swift
SPEC CHECKSUMS:
Alamofire: f36a35757af4587d8e4f4bfa223ad10be2422b8c
CocoaLumberjack: 6a459bc897d6d80bd1b8c78482ec7ad05dffc3f0
R.swift: 0af0d882f49f03711415cb4e5215daa977d8a480
PODFILE CHECKSUM: 4e22825b4e4b080e749be4d7c6766ee2c290500e
COCOAPODS: 1.15.2
//
// This is a generated file, do not edit!
// Generated by R.swift, see https://github.com/mac-cain13/R.swift
//
import Foundation
import RswiftResources
import UIKit
private class BundleFinder {}
let R = _R(bundle: Bundle(for: BundleFinder.self))
struct _R {
let bundle: Foundation.Bundle
var string: string { .init(bundle: bundle, preferredLanguages: nil, locale: nil) }
var color: color { .init(bundle: bundle) }
var image: image { .init(bundle: bundle) }
var file: file { .init(bundle: bundle) }
var storyboard: storyboard { .init(bundle: bundle) }
func string(bundle: Foundation.Bundle) -> string {
.init(bundle: bundle, preferredLanguages: nil, locale: nil)
}
func string(locale: Foundation.Locale) -> string {
.init(bundle: bundle, preferredLanguages: nil, locale: locale)
}
func string(preferredLanguages: [String], locale: Locale? = nil) -> string {
.init(bundle: bundle, preferredLanguages: preferredLanguages, locale: locale)
}
func color(bundle: Foundation.Bundle) -> color {
.init(bundle: bundle)
}
func image(bundle: Foundation.Bundle) -> image {
.init(bundle: bundle)
}
func file(bundle: Foundation.Bundle) -> file {
.init(bundle: bundle)
}
func storyboard(bundle: Foundation.Bundle) -> storyboard {
.init(bundle: bundle)
}
func validate() throws {
try self.storyboard.validate()
}
struct project {
let developmentRegion = "en"
}
/// This `_R.string` struct is generated, and contains static references to 1 localization tables.
struct string {
let bundle: Foundation.Bundle
let preferredLanguages: [String]?
let locale: Locale?
var launchScreen: launchScreen { .init(source: .init(bundle: bundle, tableName: "LaunchScreen", preferredLanguages: preferredLanguages, locale: locale)) }
func launchScreen(preferredLanguages: [String]) -> launchScreen {
.init(source: .init(bundle: bundle, tableName: "LaunchScreen", preferredLanguages: preferredLanguages, locale: locale))
}
/// This `_R.string.launchScreen` struct is generated, and contains static references to 0 localization keys.
struct launchScreen {
let source: RswiftResources.StringResource.Source
}
}
/// This `_R.color` struct is generated, and contains static references to 1 colors.
struct color {
let bundle: Foundation.Bundle
/// Color `AccentColor`.
var accentColor: RswiftResources.ColorResource { .init(name: "AccentColor", path: [], bundle: bundle) }
}
/// This `_R.image` struct is generated, and contains static references to 8 images.
struct image {
let bundle: Foundation.Bundle
/// Image `home`.
var home: RswiftResources.ImageResource { .init(name: "home", path: [], bundle: bundle, locale: nil, onDemandResourceTags: nil) }
/// Image `home_selected`.
var home_selected: RswiftResources.ImageResource { .init(name: "home_selected", path: [], bundle: bundle, locale: nil, onDemandResourceTags: nil) }
/// Image `launch_bg`.
var launch_bg: RswiftResources.ImageResource { .init(name: "launch_bg", path: [], bundle: bundle, locale: LocaleReference.none, onDemandResourceTags: nil) }
/// Image `launch_foot`.
var launch_foot: RswiftResources.ImageResource { .init(name: "launch_foot", path: [], bundle: bundle, locale: LocaleReference.none, onDemandResourceTags: nil) }
/// Image `match_filter`.
var match_filter: RswiftResources.ImageResource { .init(name: "match_filter", path: [], bundle: bundle, locale: nil, onDemandResourceTags: nil) }
/// Image `match_setting`.
var match_setting: RswiftResources.ImageResource { .init(name: "match_setting", path: [], bundle: bundle, locale: nil, onDemandResourceTags: nil) }
/// Image `profile`.
var profile: RswiftResources.ImageResource { .init(name: "profile", path: [], bundle: bundle, locale: nil, onDemandResourceTags: nil) }
/// Image `profile_selected`.
var profile_selected: RswiftResources.ImageResource { .init(name: "profile_selected", path: [], bundle: bundle, locale: nil, onDemandResourceTags: nil) }
}
/// This `_R.file` struct is generated, and contains static references to 6 resource files.
struct file {
let bundle: Foundation.Bundle
/// Resource file `GKNavigationBarSwift.bundle`.
var gkNavigationBarSwiftBundle: RswiftResources.FileResource { .init(name: "GKNavigationBarSwift", pathExtension: "bundle", bundle: bundle, locale: LocaleReference.none) }
/// Resource file `goal.mp3`.
var goalMp3: RswiftResources.FileResource { .init(name: "goal", pathExtension: "mp3", bundle: bundle, locale: LocaleReference.none) }
/// Resource file `launch_bg.png`.
var launch_bgPng: RswiftResources.FileResource { .init(name: "launch_bg", pathExtension: "png", bundle: bundle, locale: LocaleReference.none) }
/// Resource file `launch_foot.png`.
var launch_footPng: RswiftResources.FileResource { .init(name: "launch_foot", pathExtension: "png", bundle: bundle, locale: LocaleReference.none) }
/// Resource file `red.mp3`.
var redMp3: RswiftResources.FileResource { .init(name: "red", pathExtension: "mp3", bundle: bundle, locale: LocaleReference.none) }
/// Resource file `yellow.mp3`.
var yellowMp3: RswiftResources.FileResource { .init(name: "yellow", pathExtension: "mp3", bundle: bundle, locale: LocaleReference.none) }
}
/// This `_R.storyboard` struct is generated, and contains static references to 1 storyboards.
struct storyboard {
let bundle: Foundation.Bundle
var launchScreen: launchScreen { .init(bundle: bundle) }
func launchScreen(bundle: Foundation.Bundle) -> launchScreen {
.init(bundle: bundle)
}
func validate() throws {
try self.launchScreen.validate()
}
/// Storyboard `LaunchScreen`.
struct launchScreen: RswiftResources.StoryboardReference, RswiftResources.InitialControllerContainer {
typealias InitialController = UIKit.UIViewController
let bundle: Foundation.Bundle
let name = "LaunchScreen"
func validate() throws {
if UIKit.UIImage(named: "launch_bg.png", in: bundle, compatibleWith: nil) == nil { throw RswiftResources.ValidationError("[R.swift] Image named 'launch_bg.png' is used in storyboard 'LaunchScreen', but couldn't be loaded.") }
if UIKit.UIImage(named: "launch_foot.png", in: bundle, compatibleWith: nil) == nil { throw RswiftResources.ValidationError("[R.swift] Image named 'launch_foot.png' is used in storyboard 'LaunchScreen', but couldn't be loaded.") }
}
}
}
}
\ No newline at end of file
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!