Commit 5b930306 authored by David黄金龙's avatar David黄金龙

删除不使用的文件

parent 79457af8
...@@ -32,24 +32,12 @@ ...@@ -32,24 +32,12 @@
A52DF0CE2B330A20006618D6 /* BsOverlayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A52DEEBF2B330A1F006618D6 /* BsOverlayView.swift */; }; A52DF0CE2B330A20006618D6 /* BsOverlayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A52DEEBF2B330A1F006618D6 /* BsOverlayView.swift */; };
A52DF0CF2B330A20006618D6 /* String-Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A52DEEC02B330A1F006618D6 /* String-Extension.swift */; }; A52DF0CF2B330A20006618D6 /* String-Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A52DEEC02B330A1F006618D6 /* String-Extension.swift */; };
A52DF0D02B330A20006618D6 /* UILable-Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A52DEEC12B330A1F006618D6 /* UILable-Extension.swift */; }; A52DF0D02B330A20006618D6 /* UILable-Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A52DEEC12B330A1F006618D6 /* UILable-Extension.swift */; };
A52DF0D12B330A20006618D6 /* BsKVOHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = A52DEEC32B330A1F006618D6 /* BsKVOHelper.swift */; };
A52DF0DA2B330A20006618D6 /* BsMapManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A52DEECD2B330A1F006618D6 /* BsMapManager.swift */; };
A52DF0DB2B330A20006618D6 /* BsPageTitleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A52DEECF2B330A1F006618D6 /* BsPageTitleView.swift */; };
A52DF0DC2B330A20006618D6 /* BsPageContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A52DEED02B330A1F006618D6 /* BsPageContentView.swift */; };
A52DF0DD2B330A20006618D6 /* BsConstant.swift in Sources */ = {isa = PBXBuildFile; fileRef = A52DEED12B330A1F006618D6 /* BsConstant.swift */; }; A52DF0DD2B330A20006618D6 /* BsConstant.swift in Sources */ = {isa = PBXBuildFile; fileRef = A52DEED12B330A1F006618D6 /* BsConstant.swift */; };
A52DF0DE2B330A20006618D6 /* BsPresentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A52DEED22B330A1F006618D6 /* BsPresentView.swift */; };
A52DF0DF2B330A20006618D6 /* BSJsonUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = A52DEED32B330A1F006618D6 /* BSJsonUtil.swift */; }; A52DF0DF2B330A20006618D6 /* BSJsonUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = A52DEED32B330A1F006618D6 /* BSJsonUtil.swift */; };
A52DF0E92B330A20006618D6 /* MCClipImageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A52DEEE32B330A1F006618D6 /* MCClipImageViewController.swift */; };
A52DF0EA2B330A20006618D6 /* ClipImage_cancel.png in Resources */ = {isa = PBXBuildFile; fileRef = A52DEEE52B330A1F006618D6 /* ClipImage_cancel.png */; };
A52DF0EB2B330A20006618D6 /* ClipImage_sure.png in Resources */ = {isa = PBXBuildFile; fileRef = A52DEEE62B330A20006618D6 /* ClipImage_sure.png */; };
A52DF0EC2B330A20006618D6 /* ClipImage_rotating.png in Resources */ = {isa = PBXBuildFile; fileRef = A52DEEE72B330A20006618D6 /* ClipImage_rotating.png */; };
A52DF0ED2B330A20006618D6 /* MCClipImageTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = A52DEEE82B330A20006618D6 /* MCClipImageTool.swift */; };
A52DF0EE2B330A20006618D6 /* BsWebViewPreloadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A52DEEE92B330A20006618D6 /* BsWebViewPreloadManager.swift */; };
A52DF2342B330A21006618D6 /* BsBaseModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A52DF0B02B330A20006618D6 /* BsBaseModel.swift */; }; A52DF2342B330A21006618D6 /* BsBaseModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A52DF0B02B330A20006618D6 /* BsBaseModel.swift */; };
A52DF2352B330A21006618D6 /* YHNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A52DF0B22B330A20006618D6 /* YHNavigationController.swift */; }; A52DF2352B330A21006618D6 /* YHNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A52DF0B22B330A20006618D6 /* YHNavigationController.swift */; };
A52DF2362B330A21006618D6 /* YHBaseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A52DF0B32B330A20006618D6 /* YHBaseViewController.swift */; }; A52DF2362B330A21006618D6 /* YHBaseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A52DF0B32B330A20006618D6 /* YHBaseViewController.swift */; };
A52DF2372B330A21006618D6 /* YHTabBarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A52DF0B42B330A20006618D6 /* YHTabBarViewController.swift */; }; A52DF2372B330A21006618D6 /* YHTabBarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A52DF0B42B330A20006618D6 /* YHTabBarViewController.swift */; };
A52DF2392B330A21006618D6 /* YHWebViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A52DF0B62B330A20006618D6 /* YHWebViewController.swift */; };
A52DF23B2B330A21006618D6 /* YHNoDataTipView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A52DF0B92B330A20006618D6 /* YHNoDataTipView.swift */; }; A52DF23B2B330A21006618D6 /* YHNoDataTipView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A52DF0B92B330A20006618D6 /* YHNoDataTipView.swift */; };
A52DF23F2B3316A0006618D6 /* YHBasicContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A52DF23D2B3316A0006618D6 /* YHBasicContentView.swift */; }; A52DF23F2B3316A0006618D6 /* YHBasicContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A52DF23D2B3316A0006618D6 /* YHBasicContentView.swift */; };
A52DF2402B3316A0006618D6 /* YHBouncesContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A52DF23E2B3316A0006618D6 /* YHBouncesContentView.swift */; }; A52DF2402B3316A0006618D6 /* YHBouncesContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A52DF23E2B3316A0006618D6 /* YHBouncesContentView.swift */; };
...@@ -112,24 +100,12 @@ ...@@ -112,24 +100,12 @@
A52DEEBF2B330A1F006618D6 /* BsOverlayView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BsOverlayView.swift; sourceTree = "<group>"; }; A52DEEBF2B330A1F006618D6 /* BsOverlayView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BsOverlayView.swift; sourceTree = "<group>"; };
A52DEEC02B330A1F006618D6 /* String-Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String-Extension.swift"; sourceTree = "<group>"; }; A52DEEC02B330A1F006618D6 /* String-Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String-Extension.swift"; sourceTree = "<group>"; };
A52DEEC12B330A1F006618D6 /* UILable-Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UILable-Extension.swift"; sourceTree = "<group>"; }; A52DEEC12B330A1F006618D6 /* UILable-Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UILable-Extension.swift"; sourceTree = "<group>"; };
A52DEEC32B330A1F006618D6 /* BsKVOHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BsKVOHelper.swift; sourceTree = "<group>"; };
A52DEECD2B330A1F006618D6 /* BsMapManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BsMapManager.swift; sourceTree = "<group>"; };
A52DEECF2B330A1F006618D6 /* BsPageTitleView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BsPageTitleView.swift; sourceTree = "<group>"; };
A52DEED02B330A1F006618D6 /* BsPageContentView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BsPageContentView.swift; sourceTree = "<group>"; };
A52DEED12B330A1F006618D6 /* BsConstant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BsConstant.swift; sourceTree = "<group>"; }; A52DEED12B330A1F006618D6 /* BsConstant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BsConstant.swift; sourceTree = "<group>"; };
A52DEED22B330A1F006618D6 /* BsPresentView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BsPresentView.swift; sourceTree = "<group>"; };
A52DEED32B330A1F006618D6 /* BSJsonUtil.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BSJsonUtil.swift; sourceTree = "<group>"; }; A52DEED32B330A1F006618D6 /* BSJsonUtil.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BSJsonUtil.swift; sourceTree = "<group>"; };
A52DEEE32B330A1F006618D6 /* MCClipImageViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MCClipImageViewController.swift; sourceTree = "<group>"; };
A52DEEE52B330A1F006618D6 /* ClipImage_cancel.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ClipImage_cancel.png; sourceTree = "<group>"; };
A52DEEE62B330A20006618D6 /* ClipImage_sure.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ClipImage_sure.png; sourceTree = "<group>"; };
A52DEEE72B330A20006618D6 /* ClipImage_rotating.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ClipImage_rotating.png; sourceTree = "<group>"; };
A52DEEE82B330A20006618D6 /* MCClipImageTool.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MCClipImageTool.swift; sourceTree = "<group>"; };
A52DEEE92B330A20006618D6 /* BsWebViewPreloadManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BsWebViewPreloadManager.swift; sourceTree = "<group>"; };
A52DF0B02B330A20006618D6 /* BsBaseModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BsBaseModel.swift; sourceTree = "<group>"; }; A52DF0B02B330A20006618D6 /* BsBaseModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BsBaseModel.swift; sourceTree = "<group>"; };
A52DF0B22B330A20006618D6 /* YHNavigationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YHNavigationController.swift; sourceTree = "<group>"; }; A52DF0B22B330A20006618D6 /* YHNavigationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YHNavigationController.swift; sourceTree = "<group>"; };
A52DF0B32B330A20006618D6 /* YHBaseViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YHBaseViewController.swift; sourceTree = "<group>"; }; A52DF0B32B330A20006618D6 /* YHBaseViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YHBaseViewController.swift; sourceTree = "<group>"; };
A52DF0B42B330A20006618D6 /* YHTabBarViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YHTabBarViewController.swift; sourceTree = "<group>"; }; A52DF0B42B330A20006618D6 /* YHTabBarViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YHTabBarViewController.swift; sourceTree = "<group>"; };
A52DF0B62B330A20006618D6 /* YHWebViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YHWebViewController.swift; sourceTree = "<group>"; };
A52DF0B92B330A20006618D6 /* YHNoDataTipView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YHNoDataTipView.swift; sourceTree = "<group>"; }; A52DF0B92B330A20006618D6 /* YHNoDataTipView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YHNoDataTipView.swift; sourceTree = "<group>"; };
A52DF23D2B3316A0006618D6 /* YHBasicContentView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YHBasicContentView.swift; sourceTree = "<group>"; }; A52DF23D2B3316A0006618D6 /* YHBasicContentView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YHBasicContentView.swift; sourceTree = "<group>"; };
A52DF23E2B3316A0006618D6 /* YHBouncesContentView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YHBouncesContentView.swift; sourceTree = "<group>"; }; A52DF23E2B3316A0006618D6 /* YHBouncesContentView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YHBouncesContentView.swift; sourceTree = "<group>"; };
...@@ -308,48 +284,13 @@ ...@@ -308,48 +284,13 @@
A52DEEC22B330A1F006618D6 /* Helper */ = { A52DEEC22B330A1F006618D6 /* Helper */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
A52DEEE22B330A1F006618D6 /* ClipImage(裁切图片) */,
A52DEECE2B330A1F006618D6 /* BsPageView */,
A52DF2412B33177F006618D6 /* BsHUD */, A52DF2412B33177F006618D6 /* BsHUD */,
A52DEEC32B330A1F006618D6 /* BsKVOHelper.swift */,
A52DEECD2B330A1F006618D6 /* BsMapManager.swift */,
A52DEED12B330A1F006618D6 /* BsConstant.swift */, A52DEED12B330A1F006618D6 /* BsConstant.swift */,
A52DEED22B330A1F006618D6 /* BsPresentView.swift */,
A52DEED32B330A1F006618D6 /* BSJsonUtil.swift */, A52DEED32B330A1F006618D6 /* BSJsonUtil.swift */,
A52DEEE92B330A20006618D6 /* BsWebViewPreloadManager.swift */,
); );
path = Helper; path = Helper;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
A52DEECE2B330A1F006618D6 /* BsPageView */ = {
isa = PBXGroup;
children = (
A52DEECF2B330A1F006618D6 /* BsPageTitleView.swift */,
A52DEED02B330A1F006618D6 /* BsPageContentView.swift */,
);
path = BsPageView;
sourceTree = "<group>";
};
A52DEEE22B330A1F006618D6 /* ClipImage(裁切图片) */ = {
isa = PBXGroup;
children = (
A52DEEE42B330A1F006618D6 /* Images */,
A52DEEE32B330A1F006618D6 /* MCClipImageViewController.swift */,
A52DEEE82B330A20006618D6 /* MCClipImageTool.swift */,
);
path = "ClipImage(裁切图片)";
sourceTree = "<group>";
};
A52DEEE42B330A1F006618D6 /* Images */ = {
isa = PBXGroup;
children = (
A52DEEE52B330A1F006618D6 /* ClipImage_cancel.png */,
A52DEEE62B330A20006618D6 /* ClipImage_sure.png */,
A52DEEE72B330A20006618D6 /* ClipImage_rotating.png */,
);
path = Images;
sourceTree = "<group>";
};
A52DF0AE2B330A20006618D6 /* Base */ = { A52DF0AE2B330A20006618D6 /* Base */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
...@@ -374,7 +315,6 @@ ...@@ -374,7 +315,6 @@
A52DF0B22B330A20006618D6 /* YHNavigationController.swift */, A52DF0B22B330A20006618D6 /* YHNavigationController.swift */,
A52DF0B32B330A20006618D6 /* YHBaseViewController.swift */, A52DF0B32B330A20006618D6 /* YHBaseViewController.swift */,
A52DF0B42B330A20006618D6 /* YHTabBarViewController.swift */, A52DF0B42B330A20006618D6 /* YHTabBarViewController.swift */,
A52DF0B62B330A20006618D6 /* YHWebViewController.swift */,
); );
path = C; path = C;
sourceTree = "<group>"; sourceTree = "<group>";
...@@ -582,9 +522,6 @@ ...@@ -582,9 +522,6 @@
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
A5573EDB2B317C0000D98EC0 /* Assets.xcassets in Resources */, A5573EDB2B317C0000D98EC0 /* Assets.xcassets in Resources */,
A52DF0EB2B330A20006618D6 /* ClipImage_sure.png in Resources */,
A52DF0EA2B330A20006618D6 /* ClipImage_cancel.png in Resources */,
A52DF0EC2B330A20006618D6 /* ClipImage_rotating.png in Resources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
...@@ -655,7 +592,6 @@ ...@@ -655,7 +592,6 @@
A52DF0DF2B330A20006618D6 /* BSJsonUtil.swift in Sources */, A52DF0DF2B330A20006618D6 /* BSJsonUtil.swift in Sources */,
A52DF2502B33177F006618D6 /* BsHUDRotatingImageView.swift in Sources */, A52DF2502B33177F006618D6 /* BsHUDRotatingImageView.swift in Sources */,
A52DF0BB2B330A20006618D6 /* YHAllApiName.swift in Sources */, A52DF0BB2B330A20006618D6 /* YHAllApiName.swift in Sources */,
A52DF0E92B330A20006618D6 /* MCClipImageViewController.swift in Sources */,
A52DF2372B330A21006618D6 /* YHTabBarViewController.swift in Sources */, A52DF2372B330A21006618D6 /* YHTabBarViewController.swift in Sources */,
A52DF0C22B330A20006618D6 /* AppDelegate + UIAppearance.swift in Sources */, A52DF0C22B330A20006618D6 /* AppDelegate + UIAppearance.swift in Sources */,
A52DF2352B330A21006618D6 /* YHNavigationController.swift in Sources */, A52DF2352B330A21006618D6 /* YHNavigationController.swift in Sources */,
...@@ -663,34 +599,26 @@ ...@@ -663,34 +599,26 @@
A5573ED22B317BFF00D98EC0 /* AppDelegate.swift in Sources */, A5573ED22B317BFF00D98EC0 /* AppDelegate.swift in Sources */,
04FAC54A2B32CF1000D24B36 /* YHNetRequest.swift in Sources */, 04FAC54A2B32CF1000D24B36 /* YHNetRequest.swift in Sources */,
04FAC5452B32BA7000D24B36 /* YHMyViewController.swift in Sources */, 04FAC5452B32BA7000D24B36 /* YHMyViewController.swift in Sources */,
A52DF0DE2B330A20006618D6 /* BsPresentView.swift in Sources */,
A52DF0CE2B330A20006618D6 /* BsOverlayView.swift in Sources */, A52DF0CE2B330A20006618D6 /* BsOverlayView.swift in Sources */,
A52DF0C92B330A20006618D6 /* AlignedCollectionViewFlowLayout.swift in Sources */, A52DF0C92B330A20006618D6 /* AlignedCollectionViewFlowLayout.swift in Sources */,
A52DF0BC2B330A20006618D6 /* YHNetworkStatusManager.swift in Sources */, A52DF0BC2B330A20006618D6 /* YHNetworkStatusManager.swift in Sources */,
A52DF0CA2B330A20006618D6 /* UIViewController+Navigation.swift in Sources */, A52DF0CA2B330A20006618D6 /* UIViewController+Navigation.swift in Sources */,
A52DF0C12B330A20006618D6 /* UIButton-Extension.swift in Sources */, A52DF0C12B330A20006618D6 /* UIButton-Extension.swift in Sources */,
A52DF0EE2B330A20006618D6 /* BsWebViewPreloadManager.swift in Sources */,
A52DF0CF2B330A20006618D6 /* String-Extension.swift in Sources */, A52DF0CF2B330A20006618D6 /* String-Extension.swift in Sources */,
A52DF2402B3316A0006618D6 /* YHBouncesContentView.swift in Sources */, A52DF2402B3316A0006618D6 /* YHBouncesContentView.swift in Sources */,
A52DF2362B330A21006618D6 /* YHBaseViewController.swift in Sources */, A52DF2362B330A21006618D6 /* YHBaseViewController.swift in Sources */,
A52DF0BF2B330A20006618D6 /* Date-Extension.swift in Sources */, A52DF0BF2B330A20006618D6 /* Date-Extension.swift in Sources */,
A52DF0DA2B330A20006618D6 /* BsMapManager.swift in Sources */,
A52DF0CD2B330A20006618D6 /* BsGestureTableView.swift in Sources */, A52DF0CD2B330A20006618D6 /* BsGestureTableView.swift in Sources */,
A52DF0DD2B330A20006618D6 /* BsConstant.swift in Sources */, A52DF0DD2B330A20006618D6 /* BsConstant.swift in Sources */,
A52DF0D12B330A20006618D6 /* BsKVOHelper.swift in Sources */,
A52DF2512B33177F006618D6 /* BsHUDErrorView.swift in Sources */, A52DF2512B33177F006618D6 /* BsHUDErrorView.swift in Sources */,
A52DF0CB2B330A20006618D6 /* UIView-Extension.swift in Sources */, A52DF0CB2B330A20006618D6 /* UIView-Extension.swift in Sources */,
A52DF24D2B33177F006618D6 /* BsHUDWariningView.swift in Sources */, A52DF24D2B33177F006618D6 /* BsHUDWariningView.swift in Sources */,
A52DF0C32B330A20006618D6 /* BsCacheTool.swift in Sources */, A52DF0C32B330A20006618D6 /* BsCacheTool.swift in Sources */,
A52DF2392B330A21006618D6 /* YHWebViewController.swift in Sources */,
A52DF24A2B33177F006618D6 /* BsHUDContainerView.swift in Sources */, A52DF24A2B33177F006618D6 /* BsHUDContainerView.swift in Sources */,
A52DF0BD2B330A20006618D6 /* YHBaseUrlManager.swift in Sources */, A52DF0BD2B330A20006618D6 /* YHBaseUrlManager.swift in Sources */,
A52DF0DC2B330A20006618D6 /* BsPageContentView.swift in Sources */,
A52DF2342B330A21006618D6 /* BsBaseModel.swift in Sources */, A52DF2342B330A21006618D6 /* BsBaseModel.swift in Sources */,
04F526AF2B32D4B600FC6CE6 /* YHPersonalCenterCell.swift in Sources */, 04F526AF2B32D4B600FC6CE6 /* YHPersonalCenterCell.swift in Sources */,
A52DF0ED2B330A20006618D6 /* MCClipImageTool.swift in Sources */,
A52DF23B2B330A21006618D6 /* YHNoDataTipView.swift in Sources */, A52DF23B2B330A21006618D6 /* YHNoDataTipView.swift in Sources */,
A52DF0DB2B330A20006618D6 /* BsPageTitleView.swift in Sources */,
A52DF23F2B3316A0006618D6 /* YHBasicContentView.swift in Sources */, A52DF23F2B3316A0006618D6 /* YHBasicContentView.swift in Sources */,
A52DF0C42B330A20006618D6 /* UIApplication-Extension.swift in Sources */, A52DF0C42B330A20006618D6 /* UIApplication-Extension.swift in Sources */,
A52DF0C72B330A20006618D6 /* UIFont-Extension.swift in Sources */, A52DF0C72B330A20006618D6 /* UIFont-Extension.swift in Sources */,
......
...@@ -60,7 +60,7 @@ extension AppDelegate { ...@@ -60,7 +60,7 @@ extension AppDelegate {
IQKeyboardManager.shared.shouldResignOnTouchOutside = true // 控制点击背景是否收起键盘 IQKeyboardManager.shared.shouldResignOnTouchOutside = true // 控制点击背景是否收起键盘
//webView 预加载 //webView 预加载
BsWebViewPreloadManager.share.addPreloadingView() // BsWebViewPreloadManager.share.addPreloadingView()
// //
customAppearance() customAppearance()
......
...@@ -18,13 +18,6 @@ class YHNavigationController: UINavigationController { ...@@ -18,13 +18,6 @@ class YHNavigationController: UINavigationController {
super.viewDidLoad() super.viewDidLoad()
self.interactivePopGestureRecognizer?.delegate = self self.interactivePopGestureRecognizer?.delegate = self
} }
// override func viewWillLayoutSubviews() {
// super.viewWillLayoutSubviews()
// if #available(iOS 14.0, *){
// self.navigationBar.topItem?.backButtonDisplayMode = .minimal
// }
// }
override func pushViewController(_ viewController: UIViewController, animated: Bool) { override func pushViewController(_ viewController: UIViewController, animated: Bool) {
// 隐藏要push的控制器的tabbar // 隐藏要push的控制器的tabbar
......
//
// BsWebViewController.swift
// BaiSiSMApp
//
// Created by davidhuang on 2022/11/11.
// Copyright © 2022 www.davidhuang.com. All rights reserved.
//
import UIKit
import WebKit
extension WKWebView {
open override var safeAreaInsets: UIEdgeInsets {
return UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
}
}
class YHWebViewController: YHBaseViewController {
public var isShowNavigation = true
public var isPresent = false
public var isShowShared = true
// MARK: - 懒加载方法
lazy var kvoHelper = BsKVOHelper()
var urlString : String?
var userAgent:String {
get {
if let content = WKWebView().value(forKey: "userAgent") as? String {
return content
} else {
return ""
}
}
}
public func joinNav() -> UINavigationController {
self.isPresent = true
self.isShowShared = false
let nav = YHNavigationController(rootViewController: self)
nav.modalPresentationStyle = .fullScreen
return nav
}
var isStatusBarHidden = false{
didSet{
if isStatusBarHidden != oldValue, isViewLoaded{
setNeedsStatusBarAppearanceUpdate()
}
}
}
var statusBarStyle = UIStatusBarStyle.lightContent{
didSet{
if statusBarStyle != oldValue, isViewLoaded{
setNeedsStatusBarAppearanceUpdate()
}
}
}
override var prefersStatusBarHidden: Bool{
return isStatusBarHidden
}
override var preferredStatusBarStyle: UIStatusBarStyle{
return statusBarStyle
}
var webView: WKWebView!
lazy var progressView: UIProgressView = {
let temp = UIProgressView()
temp.tintColor = .mainColor
temp.trackTintColor = .white
return temp
}()
//是否加载了js方法
var hasAddJsMethodFlag : Bool = false
// MARK: - 生命周期方法
deinit {
if isViewLoaded {
kvoHelper.remove(observer: self, atObject: webView, forKeyPath: "estimatedProgress")
kvoHelper.remove(observer: self, atObject: webView, forKeyPath: "title")
}
}
override func viewDidLoad() {
super.viewDidLoad()
setupSubview()
addLayout()
registeGlobalUserAgent()
(self.navigationController as? YHNavigationController)?.myDelegate = self
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if isShowNavigation == false {
self.navigationController?.navigationBar.isHidden = true
}
if hasAddJsMethodFlag == false {
webView.configuration.userContentController.add(self, name: "methodForJsInvoke")
hasAddJsMethodFlag = true
}
}
func deinitAction() {
if isShowNavigation == false {
self.navigationController?.navigationBar.isHidden = false
}
//不执行会导致循环引用
webView?.configuration.userContentController.removeScriptMessageHandler(forName: "methodForJsInvoke")
//webView.configuration.userContentController.removeAllContentRuleLists()
(self.navigationController as? YHNavigationController)?.myDelegate = nil
}
}
// MARK: - WKNavigationDelegate
extension YHWebViewController:WKUIDelegate,WKNavigationDelegate {
func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
// showEmptyView(showFlag: true)
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
// showEmptyView(showFlag: false)
}
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
// showEmptyView(showFlag: false)
}
// func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
//// var host: String? = nil
//// if let ipHost = webView.url?.host,let realHost = hostMap[ipHost]{
//// host = realHost
//// }
//// sessionTaskDelegate.handlerChallenge(challenge, host: host,
//// completionHandler: completionHandler)
// }
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
// if let ipHost = navigationAction.request.url?.host,
// let realHost = hostMap[ipHost]{
// var copyRequest = (navigationAction.request as NSURLRequest).httpdns_getPostIncludeBody()
// if copyRequest.allHTTPHeaderFields?["Host"] == nil{
// copyRequest.addValue(realHost, forHTTPHeaderField: "Host")
// webView.load(copyRequest)
// decisionHandler(.cancel)
// return
// }
// }
//
// if let requestUrl = navigationAction.request.url?.absoluteString,
// requestUrl.hasPrefix(RyMTAHybRequest.prefix) {
// print("mta-ry: \(navigationAction.request.url?.absoluteString ?? "null")")
// var requestUrlRemovingPercentEncoding = requestUrl.removingPercentEncoding ?? requestUrl
// requestUrlRemovingPercentEncoding = requestUrlRemovingPercentEncoding.substring(from: RyMTAHybRequest.prefix.count)
// if let obj = RyMTAHybRequest(JSONString: requestUrlRemovingPercentEncoding), obj.trackEvent() {
// decisionHandler(.cancel)
// return
// }
// if MTAHybrid.handle(navigationAction, from: webView){
// decisionHandler(.cancel)
// return
// }
// }
decisionHandler(.allow)
}
}
extension YHWebViewController {
func hideProgress() {
progressView.isHidden = true
}
func showProgress() {
progressView.isHidden = false
}
func goBack(){
if webView.window != nil,webView.canGoBack{
webView.goBack()
}else if navigationController?.viewControllers.count ?? 0 > 1{
navigationController?.popViewController(animated: true)
deinitAction()
}else{
dismiss(animated: true, completion: nil)
deinitAction()
}
}
func setupSubview(){
view.backgroundColor = .white
if let urlString = urlString {
webView = BsWebViewPreloadManager.share.getWebView(urlString: urlString)
webView.frame = UIScreen.main.bounds
webView.scrollView.keyboardDismissMode = .onDrag
webView.backgroundColor = .backgroundColor
webView.isOpaque = false
webView.uiDelegate = self
webView.navigationDelegate = self
webView.allowsLinkPreview = false
webView.scrollView.bounces = false
webView.scrollView.showsVerticalScrollIndicator = false
webView.scrollView.showsHorizontalScrollIndicator = false
kvoHelper.add(observer: self, toObject: webView, forKeyPath: "estimatedProgress", options: .new, context: nil)
kvoHelper.add(observer: self, toObject: webView, forKeyPath: "title", options: .new, context: nil)
view.addSubview(webView)
} else {
BsHUD.flash(message: "urlString 为空")
//#if DEBUG
// if let url = Bundle.main.url(forResource: "WKWebView-WKScriptMessageHandler", withExtension: "html") {
// let request = URLRequest(url: url)
// webView = BsWebViewPreloadManager.share.onlyCreateWebView()
// webView.load(request)
// webView.navigationDelegate = self;
// view.addSubview(webView)
//
// webView.scrollView.contentInsetAdjustmentBehavior = .never
//
// let loginBtnItem = UIBarButtonItem(title: "测试", style: .plain, target: self, action: #selector(onClickTestItem))
// self.navigationItem.rightBarButtonItem = loginBtnItem
// }
//#endif
}
view.addSubview(progressView)
view.backgroundColor = .white
#if DEBUG
let testBtn = UIButton(type: .custom)
testBtn.setTitle("点我呀,豪哥", for: .normal)
testBtn.setTitleColor(.mainColor, for: .normal)
testBtn.backgroundColor = .purple
view.addSubview(testBtn)
testBtn.addTarget(self, action: #selector(onClickTestItem), for: .touchUpInside)
testBtn.snp.makeConstraints { make in
make.top.equalTo(200)
make.right.equalTo(-16)
make.height.equalTo(44)
make.width.equalTo(150)
}
// TODO: - for test hjl 正式发布版本前需要屏蔽下面2个代码
webView.backgroundColor = .purple
#endif
if isPresent == true {
self.bs_setupLeftButton(image: UIImage(named: "close_icon"))
}
if isShowShared == true {
self.bs_setupRightButton(image: UIImage(named: "nav_share_icon"))
}
}
// MARK: - event response 事件响应包括手势和按钮等
//事件响应,包含手势、按钮、通知等等事件的处理
@objc override func clickedNavRight() {
// //1.判断是否登录
// if BsLoginManager.checkLoginStatus(andLogin: true, invokeVc: self) == true {
// BsHUD.flash(message: "分享功能还需要讨论")
// }
}
@objc private func onClickTestItem() -> Void {
let dic = ["type":"appToken","param":["token" : "豪哥你真帅~~~","key2":"value2"]] as [String : Any]
let json = BSJsonUtil.dictionaryToJson(dic as NSDictionary)
let jsString = "methodForAppInvoke('\(json)')"
webView.evaluateJavaScript(jsString) { (result : Any?, error : Error?) in
print("result")
print(result as Any)
print("error")
print(error as Any)
}
self.webView.backgroundColor = .random
}
private func appPassTokenToH5() -> Void {
// let dic = ["type":"appToken","param":["token" : BsLoginManager.shared.loginInfoModel?.access_token ?? ""]] as [String : Any]
// let json = BSJsonUtil.dictionaryToJson(dic as NSDictionary)
// let jsString = "methodForAppInvoke('\(json)')"
// webView.evaluateJavaScript(jsString) { (result : Any?, error : Error?) in
// print("result")
// print(result as Any)
//
// print("error")
// print(error as Any)
// }
}
func addLayout(){
webView.snp.makeConstraints { (make) in
if isShowNavigation == true {
make.top.equalToSuperview().offset(UIDevice.bs_navigationFullHeight())
} else {
make.top.equalToSuperview()
}
make.left.equalToSuperview()
make.right.equalToSuperview()
make.bottom.equalToSuperview()
}
if isShowNavigation == true {
progressView.snp.makeConstraints { (make) in
make.top.equalTo(webView)
make.left.equalToSuperview()
make.right.equalToSuperview()
make.height.equalTo(2)
}
}
}
private func loadURL(url : String? = nil){
print("load url: \(url ?? "")")
if let nsURL = URL(string: url){
let request = URLRequest(url: nsURL)
webView.load(request)
}
}
func registeGlobalUserAgent() {
assert(!self.userAgent.isEmpty)
let newUserAgent = self.userAgent
let version = UIDevice.appVersion() + "." + UIDevice.appBuild()
/*
env 环境: dev 开发、trial 体验、prod 正式
token: 密钥
immerse: true / false APP是否沉浸式
scenes: app / mini / web 进入场景 (为后期做数据埋点上报使用)
*/
let token = ""//BsLoginManager.shared.loginInfoModel?.access_token ?? ""
let uid = ""//BsLoginManager.shared.loginInfoModel?.user_id ?? 0
let phone_num = ""//BsLoginManager.shared.loginInfoModel?.phone_num ?? ""
var dict = ["version":"\(version)",
"uid":"\(uid)",
"token":"\(token)",
"phone_num":"\(phone_num)",
"scenes":"iOS",
"system":newUserAgent,
"statusbar":["width":UIDevice.kScreenW,"height":UIDevice.bs_statusBarHeight()]
] as [String : Any]
#if DEBUG
dict["appName"] = "优眠健康-Dev-iOS"
dict["env"] = "dev"
#else
dict["appName"] = "优眠健康-Release-iOS"
dict["env"] = "prod"
#endif
dict["sys-wkweb"] = newUserAgent
let jsonString = dict.jsonString()
webView.customUserAgent = jsonString
}
}
// MARK: - KVO
extension YHWebViewController {
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
guard (object as? WKWebView) == webView else {
super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
return
}
switch keyPath {
case "estimatedProgress":
let progress = Float(self.webView.estimatedProgress)
progressView.setProgress(progress, animated: true)
if progress >= 1.0 {
UIView.animate(withDuration: 0.3, delay: 0.1, options: .curveEaseOut, animations: {
self.progressView.alpha = 0
}, completion: { (finish) in
self.progressView.setProgress(0.0, animated: false)
})
}else{
self.progressView.alpha = 1
}
break
case "title":
self.navigationItem.title = self.webView.title
break
default:
break
}
}
}
extension YHWebViewController : WKScriptMessageHandler {
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
if message.name == "methodForJsInvoke" {
print("message.name = \(message.name)")
print("message.body = \(message.body)")
/*
var action = {
"type": "2", //业务类型
"param": {"url":"https://www.baidu.com/","key2":"value2",.....}, //业务参数
}
*/
if message.body is [String : Any] == true {
let dic = message.body as! [String : Any]
if let type = dic["type"] as? String {
var param = dic["param"] as? Dictionary<String,Any>
if let temp = param {
param = temp
} else {
param = [:]
}
var title : String = type
switch type {
case "wxShare":
//微信分享
break
case "tabbar":
//tabbar 显示 隐藏
if let show = param?["show"] as? String {
if show == "1" {
NotificationCenter.default.post(name: BsConstant.BsNotification.tabBarShowNotification, object: nil)
} else {
NotificationCenter.default.post(name: BsConstant.BsNotification.tabBarHideNotification, object: nil)
}
}
break
case "goMap":
//地图导航
break
case "appLogin":
//app登录
DispatchQueue.main.async {
// BsLoginManager.shared.showLoginVC(invokeVC: self) {
// //登录成功后的回调
// self.appPassTokenToH5()
// }
}
return
case "callPhone":
//拨打电话
if let phone = param?["phone"] as? String {
phone.makePhone()
}
return
case "goBack":
self.goBack()
return
default:
print("未知的type 类型 \(type)")
break
}
var content : String = "无参数"
if let param = dic["param"] as? Dictionary<String,Any> {
content = BSJsonUtil.dictionaryToJson(param as NSDictionary)
}
title = title + "\n 参数是:" + content
BsHUD.flash(message: title)
}
} else {
print("h5返回数据可能有问题")
}
}
}
}
// MARK: - BsNavigationControllerDelegate
extension YHWebViewController : BsNavigationControllerDelegate {
func canBack() -> Bool {
goBack()
return false
}
override func callBackAction() {
_ = canBack()
}
}
//
// BsKVOHelper.swift
// BaiSiSMApp
//
// Created by davidhuang on 2022/10/19.
// Copyright © 2022 www.davidhuang.com. All rights reserved.
//
import UIKit
///解决重复添加;解决重复移除;解决未添加却移除
open class BsKVOHelper {
class Container: Equatable {
static func == (lhs: BsKVOHelper.Container, rhs: BsKVOHelper.Container) -> Bool {
guard let lObserver = lhs.observer,
let lObject = lhs.object,
let rObserver = rhs.observer,
let rObject = rhs.object else {
return false
}
if lObserver == rObserver, lObject == rObject{
return lhs.keyPath == rhs.keyPath
}
return false
}
var observer: Int?
var object: Int?
var keyPath: String
init(observer: Int?, object: Int?, keyPath: String) {
self.observer = observer
self.object = object
self.keyPath = keyPath
}
func clear(){
observer = nil
object = nil
}
}
private var containers: [Container] = []
public init(){
}
open func add(observer: NSObject,toObject object: NSObject,forKeyPath keyPath: String, options: NSKeyValueObservingOptions = [], context: UnsafeMutableRawPointer?){
let aContainer = Container(observer: observer.hashValue, object: object.hashValue, keyPath: keyPath)
if containers.contains(where: { (thisContainer) -> Bool in
return aContainer == thisContainer
}){
return
}
containers.append(aContainer)
object.addObserver(observer,forKeyPath: keyPath, options: options, context: context)
}
open func remove(observer: NSObject,atObject object: NSObject,forKeyPath keyPath: String){
let aContainer = Container(observer: observer.hashValue, object: object.hashValue, keyPath: keyPath)
if let first = containers.first(where: { (thisContainer) -> Bool in
return aContainer == thisContainer
}){
object.removeObserver(observer, forKeyPath: keyPath)
first.clear()
}
}
}
//
// BsMapManager.swift
// BaiSiSMApp
//
// Created by Davidhuang on 2022/12/15.
// Copyright © 2022 www.davidhuang.com. All rights reserved.
//
import UIKit
import MapKit
class BsMapManager {
// MARK: - 属性
static let sharedInstance = BsMapManager()
public let hasQqMap: Bool = UIApplication.shared.canOpenURL(URL(string: "qqmap://")!)
public let hasIosaMap: Bool = UIApplication.shared.canOpenURL(URL(string: "iosamap://")!)
public let hasBaiduMap: Bool = UIApplication.shared.canOpenURL(URL(string: "baidumap://")!)
// 当前位置或起始位置
var currentLocation: CLLocationCoordinate2D!
var currentAddress: String = ""
// 目标位置
var targetLocation: CLLocationCoordinate2D!
var targetAddress: String = ""
// MARK: - 导航位置初始化
func initNavi(currentLoc: CLLocationCoordinate2D! = nil, currentAdd: String = "", targetLoc: CLLocationCoordinate2D!, targetAdd: String) {
if currentLoc != nil {
currentLocation = currentLoc
}
currentAddress = currentAdd
if targetLoc != nil {
targetLocation = targetLoc
}
targetAddress = targetAdd
}
// MARK: - Apple地图导航
func naviWithAppleMap() {
if targetLocation == nil {
return
}
// 起始位置
let fromLocation = MKMapItem.forCurrentLocation()
fromLocation.name = "我的位置"
// 目标位置
let toCoor = CLLocationCoordinate2D(latitude: targetLocation!.latitude, longitude: targetLocation!.longitude)
let toLocation = MKMapItem(placemark: MKPlacemark(coordinate: toCoor, addressDictionary: [:]))
toLocation.name = targetAddress
// 打开地图
MKMapItem.openMaps(with: [fromLocation, toLocation],
launchOptions: [MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeDriving, MKLaunchOptionsShowsTrafficKey: NSNumber(true)])
}
// MARK: - 百度地图导航
func naviWithBaiduMap() {
if targetLocation == nil {
return
}
/// 请求格式:
/// baidumap://map/direction?origin=34.264642646862,108.95108518068&destination=40.007623,116.360582&coord_type=bd09ll&mode=driving&src=ios.baidu.openAPIdemo
var urlString: String = "baidumap://map/direction?"
// 起始位置
let origin: String = "我的位置"
urlString = urlString + "origin=\(origin)"
// 目标位置
let destination: String = "\(targetLocation!.latitude),\(targetLocation!.longitude)"
let name: String = targetAddress
urlString = urlString + "&destination=name:\(name)|latlng:\(destination)"
/// 可选的坐标系统:
/// bd09ll(百度经纬度坐标)
/// bd09mc(百度墨卡托坐标)
/// gcj02(经国测局加密的坐标)
/// wgs84(gps获取的原始坐标)
urlString = urlString + "&coord_type=gcj02&mode=driving&src=ios.ftsafe.FTSmartSudentCard"
urlString = urlString.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)!
if #available(iOS 10.0, *) {
UIApplication.shared.open(URL(string: urlString)!, options: [:], completionHandler: nil)
} else {
UIApplication.shared.openURL(URL(string: urlString)!)
}
}
// MARK: - 腾讯地图导航
func naviWithQqMap() {
if targetLocation == nil {
return
}
/// 请求格式:
/// qqmap://map/routeplan?type=drive&from=清华&fromcoord=39.994745,116.247282&to=怡和世家&tocoord=39.867192,116.493187&referer=OB4BZ-D4W3U-B7VVO-4PJWW-6TKDJ-WPB77
/// 这里可能需要开发者key,即referer
var urlString: String = "qqmap://map/routeplan?type=drive"
let origin: String = "我的位置"
urlString = urlString + "&from=\(origin)&fromcoord=CurrentLocation"
let destination: String = "\(targetLocation!.latitude),\(targetLocation!.longitude)"
let name: String = targetAddress
urlString = urlString + "&to=\(name)&tocoord=\(destination)"
urlString = urlString.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)!
if #available(iOS 10.0, *) {
UIApplication.shared.open(URL(string: urlString)!, options: [:], completionHandler: nil)
} else {
UIApplication.shared.openURL(URL(string: urlString)!)
}
}
// MARK: - 高德地图导航
func naviWithAMap() {
if targetLocation == nil {
return
}
/// 请求格式:
/// iosamap://path?sourceApplication=applicationName&sid=&slat=39.92848272&slon=116.39560823&sname=A&did=&dlat=39.98848272&dlon=116.47560823&dname=B&dev=0&t=0
var urlString: String = "iosamap://path?sourceApplication=FTSmartSudentCard"
let name: String = targetAddress
urlString = urlString + "&dlat=\(targetLocation!.latitude)&dlon=\(targetLocation!.longitude)&dname=\(name)&dev=0&t=0"
urlString = urlString.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)!
if #available(iOS 10.0, *) {
UIApplication.shared.open(URL(string: urlString)!, options: [:], completionHandler: nil)
} else {
UIApplication.shared.openURL(URL(string: urlString)!)
}
}
}
//
// BsPageContentView.swift
// GDKit
//
// Created by GDKit on 01/11/2022.
// Copyright (c) 2022 GDKit. All rights reserved.
//
import UIKit
@objc public protocol BsPageContentViewDelegate : AnyObject {
func pageContentView(_ contentView : BsPageContentView, progress : CGFloat, sourceIndex : Int, targetIndex : Int)
}
private let ContentCellID = "BsContentCellID"
open class BsPageContentView: UIView {
// MARK: - 定义属性
fileprivate var childVcs : [UIViewController]
fileprivate weak var parentVC : UIViewController?
fileprivate var startOffsetX : CGFloat = 0
fileprivate var isForbidScrollDelegate : Bool = false
@objc public weak var delegate : BsPageContentViewDelegate?
public var isScrollEnabled: Bool? {
didSet {
if let isScrollEnabled = isScrollEnabled {
collectionView.isScrollEnabled = isScrollEnabled
}
}
}
@objc public func banScrollEnabled() {
collectionView.isScrollEnabled = false
}
fileprivate func getLayout() -> UICollectionViewFlowLayout {
let layout = UICollectionViewFlowLayout()
layout.itemSize = self.bounds.size
layout.minimumLineSpacing = 0
layout.minimumInteritemSpacing = 0
layout.scrollDirection = .horizontal
return layout
}
// MARK: - 懒加载属性
fileprivate lazy var collectionView : UICollectionView = {[weak self] in
// 1.创建layout
let layout = self?.getLayout() ?? UICollectionViewFlowLayout()
// 2.创建UICollectionView
let collectionView = UICollectionView(frame: CGRect.zero, collectionViewLayout: layout)
collectionView.backgroundColor = .clear//groupTableViewBackground
collectionView.showsHorizontalScrollIndicator = false
collectionView.isPagingEnabled = true
collectionView.bounces = false
collectionView.dataSource = self
collectionView.delegate = self
collectionView.scrollsToTop = false
collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: ContentCellID)
return collectionView
}()
// MARK: - 自定义构造函数
@objc public init(frame: CGRect, childVcs : [UIViewController], parentViewController : UIViewController?) {
self.childVcs = childVcs
self.parentVC = parentViewController
super.init(frame: frame)
// 设置UI
setupUI()
}
public required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
// MARK: - 设置UI界面
extension BsPageContentView {
fileprivate func setupUI() {
// 1.将所有的子控制器添加父控制器中
for childVc in childVcs {
parentVC?.addChild(childVc)
}
// 2.添加UICollectionView,用于在Cell中存放控制器的View
addSubview(collectionView)
collectionView.frame = bounds
}
public func refreshRect() {
collectionView.frame = bounds
collectionView.collectionViewLayout = self.getLayout()
}
}
// MARK: - 遵守UICollectionViewDataSource
extension BsPageContentView : UICollectionViewDataSource {
public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return childVcs.count
}
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
// 1.创建Cell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ContentCellID, for: indexPath)
// 2.给Cell设置内容
for view in cell.contentView.subviews {
view.removeFromSuperview()
}
let childVc = childVcs[(indexPath as NSIndexPath).item]
childVc.view.frame = cell.contentView.bounds
cell.contentView.addSubview(childVc.view)
return cell
}
}
// MARK: - 遵守UICollectionViewDelegate
extension BsPageContentView : UICollectionViewDelegate {
public func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
isForbidScrollDelegate = false
startOffsetX = scrollView.contentOffset.x
}
public func scrollViewDidScroll(_ scrollView: UIScrollView) {
// 0.判断是否是点击事件
if isForbidScrollDelegate { return }
// 1.定义获取需要的数据
var progress : CGFloat = 0
var sourceIndex : Int = 0
var targetIndex : Int = 0
// 2.判断是左滑还是右滑
let currentOffsetX = scrollView.contentOffset.x
let scrollViewW = scrollView.bounds.width
if currentOffsetX > startOffsetX { // 左滑
// 1.计算progress
progress = currentOffsetX / scrollViewW - floor(currentOffsetX / scrollViewW)
// 2.计算sourceIndex
sourceIndex = Int(currentOffsetX / scrollViewW)
// 3.计算targetIndex
targetIndex = sourceIndex + 1
if targetIndex >= childVcs.count {
targetIndex = childVcs.count - 1
}
// 4.如果完全划过去
if currentOffsetX - startOffsetX == scrollViewW {
progress = 1
targetIndex = sourceIndex
}
} else { // 右滑
// 1.计算progress
progress = 1 - (currentOffsetX / scrollViewW - floor(currentOffsetX / scrollViewW))
// 2.计算targetIndex
targetIndex = Int(currentOffsetX / scrollViewW)
// 3.计算sourceIndex
sourceIndex = targetIndex + 1
if sourceIndex >= childVcs.count {
sourceIndex = childVcs.count - 1
}
}
// 3.将progress/sourceIndex/targetIndex传递给titleView
delegate?.pageContentView(self, progress: progress, sourceIndex: sourceIndex, targetIndex: targetIndex)
}
}
// MARK: - 对外暴露的方法
extension BsPageContentView {
@objc public func setCurrentIndex(_ currentIndex : Int) {
// 1.记录需要进制执行代理方法
isForbidScrollDelegate = true
// 2.滚动正确的位置
let offsetX = CGFloat(currentIndex) * collectionView.frame.width
collectionView.setContentOffset(CGPoint(x: offsetX, y: 0), animated: false)
}
}
//
// BsPageTitleView.swift
// GDKit
//
// Created by GDKit on 01/11/2022.
// Copyright (c) 2022 GDKit. All rights reserved.
//
import UIKit
// MARK: - 定义协议
@objc public protocol BsPageTitleViewDelegate : AnyObject {
/// 点击标题回调
///
/// - Parameters:
/// - titleView: BsPageTitleView
/// - index: 标题tag
func classTitleView(_ titleView : BsPageTitleView, selectedIndex index : Int)
func classTitleViewCurrentIndex(_ titleView : BsPageTitleView, currentIndex index : Int)
}
/// 滚动条高度
private let kScrollLineH : CGFloat = 2
/// 默认颜色
private let kNormalColor : (CGFloat, CGFloat, CGFloat) = (102, 102, 102)
/// 选中颜色
private let kSelectColor : (CGFloat, CGFloat, CGFloat) = (51, 51, 51)
/// 滚动条颜色
private let kBottomLineColor : (CGFloat, CGFloat, CGFloat) = (240, 240, 240)
private let kWhiteColor : (CGFloat, CGFloat, CGFloat) = (255, 255, 255)
open class BsPageTitleView: UIView {
fileprivate(set) var currentIndex : Int = 0
fileprivate var titles : [String]
@objc public weak var delegate : BsPageTitleViewDelegate?
fileprivate lazy var titleLabels : [UILabel] = [UILabel]()
fileprivate lazy var scrollView : UIScrollView = {
let scrollView = UIScrollView()
scrollView.showsHorizontalScrollIndicator = false
scrollView.scrollsToTop = false
// scrollView.bounces = false
return scrollView
}()
fileprivate var lineWidth:CGFloat
fileprivate var lineHeight:CGFloat
fileprivate var lineColor:UIColor?
fileprivate var lineBottomSpace:CGFloat
fileprivate var font:UIFont
fileprivate lazy var scrollLine : UIView = {
let scrollLine = UIView()
if let lineColor = self.lineColor {
scrollLine.backgroundColor = lineColor
} else {
scrollLine.backgroundColor = UIColor(r: self.titleNormalColor.0, g: self.titleNormalColor.1, b: self.titleNormalColor.2)
}
scrollLine.layer.cornerRadius = self.lineHeight/2
scrollLine.layer.masksToBounds = true
return scrollLine
}()
fileprivate lazy var backView : UIView = {
let view = UIView(frame: self.scrollView.bounds)
self.scrollView.addSubview(view)
return view
}()
var cellWidth:CGFloat = 0
var cellpadding:CGFloat = 0
var cellSpace:CGFloat = 20
fileprivate var scale:CGFloat = 0
/// 默认颜色
private var titleNormalColor : (CGFloat, CGFloat, CGFloat) = kNormalColor
/// 选中颜色
private var titleSelectColor : (CGFloat, CGFloat, CGFloat) = kSelectColor
/// 默认背景颜色
private var normalBackgroundColor : (CGFloat, CGFloat, CGFloat) = kWhiteColor
/// 选中背景颜色
private var selectBackgroundColor : (CGFloat, CGFloat, CGFloat) = kWhiteColor
/// 标题选中字形
private var titleSelectFont : UIFont = UIFont.boldSystemFont(ofSize: 14)
///是否隐藏底部分离线
private var isHiddenSeparator: Bool = false
///scrollView是否居中显示
private var isCenter: Bool = false
private var itemCornerRadius: CGFloat = 0 ///item圆角
/// 初始化
/// - Parameters:
/// - frame: CGRect
/// - titles: 标题
/// - lineWidth: 滚动条宽度
/// - lineHeight: 滚动条高度
/// - lineBottomSpace: 滚动条底部间隔
/// - lineColor: 滚动条颜色
/// - font: 字体
/// - cellWidth: cell宽度
/// - cellSpace: cell间隔
/// - scale: 缩放比例
/// - titleNormalColor: 标题默认颜色
/// - titleSelectColor: 标题选中颜色
/// - normalBackgroundColor: 标题默认背景颜色
/// - selectBackgroundColor: 标题选中背景颜色
/// - currentIndex: 当前选中下标
/// - isHiddenSeparator: 是否隐藏底部分割线
/// - titleSelectFont: 标题选中字形
/// - isCenter: 是否居中
/// - itemCornerRadius: item圆角
@objc public init(frame: CGRect,
titles:[String],
lineWidth: CGFloat,
lineHeight: CGFloat,
lineBottomSpace: CGFloat,
lineColor: UIColor?,
font: UIFont?,
cellWidth:CGFloat,
cellpadding:CGFloat,
cellSpace:CGFloat,
scale:CGFloat,
titleNormalColor:[CGFloat]?,
titleSelectColor:[CGFloat]?,
normalBackgroundColor:[CGFloat]?,
selectBackgroundColor:[CGFloat]?,
currentIndex:Int = 0,
isHiddenSeparator: Bool = false,
titleSelectFont: UIFont? = nil,
isCenter: Bool = false,
itemCornerRadius: CGFloat = 0) {
self.titles = titles
self.lineWidth = lineWidth // == 0 ? 50 : lineWidth
self.lineHeight = lineHeight // == 0 ? 2 : lineHeight
self.lineBottomSpace = lineBottomSpace
self.lineColor = lineColor
self.font = font == nil ? UIFont.boldSystemFont(ofSize: 14) : font!
self.cellWidth = cellWidth
self.cellpadding = cellpadding
self.cellSpace = cellSpace // == 0 ? 20 : cellSpace
self.scale = scale
if let titleNormalColor = titleNormalColor,
titleNormalColor.count == 3 {
self.titleNormalColor = (titleNormalColor[0],titleNormalColor[1],titleNormalColor[2])
}else{
self.titleNormalColor = kNormalColor
}
if let titleSelectColor = titleSelectColor,
titleSelectColor.count == 3 {
self.titleSelectColor = (titleSelectColor[0],titleSelectColor[1],titleSelectColor[2])
}else{
self.titleSelectColor = kSelectColor
}
if let normalBackgroundColor = normalBackgroundColor,
normalBackgroundColor.count == 3 {
self.normalBackgroundColor = (normalBackgroundColor[0],normalBackgroundColor[1],normalBackgroundColor[2])
}else{
self.normalBackgroundColor = kWhiteColor
}
if let selectBackgroundColor = selectBackgroundColor,
selectBackgroundColor.count == 3 {
self.selectBackgroundColor = (selectBackgroundColor[0],selectBackgroundColor[1],selectBackgroundColor[2])
}else{
self.selectBackgroundColor = kWhiteColor
}
self.isHiddenSeparator = isHiddenSeparator
self.isCenter = isCenter
self.itemCornerRadius = itemCornerRadius
if titles.count > currentIndex && currentIndex >= 0 {
self.currentIndex = currentIndex
}
if let titleSelectFont = titleSelectFont {
self.titleSelectFont = titleSelectFont
} else {
self.titleSelectFont = self.font
}
super.init(frame: frame)
// 设置UI界面
setupUI()
}
public required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
public func setup() {
scrollLine.isHidden = true
}
public func setScrollLine(isHidden: Bool) {
scrollLine.isHidden = isHidden
}
public func isScrollEnabled(_ isScrollEnabled: Bool) {
scrollView.isScrollEnabled = isScrollEnabled
}
public func setNone() {
self.titleLabelClick(UITapGestureRecognizer())
}
var tapGesList = [UITapGestureRecognizer]()
@objc public func moveToLast() {
if let tapGes = tapGesList.last {
titleLabelClick(tapGes)
}
}
@objc public func changedTitle(title: String, index: Int) {
if titleLabels.count <= index {
return
}
let label: UILabel = titleLabels[index]
label.text = title;
}
}
extension BsPageTitleView {
fileprivate func setupUI() {
// 1.添加UIScrollView
addSubview(scrollView)
scrollView.frame = bounds
// 2.添加title对应的Label
setupTitleLabels()
// 3.设置底线和滚动的滑块
setupBottomLineAndScrollLine()
}
fileprivate func setupTitleLabels(){
var contentWidth:CGFloat = 0
// 0.确定label的一些frame的值
// let labelW : CGFloat = frame.width / CGFloat(titles.count > count ? count : titles.count)
// let labelW : CGFloat = 120
let labelH : CGFloat = frame.height - lineHeight;
let labelY : CGFloat = 0
var labelX : CGFloat = cellSpace
for (index, title) in titles.enumerated() {
let label = UILabel()
label.text = title
label.tag = index
label.font = font
label.numberOfLines = 2
label.textColor = UIColor(r: self.titleNormalColor.0, g: self.titleNormalColor.1, b: self.titleNormalColor.2)
label.backgroundColor = UIColor(r: self.normalBackgroundColor.0, g: self.normalBackgroundColor.1, b: self.normalBackgroundColor.2)
label.textAlignment = .center
label.sizeToFit()
var width = cellWidth == 0 ? label.bounds.width : cellWidth
width += cellpadding * 2
label.frame = CGRect(x: labelX, y: labelY, width: width, height: labelH)
backView.addSubview(label)
labelX = label.frame.maxX + cellSpace
contentWidth = labelX
titleLabels.append(label)
if itemCornerRadius > 0 {
label.layer.cornerRadius = itemCornerRadius
label.layer.masksToBounds = true
}
// 5.给Label添加手势
label.isUserInteractionEnabled = true
let tapGes = UITapGestureRecognizer(target: self, action: #selector(self.titleLabelClick(_:)))
label.addGestureRecognizer(tapGes)
tapGesList.append(tapGes)
}
var backViewFrame = backView.frame
backViewFrame.size.width = contentWidth
backView.frame = backViewFrame
scrollView.contentSize = CGSize(width: contentWidth, height: bounds.height)
if self.bounds.size.width > contentWidth && isCenter == true {
backView.bounds.origin.x = (self.bounds.size.width - contentWidth)/2
}
}
fileprivate func setupBottomLineAndScrollLine() {
if isHiddenSeparator == false {
let bottomLine = UIView()
bottomLine.backgroundColor = UIColor(r: kBottomLineColor.0, g: kBottomLineColor.1, b: kBottomLineColor.2)
let lineH : CGFloat = 0.5
bottomLine.frame = CGRect(x: 0, y: frame.height - lineH, width: frame.width, height: lineH)
addSubview(bottomLine)
}
// 2.添加scrollLine
// 2.1.获取第一个Label
guard self.currentIndex < titleLabels.count else {
return
}
let firstLabel = titleLabels[self.currentIndex]
// guard let firstLabel = titleLabels.first else { return }
firstLabel.font = titleSelectFont
firstLabel.textColor = UIColor(r: self.titleSelectColor.0, g: self.titleSelectColor.1, b: self.titleSelectColor.2)
firstLabel.backgroundColor = UIColor(r: self.selectBackgroundColor.0, g: self.selectBackgroundColor.1, b: self.selectBackgroundColor.2)
firstLabel.transform = CGAffineTransform(scaleX: 1 + scale, y: 1 + scale)
// 2.2.设置scrollLine的属性
backView.addSubview(scrollLine)
scrollLine.frame = CGRect(x: firstLabel.frame.origin.x, y: frame.height - lineHeight - lineBottomSpace, width: lineWidth, height: lineHeight)
// scrollLine.frame = CGRect(x: firstLabel.frame.origin.x, y: frame.height - lineH, width: firstLabel.frame.width/2.5, height: lineH)
scrollLine.center.x = firstLabel.center.x
}
}
// MARK: - 监听Label的点击
extension BsPageTitleView {
@objc fileprivate func titleLabelClick(_ tapGes : UITapGestureRecognizer) {
// 0.获取当前Label
let currentLabel = tapGes.view as? UILabel ?? UILabel()
// 2.获取之前的Label
let oldLabel = titleLabels[currentIndex]
// 1.如果是重复点击同一个Title,那么直接返回
if currentLabel.tag != currentIndex {
currentLabel.font = titleSelectFont
oldLabel.font = font
// 3.切换文字的颜色
currentLabel.textColor = UIColor(r: self.titleSelectColor.0, g: self.titleSelectColor.1, b: self.titleSelectColor.2)
currentLabel.backgroundColor = UIColor(r: self.selectBackgroundColor.0, g: self.selectBackgroundColor.1, b: self.selectBackgroundColor.2)
oldLabel.textColor = UIColor(r: self.titleNormalColor.0, g: self.titleNormalColor.1, b: self.titleNormalColor.2)
oldLabel.backgroundColor = UIColor(r: self.normalBackgroundColor.0, g: self.normalBackgroundColor.1, b: self.normalBackgroundColor.2)
}
// 4.保存最新Label的下标值
currentIndex = currentLabel.tag
// 5.滚动条位置发生改变
UIView.animate(withDuration: 0.15, animations: {
self.scrollLine.center.x = currentLabel.center.x
})
let moveTotalX = currentLabel.center.x - oldLabel.center.x
if moveTotalX >= 0 {
if (currentLabel.frame.origin.x + currentLabel.bounds.size.width) > (self.scrollView.contentOffset.x + UIScreen.main.bounds.size.width) {
// 2.滚动正确的位置
let offsetX = currentLabel.frame.origin.x + currentLabel.bounds.size.width - UIScreen.main.bounds.size.width + 30
self.scrollView.setContentOffset(CGPoint(x: offsetX, y: 0), animated: true)
}
}else {
if currentIndex == 0 {
self.scrollView.setContentOffset(CGPoint(x: 0, y: 0), animated: true)
}else {
if currentLabel.frame.origin.x < self.scrollView.contentOffset.x {
// 2.滚动正确的位置
let offsetX = currentLabel.frame.origin.x - 10
self.scrollView.setContentOffset(CGPoint(x: offsetX, y: 0), animated: true)
}
}
}
delegate?.classTitleView(self, selectedIndex: currentIndex)
}
}
// MARK: - 对外暴露的方法
extension BsPageTitleView {
@objc public func setTitleWithProgress(_ progress : CGFloat, sourceIndex : Int, targetIndex : Int) {
let maxScale = 1 + scale
// 1.取出sourceLabel/targetLabel
let sourceLabel = titleLabels[sourceIndex]
let targetLabel = titleLabels[targetIndex]
// 2.处理滑块的逻辑
let moveTotalX = targetLabel.center.x - sourceLabel.center.x
let moveX = moveTotalX * progress
scrollLine.center.x = sourceLabel.center.x + moveX
// 3.颜色的渐变(复杂)
// 3.1.取出变化的范围
let colorDelta = (self.titleSelectColor.0 - self.titleNormalColor.0, self.titleSelectColor.1 - self.titleNormalColor.1, self.titleSelectColor.2 - self.titleNormalColor.2)
// 3.2.变化sourceLabel
sourceLabel.textColor = UIColor(r: self.titleSelectColor.0 - colorDelta.0 * progress, g: self.titleSelectColor.1 - colorDelta.1 * progress, b: self.titleSelectColor.2 - colorDelta.2 * progress)
// 3.2.变化targetLabel
targetLabel.textColor = UIColor(r: self.titleNormalColor.0 + colorDelta.0 * progress, g: self.titleNormalColor.1 + colorDelta.1 * progress, b: self.titleNormalColor.2 + colorDelta.2 * progress)
//背景颜色渐变
let backColorDelta = (self.selectBackgroundColor.0 - self.normalBackgroundColor.0, self.selectBackgroundColor.1 - self.normalBackgroundColor.1, self.selectBackgroundColor.2 - self.normalBackgroundColor.2)
sourceLabel.backgroundColor = UIColor(r: self.selectBackgroundColor.0 - backColorDelta.0 * progress, g: self.selectBackgroundColor.1 - backColorDelta.1 * progress, b: self.selectBackgroundColor.2 - backColorDelta.2 * progress)
targetLabel.backgroundColor = UIColor(r: self.normalBackgroundColor.0 + backColorDelta.0 * progress, g: self.normalBackgroundColor.1 + backColorDelta.1 * progress, b: self.normalBackgroundColor.2 + backColorDelta.2 * progress)
// sourceLabel缩放
sourceLabel.transform = CGAffineTransform(scaleX: maxScale - scale * progress, y:maxScale - scale * progress)
// targetLabel缩放
targetLabel.transform = CGAffineTransform(scaleX: 1 + scale * progress, y:1 + scale * progress)
if progress == 1.0 {
// 4.记录最新的index
currentIndex = targetIndex
delegate?.classTitleViewCurrentIndex(self, currentIndex: currentIndex)
if moveTotalX >= 0 {
if (targetLabel.frame.origin.x + targetLabel.bounds.size.width) > (self.scrollView.contentOffset.x + UIScreen.main.bounds.size.width) {
// 2.滚动正确的位置
let offsetX = targetLabel.frame.origin.x + targetLabel.bounds.size.width - UIScreen.main.bounds.size.width + 30
self.scrollView.setContentOffset(CGPoint(x: offsetX, y: 0), animated: true)
}
}else {
if currentIndex == 0 {
self.scrollView.setContentOffset(CGPoint(x: 0, y: 0), animated: true)
}else {
if targetLabel.frame.origin.x < self.scrollView.contentOffset.x {
// 2.滚动正确的位置
let offsetX = targetLabel.frame.origin.x - 10
self.scrollView.setContentOffset(CGPoint(x: offsetX, y: 0), animated: true)
}
}
}
}
}
}
//
// BsPresentView.swift
// BaiSiSMApp
//
// Created by Davidhuang on 2022/12/15.
// Copyright © 2022 www.davidhuang.com. All rights reserved.
//
import UIKit
/// view.tag = 98 由下往上推出
/// view.tag = 99 由frame起点缩放
open class BsPresentView: UIView {
var animated: Bool = true
///由下往上推出
@objc public func bs_showView(_ view: UIView, isTapEnabled: Bool = true) {
self.animated = true
bs_showView(view, isTapEnabled: isTapEnabled, animated: true)
}
///由下往上推出
@objc public func bs_showView(_ view: UIView, isTapEnabled: Bool = true, animated: Bool) {
// self.keyWindow = [[[UIApplication sharedApplication] delegate] window];
// self.keyVC = self.keyWindow.rootViewController;
// self.frame = self.keyWindow.bounds;
view.tag = 98
self.animated = animated
self.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height)
self.backgroundColor = UIColor.black.withAlphaComponent(0.4)
UIApplication.shared.keyWindow?.addSubview(self)
let topView = UIView(frame: self.frame)
self.addSubview(topView)
topView.height = self.height - view.height
if isTapEnabled == true {
let tap = UITapGestureRecognizer(target: self, action: #selector(bs_closeView))
topView.addGestureRecognizer(tap)
}
self.addSubview(view)
view.top = self.height
if (animated == true) {
UIView.animate(withDuration: 0.25) {
view.top = self.height - view.height
}
}else{
view.top = self.height - view.height
}
}
///由frame为起点缩放
@objc public func bs_showView(_ view: UIView, frame: CGRect) {
view.tag = 99
self.animated = true
//view.frame = CGRect(x: frame.origin.x, y: frame.origin.y, width: 0, height: 0)
self.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height)
//self.backgroundColor = UIColor.black.withAlphaComponent(0.4)
UIApplication.shared.keyWindow?.addSubview(self)
let backView = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height))
self.addSubview(backView)
let tap = UITapGestureRecognizer(target: self, action: #selector(bs_closeView))
backView.addGestureRecognizer(tap)
backView.isUserInteractionEnabled = false
self.addSubview(view)
view.frame = frame
if (animated == true) {
var offsetX = frame.size.width / 2
if frame.origin.x < (UIScreen.main.bounds.size.width - frame.size.width)/2 {
offsetX = -frame.size.width / 2
}
let offsetY = -frame.size.height / 2
view.transform = __CGAffineTransformMake(0.01, 0, 0, 0.01, offsetX, offsetY)
//view.layer.anchorPoint = CGPoint(x: 0, y: 0) //锚点
UIView.animate(withDuration: 0.3) {
view.alpha = 1.0
view.transform = __CGAffineTransformMake(1.05, 0, 0, 1.0, 0, 0)
} completion: { success in
UIView.animate(withDuration: 0.1) {
view.transform = __CGAffineTransformMake(1, 0, 0, 1, 0, 0)
} completion: { success in
// 恢复原位
view.transform = CGAffineTransform.identity
backView.isUserInteractionEnabled = true
}
}
}else{
view.frame = frame
}
}
// override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
// self.bs_closeView()
// }
@objc public func bs_closeView() {
guard let view = self.subviews.last, self.subviews.count == 2 else {
self.removeFromSuperview()
return
}
if (animated == true) {
if view.tag == 99 {
let frame = view.frame
// 动画由大变小
view.transform = __CGAffineTransformMake(1, 0, 0, 1, 0, 0)
UIView.animate(withDuration: 0.2) {
var offsetX = frame.size.width / 2
if frame.origin.x < (UIScreen.main.bounds.size.width - frame.size.width)/2 {
offsetX = -frame.size.width / 2
}
let offsetY = -frame.size.height / 2
view.transform = __CGAffineTransformMake(0.01, 0, 0, 0.01, offsetX, offsetY)
} completion: { success in
view.transform = CGAffineTransform.identity
view.alpha = 0.0
self.removeFromSuperview()
}
} else {
UIView.animate(withDuration: 0.25, animations: {
view.top = self.height
}) { (finished) in
self.removeFromSuperview()
}
}
}else{
view.top = self.height
self.removeFromSuperview()
}
}
public class func bs_closeView() {
for view in UIApplication.shared.keyWindow?.subviews ?? [] {
if let view = view as? BsPresentView {
view.bs_closeView()
break
}
}
}
}
extension UIView {
@objc public func bs_closeViewToPresentView() {
if let presentView = self.superview as? BsPresentView {
presentView.bs_closeView()
}
}
}
//
// BskWebViewPreloadManager.swift
// BaiSiSMApp
//
// Created by davidhuang on 2022/11/22.
// Copyright © 2022 www.davidhuang.com. All rights reserved.
//
import UIKit
import WebKit
class BsWebViewPreloadManager : NSObject {
private var dicPreloadedViews : [String : AnyObject] = [:]
static let share = BsWebViewPreloadManager()
override init() {
super.init()
addPreloadingView()
}
// /**
// 根据URL 预初始化若干WebView
// */
// - (void)addPreloadingView:(NSArray *)urls {
// for (NSString *url in urls) {
// if (![self.urls containsObject:url]) {
// [self.urls addObject: url];
// ReuseWebView *webView = [self createWebView];
// [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:url]]];
// [self.preloadedViews addEntriesFromDictionary:@{url:webView}];
// }
// }
// }
}
// MARK: - 私有方法 methods
extension BsWebViewPreloadManager {
private func getWebview(urlString : String) -> WKWebView {
if let wk = dicPreloadedViews[urlString] {
return wk as! WKWebView
}
return createWebView(urlString: urlString)
}
private func createWebView(urlString : String) -> WKWebView {
let jScript = "var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);"
let userScript = WKUserScript(source: jScript, injectionTime: WKUserScriptInjectionTime.atDocumentEnd, forMainFrameOnly: true)
let userContentController = WKUserContentController()
userContentController.addUserScript(userScript)
let cfg = WKWebViewConfiguration()
cfg.allowsInlineMediaPlayback = true
cfg.mediaTypesRequiringUserActionForPlayback = []
cfg.userContentController = userContentController
let wv = WKWebView(frame: UIScreen.main.bounds,configuration: cfg)
if let nsURL = URL(string: urlString){
let request = URLRequest(url: nsURL)
wv.load(request)
return wv
}
return WKWebView()
}
#if DEBUG
func onlyCreateWebView() -> WKWebView {
let jScript = "var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);"
let userScript = WKUserScript(source: jScript, injectionTime: WKUserScriptInjectionTime.atDocumentEnd, forMainFrameOnly: true)
let userContentController = WKUserContentController()
userContentController.addUserScript(userScript)
let cfg = WKWebViewConfiguration()
cfg.allowsInlineMediaPlayback = true
cfg.mediaTypesRequiringUserActionForPlayback = []
cfg.userContentController = userContentController
let wv = WKWebView(frame: UIScreen.main.bounds,configuration: cfg)
return wv
}
#endif
}
// MARK: - public methods
extension BsWebViewPreloadManager {
func addPreloadingView() {
let arrUrl = [
BsConstant.URL.medical_center_url]
for item in arrUrl {
let wv = createWebView(urlString: item)
dicPreloadedViews[item] = wv
}
}
func getWebView(urlString : String) -> WKWebView {
let urls = dicPreloadedViews.keys
if urls.contains(urlString) == false {
return getWebview(urlString: urlString)
} else {
let wk = createWebView(urlString: urlString)
dicPreloadedViews[urlString] = wk
return wk
}
}
}
//
// MCClipImageTool.swift
// MCAPI
//
// Created by MC on 2018/9/18.
// Copyright © 2018年 MC. All rights reserved.
//
import UIKit
extension UIImage {
/**
* 翻转图片
*/
func rotationImage(orientation:UIImage.Orientation) -> UIImage {
var rotate : Double = 0.0;
var rect = CGRect.init()
var translateX : CGFloat = 0.0;
var translateY : CGFloat = 0.0;
var scaleX : CGFloat = 1.0;
var scaleY : CGFloat = 1.0;
let imageWidth = self.size.width
let imageHeight = self.size.height
// 根据方向旋转
switch (orientation) {
case .left:
rotate = Double.pi / 2;
rect = CGRect.init(x: 0, y: 0, width: imageHeight, height: imageWidth)
translateX = 0
translateY = -rect.size.width;
scaleY = rect.size.width/rect.size.height;
scaleX = rect.size.height/rect.size.width;
break;
case .right:
rotate = 33 * Double.pi / 2;
rect = CGRect.init(x: 0, y: 0, width: imageHeight, height: imageWidth)
translateX = -rect.size.height;
translateY = 0;
scaleY = rect.size.width/rect.size.height;
scaleX = rect.size.height/rect.size.width;
break;
case .down:
rotate = Double.pi
rect = CGRect.init(x: 0, y: 0, width: imageWidth, height: imageHeight)
translateX = -rect.size.width;
translateY = -rect.size.height;
break;
default:
rotate = 0.0;
rect = CGRect.init(x: 0, y: 0, width: imageWidth, height: imageHeight)
translateX = 0;
translateY = 0;
break;
}
//做CTM变换,并绘制图片
UIGraphicsBeginImageContext(rect.size);
let context = UIGraphicsGetCurrentContext();
context?.translateBy(x: 0, y: rect.size.height)
context?.scaleBy(x: 1, y: -1)
context?.rotate(by: CGFloat(rotate))
context?.translateBy(x: translateX, y: translateY)
context?.scaleBy(x: scaleX, y: scaleY)
context?.draw(self.cgImage!, in: CGRect.init(x: 0, y: 0, width: rect.size.width, height: rect.size.height))
let newPic = UIGraphicsGetImageFromCurrentImageContext();
return newPic!
}
/**
* 判断图片和裁剪框的关系类型
*/
func judgeRelationTypeWithCropSize(_ cropSize: CGSize) -> Int {
var relationType = 0
let crop_W = cropSize.width
let crop_H = cropSize.height
let image_W = self.size.width
let image_H = self.size.height
let imageRadio = image_W / image_H
let cropRadio = crop_W / crop_H
/** 裁切框宽高比 > 1
0. 裁切框宽高比 >= 图片宽高比 imageView宽固定,高适配
1. 裁切框宽高比 < 图片宽高比 imageView高固定,宽适配
*/
/** 裁切框宽高比 = 1
2. 裁切框宽高比 >= 图片宽高比 imageView宽固定,高适配
3. 裁切框宽高比 < 图片宽高比 imageView高固定,宽适配
*/
/** 裁切框宽高比 < 1
4. 裁切框宽高比 >= 图片宽高比 imageView宽固定,高适配
5. 裁切框宽高比 < 图片宽高比 imageView高固定,宽适配
*/
if cropRadio > 1 {
if cropRadio >= imageRadio {
relationType = 0
} else {
relationType = 1
}
} else if cropRadio == 1 {
if cropRadio >= imageRadio {
relationType = 2
} else {
relationType = 3
}
} else {
if cropRadio >= imageRadio {
relationType = 4
} else {
relationType = 5
}
}
return relationType
}
// 将图片裁剪为圆形
func clipCircularImage() -> UIImage {
let imageWidth = self.size.width
let imageHeight = self.size.height
let arcCenterX = imageWidth / 2
let arcCenterY = imageHeight / 2
let radius = arcCenterX > arcCenterY ? arcCenterY : arcCenterX
UIGraphicsBeginImageContext(self.size)
let context = UIGraphicsGetCurrentContext()
context!.beginPath()
context?.addArc(center: CGPoint.init(x: arcCenterX, y: arcCenterY), radius: radius, startAngle: 0, endAngle: CGFloat.pi * 2, clockwise: false)
context?.clip()
self.draw(in: CGRect.init(x: 0, y: 0, width: imageWidth, height: imageHeight))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext();
return newImage!
}
}
//
// MCClipImageViewController.swift
// MCAPI
//
// Created by MC on 2018/9/14.
// Copyright © 2018年 MC. All rights reserved.
//
import UIKit
import QuartzCore
import Accelerate
/**
待拓展的功能
* 1. (完成)旋转图片。
* 2. 标出来裁剪框的尺寸和比例
* 3. 手动调整裁剪框的比例
* 4. 是否添加水印
* 5. 开放裁切框的颜色和UI。
* 6. (完成)圆形裁切框
* 7.
*/
protocol MCClipImageViewControllerDelegate : NSObjectProtocol {
func MCClipImageDidCancel()
func MCClipImageClipping(image:UIImage)
}
class MCClipImageViewController: UIViewController {
weak var delegate : MCClipImageViewControllerDelegate?
public var isRound = false
// 裁剪的目标图片
private var targetImage : UIImage = UIImage()
// 裁剪的区域
private var cropSize : CGSize = CGSize.init(width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.width/2)
// 裁切框的frame
private var cropFrame = CGRect.init()
// 待裁切的图片和裁切框的宽高关系, 用于做裁切处理。
private var relationType = 0
/// 设置初始化UI的数据,记录待裁切的图片,要裁切的尺寸
func settingUIDataWithImage(_ image: UIImage,size:CGSize = CGSize.init(width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.width/2)) {
targetImage = image
cropSize = size
//如果是圆形的话,对给的cropSize进行容错处理
if (self.isRound) {
if (cropSize.width >= cropSize.height) {
cropSize = CGSize.init(width: cropSize.height, height: cropSize.height)
}else{
cropSize = CGSize.init(width: cropSize.width, height: cropSize.width)
}
}
// 判断裁切框和图片的关系,用于做
relationType = targetImage.judgeRelationTypeWithCropSize(cropSize)
// 填充图片数据
fillData()
// 根据图片尺寸和裁切框的尺寸设置scrollView的最小缩放比例
setMinZoomScale()
if isRound {
// 设置裁切的圆形区域
transparentCutCircularArea()
} else {
// 矩形裁切框
transparentCutSquareArea()
}
scrollViewDidZoom(scrollView)
}
override func viewDidLoad() {
super.viewDidLoad()
baseSetting()
initUI()
}
// 隐藏状态栏
override var prefersStatusBarHidden: Bool {
return true
}
// MARK: - Setter & Getter
private lazy var scrollView: UIScrollView = {
let view = UIScrollView()
view.delegate = self
view.scrollsToTop = false
view.maximumZoomScale = 10
view.frame = CGRect.init(x: 0, y: 0, width: selfWidth, height: selfHeight)
view.isUserInteractionEnabled = true
view.showsVerticalScrollIndicator = false
view.showsHorizontalScrollIndicator = false
return view
}()
private lazy var imageView: UIImageView = {
let view = UIImageView()
view.isUserInteractionEnabled = true
view.contentMode = UIView.ContentMode.scaleAspectFill
return view
}()
lazy var overLayView: UIView = {
let view = UIView()
view.isUserInteractionEnabled = false
view.backgroundColor = .commonColor90
return view
}()
lazy var cancelButton: UIButton = {
let button = UIButton(type: .custom)
button.setTitle("取消", for: .normal)
button.setTitleColor(UIColor.white, for: .normal)
button.titleLabel?.font = UIFont.PFSCM(ofSize: 14)
button.addTarget(self, action: #selector(cancelButtonClicked), for: .touchUpInside)
return button
}()
lazy var rotatingButton: UIButton = {
let button = UIButton(type: .custom)
let path = Bundle.main.path(forResource: "ClipImage_rotating", ofType: "png", inDirectory: nil)
let image = UIImage.init(contentsOfFile: path!)
button.setImage(image, for: .normal)
button.addTarget(self, action: #selector(rotatingButtonClicked), for: .touchUpInside)
button.isHidden = true
return button
}()
lazy var sureButton: UIButton = {
let button = UIButton(type: .custom)
button.setTitle("确定", for: .normal)
button.setTitleColor(UIColor.mainColor, for: .normal)
button.titleLabel?.font = UIFont.PFSCM(ofSize: 14)
button.addTarget(self, action: #selector(sureButtonClicked), for: .touchUpInside)
return button
}()
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
cancelButton.snp.makeConstraints { make in
make.left.equalTo(16)
make.bottom.equalTo(UIDevice.bs_safeDistanceBottom()).offset(-50)
make.width.equalTo(80)
make.height.equalTo(40)
}
sureButton.snp.makeConstraints { make in
make.right.equalTo(-16)
make.bottom.equalTo(UIDevice.bs_safeDistanceBottom()).offset(-50)
make.width.equalTo(80)
make.height.equalTo(40)
}
}
}
// MARK: - 通知回调,闭包回调,点击事件
extension MCClipImageViewController {
// 取消
@objc func cancelButtonClicked() {
if delegate != nil {
delegate?.MCClipImageDidCancel()
}
self.dismiss(animated: true, completion: nil)
}
// 确定
@objc func sureButtonClicked() {
var image = getClippingImage()
if isRound {
image = image.clipCircularImage()
}
if delegate != nil {
delegate?.MCClipImageClipping(image: image)
}
self.dismiss(animated: true, completion: nil)
}
// 图片旋转
@objc func rotatingButtonClicked() {
// 清空之前设置的scale。否则会错乱
scrollView.minimumZoomScale = 1.0
scrollView.setZoomScale(1.0, animated: true)
targetImage = targetImage.rotationImage(orientation: .left)
imageView.image = targetImage
settingUIDataWithImage(targetImage, size: cropSize)
}
}
// MARK: - UI的处理,通知的接收
extension MCClipImageViewController {
func baseSetting() {
view.backgroundColor = UIColor.black
automaticallyAdjustsScrollViewInsets = false
}
func initUI() {
view.addSubview(scrollView)
scrollView.addSubview(imageView)
view.addSubview(overLayView)
view.addSubview(cancelButton)
view.addSubview(sureButton)
view.addSubview(rotatingButton)
let y = selfHeight - 25 - MCSafeAreaBottomHeight - 20
cancelButton.frame = CGRect.init(x: 20, y: y, width: 25, height: 25)
sureButton.frame = CGRect.init(x: selfWidth - 20 - 30, y: y, width: 25, height: 25)
rotatingButton.frame = CGRect.init(x: selfWidth/2 - 15, y: y, width: 25, height: 25)
overLayView.frame = view.frame
scrollView.frame = CGRect.init(x: 0, y: 0, width: selfWidth, height: selfHeight)
}
func fillData() {
// 1.添加图片
imageView.image = targetImage
// 2.设置裁剪区域
let x = (selfWidth - cropSize.width) / 2
let y = (selfHeight - cropSize.height) / 2
cropFrame = CGRect.init(x: x, y: y, width: cropSize.width, height: cropSize.height)
// 3.计算imgeView的frame
let imageW = targetImage.size.width
let imageH = targetImage.size.height
let cropW = cropSize.width
let cropH = cropSize.height
var imageViewW,imageViewH,imageViewX,imageViewY : CGFloat
switch relationType {
case 0,1: // 裁切框宽高比 > 0
imageViewW = cropW
imageViewH = imageH * imageViewW / imageW
imageViewX = (selfWidth - imageViewW) / 2
imageViewY = (selfHeight - imageViewH)/2
case 2,3: // 裁切框宽高比 = 0
imageViewW = cropW
imageViewH = imageH * imageViewW / imageW
imageViewX = (selfWidth - imageViewW) / 2
imageViewY = (selfHeight - imageViewH)/2
default:
imageViewH = cropH
imageViewW = imageW * imageViewH / imageH
imageViewX = (selfWidth - imageViewW) / 2
imageViewY = (selfHeight - imageViewH)/2
}
imageView.frame = CGRect.init(x: imageViewX, y: imageViewY, width: imageViewW, height: imageViewH)
}
//设置矩形裁剪区域
func transparentCutSquareArea() {
let alphaRect = CGRect.init(x: 0, y: 0, width: selfWidth, height: selfHeight)
let alphaPath = UIBezierPath.init(rect: alphaRect)
let squarePath = UIBezierPath.init(rect: cropFrame)
alphaPath.append(squarePath)
let shapeLayer = CAShapeLayer.init()
shapeLayer.path = alphaPath.cgPath
shapeLayer.fillRule = CAShapeLayerFillRule.evenOdd
overLayView.layer.mask = shapeLayer
//裁剪框
let cropRect_x = cropFrame.origin.x
let cropRect_y = cropFrame.origin.y
let cropRect_w = cropFrame.size.width
let cropRect_h = cropFrame.size.height
let cropRect = CGRect.init(x: cropRect_x, y: cropRect_y, width: cropRect_w, height: cropRect_h)
let cropPath = UIBezierPath.init(rect: cropRect)
let cropLayer = CAShapeLayer.init()
cropLayer.path = cropPath.cgPath
cropLayer.fillColor = UIColor.white.cgColor
cropLayer.strokeColor = UIColor.white.cgColor
overLayView.layer.addSublayer(cropLayer)
}
//设置圆形裁剪区域
func transparentCutCircularArea() {
let arcX = cropFrame.origin.x + cropFrame.size.width/2
let arcY = cropFrame.origin.y + cropFrame.size.height/2
var arcRadius : CGFloat = 0
if (cropSize.height > cropSize.width) {
arcRadius = cropSize.width/2
}else{
arcRadius = cropSize.height/2
}
//圆形透明区域
let alphaPath = UIBezierPath.init(rect: CGRect.init(x: 0, y: 0, width: selfWidth, height: selfHeight))
let arcPath = UIBezierPath.init(arcCenter: CGPoint.init(x: arcX, y: arcY), radius: arcRadius, startAngle: 0, endAngle: CGFloat(2*Double.pi), clockwise: false)
alphaPath.append(arcPath)
let layer = CAShapeLayer.init()
layer.path = alphaPath.cgPath
layer.fillRule = CAShapeLayerFillRule.evenOdd
overLayView.layer.mask = layer
//裁剪框
let cropPath = UIBezierPath.init(arcCenter: CGPoint.init(x: arcX, y: arcY), radius: arcRadius+1, startAngle: 0, endAngle: CGFloat(2*Double.pi), clockwise: false)
let cropLayer = CAShapeLayer.init()
cropLayer.path = cropPath.cgPath
cropLayer.strokeColor = UIColor.commonColor90.cgColor
cropLayer.fillColor = UIColor.commonColor90.cgColor
overLayView.layer.addSublayer(cropLayer)
}
// 设置最小缩放比例
func setMinZoomScale() {
// 设置最小的缩放比例。 自动填满裁剪区域
var scale : CGFloat = 0
let imageViewW = imageView.frame.size.width
let imageViewH = imageView.frame.size.height
let cropW = cropSize.width
let cropH = cropSize.height
switch relationType {
case 0: // 裁切框宽高比 > 1,并且裁切框宽高比 >= 图片宽高比
scale = imageViewW / cropW
case 1: // 裁切框宽高比 > 1,并且裁切框宽高比 < 图片宽高比
scale = cropH / imageViewH
case 2: // 裁切框宽高比 = 1, 并且裁切框宽高比 >= 图片宽高比
scale = cropW / imageViewW
case 3: // 裁切框宽高比 = 1, 并且裁切框宽高比 < 图片宽高比
scale = cropH / imageViewH
case 4: // 裁切框宽高比 < 1,并且裁切框宽高比 >= 图片宽高比
scale = cropW / imageViewW
default: // 裁切框宽高比 < 1,并且裁切框宽高比 < 图片框宽高比
scale = cropW / imageViewW
}
//自动缩放填满裁剪区域
self.scrollView.setZoomScale(scale, animated: false)
//设置刚好填充满裁剪区域的缩放比例,为最小缩放比例
self.scrollView.minimumZoomScale = scale
}
// 获取被裁剪的图片
func getClippingImage() -> UIImage {
/** 步骤
* 1. 获取图片和imageView的缩放比例。
* 2. 获取ImageView的缩放比例,即scrollView.zoomScale
* 3. 获取ImageView的原始坐标
* 4. 计算缩放后的坐标
* 5. 计算裁剪区域在原始图片上的位置
* 6. 裁剪图片,没有了release方法,CGImage会存在内存泄露么
*/
//图片大小和当前imageView的缩放比例
let scaleRatio = targetImage.size.width / imageView.frame.size.width
//scrollView的缩放比例,即是ImageView的缩放比例
let scrollScale = self.scrollView.zoomScale
//裁剪框的 左上、右上和左下三个点在初始ImageView上的坐标位置(注意:转换后的坐标为原始ImageView的坐标计算的,而非缩放后的)
var leftTopPoint = view.convert(cropFrame.origin, to: imageView)
var rightTopPoint = view.convert(CGPoint.init(x: cropFrame.origin.x + cropSize.width, y: cropFrame.origin.y), to: imageView)
var leftBottomPoint = view.convert(CGPoint.init(x: cropFrame.origin.x, y: cropFrame.origin.y + cropSize.height), to: imageView)
//计算三个点在缩放后imageView上的坐标
leftTopPoint = CGPoint.init(x: leftTopPoint.x * scrollScale, y: leftTopPoint.y*scrollScale)
rightTopPoint = CGPoint.init(x: rightTopPoint.x * scrollScale, y: rightTopPoint.y*scrollScale)
leftBottomPoint = CGPoint.init(x: leftBottomPoint.x * scrollScale, y: leftBottomPoint.y*scrollScale)
//计算裁剪区域在原始图片上的位置
let width = (rightTopPoint.x - leftTopPoint.x ) * scaleRatio
let height = (leftBottomPoint.y - leftTopPoint.y) * scaleRatio
let myImageRect = CGRect.init(x: leftTopPoint.x * scaleRatio, y: leftTopPoint.y*scaleRatio, width: width, height: height)
//裁剪图片
let imageRef : CGImage = targetImage.cgImage!
let subImageRef = imageRef.cropping(to: myImageRect)
UIGraphicsBeginImageContextWithOptions(myImageRect.size, true, 0)
let context = UIGraphicsGetCurrentContext()
context?.draw(subImageRef!, in: CGRect.init(x: 0, y: 0, width: myImageRect.size.width, height: myImageRect.size.height))
let subImage = UIImage.init(cgImage: subImageRef!)
UIGraphicsEndImageContext()
return subImage
}
}
// MARK: - UIScrollViewDelegate
extension MCClipImageViewController: UIScrollViewDelegate {
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return imageView
}
func scrollViewDidZoom(_ scrollView: UIScrollView) {
//图片比例改变以后,让改变后的ImageView保持在ScrollView的中央
let size_W = scrollView.bounds.size.width
let size_H = scrollView.bounds.size.height
let contentSize_W = scrollView.contentSize.width
let contentSize_H = scrollView.contentSize.height
let offsetX = (size_W > contentSize_W) ? (size_W - contentSize_W) * 0.5 : 0.0
let offsetY = (size_H > contentSize_H) ? (size_H - contentSize_H) * 0.5 : 0.0
imageView.center = CGPoint.init(x: contentSize_W * 0.5 + offsetX, y: contentSize_H * 0.5 + offsetY)
//设置scrollView的contentSize,最小为self.view.frame.size
let scrollW = contentSize_W >= selfWidth ? contentSize_W : selfWidth
let scrollH = contentSize_H >= selfHeight ? contentSize_H : selfHeight
scrollView.contentSize = CGSize.init(width: scrollW, height: scrollH)
//设置scrollView的contentInset
let imageWidth = imageView.frame.size.width;
let imageHeight = imageView.frame.size.height;
let cropWidth = cropSize.width;
let cropHeight = cropSize.height;
var leftRightInset : CGFloat = 0;
var topBottomInset : CGFloat = 0;
//imageview的大小和裁剪框大小的三种情况,保证imageview最多能滑动到裁剪框的边缘
if (imageWidth <= cropWidth) {
leftRightInset = 0;
} else if (imageWidth >= cropWidth && imageWidth <= selfWidth) {
leftRightInset = (imageWidth - cropWidth) * 0.5
}else{
leftRightInset = (selfWidth - cropSize.width) * 0.5
}
if (imageHeight <= cropHeight) {
topBottomInset = 0
} else if (imageHeight >= cropHeight && imageHeight <= selfHeight) {
topBottomInset = (imageHeight - cropHeight) * 0.5
} else {
topBottomInset = (selfHeight - cropSize.height) * 0.5
}
scrollView.contentInset = UIEdgeInsets(top: topBottomInset, left: leftRightInset, bottom: topBottomInset, right: leftRightInset)
}
}
//-状态栏高度
fileprivate let MCStatusBarHeight : CGFloat = UIApplication.shared.statusBarFrame.size.height
//-导航栏高度
fileprivate func MCNavigationBarHeight(_ target:UIViewController) -> CGFloat {
if target.navigationController != nil {
return target.navigationController?.navigationBar.frame.size.height ?? 44
} else {
return 44
}
}
//-底部安全区域
fileprivate let MCSafeAreaBottomHeight : CGFloat = (UIScreen.main.bounds.size.height == 812 ? 34 : 0)
// 屏幕的宽高
fileprivate var selfWidth = UIScreen.main.bounds.size.width
fileprivate var selfHeight = UIScreen.main.bounds.size.height
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment