跑马灯,首页数据整理,空白页面,账号配置,细节处理

This commit is contained in:
zjx 2025-05-27 17:50:30 +08:00
parent ed54a5eaae
commit bcefde3ce6
53 changed files with 1442 additions and 118 deletions

View File

@ -26,7 +26,6 @@ target 'Veloria' do
pod 'KTVHTTPCache' #视频缓存
pod 'Kingfisher' #图片加载
pod 'HWPanModal' #底部弹出控制器
pod "ESTabBarController-swift"
pod 'WMZPageController' #分页控制器
pod 'ZFPlayer/AVPlayer' #播放器
pod 'EmptyDataSet-Swift' #空数据页面

View File

@ -2,7 +2,6 @@ PODS:
- Alamofire (5.10.2)
- CocoaAsyncSocket (7.6.5)
- EmptyDataSet-Swift (5.0.0)
- ESTabBarController-swift (2.8.0)
- HWPanModal (0.9.9)
- Kingfisher (8.3.2)
- KTVHTTPCache (3.0.2):
@ -30,7 +29,6 @@ PODS:
DEPENDENCIES:
- EmptyDataSet-Swift
- ESTabBarController-swift
- HWPanModal
- Kingfisher
- KTVHTTPCache
@ -49,7 +47,6 @@ SPEC REPOS:
- Alamofire
- CocoaAsyncSocket
- EmptyDataSet-Swift
- ESTabBarController-swift
- HWPanModal
- Kingfisher
- KTVHTTPCache
@ -67,7 +64,6 @@ SPEC CHECKSUMS:
Alamofire: 7193b3b92c74a07f85569e1a6c4f4237291e7496
CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99
EmptyDataSet-Swift: eb382c0c87a2d9c678077385a595cec52da38171
ESTabBarController-swift: 05593a6ad64700b03c0eb60ff625916370aa4136
HWPanModal: b57a6717d3cdcd666bff44f9dd2a5be9f4d6f5d2
Kingfisher: 0621d0ac0c78fecb19f6dc5303bde2b52abaf2f5
KTVHTTPCache: 5711692cdf9a5ecfe829b1e16577deb3ffe3dc86
@ -81,6 +77,6 @@ SPEC CHECKSUMS:
YYKit: 7cda43304a8dc3696c449041e2cb3107b4e236e7
ZFPlayer: 5cf39e8d9f0c2394a014b0db4767b5b5a6bffe13
PODFILE CHECKSUM: 5a8b71939b2bf65623c166084b1e01d877b2979d
PODFILE CHECKSUM: e2712ae0c35ebb37af30822c851f06195b8f41d7
COCOAPODS: 1.16.2

View File

@ -44,11 +44,9 @@
BF0FA6F42DDC604500C9E5F2 /* VPHUD.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0FA6F32DDC604500C9E5F2 /* VPHUD.swift */; };
BF0FA6F62DDC616300C9E5F2 /* VPToast.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0FA6F52DDC616300C9E5F2 /* VPToast.swift */; };
BF0FA6F92DDC64E700C9E5F2 /* VPHomeAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0FA6F82DDC64E700C9E5F2 /* VPHomeAPI.swift */; };
BF0FA6FC2DDC657500C9E5F2 /* VPHomeDataModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0FA6FB2DDC657500C9E5F2 /* VPHomeDataModel.swift */; };
BF0FA7002DDC665300C9E5F2 /* VPShortModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0FA6FF2DDC665300C9E5F2 /* VPShortModel.swift */; };
BF0FA7022DDC667C00C9E5F2 /* VPVideoInfoModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0FA7012DDC667C00C9E5F2 /* VPVideoInfoModel.swift */; };
BF0FA7052DDC67AC00C9E5F2 /* VPHomeViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0FA7042DDC67AC00C9E5F2 /* VPHomeViewModel.swift */; };
BF0FA7072DDC687C00C9E5F2 /* VPHomeDataItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0FA7062DDC687C00C9E5F2 /* VPHomeDataItem.swift */; };
BF0FA70A2DDC69C800C9E5F2 /* VPTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0FA7092DDC69C800C9E5F2 /* VPTableViewCell.swift */; };
BF0FA70C2DDC6A3800C9E5F2 /* VPHomeBannerContentCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0FA70B2DDC6A3800C9E5F2 /* VPHomeBannerContentCell.swift */; };
BF0FA70E2DDC6ACC00C9E5F2 /* VPHomeItemContentCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0FA70D2DDC6ACC00C9E5F2 /* VPHomeItemContentCell.swift */; };
@ -136,6 +134,18 @@
BF5E75B82DE46F7100DE9DFE /* VPNetworkReachabilityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5E75B72DE46F7100DE9DFE /* VPNetworkReachabilityManager.swift */; };
BF5E75BC2DE546AD00DE9DFE /* VPAboutUsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5E75BB2DE546AD00DE9DFE /* VPAboutUsCell.swift */; };
BF5E75BE2DE54B2800DE9DFE /* VPAboutUsHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5E75BD2DE54B2800DE9DFE /* VPAboutUsHeaderView.swift */; };
BF5E75C02DE5566200DE9DFE /* VPHomePageControlView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5E75BF2DE5566200DE9DFE /* VPHomePageControlView.swift */; };
BF5E75CB2DE5692D00DE9DFE /* UINavigationController+JXTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5E75C82DE5692D00DE9DFE /* UINavigationController+JXTransition.swift */; };
BF5E75CC2DE5692D00DE9DFE /* JXTransitionDefine.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5E75C52DE5692D00DE9DFE /* JXTransitionDefine.swift */; };
BF5E75CD2DE5692D00DE9DFE /* JXTransitionDelegateBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5E75C62DE5692D00DE9DFE /* JXTransitionDelegateBridge.swift */; };
BF5E75CE2DE5692D00DE9DFE /* JXPushAnimatedTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5E75C42DE5692D00DE9DFE /* JXPushAnimatedTransition.swift */; };
BF5E75CF2DE5692D00DE9DFE /* UIViewController+JXTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5E75C92DE5692D00DE9DFE /* UIViewController+JXTransition.swift */; };
BF5E75D02DE5692D00DE9DFE /* UIGestureRecognizer+JXTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5E75C72DE5692D00DE9DFE /* UIGestureRecognizer+JXTransition.swift */; };
BF5E75D12DE5692D00DE9DFE /* JXPopAnimatedTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5E75C32DE5692D00DE9DFE /* JXPopAnimatedTransition.swift */; };
BF5E75D22DE5692D00DE9DFE /* JXNavigationInteractiveTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5E75C22DE5692D00DE9DFE /* JXNavigationInteractiveTransition.swift */; };
BF5E75D32DE5692D00DE9DFE /* JXBaseAnimatedTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5E75C12DE5692D00DE9DFE /* JXBaseAnimatedTransition.swift */; };
BF5E75D52DE56B2000DE9DFE /* VPHomeCagetoryRecommandContentCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5E75D42DE56B2000DE9DFE /* VPHomeCagetoryRecommandContentCell.swift */; };
BF5E75DB2DE5B8B700DE9DFE /* VPMarqueeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5E75DA2DE5B8B700DE9DFE /* VPMarqueeView.swift */; };
F939C04AD4003BA127F15C28 /* Pods_Veloria.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34F57E87E765BF8D72A43DCA /* Pods_Veloria.framework */; };
/* End PBXBuildFile section */
@ -186,11 +196,9 @@
BF0FA6F32DDC604500C9E5F2 /* VPHUD.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPHUD.swift; sourceTree = "<group>"; };
BF0FA6F52DDC616300C9E5F2 /* VPToast.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPToast.swift; sourceTree = "<group>"; };
BF0FA6F82DDC64E700C9E5F2 /* VPHomeAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPHomeAPI.swift; sourceTree = "<group>"; };
BF0FA6FB2DDC657500C9E5F2 /* VPHomeDataModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPHomeDataModel.swift; sourceTree = "<group>"; };
BF0FA6FF2DDC665300C9E5F2 /* VPShortModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPShortModel.swift; sourceTree = "<group>"; };
BF0FA7012DDC667C00C9E5F2 /* VPVideoInfoModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPVideoInfoModel.swift; sourceTree = "<group>"; };
BF0FA7042DDC67AC00C9E5F2 /* VPHomeViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPHomeViewModel.swift; sourceTree = "<group>"; };
BF0FA7062DDC687C00C9E5F2 /* VPHomeDataItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPHomeDataItem.swift; sourceTree = "<group>"; };
BF0FA7092DDC69C800C9E5F2 /* VPTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPTableViewCell.swift; sourceTree = "<group>"; };
BF0FA70B2DDC6A3800C9E5F2 /* VPHomeBannerContentCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPHomeBannerContentCell.swift; sourceTree = "<group>"; };
BF0FA70D2DDC6ACC00C9E5F2 /* VPHomeItemContentCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPHomeItemContentCell.swift; sourceTree = "<group>"; };
@ -278,6 +286,18 @@
BF5E75B72DE46F7100DE9DFE /* VPNetworkReachabilityManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNetworkReachabilityManager.swift; sourceTree = "<group>"; };
BF5E75BB2DE546AD00DE9DFE /* VPAboutUsCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPAboutUsCell.swift; sourceTree = "<group>"; };
BF5E75BD2DE54B2800DE9DFE /* VPAboutUsHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPAboutUsHeaderView.swift; sourceTree = "<group>"; };
BF5E75BF2DE5566200DE9DFE /* VPHomePageControlView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPHomePageControlView.swift; sourceTree = "<group>"; };
BF5E75C12DE5692D00DE9DFE /* JXBaseAnimatedTransition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JXBaseAnimatedTransition.swift; sourceTree = "<group>"; };
BF5E75C22DE5692D00DE9DFE /* JXNavigationInteractiveTransition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JXNavigationInteractiveTransition.swift; sourceTree = "<group>"; };
BF5E75C32DE5692D00DE9DFE /* JXPopAnimatedTransition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JXPopAnimatedTransition.swift; sourceTree = "<group>"; };
BF5E75C42DE5692D00DE9DFE /* JXPushAnimatedTransition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JXPushAnimatedTransition.swift; sourceTree = "<group>"; };
BF5E75C52DE5692D00DE9DFE /* JXTransitionDefine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JXTransitionDefine.swift; sourceTree = "<group>"; };
BF5E75C62DE5692D00DE9DFE /* JXTransitionDelegateBridge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JXTransitionDelegateBridge.swift; sourceTree = "<group>"; };
BF5E75C72DE5692D00DE9DFE /* UIGestureRecognizer+JXTransition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIGestureRecognizer+JXTransition.swift"; sourceTree = "<group>"; };
BF5E75C82DE5692D00DE9DFE /* UINavigationController+JXTransition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UINavigationController+JXTransition.swift"; sourceTree = "<group>"; };
BF5E75C92DE5692D00DE9DFE /* UIViewController+JXTransition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+JXTransition.swift"; sourceTree = "<group>"; };
BF5E75D42DE56B2000DE9DFE /* VPHomeCagetoryRecommandContentCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPHomeCagetoryRecommandContentCell.swift; sourceTree = "<group>"; };
BF5E75DA2DE5B8B700DE9DFE /* VPMarqueeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPMarqueeView.swift; sourceTree = "<group>"; };
E0BDA3570E00C90877E45AA0 /* Pods-VideoPlayer.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-VideoPlayer.debug.xcconfig"; path = "Target Support Files/Pods-VideoPlayer/Pods-VideoPlayer.debug.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
@ -350,6 +370,7 @@
1B056E352DDAC1DE007EE38D /* Libs */ = {
isa = PBXGroup;
children = (
BF5E75D92DE5B89300DE9DFE /* MarqueeView */,
BF5E75B42DE46D9500DE9DFE /* Empty */,
BF0FA7BF2DE45D4500C9E5F2 /* User */,
BF0FA7432DDF025A00C9E5F2 /* Player */,
@ -556,6 +577,7 @@
BF0FA6E82DDC5F6F00C9E5F2 /* Thirdparty */ = {
isa = PBXGroup;
children = (
BF5E75CA2DE5692D00DE9DFE /* JXTransition */,
BF0FA7932DE16E9300C9E5F2 /* JXTagView */,
BF0FA6ED2DDC5F8700C9E5F2 /* JXUUID */,
BF0FA7152DDC78FF00C9E5F2 /* ZKCycleScrollView-Swift */,
@ -597,8 +619,6 @@
BF0FA6FA2DDC652000C9E5F2 /* Model */ = {
isa = PBXGroup;
children = (
BF0FA6FB2DDC657500C9E5F2 /* VPHomeDataModel.swift */,
BF0FA7062DDC687C00C9E5F2 /* VPHomeDataItem.swift */,
BF0FA7112DDC6D2C00C9E5F2 /* VPHomeModuleItem.swift */,
BF0FA7332DDEC74500C9E5F2 /* VPCategoryModel.swift */,
);
@ -644,6 +664,7 @@
BF0FA70B2DDC6A3800C9E5F2 /* VPHomeBannerContentCell.swift */,
BF0FA7232DDC888F00C9E5F2 /* VPHomeRecommandContentCell.swift */,
BF0FA72B2DDD7B7300C9E5F2 /* VPHomeRankingContentCell.swift */,
BF5E75D42DE56B2000DE9DFE /* VPHomeCagetoryRecommandContentCell.swift */,
BF0FA7182DDC7F4900C9E5F2 /* VPHomeBannerCell.swift */,
BF0FA7292DDC922F00C9E5F2 /* VPHomeRecommandCell.swift */,
BF0FA72D2DDD7DD400C9E5F2 /* VPHomeRankingCell.swift */,
@ -657,6 +678,7 @@
BF0FA7882DE161F200C9E5F2 /* VPSearchResultView.swift */,
BF0FA78A2DE164C100C9E5F2 /* VPSearchResultCell.swift */,
BF0FA7902DE16CBF00C9E5F2 /* VPSearchHistoryView.swift */,
BF5E75BF2DE5566200DE9DFE /* VPHomePageControlView.swift */,
);
path = View;
sourceTree = "<group>";
@ -862,6 +884,30 @@
path = Empty;
sourceTree = "<group>";
};
BF5E75CA2DE5692D00DE9DFE /* JXTransition */ = {
isa = PBXGroup;
children = (
BF5E75C12DE5692D00DE9DFE /* JXBaseAnimatedTransition.swift */,
BF5E75C22DE5692D00DE9DFE /* JXNavigationInteractiveTransition.swift */,
BF5E75C32DE5692D00DE9DFE /* JXPopAnimatedTransition.swift */,
BF5E75C42DE5692D00DE9DFE /* JXPushAnimatedTransition.swift */,
BF5E75C52DE5692D00DE9DFE /* JXTransitionDefine.swift */,
BF5E75C62DE5692D00DE9DFE /* JXTransitionDelegateBridge.swift */,
BF5E75C72DE5692D00DE9DFE /* UIGestureRecognizer+JXTransition.swift */,
BF5E75C82DE5692D00DE9DFE /* UINavigationController+JXTransition.swift */,
BF5E75C92DE5692D00DE9DFE /* UIViewController+JXTransition.swift */,
);
path = JXTransition;
sourceTree = "<group>";
};
BF5E75D92DE5B89300DE9DFE /* MarqueeView */ = {
isa = PBXGroup;
children = (
BF5E75DA2DE5B8B700DE9DFE /* VPMarqueeView.swift */,
);
path = MarqueeView;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@ -990,11 +1036,13 @@
BF0FA7B82DE44FCC00C9E5F2 /* VPWebViewController.swift in Sources */,
BF0FA72A2DDC922F00C9E5F2 /* VPHomeRecommandCell.swift in Sources */,
BF0FA7322DDEBD6400C9E5F2 /* AppDelegate+Config.swift in Sources */,
BF5E75D52DE56B2000DE9DFE /* VPHomeCagetoryRecommandContentCell.swift in Sources */,
BF0FA7B32DE447FE00C9E5F2 /* VPMeCell.swift in Sources */,
BF0FA6DF2DDC5E4D00C9E5F2 /* String+VPAdd.swift in Sources */,
BF0FA7002DDC665300C9E5F2 /* VPShortModel.swift in Sources */,
1B056E7B2DDB37BA007EE38D /* VPGradientView.swift in Sources */,
BF0FA7262DDC8F7600C9E5F2 /* VPCollectionView.swift in Sources */,
BF5E75DB2DE5B8B700DE9DFE /* VPMarqueeView.swift in Sources */,
BF0FA7C32DE45DE300C9E5F2 /* VPUserAPI.swift in Sources */,
BF0FA78B2DE164C100C9E5F2 /* VPSearchResultCell.swift in Sources */,
BF0FA71D2DDC807200C9E5F2 /* UIImageView+VPAdd.swift in Sources */,
@ -1031,6 +1079,15 @@
BF0FA7B12DE447EB00C9E5F2 /* VPMeItem.swift in Sources */,
1B056E2C2DDAC0FD007EE38D /* SceneDelegate.swift in Sources */,
BF0FA75D2DDF208400C9E5F2 /* VPExplorePlayerControlView.swift in Sources */,
BF5E75CB2DE5692D00DE9DFE /* UINavigationController+JXTransition.swift in Sources */,
BF5E75CC2DE5692D00DE9DFE /* JXTransitionDefine.swift in Sources */,
BF5E75CD2DE5692D00DE9DFE /* JXTransitionDelegateBridge.swift in Sources */,
BF5E75CE2DE5692D00DE9DFE /* JXPushAnimatedTransition.swift in Sources */,
BF5E75CF2DE5692D00DE9DFE /* UIViewController+JXTransition.swift in Sources */,
BF5E75D02DE5692D00DE9DFE /* UIGestureRecognizer+JXTransition.swift in Sources */,
BF5E75D12DE5692D00DE9DFE /* JXPopAnimatedTransition.swift in Sources */,
BF5E75D22DE5692D00DE9DFE /* JXNavigationInteractiveTransition.swift in Sources */,
BF5E75D32DE5692D00DE9DFE /* JXBaseAnimatedTransition.swift in Sources */,
1B056E462DDAC370007EE38D /* UIScreen+VPAdd.swift in Sources */,
BF0FA7692DE0502900C9E5F2 /* VPEpisodeCell.swift in Sources */,
BF5E75BE2DE54B2800DE9DFE /* VPAboutUsHeaderView.swift in Sources */,
@ -1047,6 +1104,7 @@
BF0FA75F2DDFFDB000C9E5F2 /* VPDetailPlayerViewController.swift in Sources */,
BF0FA7732DE0671200C9E5F2 /* VPRateSelectedCell.swift in Sources */,
1B056E4D2DDAC7C1007EE38D /* VPTabBarController.swift in Sources */,
BF5E75C02DE5566200DE9DFE /* VPHomePageControlView.swift in Sources */,
BF0FA6DA2DDC5CB600C9E5F2 /* VPLoginManager.swift in Sources */,
BF0FA74A2DDF04E200C9E5F2 /* VPPlayerProtocol.swift in Sources */,
BF0FA72C2DDD7B7300C9E5F2 /* VPHomeRankingContentCell.swift in Sources */,
@ -1059,7 +1117,6 @@
1B056E3F2DDAC2DB007EE38D /* VPCryptorService.swift in Sources */,
BF0FA7202DDC83AE00C9E5F2 /* JXButton.swift in Sources */,
BF0FA7912DE16CBF00C9E5F2 /* VPSearchHistoryView.swift in Sources */,
BF0FA7072DDC687C00C9E5F2 /* VPHomeDataItem.swift in Sources */,
BF0FA7992DE1951A00C9E5F2 /* VPMyListViewController.swift in Sources */,
BF0FA7452DDF027900C9E5F2 /* VPPlayer.swift in Sources */,
BF0FA70E2DDC6ACC00C9E5F2 /* VPHomeItemContentCell.swift in Sources */,
@ -1096,7 +1153,6 @@
BF5E75B82DE46F7100DE9DFE /* VPNetworkReachabilityManager.swift in Sources */,
BF0FA6D52DDC5B5D00C9E5F2 /* VPApi.swift in Sources */,
BF0FA7C12DE45D5D00C9E5F2 /* VPUserInfo.swift in Sources */,
BF0FA6FC2DDC657500C9E5F2 /* VPHomeDataModel.swift in Sources */,
BF0FA7392DDECF8900C9E5F2 /* VPHomeListViewController.swift in Sources */,
BF0FA6F62DDC616300C9E5F2 /* VPToast.swift in Sources */,
BF0FA7B62DE44E8000C9E5F2 /* VPWebView.swift in Sources */,
@ -1140,7 +1196,7 @@
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = "";
DEVELOPMENT_TEAM = 394VH538M8;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = Veloria/Source/Info.plist;
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
@ -1154,7 +1210,7 @@
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.zeng.VideoPlayer;
PRODUCT_BUNDLE_IDENTIFIER = com.qjwl168.veloria.ios;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
@ -1175,7 +1231,7 @@
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = "";
DEVELOPMENT_TEAM = 394VH538M8;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = Veloria/Source/Info.plist;
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
@ -1189,7 +1245,7 @@
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.zeng.VideoPlayer;
PRODUCT_BUNDLE_IDENTIFIER = com.qjwl168.veloria.ios;
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;

View File

@ -11,8 +11,7 @@ class VPNavigationController: UINavigationController {
override func viewDidLoad() {
super.viewDidLoad()
// self.interactivePopGestureRecognizer?.delegate = self
self.jx_transitionAwake()
}
override func pushViewController(_ viewController: UIViewController, animated: Bool) {

View File

@ -17,8 +17,8 @@ let VPCampaignWebURL = "https://campaign.qjwl168.com"
let VPBaseURL = "https://api-qjwl168.qjwl168.com"
let VPURLPathPrefix = "/velo"
let VPWebBaseURL = "https://www.thimratv.com"
let VPCampaignWebURL = "https://campaign.moviatv.com"
let VPWebBaseURL = "https://www.qjwl168.com"
let VPCampaignWebURL = "https://campaign.qjwl168.com"
#endif
///
@ -43,4 +43,4 @@ let kVPFeedBackListWebUrl = VPCampaignWebURL + "/pages/leave/list"
///
let kVPFeedBackDetailWebUrl = VPCampaignWebURL + "/pages/leave/detail"
///
let kVPRewardsWebUrl = VPCampaignWebURL
let kVPRewardsWebUrl = VPCampaignWebURL + "/pages/reward/theme4"

View File

@ -6,7 +6,6 @@
//
import UIKit
import ESTabBarController_swift
class VPTabBarItemContentView: UIView {

View File

@ -64,13 +64,13 @@ class VPHomePageViewController: VPViewController {
let height = UIScreen.height - y
let pageView = WMZPageView(frame: CGRect(x: 0, y: y, width: width, height: height), param: pageParam, parentReponder: self)
pageView.param = pageParam
// pageView.downSc?.delegate = self
pageView.downSc?.dataSource = self
pageView.downSc?.isScrollEnabled = true
pageView.downSc?.separatorStyle = .none
pageView.downSc?.register(VPHomeItemContentCell.self, forCellReuseIdentifier: "cell")
pageView.downSc?.register(VPHomeBannerContentCell.self, forCellReuseIdentifier: VPHomeBannerContentCell.moduleKey.rawValue)
pageView.downSc?.register(VPHomeRecommandContentCell.self, forCellReuseIdentifier: VPHomeRecommandContentCell.moduleKey.rawValue)
pageView.downSc?.register(VPHomeCagetoryRecommandContentCell.self, forCellReuseIdentifier: VPHomeCagetoryRecommandContentCell.moduleKey.rawValue)
pageView.downSc?.register(VPHomeRankingContentCell.self, forCellReuseIdentifier: VPHomeRankingContentCell.moduleKey.rawValue)
pageView.downSc?.vp_addRefreshHeader(block: { [weak self] in
self?.handleHeaderRefresh(nil)
@ -146,6 +146,7 @@ class VPHomePageViewController: VPViewController {
} else {
self.pageView.downSc?.vp_endHeaderRefreshing()
}
self.requestHomeData()
}
@ -246,9 +247,13 @@ extension VPHomePageViewController {
guard let self = self else { return }
if let list = list {
self.viewModel.oldModuleList = list
self.pageParam.wTitleArr = self.viewModel.categoryTitleList
self.pageView.updateMenuData()
self.setupPageView()
if self.viewModel.needUpdateCategory {
self.viewModel.needUpdateCategory = false
self.pageParam.wTitleArr = self.viewModel.categoryTitleList
self.pageView.updateMenuData()
self.setupPageView()
}
self.searchButton.marqueeArr = self.viewModel.marqueeArr
self.pageView.downSc?.reloadData()
}

View File

@ -21,6 +21,7 @@ class VPSearchViewController: VPViewController {
private lazy var textView: VPSearchInputView = {
let view = VPSearchInputView()
view.textField.delegate = self
view.textDidChange = { [weak self] text in
self?.textDidChange(text: text)
}
@ -45,12 +46,20 @@ class VPSearchViewController: VPViewController {
vp_setupUI()
vp_addAction()
let tap = UITapGestureRecognizer(target: self, action: #selector(handleScreen))
self.view.addGestureRecognizer(tap)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.setNavigationBarHidden(true, animated: true)
}
@objc private func handleScreen() {
VPAppTool.keyWindow?.endEditing(true)
}
}
@ -109,3 +118,13 @@ extension VPSearchViewController {
}
}
}
//MARK: -------------- UITextFieldDelegate --------------
extension VPSearchViewController: UITextFieldDelegate {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
self.viewModel.addHistory(text: textField.text ?? "")
VPAppTool.keyWindow?.endEditing(true)
return true
}
}

View File

@ -1,20 +0,0 @@
//
// VPHomeDataItem.swift
// Veloria
//
// Created by Veloria on 2025/5/20.
//
import UIKit
class VPHomeDataItem: VPModel {
enum ItemType: String {
case banner
}
var type: ItemType = .banner
var list: [VPShortModel]?
}

View File

@ -1,27 +0,0 @@
//
// VPHomeDataModel.swift
// Veloria
//
// Created by Veloria on 2025/5/20.
//
import UIKit
import SmartCodable
class VPHomeDataModel: VPModel, SmartCodable {
var bannerData: [VPShortModel]?
///
var nineSquare: VPNineSquareModel?
///
var manualNewestRecommand: [VPShortModel]?
///
var hotData: [VPShortModel]?
}
class VPNineSquareModel: VPModel, SmartCodable {
var list: [VPShortModel]?
var title: String?
}

View File

@ -13,8 +13,12 @@ class VPHomeModuleItem: VPModel, SmartCodable {
enum ModuleKey: String, SmartCaseDefaultable {
case banner = "home_banner"
case v3_recommand = "home_v3_recommand"
///
case cagetory_recommand = "home_cagetory_recommand"
case week_ranking = "week_ranking"
case category_navigation = "category_navigation"
///
case marquee = "marquee"
}
@ -41,6 +45,7 @@ class VPHomeModuleItem: VPModel, SmartCodable {
dataList = list
} else if let list = data["shortPlayList"] as? [[String : Any]] {
self.title = data["category_name"] as? String
dataList = list
}

View File

@ -15,6 +15,7 @@ class VPHomeBannerContentCell: VPHomeItemContentCell {
override var item: VPHomeModuleItem? {
didSet {
pageControl.count = item?.list?.count ?? 0
bannerView.reloadData()
}
}
@ -26,9 +27,18 @@ class VPHomeBannerContentCell: VPHomeItemContentCell {
view.hidesPageControl = true
view.layer.cornerRadius = 10
view.layer.masksToBounds = true
view.loadCompletion = { [weak self] in
guard let self = self else { return }
self.pageControl.currentIndex = self.bannerView.currentIdx
}
view.register(VPHomeBannerCell.self, forCellWithReuseIdentifier: "cell")
return view
}()
private lazy var pageControl: VPHomePageControlView = {
let view = VPHomePageControlView()
return view
}()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
@ -46,6 +56,7 @@ extension VPHomeBannerContentCell {
private func vp_setupUI() {
containerView.addSubview(bannerView)
bannerView.addSubview(pageControl)
bannerView.snp.makeConstraints { make in
make.left.equalToSuperview().offset(15)
@ -54,6 +65,11 @@ extension VPHomeBannerContentCell {
make.bottom.equalToSuperview()
make.height.equalTo(182)
}
pageControl.snp.makeConstraints { make in
make.bottom.equalToSuperview().offset(-10)
make.right.equalToSuperview().offset(-10)
}
}
@ -72,6 +88,10 @@ extension VPHomeBannerContentCell: ZKCycleScrollViewDataSource, ZKCycleScrollVie
return cell
}
func cycleScrollView(_ cycleScrollView: ZKCycleScrollView, didScrollFromIndex fromIndex: Int, toIndex: Int) {
pageControl.currentIndex = toIndex
}
func cycleScrollView(_ cycleScrollView: ZKCycleScrollView, didSelectItemAt index: Int) {
guard let model = self.item?.list?[index] else { return }

View File

@ -0,0 +1,18 @@
//
// VPHomeCagetoryRecommandContentCell.swift
// Veloria
//
// Created by on 2025/5/27.
//
import UIKit
class VPHomeCagetoryRecommandContentCell: VPHomeRecommandContentCell {
override class var moduleKey: VPHomeModuleItem.ModuleKey {
return .cagetory_recommand
}
}

View File

@ -0,0 +1,90 @@
//
// VPHomePageControlView.swift
// Veloria
//
// Created by on 2025/5/27.
//
import UIKit
class VPHomePageControlView: UIView {
var currentIndex: Int = 0 {
didSet {
if count == 0 { return }
if currentIndex >= count {
currentIndex = 0
return
}
for view in self.stackView.arrangedSubviews {
if let view = view as? UIButton {
view.isSelected = view.tag == currentIndex
}
}
}
}
var count = 0 {
didSet {
self.stackView.removeAllArrangedSubview()
for i in 0..<count {
let view = createDotView()
view.tag = i
view.isSelected = i == currentIndex
stackView.addArrangedSubview(view)
}
}
}
private lazy var stackView: UIStackView = {
let view = UIStackView()
view.axis = .horizontal
view.spacing = 4
return view
}()
override init(frame: CGRect) {
super.init(frame: frame)
addSubview(stackView)
stackView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func createDotView() -> UIButton {
var config = UIButton.Configuration.plain()
config.contentInsets = .zero
let button = UIButton(configuration: config)
button.configurationUpdateHandler = { [weak self] button in
guard let _ = self else { return }
if button.isSelected {
button.backgroundColor = .color7C174F()
button.layer.borderWidth = 0
} else {
button.backgroundColor = .clear
button.layer.borderWidth = 1
}
}
button.layer.cornerRadius = 3
button.layer.masksToBounds = true
button.layer.borderColor = UIColor.colorFFFFFF(alpha: 0.35).cgColor
button.snp.makeConstraints { make in
make.width.height.equalTo(6)
}
return button
}
}

View File

@ -15,6 +15,12 @@ class VPHomeRankingContentCell: VPHomeItemContentCell {
override var item: VPHomeModuleItem? {
didSet {
let list = item?.list ?? []
if list.count > 3, list.count % 3 != 0 {
var newCount = list.count / 3
newCount = newCount * 3
item?.list = Array(list.prefix(upTo: newCount))
}
collectionView.reloadData()
}
}

View File

@ -20,6 +20,11 @@ class VPHomeRecommandContentCell: VPHomeItemContentCell {
}
}
private lazy var iconImageView: UIImageView = {
let imageView = UIImageView(image: UIImage(named: "hot_icon_03"))
return imageView
}()
private lazy var titleLabel: UILabel = {
let label = UILabel()
label.font = .fontMedium(ofSize: 15)
@ -63,11 +68,29 @@ extension VPHomeRecommandContentCell {
containerView.addSubview(titleLabel)
containerView.addSubview(collectionView)
titleLabel.snp.makeConstraints { make in
make.left.equalToSuperview().offset(15)
make.top.equalToSuperview()
if Self.moduleKey == .v3_recommand {
containerView.addSubview(iconImageView)
iconImageView.snp.makeConstraints { make in
make.left.equalToSuperview().offset(15)
make.top.equalToSuperview()
}
titleLabel.snp.makeConstraints { make in
make.left.equalToSuperview().offset(38)
make.centerY.equalTo(iconImageView)
}
} else {
titleLabel.snp.makeConstraints { make in
make.left.equalToSuperview().offset(15)
// make.centerY.equalTo(iconImageView)
make.top.equalToSuperview()
}
}
collectionView.snp.makeConstraints { make in
make.left.right.equalToSuperview()
make.bottom.equalToSuperview()

View File

@ -9,11 +9,27 @@ import UIKit
class VPHomeSearchButton: UIControl {
var marqueeArr: [VPShortModel] = [] {
didSet {
marqueeView.reloadData()
}
}
private lazy var currentIndex = 0
private lazy var iconImageView: UIImageView = {
let imageView = UIImageView(image: UIImage(named: "search_icon_01"))
return imageView
}()
private lazy var marqueeView: VPMarqueeView = {
let view = VPMarqueeView()
view.dataSource = self
view.start()
return view
}()
private lazy var textLabel: UILabel = {
let label = UILabel()
label.font = .fontRegular(ofSize: 14)
@ -46,7 +62,7 @@ extension VPHomeSearchButton {
addSubview(iconImageView)
addSubview(textLabel)
addSubview(marqueeView)
iconImageView.snp.makeConstraints { make in
@ -54,10 +70,32 @@ extension VPHomeSearchButton {
make.left.equalToSuperview().offset(10)
}
textLabel.snp.makeConstraints { make in
make.centerY.equalToSuperview()
marqueeView.snp.makeConstraints { make in
make.left.equalTo(iconImageView.snp.right).offset(6)
make.top.bottom.equalToSuperview()
make.right.equalToSuperview().offset(-10)
}
}
}
extension VPHomeSearchButton: VPMarqueeViewDataSource {
func numberOfItems(_ marqueeView: VPMarqueeView) -> Int {
return marqueeArr.count == 0 ? 1 : marqueeArr.count
}
func marqueeView(_ marqueeView: VPMarqueeView, cellForItemAt index: Int) -> NSAttributedString {
var text: String
if marqueeArr.count == 0 {
text = "kSearchPlaceholderText1".localized
} else {
text = marqueeArr[index].name ?? ""
}
let string = NSMutableAttributedString(string: text)
string.font = .fontRegular(ofSize: 14)
string.color = .colorFFFFFF(alpha: 0.3)
return string
}
}

View File

@ -78,7 +78,7 @@ extension VPSearchHistoryView {
titleLabel.snp.makeConstraints { make in
make.left.equalToSuperview().offset(15)
make.top.equalToSuperview().offset(20)
make.top.equalToSuperview().offset(0)
}
deleteButton.snp.makeConstraints { make in
@ -90,7 +90,7 @@ extension VPSearchHistoryView {
tagView.snp.makeConstraints { make in
make.left.right.equalToSuperview()
make.top.equalToSuperview().offset(48)
make.top.equalToSuperview().offset(28)
make.bottom.equalToSuperview()
}
}

View File

@ -25,9 +25,10 @@ class VPSearchInputView: UIView {
return imageView
}()
private lazy var textField: VPTextField = {
private(set) lazy var textField: VPTextField = {
let textField = VPTextField()
textField.font = .fontRegular(ofSize: 14)
textField.returnKeyType = .search
textField.vp_placeholder = "kSearchPlaceholderText2".localized
textField.vp_placeholderFont = textField.font
textField.textDidChange = { [weak self] text in

View File

@ -88,6 +88,7 @@ class VPSearchRecommendedContentView: VPGradientView {
collectionView.dataSource = self
collectionView.showsVerticalScrollIndicator = false
collectionView.register(VPSearchRecommendedCell.self, forCellWithReuseIdentifier: "cell")
collectionView.keyboardDismissMode = .onDrag
return collectionView
}()

View File

@ -90,7 +90,7 @@ extension VPSearchRecommendedView {
make.left.equalToSuperview().offset(15)
make.right.equalToSuperview().offset(-15)
make.top.equalToSuperview()
make.height.equalTo(self).offset(-(30 + UIScreen.tabbarSafeBottomMargin))
make.height.equalTo(self).offset(-(30 + UIScreen.tabbarSafeBottomMargin + 10))
}
}

View File

@ -36,6 +36,8 @@ class VPSearchResultView: UIView {
collectionView.delegate = self
collectionView.dataSource = self
collectionView.register(VPSearchResultCell.self, forCellWithReuseIdentifier: "cell")
collectionView.vp_addNormalEmpty(image: UIImage(named: "empty_image_02"))
collectionView.keyboardDismissMode = .onDrag
return collectionView
}()

View File

@ -19,10 +19,16 @@ class VPHomeViewModel: VPModel {
///
private(set) lazy var newModuleList: [VPHomeModuleItem] = []
///
var needUpdateCategory = true
///
private(set) lazy var categoryList: [VPCategoryModel] = []
private(set) lazy var categoryTitleList: [String] = []
///
private(set) lazy var marqueeArr: [VPShortModel] = []
///
private func filterModuleData() {
@ -33,20 +39,24 @@ class VPHomeViewModel: VPModel {
if key == .banner {
newModuleList.insert($0, at: 0)
} else if key == .category_navigation {
categoryList.removeAll()
categoryTitleList.removeAll()
let allCategory = VPCategoryModel()
allCategory.category_name = "All".localized
allCategory.category_id = "0"
categoryList.append(allCategory)
categoryList += ($0.categoryList ?? [])
categoryList.forEach { model in
categoryTitleList.append(model.category_name ?? "")
} else if key == .category_navigation { //
if needUpdateCategory {
categoryList.removeAll()
categoryTitleList.removeAll()
let allCategory = VPCategoryModel()
allCategory.category_name = "All".localized
allCategory.category_id = "0"
categoryList.append(allCategory)
categoryList += ($0.categoryList ?? [])
categoryList.forEach { model in
categoryTitleList.append(model.category_name ?? "")
}
}
} else if key == .marquee { //
marqueeArr = $0.list ?? []
} else {
newModuleList.append($0)
}

View File

@ -64,7 +64,8 @@ class VPCollectListViewController: VPViewController {
private lazy var dataArr: [VPShortModel] = []
private var page: Int = 1
///1
private var updateNode = 0
private lazy var allSelectedButton: UIButton = {
var config = UIButton.Configuration.plain()
@ -117,9 +118,14 @@ class VPCollectListViewController: VPViewController {
return collectionView
}()
deinit {
NotificationCenter.default.removeObserver(self)
}
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(updateShortCollectStateNotification), name: VPVideoAPI.updateShortCollectStateNotification, object: nil)
self.bgImageView.isHidden = true
self.view.backgroundColor = .clear
@ -128,6 +134,14 @@ class VPCollectListViewController: VPViewController {
requestDataArr(page: 1, completer: nil)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if updateNode > 0 {
updateNode = 0
requestDataArr(page: 1, completer: nil)
}
}
override func handleHeaderRefresh(_ completer: (() -> Void)?) {
requestDataArr(page: 1) { [weak self] in
self?.collectionView.vp_endHeaderRefreshing()
@ -220,6 +234,15 @@ extension VPCollectListViewController: UICollectionViewDelegate, UICollectionVie
}
extension VPCollectListViewController {
@objc private func updateShortCollectStateNotification() {
if !self.isDidAppear {
updateNode += 1
}
}
}
extension VPCollectListViewController {
private func requestDataArr(page: Int, completer: (() -> Void)?) {

View File

@ -47,7 +47,8 @@ class VPShortModel: VPModel, SmartCodable {
static func mappingForKey() -> [SmartKeyTransformer]? {
return [
CodingKeys.vp_description <--- ["description"]
CodingKeys.vp_description <--- ["description"],
CodingKeys.name <--- ["short_video_title", "name"]
]
}
}

View File

@ -0,0 +1,131 @@
//
// VPMarqueeView.swift
// Veloria
//
// Created by on 2025/5/27.
//
import UIKit
protocol VPMarqueeViewDataSource: NSObjectProtocol {
/// MARK: -
func numberOfItems(_ marqueeView:VPMarqueeView) -> Int
/// MARK: - attributedString
func marqueeView(_ marqueeView:VPMarqueeView, cellForItemAt index:Int) -> NSAttributedString
}
class VPMarqueeView: UIView {
weak var dataSource: VPMarqueeViewDataSource?
private var timer: Timer?
private var totalCount = 0
private var currentIndex = 0
private var isFirstLayout = true
private lazy var scrollView: UIScrollView = {
let scrollView = UIScrollView()
scrollView.delegate = self
scrollView.contentInsetAdjustmentBehavior = .never
return scrollView
}()
private lazy var oneLabel: UILabel = {
let label = UILabel()
return label
}()
private lazy var twoLabel: UILabel = {
let label = UILabel()
return label
}()
override init(frame: CGRect) {
super.init(frame: frame)
self.isUserInteractionEnabled = false
addSubview(scrollView)
scrollView.addSubview(oneLabel)
scrollView.addSubview(twoLabel)
}
override func layoutSubviews() {
super.layoutSubviews()
scrollView.frame = self.bounds
oneLabel.frame = self.bounds
twoLabel.frame = .init(x: 0, y: self.bounds.height, width: self.bounds.width, height: self.bounds.height)
scrollView.contentSize = CGSize(width: self.bounds.width, height: self.bounds.height * 2)
if isFirstLayout {
isFirstLayout = false
reloadData()
}
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func reloadData() {
totalCount = self.dataSource?.numberOfItems(self) ?? 0
_setData()
}
func start() {
if self.timer == nil {
self.timer = Timer.scheduledTimer(timeInterval: 4, target: YYWeakProxy(target: self), selector: #selector(handleTimer), userInfo: nil, repeats: true)
}
}
}
extension VPMarqueeView {
///
private func _setData() {
guard totalCount > 0 else { return }
let nextIndex = getNextIndex()
oneLabel.attributedText = self.dataSource?.marqueeView(self, cellForItemAt: currentIndex)
twoLabel.attributedText = self.dataSource?.marqueeView(self, cellForItemAt: nextIndex)
}
@objc private func handleTimer() {
self.scrollView.setContentOffset(.init(x: 0, y: self.bounds.height), animated: true)
}
private func getNextIndex() -> Int {
guard totalCount > 0 else { return 0 }
var nextIndex = currentIndex + 1
if nextIndex >= totalCount {
nextIndex = 0
}
return nextIndex
}
}
//MARK: UIScrollViewDelegate
extension VPMarqueeView: UIScrollViewDelegate {
func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
guard totalCount > 0 else { return }
let nextIndex = getNextIndex()
currentIndex = nextIndex
_setData()
self.scrollView.contentOffset = .zero
}
}

View File

@ -45,23 +45,24 @@ class VPUserInfo: VPModel, SmartCodable, NSSecureCoding {
func encode(with coder: NSCoder) {
// coder.encode(id, forKey: "id")
// coder.encode(phone, forKey: "phone")
// coder.encode(userToken, forKey: "userToken")
// coder.encode(ipAddress, forKey: "ipAddress")
// coder.encode(audioNum, forKey: "audioNum")
// coder.encode(audioSeconds, forKey: "audioSeconds")
coder.encode(id, forKey: "id")
coder.encode(customer_id, forKey: "customer_id")
coder.encode(is_tourist, forKey: "is_tourist")
coder.encode(is_vip, forKey: "is_vip")
coder.encode(avator, forKey: "avator")
coder.encode(family_name, forKey: "family_name")
coder.encode(giving_name, forKey: "giving_name")
}
required init?(coder: NSCoder) {
super.init()
// id = coder.decodeObject(of: NSString.self, forKey: "id") as? String
// phone = coder.decodeObject(of: NSString.self, forKey: "phone") as? String
// userToken = coder.decodeObject(of: NSString.self, forKey: "userToken") as? String
// ipAddress = coder.decodeObject(of: NSString.self, forKey: "ipAddress") as? String
// audioNum = coder.decodeObject(of: NSNumber.self, forKey: "audioNum")?.intValue
// audioSeconds = coder.decodeObject(of: NSNumber.self, forKey: "audioSeconds")?.intValue
id = coder.decodeObject(of: NSString.self, forKey: "id") as? String
customer_id = coder.decodeObject(of: NSString.self, forKey: "customer_id") as? String
is_tourist = coder.decodeObject(of: NSNumber.self, forKey: "is_tourist")?.boolValue
is_vip = coder.decodeObject(of: NSNumber.self, forKey: "is_vip")?.boolValue
avator = coder.decodeObject(of: NSString.self, forKey: "avator") as? String
family_name = coder.decodeObject(of: NSString.self, forKey: "family_name") as? String
giving_name = coder.decodeObject(of: NSString.self, forKey: "giving_name") as? String
}
}

View File

@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "Frame@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "Frame@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "缺省页-搜索不到-切图图层@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "缺省页-搜索不到-切图图层@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

View File

@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "bg@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "bg@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

View File

@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "logo 8@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "logo 8@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

View File

@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "Veloria-白 2@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "Veloria-白 2@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -1,7 +1,9 @@
<?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">
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="23504" 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>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23506"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
@ -11,10 +13,31 @@
<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"/>
<rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="launch_screen_bg" translatesAutoresizingMaskIntoConstraints="NO" id="qWu-nj-f9Q">
<rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
</imageView>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="launch_screen_logo_01" translatesAutoresizingMaskIntoConstraints="NO" id="EQ4-Jv-Z6q">
<rect key="frame" x="146.66666666666666" y="180" width="100" height="100"/>
</imageView>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="launch_screen_logo_02" translatesAutoresizingMaskIntoConstraints="NO" id="Qh8-hT-7Mf">
<rect key="frame" x="145.66666666666666" y="305" width="102" height="23"/>
</imageView>
</subviews>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="qWu-nj-f9Q" firstAttribute="leading" secondItem="Ze5-6b-2t3" secondAttribute="leading" id="5Xc-kg-HlL"/>
<constraint firstItem="qWu-nj-f9Q" firstAttribute="top" secondItem="EQ4-Jv-Z6q" secondAttribute="top" constant="-180" id="AhQ-4f-lgy"/>
<constraint firstAttribute="trailing" secondItem="qWu-nj-f9Q" secondAttribute="trailing" id="IpB-7D-pNp"/>
<constraint firstItem="qWu-nj-f9Q" firstAttribute="top" secondItem="Ze5-6b-2t3" secondAttribute="top" id="R3a-fq-9AO"/>
<constraint firstItem="EQ4-Jv-Z6q" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="dgm-le-gMF"/>
<constraint firstItem="Qh8-hT-7Mf" firstAttribute="top" secondItem="EQ4-Jv-Z6q" secondAttribute="bottom" constant="25" id="wDA-4J-bqp"/>
<constraint firstItem="Qh8-hT-7Mf" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="yZa-Ua-bSM"/>
<constraint firstAttribute="bottom" secondItem="qWu-nj-f9Q" secondAttribute="bottom" id="z8R-Xt-OX9"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
@ -22,4 +45,9 @@
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
<resources>
<image name="launch_screen_bg" width="375" height="812"/>
<image name="launch_screen_logo_01" width="100" height="100"/>
<image name="launch_screen_logo_02" width="102" height="23"/>
</resources>
</document>

View File

@ -0,0 +1,86 @@
//
// JXBaseAnimatedTransition.swift
// Test
//
// Created by on 2022/10/10.
//
import UIKit
class JXBaseAnimatedTransition: NSObject {
open var isHideTabBar = false
open var transitionContext: UIViewControllerContextTransitioning?
open weak var containerView: UIView?
open weak var fromViewController: UIViewController?
open weak var toViewController: UIViewController?
open var contentView: UIView?
// open var isScale = false
// open var shadowView: UIView!
// open var isHideTabBar = false
// open var contentView: UIView?
open func getCapture(with view: UIView) -> UIImage? {
UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.isOpaque, 0)
view.drawHierarchy(in: view.bounds, afterScreenUpdates: false)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}
}
extension JXBaseAnimatedTransition: UIViewControllerAnimatedTransitioning {
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return TimeInterval(UINavigationController.hideShowBarDuration)
}
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()
}
@objc open func animateTransition() {
// SubClass Implementation
}
public func completeTransition() {
guard let transitionContext = self.transitionContext else { return }
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
}
public func animationDuration() -> TimeInterval {
return self.transitionDuration(using: self.transitionContext)
}
}
extension UIViewController {
fileprivate struct AssociatedKeys {
static var defCaptureImage: Int?
}
public var jx_captureImage: UIImage? {
get {
guard let obj = objc_getAssociatedObject(self, &AssociatedKeys.defCaptureImage) else { return nil }
return obj as? UIImage
}
set {
objc_setAssociatedObject(self, &AssociatedKeys.defCaptureImage, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
}

View File

@ -0,0 +1,202 @@
//
// JXNavigationInteractiveTransition.swift
// Test
//
// Created by on 2022/10/10.
//
import UIKit
class JXNavigationInteractiveTransition: NSObject {
var interactionController: UIPercentDrivenInteractiveTransition?
var isGesturePush = false
weak var navigationController: UINavigationController!
weak var visibleVC: UIViewController?
}
extension JXNavigationInteractiveTransition {
@objc func panGestureRecognizerAction(_ sender: UIPanGestureRecognizer) {
guard let view = sender.view else { return }
var progress = sender.translation(in: view).x / UIScreen.main.bounds.width
let velocity = sender.velocity(in: sender.view)
// pushpop
if sender.state == .began {
isGesturePush = velocity.x < 0 ? true : false
visibleVC = self.navigationController.visibleViewController
}
if isGesturePush {
progress = -progress
}
progress = min(1, max(0, progress))
// bcLog(message: progress)
switch sender.state {
case .began:
if self.isGesturePush {
if let visibleVC = self.visibleVC {
if visibleVC.jx_pushDelegate != nil {
self.interactionController = UIPercentDrivenInteractiveTransition()
visibleVC.jx_pushDelegate?.pushToNextViewController?()
self.pushScrollBegan()
}
}
} else {
self.interactionController = UIPercentDrivenInteractiveTransition()
self.navigationController.popViewController(animated: true)
self.popScrollBegan()
}
case .changed:
self.interactionController?.update(progress)
if self.isGesturePush {
self.pushScrollUpdate(progress: progress)
} else {
self.popScrollUpdate(progress: progress)
}
default:
var pushFinished: Bool = false
var finishProgress = 0.5
if self.isGesturePush {
finishProgress = 0.3
}
if progress > finishProgress {
pushFinished = true
self.interactionController?.finish()
} else {
pushFinished = false
self.interactionController?.cancel()
}
if self.isGesturePush {
pushScrollEnded(finished: pushFinished)
} else {
popScrollEnded(finished: pushFinished)
}
self.interactionController = nil
}
}
func pushScrollBegan() {
if let visibleVC = self.visibleVC {
visibleVC.jx_pushDelegate?.viewControllerPushScrollBegan?()
}
}
func pushScrollUpdate(progress: CGFloat) {
if let visibleVC = self.visibleVC {
visibleVC.jx_pushDelegate?.viewControllerPushScrollUpdate?(progress: progress)
}
}
func pushScrollEnded(finished: Bool) {
if let visibleVC = self.visibleVC {
visibleVC.jx_pushDelegate?.viewControllerPushScrollEnded?(finished: finished)
}
}
func popScrollBegan() {
if let visibleVC = self.visibleVC {
visibleVC.jx_popDelegate?.viewControllerPopScrollBegan?()
}
}
func popScrollUpdate(progress: CGFloat) {
if let visibleVC = self.visibleVC {
visibleVC.jx_popDelegate?.viewControllerPopScrollUpdate?(progress: progress)
}
}
func popScrollEnded(finished: Bool) {
if let visibleVC = self.visibleVC {
visibleVC.jx_popDelegate?.viewControllerPopScrollEnded?(finished: finished)
}
}
}
extension JXNavigationInteractiveTransition: UIGestureRecognizerDelegate {
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
// ydLog(message: "========\(gestureRecognizer.jxTag ?? "")")
guard let jxTag = gestureRecognizer.jxTag else { return true }
//
if self.navigationController.jx_isTransitioning == true { return false }
// visibleViewController
guard let visibleVC = self.navigationController.visibleViewController else { return true }
//
if visibleVC.jx_popGestureType == .disabled { return false }
if let _ = gestureRecognizer as? UIScreenEdgePanGestureRecognizer {
if visibleVC.jx_popGestureType == .fullScreen { return false } //
// bug
if self.navigationController.viewControllers.count <= 1 { return false }
// ydLog(message: "========")
return true
} else if let panGesture = gestureRecognizer as? UIPanGestureRecognizer { //
// transition
let transition = panGesture.translation(in: gestureRecognizer.view)
if transition.x == 0 { return false }
if jxTag == "pop" {
if visibleVC.jx_popGestureType == .edge { return false }
if transition.x <= 0 { return false } //
if self.navigationController.viewControllers.count <= 1 { return false }
if visibleVC.jx_popDelegate?.viewControllerPopShouldScrollBegan?() == false { return false }
visibleVC.jx_popDelegate?.viewControllerPopScrollBegan?()
// ydLog(message: "========pop")
return true
} else if jxTag == "push" {
if transition.x >= 0 { return false } //
if visibleVC.jx_pushDelegate == nil { return false }
// ydLog(message: "========push")
return true
}
}
return true
}
}
extension JXNavigationInteractiveTransition: UINavigationControllerDelegate {
func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationController.Operation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
if interactionController != nil, operation == .pop {
return JXPopAnimatedTransition()
} else if interactionController != nil, operation == .push {
return JXPushAnimatedTransition()
}
return nil
}
///
func navigationController(_ navigationController: UINavigationController, interactionControllerFor animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
if animationController.isKind(of: JXBaseAnimatedTransition.self) {
return interactionController
}
return nil
}
}

View File

@ -0,0 +1,72 @@
//
// JXPopAnimatedTransition.swift
// Test
//
// Created by on 2022/10/10.
//
import UIKit
class JXPopAnimatedTransition: JXBaseAnimatedTransition {
override func animateTransition() {
guard let fromView = self.fromViewController?.view else { return }
var toView = self.toViewController?.view
if toView == nil { return }
self.containerView?.insertSubview(toView!, belowSubview: fromView)
let size = self.containerView?.bounds.size ?? .zero
self.isHideTabBar = (self.toViewController?.tabBarController != nil) && (self.fromViewController?.hidesBottomBarWhenPushed == true) && (self.toViewController?.jx_captureImage != nil)
if self.isHideTabBar {
let captureView = UIImageView(image: self.toViewController?.jx_captureImage!)
captureView.frame = CGRect(x: 0, y: 0, width: size.width, height: size.height)
self.containerView?.insertSubview(captureView, belowSubview: fromView)
toView = captureView
self.toViewController?.view.isHidden = true
self.toViewController?.tabBarController?.tabBar.isHidden = true
}
self.contentView = toView
fromView.frame = CGRect(x: 0, y: 0, width: size.width, height: size.height)
toView!.frame = CGRect(x: -(0.3 * size.width), y: 0, width: size.width, height: size.height)
fromView.layer.shadowColor = UIColor.black.cgColor
fromView.layer.shadowOpacity = 0.15
fromView.layer.shadowRadius = 3.0
UIView.animate(withDuration: animationDuration(), delay: 0, options: .curveEaseInOut) {
fromView.frame = CGRect(x: size.width, y: 0, width: size.width, height: size.height)
if #available(iOS 11.0, *) {
toView!.frame = CGRect(x: 0, y: 0, width: size.width, height: size.height)
}else {
toView!.transform = .identity
}
} completion: { finish in
if self.isHideTabBar {
if self.contentView != nil {
self.contentView?.removeFromSuperview()
self.contentView = nil
}
self.toViewController?.view.isHidden = false
if self.toViewController?.navigationController?.children.count == 1 {
self.toViewController?.tabBarController?.tabBar.isHidden = false
}
}
self.completeTransition()
}
}
}

View File

@ -0,0 +1,79 @@
//
// JXPushAnimatedTransition.swift
// Test
//
// Created by on 2022/10/10.
//
import UIKit
class JXPushAnimatedTransition: JXBaseAnimatedTransition {
override func animateTransition() {
guard let toView = self.toViewController?.view else { return }
var fromView = self.fromViewController?.view
let size = self.containerView?.bounds.size ?? .zero
// UITabBarControllerpush
self.isHideTabBar = (self.fromViewController?.tabBarController != nil) && (self.toViewController?.hidesBottomBarWhenPushed == true)
if self.isHideTabBar {
// fromViewController
let view: UIView?
if self.fromViewController?.view.window != nil {
view = self.fromViewController?.view.window
}else {
view = self.fromViewController?.view
}
if view != nil {
let captureImage = self.getCapture(with: view!)
let captureView = UIImageView(image: captureImage)
captureView.frame = CGRect(x: 0, y: 0, width: size.width, height: size.height)
containerView?.addSubview(captureView)
fromView = captureView
self.fromViewController?.jx_captureImage = captureImage
self.fromViewController?.view.isHidden = true
self.fromViewController?.tabBarController?.tabBar.isHidden = true
}
}
self.contentView = fromView
self.containerView?.addSubview(toView)
toView.frame = CGRect(x: size.width, y: 0, width: size.width, height: size.height)
toView.layer.shadowColor = UIColor.black.cgColor
toView.layer.shadowOpacity = 0.15
toView.layer.shadowRadius = 3.0
UIView.animate(withDuration: transitionDuration(using: transitionContext), delay: 0, options: .curveEaseInOut) {
fromView?.frame = CGRect(x: -(0.3 * size.width), y: 0, width: size.width, height: size.height)
toView.frame = CGRect(x: 0, y: 0, width: size.width, height: size.height)
} completion: { finish in
if self.isHideTabBar {
if self.contentView != nil {
self.contentView!.removeFromSuperview()
self.contentView = nil
}
self.fromViewController?.view.isHidden = false
if self.fromViewController?.navigationController?.children.count == 1 {
self.fromViewController?.tabBarController?.tabBar.isHidden = false
}
}
self.completeTransition()
}
}
}

View File

@ -0,0 +1,47 @@
//
// JXTransitionDefine.swift
// Test
//
// Created by on 2022/10/11.
//
import UIKit
public func jx_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!)
}
}
// MARK: - SwizzlingDispatchQueue.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()
}
}

View File

@ -0,0 +1,16 @@
//
// JXTransitionDelegateBridge.swift
// Test
//
// Created by on 2022/10/10.
//
import UIKit
class JXTransitionDelegateBridge: NSObject {
weak var jx_pushDelegate: JXViewControllerPushDelegate?
weak var jx_popDelegate: JXViewControllerPopDelegate?
}

View File

@ -0,0 +1,25 @@
//
// UIGestureRecognizer+JXTransition.swift
// YDLive
//
// Created by on 2022/11/29.
//
import UIKit
extension UIGestureRecognizer {
fileprivate struct AssociatedKeys {
static var jxTag: Int?
}
var jxTag: String? {
get {
guard let obj = objc_getAssociatedObject(self, &AssociatedKeys.jxTag) as? String else { return nil }
return obj
}
set {
objc_setAssociatedObject(self, &AssociatedKeys.jxTag, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
}

View File

@ -0,0 +1,130 @@
//
// UINavigationController+JXTransition.swift
// Test
//
// Created by on 2022/10/10.
//
import UIKit
extension UINavigationController {
/**
*/
private var gestureView: UIView? {
return self.interactivePopGestureRecognizer?.view
}
/**
*/
func jx_transitionAwake() {
// UIViewController.jxTransitionAwake()
self.delegate = self.interactiveTransition
self.interactivePopGestureRecognizer?.isEnabled = false
self.gestureView?.addGestureRecognizer(pushGesture)
self.gestureView?.addGestureRecognizer(popGesture)
self.gestureView?.addGestureRecognizer(edgePopGesture)
}
}
extension UINavigationController {
fileprivate struct AssociatedKeys {
static var screenPanGesture: Int?
static var panGesture: Int?
static var panPushGesture: Int?
static var transition: Int?
}
var interactiveTransition: JXNavigationInteractiveTransition {
get {
var transition = objc_getAssociatedObject(self, &AssociatedKeys.transition) as? JXNavigationInteractiveTransition
if transition == nil {
transition = JXNavigationInteractiveTransition()
transition?.navigationController = self
objc_setAssociatedObject(self, &AssociatedKeys.transition, transition, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
return transition!
}
}
/**
*/
var edgePopGesture: UIScreenEdgePanGestureRecognizer {
get {
var panGesture = objc_getAssociatedObject(self, &AssociatedKeys.screenPanGesture) as? UIScreenEdgePanGestureRecognizer
if panGesture == nil {
panGesture = UIScreenEdgePanGestureRecognizer(target: self.systemTarget, action: self.systemAction)
panGesture?.jxTag = "edgePop"
panGesture?.edges = .left
panGesture?.delegate = self.interactiveTransition
objc_setAssociatedObject(self, &AssociatedKeys.screenPanGesture, panGesture, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
return panGesture!
}
}
/**
*/
var popGesture: UIPanGestureRecognizer {
get {
var panGesture = objc_getAssociatedObject(self, &AssociatedKeys.panGesture) as? UIPanGestureRecognizer
if panGesture == nil {
panGesture = UIPanGestureRecognizer(target: self.systemTarget, action: self.systemAction)
panGesture?.jxTag = "pop"
panGesture?.maximumNumberOfTouches = 1
panGesture?.delegate = self.interactiveTransition
objc_setAssociatedObject(self, &AssociatedKeys.panGesture, panGesture, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
return panGesture!
}
}
/**
push手势
*/
var pushGesture: UIPanGestureRecognizer {
get {
var panGesture = objc_getAssociatedObject(self, &AssociatedKeys.panPushGesture) as? UIPanGestureRecognizer
if panGesture == nil {
panGesture = UIPanGestureRecognizer(target: self.interactiveTransition, action: #selector(self.interactiveTransition.panGestureRecognizerAction(_:)))
panGesture?.jxTag = "push"
panGesture?.maximumNumberOfTouches = 1
panGesture?.delegate = self.interactiveTransition
objc_setAssociatedObject(self, &AssociatedKeys.panPushGesture, panGesture, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
return panGesture!
}
}
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:")
}
/**
*/
var jx_isTransitioning: Bool? {
return value(forKey: "_isTransitioning") as? Bool
}
}

View File

@ -0,0 +1,127 @@
//
// UIViewController+JXTransition.swift
// Test
//
// Created by on 2022/10/10.
//
import UIKit
// push
@objc public protocol JXViewControllerPushDelegate: NSObjectProtocol {
/// pushpush
@objc optional func pushToNextViewController()
/// push
@objc optional func viewControllerPushScrollBegan()
/// push
/// - Parameter progress: 0-1
@objc optional func viewControllerPushScrollUpdate(progress: CGFloat)
/// push
/// - Parameter finished: pushtruepush falsepush
@objc optional func viewControllerPushScrollEnded(finished: Bool)
}
// pop
@objc public protocol JXViewControllerPopDelegate: NSObjectProtocol {
@objc optional func viewControllerPopShouldScrollBegan() -> Bool
/// pop
@objc optional func viewControllerPopScrollBegan()
/// pop
/// - Parameter progress: 0-1
@objc optional func viewControllerPopScrollUpdate(progress: CGFloat)
/// pop
/// - Parameter finished: poptruepop falsepop
@objc optional func viewControllerPopScrollEnded(finished: Bool)
}
extension UIViewController {
// // MARK: -
// private static let onceToken = UUID().uuidString
// @objc public static func jxTransitionAwake() {
// DispatchQueue.once(token: onceToken) {
// let oriSels = ["viewDidAppear:",]
// for oriSel in oriSels {
// jx_swizzled_instanceMethod("jxGesture", oldClass: self, oldSelector: oriSel, newClass: self)
// }
// }
// }
//
// @objc func jxGesture_viewDidAppear(_ animated: Bool) {
// jxGesture_viewDidAppear(animated)
// }
}
extension UIViewController {
enum GestureTransitionType: Int {
///
case fullScreen
///
case edge
///
case disabled
}
fileprivate struct AssociatedKeys {
static var jxDelegateBridge: Int?
static var jx_gestureType: Int?
}
/**
*/
var jx_popGestureType: GestureTransitionType {
get {
guard let obj = objc_getAssociatedObject(self, &AssociatedKeys.jx_gestureType) as? GestureTransitionType else { return .fullScreen }
return obj
}
set {
objc_setAssociatedObject(self, &AssociatedKeys.jx_gestureType, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
/**
*/
fileprivate var jx_delegateBridge: JXTransitionDelegateBridge {
get {
var bridge = objc_getAssociatedObject(self, &AssociatedKeys.jxDelegateBridge) as? JXTransitionDelegateBridge
if bridge == nil {
bridge = JXTransitionDelegateBridge()
objc_setAssociatedObject(self, &AssociatedKeys.jxDelegateBridge, bridge, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
return bridge!
}
}
var jx_pushDelegate: JXViewControllerPushDelegate? {
get {
return jx_delegateBridge.jx_pushDelegate
}
set {
jx_delegateBridge.jx_pushDelegate = newValue
}
}
var jx_popDelegate: JXViewControllerPopDelegate? {
get {
return jx_delegateBridge.jx_popDelegate
}
set {
jx_delegateBridge.jx_popDelegate = newValue
}
}
}