Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
galaxy-iOS
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
mobile-group
galaxy-iOS
Commits
0b841956
Commit
0b841956
authored
Dec 20, 2023
by
David黄金龙
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
文件移动
parent
277f5d93
Changes
49
Hide whitespace changes
Inline
Side-by-side
Showing
49 changed files
with
6075 additions
and
0 deletions
+6075
-0
YHBaseViewController.swift
galaxy/galaxy/Classes/Base/C/YHBaseViewController.swift
+71
-0
YHNavigationController.swift
galaxy/galaxy/Classes/Base/C/YHNavigationController.swift
+61
-0
YHTabBarViewController.swift
galaxy/galaxy/Classes/Base/C/YHTabBarViewController.swift
+34
-0
YHWebViewController.swift
galaxy/galaxy/Classes/Base/C/YHWebViewController.swift
+511
-0
BsBaseModel.swift
galaxy/galaxy/Classes/Base/M/BsBaseModel.swift
+22
-0
YHBasicContentView.swift
galaxy/galaxy/Classes/Base/V/YHBasicContentView.swift
+29
-0
YHBouncesContentView.swift
galaxy/galaxy/Classes/Base/V/YHBouncesContentView.swift
+40
-0
YHNoDataTipView.swift
galaxy/galaxy/Classes/Base/V/YHNoDataTipView.swift
+133
-0
AlignedCollectionViewFlowLayout.swift
...ses/Tools/Extention/AlignedCollectionViewFlowLayout.swift
+490
-0
AppDelegate + UIAppearance.swift
.../Classes/Tools/Extention/AppDelegate + UIAppearance.swift
+67
-0
BsCacheTool.swift
galaxy/galaxy/Classes/Tools/Extention/BsCacheTool.swift
+79
-0
BsGestureTableView.swift
...y/galaxy/Classes/Tools/Extention/BsGestureTableView.swift
+65
-0
BsOverlayView.swift
galaxy/galaxy/Classes/Tools/Extention/BsOverlayView.swift
+83
-0
Date-Extension.swift
galaxy/galaxy/Classes/Tools/Extention/Date-Extension.swift
+23
-0
NSAttributedString+Extension.swift
...lasses/Tools/Extention/NSAttributedString+Extension.swift
+102
-0
String-Extension.swift
galaxy/galaxy/Classes/Tools/Extention/String-Extension.swift
+176
-0
UIApplication-Extension.swift
...axy/Classes/Tools/Extention/UIApplication-Extension.swift
+29
-0
UIButton-Extension.swift
...y/galaxy/Classes/Tools/Extention/UIButton-Extension.swift
+102
-0
UIColor-Extension.swift
...xy/galaxy/Classes/Tools/Extention/UIColor-Extension.swift
+52
-0
UIDevice-Extension.swift
...y/galaxy/Classes/Tools/Extention/UIDevice-Extension.swift
+116
-0
UIFont-Extension.swift
galaxy/galaxy/Classes/Tools/Extention/UIFont-Extension.swift
+26
-0
UIImage-Extension.swift
...xy/galaxy/Classes/Tools/Extention/UIImage-Extension.swift
+145
-0
UILable-Extension.swift
...xy/galaxy/Classes/Tools/Extention/UILable-Extension.swift
+53
-0
UIView-Extension.swift
galaxy/galaxy/Classes/Tools/Extention/UIView-Extension.swift
+284
-0
UIViewController+Navigation.swift
...Classes/Tools/Extention/UIViewController+Navigation.swift
+263
-0
BSJsonUtil.swift
galaxy/galaxy/Classes/Tools/Helper/BSJsonUtil.swift
+114
-0
BsConstant.swift
galaxy/galaxy/Classes/Tools/Helper/BsConstant.swift
+259
-0
BsHUD.swift
galaxy/galaxy/Classes/Tools/Helper/BsHUD/BsHUD.swift
+159
-0
BsHUDContainerView.swift
...alaxy/Classes/Tools/Helper/BsHUD/BsHUDContainerView.swift
+45
-0
BsHUDErrorView.swift
...xy/galaxy/Classes/Tools/Helper/BsHUD/BsHUDErrorView.swift
+22
-0
BsHUDProgressView.swift
...galaxy/Classes/Tools/Helper/BsHUD/BsHUDProgressView.swift
+30
-0
BsHUDRotatingImageView.swift
...y/Classes/Tools/Helper/BsHUD/BsHUDRotatingImageView.swift
+21
-0
BsHUDSquareBaseView.swift
...laxy/Classes/Tools/Helper/BsHUD/BsHUDSquareBaseView.swift
+76
-0
BsHUDSuccessView.swift
.../galaxy/Classes/Tools/Helper/BsHUD/BsHUDSuccessView.swift
+20
-0
BsHUDWariningView.swift
...galaxy/Classes/Tools/Helper/BsHUD/BsHUDWariningView.swift
+21
-0
BsKVOHelper.swift
galaxy/galaxy/Classes/Tools/Helper/BsKVOHelper.swift
+70
-0
BsMapManager.swift
galaxy/galaxy/Classes/Tools/Helper/BsMapManager.swift
+151
-0
BsPageContentView.swift
...y/Classes/Tools/Helper/BsPageView/BsPageContentView.swift
+200
-0
BsPageTitleView.swift
...axy/Classes/Tools/Helper/BsPageView/BsPageTitleView.swift
+461
-0
BsPresentView.swift
galaxy/galaxy/Classes/Tools/Helper/BsPresentView.swift
+163
-0
BsWebViewPreloadManager.swift
...galaxy/Classes/Tools/Helper/BsWebViewPreloadManager.swift
+120
-0
ClipImage_cancel.png
.../Tools/Helper/ClipImage(裁切图片)/Images/ClipImage_cancel.png
+0
-0
ClipImage_rotating.png
...ools/Helper/ClipImage(裁切图片)/Images/ClipImage_rotating.png
+0
-0
ClipImage_sure.png
...es/Tools/Helper/ClipImage(裁切图片)/Images/ClipImage_sure.png
+0
-0
MCClipImageTool.swift
...lasses/Tools/Helper/ClipImage(裁切图片)/MCClipImageTool.swift
+160
-0
MCClipImageViewController.swift
...ls/Helper/ClipImage(裁切图片)/MCClipImageViewController.swift
+496
-0
YHAllApiName.swift
galaxy/galaxy/Classes/Tools/NetWork/YHAllApiName.swift
+294
-0
YHBaseUrlManager.swift
galaxy/galaxy/Classes/Tools/NetWork/YHBaseUrlManager.swift
+55
-0
YHNetworkStatusManager.swift
...galaxy/Classes/Tools/NetWork/YHNetworkStatusManager.swift
+82
-0
No files found.
galaxy/galaxy/Classes/Base/C/YHBaseViewController.swift
0 → 100755
View file @
0b841956
//
// BsBaseViewController.swift
// BaiSiSMApp
//
// Created by davidhuang on 2022/10/21.
// Copyright © 2022 www.davidhuang.com. All rights reserved.
//
import
UIKit
//import Kingfisher
class
YHBaseViewController
:
UIViewController
{
lazy
var
noDataView
:
YHNoDataTipView
=
{
let
temp
=
YHNoDataTipView
()
temp
.
frame
=
view
.
bounds
temp
.
isHidden
=
true
let
tap
=
UITapGestureRecognizer
(
target
:
self
,
action
:
#selector(
tapNodataViewEvent(tap:)
)
)
temp
.
addGestureRecognizer
(
tap
)
return
temp
}()
override
func
viewDidLoad
()
{
super
.
viewDidLoad
()
self
.
bs_setupLeftButton
()
//0
setupNavigationAttributed
()
//1、
view
.
addSubview
(
noDataView
)
view
.
backgroundColor
=
.
white
}
deinit
{
#if DEBUG
print
(
#function
)
#endif
}
}
// MARK: - 私有操作方法
extension
YHBaseViewController
{
@objc
func
tapNodataViewEvent
(
tap
:
UITapGestureRecognizer
)
->
Void
{
print
(
"do nothing~~~ 子类根据具体情况来实现
\(
#function
)
"
)
}
func
openFullScreenBackGes
(
_
openFlag
:
Bool
)
{
if
self
.
navigationController
is
YHNavigationController
{
self
.
navigationItem
.
hidesBackButton
=
!
openFlag
}
}
///设置导航条属性
func
setupNavigationAttributed
(
_
color
:
UIColor
?
=
nil
)
{
if
let
color
=
color
{
self
.
navigationController
?
.
navigationBar
.
setBackgroundImage
(
UIImage
.
from
(
color
:
color
),
for
:
.
default
)
//设置导航栏背景色
self
.
navigationController
?
.
navigationBar
.
barTintColor
=
color
}
else
{
self
.
navigationController
?
.
navigationBar
.
setBackgroundImage
(
UIImage
(),
for
:
.
default
)
//设置导航栏背景透明色
self
.
navigationController
?
.
navigationBar
.
barTintColor
=
nil
}
self
.
navigationController
?
.
navigationBar
.
shadowImage
=
UIImage
()
//隐藏下划线
}
}
galaxy/galaxy/Classes/Base/C/YHNavigationController.swift
0 → 100755
View file @
0b841956
//
// CustomNavigationController.swift
// DYZB
//
// Created by 1 on 16/10/14.
// Copyright © 2016年 小码哥. All rights reserved.
//
import
UIKit
public
protocol
BsNavigationControllerDelegate
:
NSObject
{
func
canBack
()
->
Bool
}
class
YHNavigationController
:
UINavigationController
{
weak
var
myDelegate
:
BsNavigationControllerDelegate
?
override
func
viewDidLoad
()
{
super
.
viewDidLoad
()
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
)
{
// 隐藏要push的控制器的tabbar
if
animated
==
true
{
viewController
.
hidesBottomBarWhenPushed
=
true
}
super
.
pushViewController
(
viewController
,
animated
:
animated
)
}
}
// MARK: - UIGestureRecognizerDelegate, UINavigationBarDelegate
extension
YHNavigationController
:
UIGestureRecognizerDelegate
,
UINavigationBarDelegate
{
//这个方法是在手势将要激活前调用:返回YES允许右滑手势的激活,返回NO不允许右滑手势的激活
func
gestureRecognizerShouldBegin
(
_
gestureRecognizer
:
UIGestureRecognizer
)
->
Bool
{
print
(
#function
)
if
let
returnValue
=
myDelegate
?
.
canBack
(){
return
returnValue
}
else
{
#if DEBUG
print
(
#function
)
print
(
"myDelegate == nil 或者其他"
)
#endif
}
return
true
}
public
func
navigationBar
(
_
navigationBar
:
UINavigationBar
,
shouldPop
item
:
UINavigationItem
)
->
Bool
{
if
let
returnValue
=
myDelegate
?
.
canBack
(){
return
returnValue
}
return
true
}
}
galaxy/galaxy/Classes/Base/C/YHTabBarViewController.swift
0 → 100755
View file @
0b841956
//
// BsTabBarViewController.swift
// BaiSiSMApp
//
// Created by davidhuang on 2022/12/4.
// Copyright © 2022 www.davidhuang.com. All rights reserved.
//
import
UIKit
import
ESTabBarController_swift
class
YHTabBarViewController
:
ESTabBarController
{
override
func
viewDidLoad
()
{
super
.
viewDidLoad
()
self
.
tabBar
.
shadowImage
=
UIImage
()
self
.
tabBar
.
backgroundImage
=
UIImage
()
// NotificationCenter.default.addObserver(self, selector: #selector(hideTabBar), name: BsConstant.BsNotification.tabBarHideNotification, object: nil)
//
// NotificationCenter.default.addObserver(self, selector: #selector(showTabBar), name: BsConstant.BsNotification.tabBarShowNotification, object: nil)
}
}
extension
YHTabBarViewController
{
@objc
func
hideTabBar
()
->
Void
{
self
.
tabBar
.
isHidden
=
true
}
@objc
func
showTabBar
()
->
Void
{
self
.
tabBar
.
isHidden
=
false
}
}
galaxy/galaxy/Classes/Base/C/YHWebViewController.swift
0 → 100755
View file @
0b841956
//
// 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
()
}
}
galaxy/galaxy/Classes/Base/M/BsBaseModel.swift
0 → 100755
View file @
0b841956
//
// BaseModel.swift
// DouYuUI
//
// Created by davidhuang on 2022/8/15.
// Copyright © 2022 davidhuang. All rights reserved.
//
import
UIKit
import
HandyJSON
// MARK: - JSon解析模型的基类
class
BsBaseModel
:
HandyJSON
{
var
data
:
Any
?
var
errorCode
:
Int
=
-
1
var
errorMessage
:
String
=
""
var
success
:
Bool
=
false
// MARK: - 使用 HandyJSON 进行解析
required
init
()
{}
}
galaxy/galaxy/Classes/Base/V/YHBasicContentView.swift
0 → 100755
View file @
0b841956
//
// ExampleBasicContentView.swift
// ESTabBarControllerExample
//
// Created by lihao on 2017/2/9.
// Copyright © 2018年 Egg Swift. All rights reserved.
//
import
UIKit
import
ESTabBarController_swift
class
YHBasicContentView
:
ESTabBarItemContentView
{
override
init
(
frame
:
CGRect
)
{
super
.
init
(
frame
:
frame
)
textColor
=
UIColor
.
init
(
white
:
175.0
/
255.0
,
alpha
:
1.0
)
highlightTextColor
=
.
commonColor100
iconColor
=
UIColor
.
init
(
white
:
175.0
/
255.0
,
alpha
:
1.0
)
highlightIconColor
=
.
commonColor100
titleLabel
.
font
=
UIFont
.
PFSCR
(
ofSize
:
10
)
}
public
required
init
?(
coder
aDecoder
:
NSCoder
)
{
fatalError
(
"init(coder:) has not been implemented"
)
}
}
galaxy/galaxy/Classes/Base/V/YHBouncesContentView.swift
0 → 100755
View file @
0b841956
//
// ExampleBouncesContentView.swift
// ESTabBarControllerExample
//
// Created by lihao on 2017/2/9.
// Copyright © 2018年 Egg Swift. All rights reserved.
//
import
UIKit
class
YHBouncesContentView
:
YHBasicContentView
{
public
var
duration
=
0.3
override
init
(
frame
:
CGRect
)
{
super
.
init
(
frame
:
frame
)
}
public
required
init
?(
coder
aDecoder
:
NSCoder
)
{
fatalError
(
"init(coder:) has not been implemented"
)
}
override
func
selectAnimation
(
animated
:
Bool
,
completion
:
(()
->
())?)
{
self
.
bounceAnimation
()
completion
?()
}
override
func
reselectAnimation
(
animated
:
Bool
,
completion
:
(()
->
())?)
{
self
.
bounceAnimation
()
completion
?()
}
func
bounceAnimation
()
{
let
impliesAnimation
=
CAKeyframeAnimation
(
keyPath
:
"transform.scale"
)
impliesAnimation
.
values
=
[
1.0
,
1.4
,
0.9
,
1.15
,
0.95
,
1.02
,
1.0
]
impliesAnimation
.
duration
=
duration
*
2
impliesAnimation
.
calculationMode
=
CAAnimationCalculationMode
.
cubic
imageView
.
layer
.
add
(
impliesAnimation
,
forKey
:
nil
)
}
}
galaxy/galaxy/Classes/Base/V/YHNoDataTipView.swift
0 → 100755
View file @
0b841956
//
// YHNoDataTipView.swift
// BaiSiSMApp
//
// Created by davidhuang on 2022/10/25.
// Copyright © 2022 www.davidhuang.com. All rights reserved.
//
import
UIKit
class
YHNoDataTipView
:
UIView
{
public
var
reloadBlock
:
(()
->
())?
private
var
imageStr
:
String
=
"no-order-bkg-icon"
private
var
title
:
String
=
"暂无数据"
private
lazy
var
imageView
:
UIImageView
=
{
let
imageView
=
UIImageView
(
image
:
UIImage
(
named
:
"no-order-bkg-icon"
))
return
imageView
}()
private
lazy
var
titleLabel
:
UILabel
=
{
let
label
=
UILabel
(
text
:
"暂无数据"
,
font
:
UIFont
.
PFSCR
(
ofSize
:
14
),
color
:
UIColor
.
commonColor45
)
return
label
}()
private
lazy
var
descLabel
:
UILabel
=
{
let
label
=
UILabel
(
text
:
""
,
font
:
UIFont
.
PFSCR
(
ofSize
:
12
),
color
:
UIColor
.
commonColor45
)
return
label
}()
private
lazy
var
reloadBtn
:
UIButton
=
{
let
btn
=
UIButton
.
bs_button
(
title
:
"重新加载"
,
font
:
UIFont
.
PFSCM
(
ofSize
:
12
),
normalColor
:
UIColor
.
commonColor100
)
btn
.
layer
.
cornerRadius
=
6
btn
.
layer
.
masksToBounds
=
true
btn
.
layer
.
borderWidth
=
1
btn
.
layer
.
borderColor
=
UIColor
.
commonColor10
.
cgColor
btn
.
addTarget
(
self
,
action
:
#selector(
onReloadData
)
,
for
:
.
touchUpInside
)
return
btn
}()
override
init
(
frame
:
CGRect
)
{
super
.
init
(
frame
:
frame
)
initView
()
}
required
init
?(
coder
aDecoder
:
NSCoder
)
{
fatalError
(
"init(coder:) has not been implemented"
)
}
public
func
setup
(
image
:
String
?
=
nil
,
title
:
String
)
{
if
let
image
=
image
{
imageView
.
image
=
UIImage
(
named
:
image
)
self
.
imageStr
=
image
}
titleLabel
.
text
=
title
self
.
title
=
title
}
override
var
isHidden
:
Bool
{
didSet
{
if
isHidden
==
false
{
if
YHNetworkStatusManager
.
shared
.
isNetWorkOK
==
true
{
imageView
.
image
=
UIImage
(
named
:
self
.
imageStr
)
titleLabel
.
text
=
title
descLabel
.
isHidden
=
true
reloadBtn
.
isHidden
=
true
}
else
{
imageView
.
image
=
UIImage
(
named
:
"no_data_network_icon"
)
titleLabel
.
text
=
"网络好像断开了哦"
descLabel
.
isHidden
=
false
reloadBtn
.
isHidden
=
false
}
}
}
}
}
// MARK: - 提供快速创建的类方法
extension
YHNoDataTipView
{
private
func
initView
()
{
self
.
addSubview
(
imageView
)
self
.
addSubview
(
titleLabel
)
self
.
addSubview
(
descLabel
)
self
.
addSubview
(
reloadBtn
)
let
imageViewTop
=
132
/
(
UIDevice
.
kScreenW
-
UIDevice
.
bs_navigationFullHeight
())
imageView
.
snp
.
makeConstraints
{
make
in
make
.
top
.
equalToSuperview
()
.
offset
(
imageViewTop
)
make
.
centerX
.
equalToSuperview
()
make
.
width
.
height
.
equalTo
(
165
)
}
titleLabel
.
snp
.
makeConstraints
{
make
in
make
.
top
.
equalTo
(
imageView
.
snp
.
bottom
)
make
.
centerX
.
equalToSuperview
()
}
descLabel
.
snp
.
makeConstraints
{
make
in
make
.
top
.
equalTo
(
titleLabel
.
snp
.
bottom
)
.
offset
(
4
)
make
.
centerX
.
equalToSuperview
()
}
reloadBtn
.
snp
.
makeConstraints
{
make
in
make
.
top
.
equalTo
(
descLabel
.
snp
.
bottom
)
.
offset
(
16
)
make
.
centerX
.
equalToSuperview
()
make
.
width
.
equalTo
(
80
)
make
.
height
.
equalTo
(
28
)
}
descLabel
.
isHidden
=
true
reloadBtn
.
isHidden
=
true
}
// class func noDataTipView() -> YHNoDataTipView {
// return YHNoDataTipView()
// //return Bundle.main.loadNibNamed("YHNoDataTipView", owner: nil, options: nil)?.first as! YHNoDataTipView
// }
override
func
layoutSubviews
()
{
super
.
layoutSubviews
()
let
imageViewTop
=
(
132
+
UIDevice
.
bs_navigationFullHeight
())
/
UIDevice
.
kScreenH
*
self
.
frame
.
size
.
height
imageView
.
snp
.
updateConstraints
{
make
in
make
.
top
.
equalToSuperview
()
.
offset
(
imageViewTop
)
}
}
@objc
private
func
onReloadData
()
{
reloadBlock
?()
}
}
galaxy/galaxy/Classes/Tools/Extention/AlignedCollectionViewFlowLayout.swift
0 → 100755
View file @
0b841956
//
// AlignedCollectionViewFlowLayout.swift
//
// Created by Mischa Hildebrand on 12/04/2017.
// Copyright © 2017 Mischa Hildebrand.
//
// Licensed under the terms of the MIT license:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
import
UIKit
// MARK: - 🦆 Type definitions
/// An abstract protocol that defines an alignment.
protocol
Alignment
{}
/// Defines a horizontal alignment for UI elements.
public
enum
HorizontalAlignment
:
Alignment
{
case
left
case
right
case
leading
case
trailing
case
justified
}
/// Defines a vertical alignment for UI elements.
public
enum
VerticalAlignment
:
Alignment
{
case
top
case
center
case
bottom
}
/// A horizontal alignment used internally by `AlignedCollectionViewFlowLayout`
/// to layout the items, after resolving layout direction specifics.
private
enum
EffectiveHorizontalAlignment
:
Alignment
{
case
left
case
right
case
justified
}
/// Describes an axis with respect to which items can be aligned.
private
struct
AlignmentAxis
<
A
:
Alignment
>
{
/// Determines how items are aligned relative to the axis.
let
alignment
:
A
/// Defines the position of the axis.
/// * If the `Alignment` is horizontal, the alignment axis is vertical and this is the position on the `x` axis.
/// * If the `Alignment` is vertical, the alignment axis is horizontal and this is the position on the `y` axis.
let
position
:
CGFloat
}
// MARK: - Flow Layout
/// A `UICollectionViewFlowLayout` subclass that gives you control
/// over the horizontal and vertical alignment of the cells.
/// You can use it to align the cells like words in a left- or right-aligned text
/// and you can specify how the cells are vertically aligned in their row.
open
class
AlignedCollectionViewFlowLayout
:
UICollectionViewFlowLayout
{
// MARK: - 🔶 Properties
/// Determines how the cells are horizontally aligned in a row.
/// - Note: The default is `.justified`.
public
var
horizontalAlignment
:
HorizontalAlignment
=
.
justified
/// Determines how the cells are vertically aligned in a row.
/// - Note: The default is `.center`.
public
var
verticalAlignment
:
VerticalAlignment
=
.
center
/// The `horizontalAlignment` with its layout direction specifics resolved,
/// i.e. `.leading` and `.trailing` alignments are mapped to `.left` or `right`,
/// depending on the current layout direction.
fileprivate
var
effectiveHorizontalAlignment
:
EffectiveHorizontalAlignment
{
var
trivialMapping
:
[
HorizontalAlignment
:
EffectiveHorizontalAlignment
]
{
return
[
.
left
:
.
left
,
.
right
:
.
right
,
.
justified
:
.
justified
]
}
let
layoutDirection
=
UIApplication
.
shared
.
userInterfaceLayoutDirection
switch
layoutDirection
{
case
.
leftToRight
:
switch
horizontalAlignment
{
case
.
leading
:
return
.
left
case
.
trailing
:
return
.
right
default
:
break
}
case
.
rightToLeft
:
switch
horizontalAlignment
{
case
.
leading
:
return
.
right
case
.
trailing
:
return
.
left
default
:
break
}
}
// It's safe to force-unwrap as `.leading` and `.trailing` are covered
// above and the `trivialMapping` dictionary contains all other keys.
return
trivialMapping
[
horizontalAlignment
]
??
.
left
}
/// The vertical axis with respect to which the cells are horizontally aligned.
/// For a `justified` alignment the alignment axis is not defined and this value is `nil`.
fileprivate
var
alignmentAxis
:
AlignmentAxis
<
HorizontalAlignment
>
?
{
switch
effectiveHorizontalAlignment
{
case
.
left
:
return
AlignmentAxis
(
alignment
:
HorizontalAlignment
.
left
,
position
:
sectionInset
.
left
)
case
.
right
:
guard
let
collectionViewWidth
=
collectionView
?
.
frame
.
size
.
width
else
{
return
nil
}
return
AlignmentAxis
(
alignment
:
HorizontalAlignment
.
right
,
position
:
collectionViewWidth
-
sectionInset
.
right
)
default
:
return
nil
}
}
/// The width of the area inside the collection view that can be filled with cells.
private
var
contentWidth
:
CGFloat
?
{
guard
let
collectionViewWidth
=
collectionView
?
.
frame
.
size
.
width
else
{
return
nil
}
return
collectionViewWidth
-
sectionInset
.
left
-
sectionInset
.
right
}
// MARK: - 👶 Initialization
/// The designated initializer.
///
/// - Parameters:
/// - horizontalAlignment: Specifies how the cells are horizontally aligned in a row. --
/// (Default: `.justified`)
/// - verticalAlignment: Specified how the cells are vertically aligned in a row. --
/// (Default: `.center`)
public
init
(
horizontalAlignment
:
HorizontalAlignment
=
.
justified
,
verticalAlignment
:
VerticalAlignment
=
.
center
)
{
super
.
init
()
self
.
horizontalAlignment
=
horizontalAlignment
self
.
verticalAlignment
=
verticalAlignment
}
required
public
init
?(
coder
aDecoder
:
NSCoder
)
{
super
.
init
(
coder
:
aDecoder
)
}
// MARK: - 🅾️ Overrides
override
open
func
layoutAttributesForItem
(
at
indexPath
:
IndexPath
)
->
UICollectionViewLayoutAttributes
?
{
// 💡 IDEA:
// The approach for computing a cell's frame is to create a rectangle that covers the current line.
// Then we check if the preceding cell's frame intersects with this rectangle.
// If it does, the current item is not the first item in the line. Otherwise it is.
// (Vice-versa for right-aligned cells.)
//
// +---------+----------------------------------------------------------------+---------+
// | | | |
// | | +------------+ | |
// | | | | | |
// | section |- - -|- - - - - - |- - - - +---------------------+ - - - - - - -| section |
// | inset | |intersection| | | line rect | inset |
// | |- - -|- - - - - - |- - - - +---------------------+ - - - - - - -| |
// | (left) | | | current item | (right) |
// | | +------------+ | |
// | | previous item | |
// +---------+----------------------------------------------------------------+---------+
//
// ℹ️ We need this rather complicated approach because the first item in a line
// is not always left-aligned and the last item in a line is not always right-aligned:
// If there is only one item in a line UICollectionViewFlowLayout will center it.
// We may not change the original layout attributes or UICollectionViewFlowLayout might complain.
guard
let
layoutAttributes
=
super
.
layoutAttributesForItem
(
at
:
indexPath
)?
.
copy
()
as?
UICollectionViewLayoutAttributes
else
{
return
nil
}
// For a justified layout there's nothing to do here
// as UICollectionViewFlowLayout justifies the items in a line by default.
if
horizontalAlignment
!=
.
justified
{
layoutAttributes
.
alignHorizontally
(
collectionViewLayout
:
self
)
}
// For a vertically centered layout there's nothing to do here
// as UICollectionViewFlowLayout center-aligns the items in a line by default.
if
verticalAlignment
!=
.
center
{
layoutAttributes
.
alignVertically
(
collectionViewLayout
:
self
)
}
return
layoutAttributes
}
override
open
func
layoutAttributesForElements
(
in
rect
:
CGRect
)
->
[
UICollectionViewLayoutAttributes
]?
{
// We may not change the original layout attributes or UICollectionViewFlowLayout might complain.
let
layoutAttributesObjects
=
copy
(
super
.
layoutAttributesForElements
(
in
:
rect
))
layoutAttributesObjects
?
.
forEach
({
(
layoutAttributes
)
in
setFrame
(
forLayoutAttributes
:
layoutAttributes
)
})
return
layoutAttributesObjects
}
// MARK: - 👷 Private layout helpers
/// Sets the frame for the passed layout attributes object by calling the `layoutAttributesForItem(at:)` function.
private
func
setFrame
(
forLayoutAttributes
layoutAttributes
:
UICollectionViewLayoutAttributes
)
{
if
layoutAttributes
.
representedElementCategory
==
.
cell
{
// Do not modify header views etc.
let
indexPath
=
layoutAttributes
.
indexPath
if
let
newFrame
=
layoutAttributesForItem
(
at
:
indexPath
)?
.
frame
{
layoutAttributes
.
frame
=
newFrame
}
}
}
/// A function to access the `super` implementation of `layoutAttributesForItem(at:)` externally.
///
/// - Parameter indexPath: The index path of the item for which to return the layout attributes.
/// - Returns: The unmodified layout attributes for the item at the specified index path
/// as computed by `UICollectionViewFlowLayout`.
fileprivate
func
originalLayoutAttribute
(
forItemAt
indexPath
:
IndexPath
)
->
UICollectionViewLayoutAttributes
?
{
return
super
.
layoutAttributesForItem
(
at
:
indexPath
)
}
/// Determines if the `firstItemAttributes`' frame is in the same line
/// as the `secondItemAttributes`' frame.
///
/// - Parameters:
/// - firstItemAttributes: The first layout attributes object to be compared.
/// - secondItemAttributes: The second layout attributes object to be compared.
/// - Returns: `true` if the frames of the two layout attributes are in the same line, else `false`.
/// `false` is also returned when the layout's `collectionView` property is `nil`.
fileprivate
func
isFrame
(
for
firstItemAttributes
:
UICollectionViewLayoutAttributes
,
inSameLineAsFrameFor
secondItemAttributes
:
UICollectionViewLayoutAttributes
)
->
Bool
{
guard
let
lineWidth
=
contentWidth
else
{
return
false
}
let
firstItemFrame
=
firstItemAttributes
.
frame
let
lineFrame
=
CGRect
(
x
:
sectionInset
.
left
,
y
:
firstItemFrame
.
origin
.
y
,
width
:
lineWidth
,
height
:
firstItemFrame
.
size
.
height
)
return
lineFrame
.
intersects
(
secondItemAttributes
.
frame
)
}
/// Determines the layout attributes objects for all items displayed in the same line as the item
/// represented by the passed `layoutAttributes` object.
///
/// - Parameter layoutAttributes: The layout attributed that represents the reference item.
/// - Returns: The layout attributes objects representing all other items in the same line.
/// The passed `layoutAttributes` object itself is always contained in the returned array.
fileprivate
func
layoutAttributes
(
forItemsInLineWith
layoutAttributes
:
UICollectionViewLayoutAttributes
)
->
[
UICollectionViewLayoutAttributes
]
{
guard
let
lineWidth
=
contentWidth
else
{
return
[
layoutAttributes
]
}
var
lineFrame
=
layoutAttributes
.
frame
lineFrame
.
origin
.
x
=
sectionInset
.
left
lineFrame
.
size
.
width
=
lineWidth
return
super
.
layoutAttributesForElements
(
in
:
lineFrame
)
??
[]
}
/// Copmutes the alignment axis with which to align the items represented by the `layoutAttributes` objects vertically.
///
/// - Parameter layoutAttributes: The layout attributes objects to be vertically aligned.
/// - Returns: The axis with respect to which the layout attributes can be aligned
/// or `nil` if the `layoutAttributes` array is empty.
private
func
verticalAlignmentAxisForLine
(
with
layoutAttributes
:
[
UICollectionViewLayoutAttributes
])
->
AlignmentAxis
<
VerticalAlignment
>
?
{
guard
let
firstAttribute
=
layoutAttributes
.
first
else
{
return
nil
}
switch
verticalAlignment
{
case
.
top
:
let
minY
=
layoutAttributes
.
reduce
(
CGFloat
.
greatestFiniteMagnitude
)
{
min
(
$0
,
$1
.
frame
.
minY
)
}
return
AlignmentAxis
(
alignment
:
.
top
,
position
:
minY
)
case
.
bottom
:
let
maxY
=
layoutAttributes
.
reduce
(
0
)
{
max
(
$0
,
$1
.
frame
.
maxY
)
}
return
AlignmentAxis
(
alignment
:
.
bottom
,
position
:
maxY
)
default
:
let
centerY
=
firstAttribute
.
center
.
y
return
AlignmentAxis
(
alignment
:
.
center
,
position
:
centerY
)
}
}
/// Computes the axis with which to align the item represented by the `currentLayoutAttributes` vertically.
///
/// - Parameter currentLayoutAttributes: The layout attributes representing the item to be vertically aligned.
/// - Returns: The axis with respect to which the item can be aligned.
fileprivate
func
verticalAlignmentAxis
(
for
currentLayoutAttributes
:
UICollectionViewLayoutAttributes
)
->
AlignmentAxis
<
VerticalAlignment
>
{
let
layoutAttributesInLine
=
layoutAttributes
(
forItemsInLineWith
:
currentLayoutAttributes
)
// It's okay to force-unwrap here because we pass a non-empty array.
let
axis
=
verticalAlignmentAxisForLine
(
with
:
layoutAttributesInLine
)
??
AlignmentAxis
(
alignment
:
VerticalAlignment
.
top
,
position
:
0
)
return
axis
}
/// Creates a deep copy of the passed array by copying all its items.
///
/// - Parameter layoutAttributesArray: The array to be copied.
/// - Returns: A deep copy of the passed array.
private
func
copy
(
_
layoutAttributesArray
:
[
UICollectionViewLayoutAttributes
]?)
->
[
UICollectionViewLayoutAttributes
]?
{
return
layoutAttributesArray
?
.
map
{
$0
.
copy
()
}
as?
[
UICollectionViewLayoutAttributes
]
}
}
// MARK: - 👷 Layout attributes helpers
fileprivate
extension
UICollectionViewLayoutAttributes
{
private
var
currentSection
:
Int
{
return
indexPath
.
section
}
private
var
currentItem
:
Int
{
return
indexPath
.
item
}
/// The index path for the item preceding the item represented by this layout attributes object.
private
var
precedingIndexPath
:
IndexPath
{
return
IndexPath
(
item
:
currentItem
-
1
,
section
:
currentSection
)
}
/// The index path for the item following the item represented by this layout attributes object.
private
var
followingIndexPath
:
IndexPath
{
return
IndexPath
(
item
:
currentItem
+
1
,
section
:
currentSection
)
}
/// Checks if the item represetend by this layout attributes object is the first item in the line.
///
/// - Parameter collectionViewLayout: The layout for which to perform the check.
/// - Returns: `true` if the represented item is the first item in the line, else `false`.
func
isRepresentingFirstItemInLine
(
collectionViewLayout
:
AlignedCollectionViewFlowLayout
)
->
Bool
{
if
currentItem
<=
0
{
return
true
}
else
{
if
let
layoutAttributesForPrecedingItem
=
collectionViewLayout
.
originalLayoutAttribute
(
forItemAt
:
precedingIndexPath
)
{
return
!
collectionViewLayout
.
isFrame
(
for
:
self
,
inSameLineAsFrameFor
:
layoutAttributesForPrecedingItem
)
}
else
{
return
true
}
}
}
/// Checks if the item represetend by this layout attributes object is the last item in the line.
///
/// - Parameter collectionViewLayout: The layout for which to perform the check.
/// - Returns: `true` if the represented item is the last item in the line, else `false`.
func
isRepresentingLastItemInLine
(
collectionViewLayout
:
AlignedCollectionViewFlowLayout
)
->
Bool
{
guard
let
itemCount
=
collectionViewLayout
.
collectionView
?
.
numberOfItems
(
inSection
:
currentSection
)
else
{
return
false
}
if
currentItem
>=
itemCount
-
1
{
return
true
}
else
{
if
let
layoutAttributesForFollowingItem
=
collectionViewLayout
.
originalLayoutAttribute
(
forItemAt
:
followingIndexPath
)
{
return
!
collectionViewLayout
.
isFrame
(
for
:
self
,
inSameLineAsFrameFor
:
layoutAttributesForFollowingItem
)
}
else
{
return
true
}
}
}
/// Moves the layout attributes object's frame so that it is aligned horizontally with the alignment axis.
func
align
(
toAlignmentAxis
alignmentAxis
:
AlignmentAxis
<
HorizontalAlignment
>
)
{
switch
alignmentAxis
.
alignment
{
case
.
left
:
frame
.
origin
.
x
=
alignmentAxis
.
position
case
.
right
:
frame
.
origin
.
x
=
alignmentAxis
.
position
-
frame
.
size
.
width
default
:
break
}
}
/// Moves the layout attributes object's frame so that it is aligned vertically with the alignment axis.
func
align
(
toAlignmentAxis
alignmentAxis
:
AlignmentAxis
<
VerticalAlignment
>
)
{
switch
alignmentAxis
.
alignment
{
case
.
top
:
frame
.
origin
.
y
=
alignmentAxis
.
position
case
.
bottom
:
frame
.
origin
.
y
=
alignmentAxis
.
position
-
frame
.
size
.
height
default
:
center
.
y
=
alignmentAxis
.
position
}
}
/// Positions the frame right of the preceding item's frame, leaving a spacing between the frames
/// as defined by the collection view layout's `minimumInteritemSpacing`.
///
/// - Parameter collectionViewLayout: The layout on which to perfom the calculations.
private
func
alignToPrecedingItem
(
collectionViewLayout
:
AlignedCollectionViewFlowLayout
)
{
let
itemSpacing
=
collectionViewLayout
.
minimumInteritemSpacing
if
let
precedingItemAttributes
=
collectionViewLayout
.
layoutAttributesForItem
(
at
:
precedingIndexPath
)
{
frame
.
origin
.
x
=
precedingItemAttributes
.
frame
.
maxX
+
itemSpacing
}
}
/// Positions the frame left of the following item's frame, leaving a spacing between the frames
/// as defined by the collection view layout's `minimumInteritemSpacing`.
///
/// - Parameter collectionViewLayout: The layout on which to perfom the calculations.
private
func
alignToFollowingItem
(
collectionViewLayout
:
AlignedCollectionViewFlowLayout
)
{
let
itemSpacing
=
collectionViewLayout
.
minimumInteritemSpacing
if
let
followingItemAttributes
=
collectionViewLayout
.
layoutAttributesForItem
(
at
:
followingIndexPath
)
{
frame
.
origin
.
x
=
followingItemAttributes
.
frame
.
minX
-
itemSpacing
-
frame
.
size
.
width
}
}
/// Aligns the frame horizontally as specified by the collection view layout's `horizontalAlignment`.
///
/// - Parameters:
/// - collectionViewLayout: The layout providing the alignment information.
func
alignHorizontally
(
collectionViewLayout
:
AlignedCollectionViewFlowLayout
)
{
guard
let
alignmentAxis
=
collectionViewLayout
.
alignmentAxis
else
{
return
}
switch
collectionViewLayout
.
effectiveHorizontalAlignment
{
case
.
left
:
if
isRepresentingFirstItemInLine
(
collectionViewLayout
:
collectionViewLayout
)
{
align
(
toAlignmentAxis
:
alignmentAxis
)
}
else
{
alignToPrecedingItem
(
collectionViewLayout
:
collectionViewLayout
)
}
case
.
right
:
if
isRepresentingLastItemInLine
(
collectionViewLayout
:
collectionViewLayout
)
{
align
(
toAlignmentAxis
:
alignmentAxis
)
}
else
{
alignToFollowingItem
(
collectionViewLayout
:
collectionViewLayout
)
}
default
:
return
}
}
/// Aligns the frame vertically as specified by the collection view layout's `verticalAlignment`.
///
/// - Parameter collectionViewLayout: The layout providing the alignment information.
func
alignVertically
(
collectionViewLayout
:
AlignedCollectionViewFlowLayout
)
{
let
alignmentAxis
=
collectionViewLayout
.
verticalAlignmentAxis
(
for
:
self
)
align
(
toAlignmentAxis
:
alignmentAxis
)
}
}
galaxy/galaxy/Classes/Tools/Extention/AppDelegate + UIAppearance.swift
0 → 100755
View file @
0b841956
//
// AppDelegate + UIAppearance.swift
// SleepDoctor
//
// Created by DAVIDiOS1 on 2020/12/24.
// Copyright © 2020 sumian. All rights reserved.
//
import
UIKit
// MARK: - 设置导航栏样式
extension
AppDelegate
{
func
customAppearance
()
{
setNavigationBarAppearanceWhenContainedInInstancesOf
(
containers
:
[
YHNavigationController
.
self
])
setNavigationBarAppearanceWhenContainedInInstancesOf
(
containers
:
[
YHBaseViewController
.
self
])
}
func
setNavigationBarAppearanceWhenContainedInInstancesOf
(
containers
:
[
UIAppearanceContainer
.
Type
]){
let
navigationBarAppearance
=
UINavigationBar
.
appearance
(
whenContainedInInstancesOf
:
containers
)
navigationBarAppearance
.
titleTextAttributes
=
[
NSAttributedString
.
Key
.
foregroundColor
:
UIColor
.
commonColor100
,
NSAttributedString
.
Key
.
font
:
UIFont
.
PFSCM
(
ofSize
:
16
)]
navigationBarAppearance
.
barTintColor
=
UIColor
.
yellow
navigationBarAppearance
.
tintColor
=
UIColor
.
commonColor100
navigationBarAppearance
.
backIndicatorImage
=
UIImage
(
named
:
"back_icon"
)
navigationBarAppearance
.
backIndicatorTransitionMaskImage
=
UIImage
(
named
:
"back_icon"
)
navigationBarAppearance
.
setBackgroundImage
(
UIImage
.
from
(
color
:
UIColor
.
clear
),
for
:
.
default
)
navigationBarAppearance
.
isOpaque
=
true
navigationBarAppearance
.
shadowImage
=
nil
//隐藏返回文字
if
#available(iOS 13, *)
{
UIBarButtonItem
.
appearance
()
.
setBackButtonTitlePositionAdjustment
(
UIOffset
(
horizontal
:
-
UIDevice
.
kScreenW
,
vertical
:
0
),
for
:
.
default
)
}
let
barItemAppearance
=
UIBarButtonItem
.
appearance
(
whenContainedInInstancesOf
:
containers
)
barItemAppearance
.
setTitleTextAttributes
([
NSAttributedString
.
Key
.
foregroundColor
:
UIColor
.
clear
,
NSAttributedString
.
Key
.
font
:
UIFont
.
systemFont
(
ofSize
:
14
)],
for
:
UIControl
.
State
.
normal
)
barItemAppearance
.
setTitleTextAttributes
([
NSAttributedString
.
Key
.
foregroundColor
:
UIColor
.
clear
,
NSAttributedString
.
Key
.
font
:
UIFont
.
systemFont
(
ofSize
:
14
)],
for
:
UIControl
.
State
.
highlighted
)
}
}
// MARK: - Pay 支付
extension
AppDelegate
{
func
payCallback
(
url
:
URL
)
{
// //支付宝支付
// if url.host == "safepay" {
// AlipaySDK.defaultService().processOrder(withPaymentResult: url, standbyCallback: { resultDic in
// let status = resultDic?["resultStatus"] as? String ?? ""
// var success: Bool = false
// if status == "9000" {
// success = true
// print("支付宝: 支付成功")
// } else {
// success = false
// print("支付宝: 支付失败")
// }
// NotificationCenter.default.post(name: BsConstant.BsNotification.payResultNotification, object: success)
// })
// }
}
}
galaxy/galaxy/Classes/Tools/Extention/BsCacheTool.swift
0 → 100755
View file @
0b841956
//
// BsCacheTool.swift
// BaiSiSMApp
//
// Created by DAVID on 2023/1/4.
// Copyright © 2023 www.sumian.com. All rights reserved.
//
import
Foundation
open
class
BsCacheTool
:
NSObject
{
/// 计算缓存大小
public
static
var
cacheSize
:
String
{
get
{
// 路径
let
basePath
=
NSSearchPathForDirectoriesInDomains
(
FileManager
.
SearchPathDirectory
.
cachesDirectory
,
FileManager
.
SearchPathDomainMask
.
userDomainMask
,
true
)
.
first
let
fileManager
=
FileManager
.
default
// 遍历出所有缓存文件加起来的大小
func
caculateCache
()
->
CGFloat
{
var
total
:
CGFloat
=
0
if
fileManager
.
fileExists
(
atPath
:
basePath
!
){
let
childrenPath
=
fileManager
.
subpaths
(
atPath
:
basePath
!
)
if
childrenPath
!=
nil
{
for
path
in
childrenPath
!
{
if
path
!=
"iconName.png"
&&
path
!=
"Collect.json"
{
let
childPath
=
basePath
!.
appending
(
"/"
)
.
appending
(
path
)
do
{
let
attr
:
NSDictionary
=
try
fileManager
.
attributesOfItem
(
atPath
:
childPath
)
as
NSDictionary
if
let
fileSize
=
attr
[
"NSFileSize"
]
as?
CGFloat
{
total
+=
fileSize
}
}
catch
_
{
}
}
}
}
}
// 缓存文件大小
return
total
}
// 调用函数
let
totalCache
=
caculateCache
()
return
NSString
(
format
:
"%.2fM"
,
totalCache
/
1024.0
/
1024.0
)
as
String
}
}
/// 清除缓存
///
/// - returns: 是否清理成功
public
class
func
clearCache
()
->
Bool
{
var
result
=
true
// 取出cache文件夹目录 缓存文件都在这个目录下
let
cachePath
=
NSSearchPathForDirectoriesInDomains
(
FileManager
.
SearchPathDirectory
.
cachesDirectory
,
FileManager
.
SearchPathDomainMask
.
userDomainMask
,
true
)
.
first
// 取出文件夹下所有文件数组
let
fileArr
=
FileManager
.
default
.
subpaths
(
atPath
:
cachePath
!
)
// 遍历删除
for
file
in
fileArr
!
{
if
file
!=
"iconName.png"
&&
file
!=
"Collect.json"
{
// 拼接文件路径
let
path
=
cachePath
?
.
appending
(
"/
\(
file
)
"
)
if
FileManager
.
default
.
fileExists
(
atPath
:
path
!
)
{
// 循环删除
do
{
try
FileManager
.
default
.
removeItem
(
atPath
:
path
!
)
}
catch
{
// 删除失败
result
=
false
}
}
}
}
return
result
}
}
galaxy/galaxy/Classes/Tools/Extention/BsGestureTableView.swift
0 → 100755
View file @
0b841956
//
// BsGestureTableView.swift
// GDKit
//
// Created by GDKit on 01/11/2022.
// Copyright (c) 2022 GDKit. All rights reserved.
//
import
UIKit
open
class
BsGestureTableView
:
UITableView
{
}
// MARK: - UIGestureRecognizerDelegate
extension
BsGestureTableView
:
UIGestureRecognizerDelegate
{
public
func
gestureRecognizer
(
_
gestureRecognizer
:
UIGestureRecognizer
,
shouldRecognizeSimultaneouslyWith
otherGestureRecognizer
:
UIGestureRecognizer
)
->
Bool
{
return
true
}
open
override
func
gestureRecognizerShouldBegin
(
_
gestureRecognizer
:
UIGestureRecognizer
)
->
Bool
{
return
true
}
}
open
class
BsGestureScrollView
:
UIScrollView
{
}
// MARK: - UIGestureRecognizerDelegate
extension
BsGestureScrollView
:
UIGestureRecognizerDelegate
{
public
func
gestureRecognizer
(
_
gestureRecognizer
:
UIGestureRecognizer
,
shouldRecognizeSimultaneouslyWith
otherGestureRecognizer
:
UIGestureRecognizer
)
->
Bool
{
return
true
}
open
override
func
gestureRecognizerShouldBegin
(
_
gestureRecognizer
:
UIGestureRecognizer
)
->
Bool
{
return
true
}
}
open
class
BsGestureCollectionView
:
UICollectionView
{
}
// MARK: - UIGestureRecognizerDelegate
extension
BsGestureCollectionView
:
UIGestureRecognizerDelegate
{
public
func
gestureRecognizer
(
_
gestureRecognizer
:
UIGestureRecognizer
,
shouldRecognizeSimultaneouslyWith
otherGestureRecognizer
:
UIGestureRecognizer
)
->
Bool
{
return
true
}
open
override
func
gestureRecognizerShouldBegin
(
_
gestureRecognizer
:
UIGestureRecognizer
)
->
Bool
{
return
true
}
}
galaxy/galaxy/Classes/Tools/Extention/BsOverlayView.swift
0 → 100755
View file @
0b841956
//
// BsOverlayView.swift
// BaiSiSMApp
//
// Created by DAVID on 2022/11/22.
// Copyright © 2022 www.davidhuang.com. All rights reserved.
//
import
UIKit
class
BsOverlayView
:
UIView
{
// MARK: - 属性
public
var
overlayView
:
UIControl
!
//遮罩层view
private
var
keyWindow
:
UIWindow
?
// MARK: - 生命周期函数
override
init
(
frame
:
CGRect
)
{
super
.
init
(
frame
:
frame
)
setupOverlayView
()
}
required
init
?(
coder
aDecoder
:
NSCoder
)
{
fatalError
(
"init(coder:) has not been implemented"
)
}
private
func
setupOverlayView
()
{
// 1 获取window
if
(
keyWindow
==
nil
)
{
self
.
keyWindow
=
UIApplication
.
shared
.
bsKeyWindow
()
}
// 2.遮罩view
overlayView
=
UIControl
.
init
(
frame
:
UIScreen
.
main
.
bounds
)
overlayView
?
.
backgroundColor
=
UIColor
.
init
(
red
:
0
,
green
:
0
,
blue
:
0
,
alpha
:
0.5
)
overlayView
?
.
addTarget
(
self
,
action
:
#selector(
hide
)
,
for
:
.
touchUpInside
)
overlayView
?
.
alpha
=
0
}
// MARK: - ACTIONS
//显示
public
func
show
()
{
keyWindow
?
.
addSubview
(
overlayView
!
)
keyWindow
?
.
addSubview
(
self
)
UIView
.
animate
(
withDuration
:
0.25
,
animations
:
{
self
.
overlayView
?
.
alpha
=
1.0
var
frame
=
self
.
frame
frame
.
origin
.
y
=
UIScreen
.
main
.
bounds
.
size
.
height
-
self
.
bounds
.
size
.
height
self
.
frame
=
frame
})
{
(
isFinished
)
in
//
}
}
//隐藏
@objc
public
func
hide
()
{
UIView
.
animate
(
withDuration
:
0.25
,
animations
:
{
self
.
overlayView
?
.
alpha
=
0
var
frame
=
self
.
frame
frame
.
origin
.
y
=
UIScreen
.
main
.
bounds
.
size
.
height
self
.
frame
=
frame
})
{
(
isFinished
)
in
self
.
overlayView
?
.
removeFromSuperview
()
self
.
removeFromSuperview
()
}
}
// MARK: - 私有方法
// MARK: - 事件响应包括手势和按钮等
// MARK: - UITableViewDataSource 和 UITableViewDelegate
}
galaxy/galaxy/Classes/Tools/Extention/Date-Extension.swift
0 → 100755
View file @
0b841956
//
// Date-Extension.swift
// DouYuUI
//
// Created by davidhuang on 2022/8/11.
// Copyright © 2022 davidhuang. All rights reserved.
//
import
UIKit
extension
Date
{
static
func
getCurrentDate
()
->
String
{
let
now
=
Int
(
Date
.
timeIntervalSinceReferenceDate
)
return
"
\(
now
)
"
}
init
(
_
dateString
:
String
,
dateFormat
:
String
=
"yyyy-MM-dd"
)
{
let
df
=
DateFormatter
()
df
.
dateFormat
=
dateFormat
let
date
=
df
.
date
(
from
:
dateString
)
!
self
.
init
(
timeInterval
:
0
,
since
:
date
)
}
}
galaxy/galaxy/Classes/Tools/Extention/NSAttributedString+Extension.swift
0 → 100755
View file @
0b841956
//
// NSAttributedString+Extension.swift
// BaiSiSMApp
//
// Created by DAVID on 2022/12/6.
// Copyright © 2022 www.davidhuang.com. All rights reserved.
//
import
UIKit
extension
NSAttributedString
{
//添加富文本
public
class
func
bs_create
(
string
str
:
String
,
font
:
UIFont
?
=
nil
,
color
textColor
:
UIColor
?
=
nil
,
url
:
String
?
=
nil
,
lineSpacing
:
CGFloat
?
=
nil
)
->
NSAttributedString
{
var
attributes
:
[
NSAttributedString
.
Key
:
Any
]
=
[:]
if
let
font
=
font
{
attributes
[
.
font
]
=
font
}
if
let
textColor
=
textColor
{
attributes
[
.
foregroundColor
]
=
textColor
}
if
let
url
=
url
{
//添加链接文本
attributes
[
.
link
]
=
url
}
if
let
lineSpacing
=
lineSpacing
{
//格式调整
let
style
=
NSMutableParagraphStyle
()
/**调行间距*/
style
.
lineSpacing
=
lineSpacing
style
.
alignment
=
.
left
attributes
[
.
paragraphStyle
]
=
style
}
let
attributedString
=
NSAttributedString
(
string
:
str
,
attributes
:
attributes
)
return
attributedString
}
//添加图片
public
class
func
gd_create
(
image
:
UIImage
)
->
NSAttributedString
{
let
textAttachment
=
NSTextAttachment
()
textAttachment
.
image
=
image
let
attrStringWithImage
=
NSAttributedString
(
attachment
:
textAttachment
)
return
attrStringWithImage
}
}
extension
NSAttributedString
{
/// 富文本转html字符串
public
class
func
attriToStr
(
attri
:
NSAttributedString
)
->
String
{
let
tempDic
:
[
NSAttributedString
.
DocumentAttributeKey
:
Any
]
=
[
NSAttributedString
.
DocumentAttributeKey
.
documentType
:
NSAttributedString
.
DocumentType
.
html
,
NSAttributedString
.
DocumentAttributeKey
.
characterEncoding
:
String
.
Encoding
.
utf8
.
rawValue
]
do
{
let
htmlData
=
try
attri
.
data
(
from
:
NSRange
(
location
:
0
,
length
:
attri
.
length
-
1
),
documentAttributes
:
tempDic
)
return
String
(
data
:
htmlData
,
encoding
:
String
.
Encoding
.
utf8
)
??
""
}
catch
{
return
""
}
}
/// 字符串转富文本
public
class
func
strToAttri
(
htmlStr
:
String
)
->
NSAttributedString
{
guard
let
data
=
htmlStr
.
data
(
using
:
String
.
Encoding
.
unicode
)
else
{
return
NSAttributedString
()
}
do
{
let
attri
=
try
NSAttributedString
(
data
:
data
,
options
:
[
NSAttributedString
.
DocumentReadingOptionKey
.
documentType
:
NSAttributedString
.
DocumentType
.
html
],
documentAttributes
:
nil
)
return
attri
}
catch
{
return
NSAttributedString
()
}
}
}
extension
NSMutableAttributedString
{
//添加图片和点击事件
public
class
func
bs_create
(
image
:
UIImage
)
->
NSMutableAttributedString
{
let
textAttachment
=
NSTextAttachment
()
textAttachment
.
image
=
image
let
attrStringWithImage
=
NSMutableAttributedString
(
attachment
:
textAttachment
)
attrStringWithImage
.
addAttributes
([
.
link
:
"checkbox://"
],
range
:
NSMakeRange
(
0
,
attrStringWithImage
.
length
))
return
attrStringWithImage
}
public
func
setStyle
(
lineSpacing
:
CGFloat
)
{
//格式调整
let
style
=
NSMutableParagraphStyle
()
/**调行间距*/
style
.
lineSpacing
=
lineSpacing
style
.
alignment
=
.
left
self
.
addAttributes
([
NSAttributedString
.
Key
.
paragraphStyle
:
style
],
range
:
NSRange
(
location
:
0
,
length
:
self
.
string
.
count
))
}
}
galaxy/galaxy/Classes/Tools/Extention/String-Extension.swift
0 → 100755
View file @
0b841956
//
// String-Extension.swift
// BaiSiSMApp
//
// Created by davidhuang on 2022/10/12.
// Copyright © 2022 www.davidhuang.com. All rights reserved.
//
import
UIKit
extension
String
{
// MARK: - 拨打电话
func
makePhone
()
{
let
phone
=
"telprompt://"
+
self
if
UIApplication
.
shared
.
canOpenURL
(
URL
(
string
:
phone
)
!
)
==
true
{
UIApplication
.
shared
.
open
(
URL
(
string
:
phone
)
!
,
options
:
[:],
completionHandler
:
nil
)
}
}
// MARK: - 判断是否为手机号码
func
isMobile
()
->
Bool
{
let
reg
=
"^1[3456789]
\\
d{9}$"
let
regextestmobile
=
NSPredicate
(
format
:
"SELF MATCHES %@"
,
reg
)
return
regextestmobile
.
evaluate
(
with
:
self
);
}
// MARK: - 判断密码是否合法
//密码至少包含一个数字,一个字母,一个特殊字符
func
isPwdLegal
()
->
Bool
{
let
reg
=
"^(?=.*)(?=.*[a-zA-Z])(?=.*[0-9])(?=.*[-~!@#$%^&*:;,.=?$
\\
x22]).{8,20}$"
let
regextestmobile
=
NSPredicate
(
format
:
"SELF MATCHES %@"
,
reg
)
return
regextestmobile
.
evaluate
(
with
:
self
);
}
// MARK: - 是否包含字符
func
isIncludeChinese
()
->
Bool
{
for
char
in
self
{
if
(
"
\u{4E00}
"
<=
char
&&
char
<=
"
\u{9FA5}
"
)
{
return
true
}
}
return
false
}
func
phoneNumberForUI
()
->
String
{
let
phone
=
self
.
replacingOccurrences
(
of
:
" "
,
with
:
""
)
if
phone
.
count
==
11
{
let
st1
=
phone
.
slicing
(
from
:
0
,
length
:
3
)
let
st2
=
phone
.
slicing
(
from
:
7
,
length
:
4
)
return
st1
!
+
"****"
+
st2
!
}
return
self
}
var
unicodeDescription
:
String
{
return
self
.
stringByReplaceUnicode
}
var
stringByReplaceUnicode
:
String
{
let
jsonDict
=
try
?
JSONSerialization
.
jsonObject
(
with
:
self
.
data
(
using
:
String
.
Encoding
.
utf8
,
allowLossyConversion
:
true
)
!
,
options
:
JSONSerialization
.
ReadingOptions
.
mutableLeaves
)
let
jsonData
=
try
?
JSONSerialization
.
data
(
withJSONObject
:
jsonDict
as
Any
,
options
:
.
prettyPrinted
)
let
string_r
=
String
(
data
:
jsonData
!
,
encoding
:
String
.
Encoding
.
utf8
)
return
string_r
??
self
}
//时间戳转Date
func
stringConvertDate
(
dateFormat
:
String
=
"yyyy-MM-dd HH:mm:ss"
)
->
Date
{
let
timeZone
=
TimeZone
.
init
(
identifier
:
"UTC"
)
//这是重点
let
dateFormatter
=
DateFormatter
.
init
()
dateFormatter
.
timeZone
=
timeZone
dateFormatter
.
dateFormat
=
dateFormat
let
date
=
dateFormatter
.
date
(
from
:
self
)
return
date
!
}
//时间戳转Date
func
convertDate
(
dateFormat
:
String
=
"yyyy-MM-dd HH:mm:ss"
)
->
Date
{
let
dateFormatter
=
DateFormatter
.
init
()
dateFormatter
.
dateFormat
=
dateFormat
let
date
=
dateFormatter
.
date
(
from
:
self
)
??
Date
()
return
date
}
//时间戳转 DateString
func
timeStampToString
()
->
String
{
guard
let
timeStamp
=
self
.
cgFloat
()
else
{
return
"--"
}
//时间戳为毫秒级要 / 1000, 秒就不用除1000,参数带没带000
let
timeSta
:
TimeInterval
=
TimeInterval
(
timeStamp
)
let
date
=
NSDate
(
timeIntervalSince1970
:
timeSta
)
let
dateformatter
=
DateFormatter
()
dateformatter
.
dateFormat
=
"yyyy-MM-dd HH:mm:ss"
return
dateformatter
.
string
(
from
:
date
as
Date
)
}
}
// MARK: - 计算文字的宽高
extension
String
{
/// 计算文字的宽高
///
/// - Parameters:
/// - font: 字体大小
/// - lineSpacing: 行高
/// - constraintRect: 大小范围
/// - Returns: 宽高
public
func
bs_sizeWithConstrained
(
_
font
:
UIFont
,
lineSpacing
:
CGFloat
?
=
nil
,
constraintRect
:
CGSize
=
CGSize
(
width
:
CGFloat
.
greatestFiniteMagnitude
,
height
:
CGFloat
.
greatestFiniteMagnitude
))
->
CGSize
{
var
attributes
:
[
NSAttributedString
.
Key
:
Any
]
=
[
NSAttributedString
.
Key
.
font
:
font
]
if
let
lineSpacing
=
lineSpacing
{
//格式调整
let
style
=
NSMutableParagraphStyle
()
/**调行间距*/
style
.
lineSpacing
=
lineSpacing
style
.
alignment
=
.
left
attributes
[
.
paragraphStyle
]
=
style
}
let
boundingBox
=
self
.
boundingRect
(
with
:
constraintRect
,
options
:
NSStringDrawingOptions
.
usesLineFragmentOrigin
,
attributes
:
attributes
,
context
:
nil
)
return
boundingBox
.
size
}
}
// MARK: - 正则获取http
extension
String
{
//获取http链接字符串的参数
public
var
urlParameters
:
[
String
:
String
]
{
guard
let
url
=
URL
(
string
:
self
)
else
{
return
[:]
}
guard
let
components
=
URLComponents
(
url
:
url
,
resolvingAgainstBaseURL
:
true
),
let
queryItems
=
components
.
queryItems
else
{
return
[:]
}
return
queryItems
.
reduce
(
into
:
[
String
:
String
]())
{
(
result
,
item
)
in
result
[
item
.
name
]
=
item
.
value
}
}
///获取http链接字符串的range
public
func
getHttpRangeOfString
()
->
[
NSTextCheckingResult
]?
{
let
regulaStr
=
"((http[s]{0,1}|ftp)://[a-zA-Z0-9
\\
.
\\
-]+
\\
.([a-zA-Z]{2,4})(:
\\
d+)?(/[a-zA-Z0-9
\\
.
\\
-~!@#$%^&*+?:_/=<>]*)?)|(www.[a-zA-Z0-9
\\
.
\\
-]+
\\
.([a-zA-Z]{2,4})(:
\\
d+)?(/[a-zA-Z0-9
\\
.
\\
-~!@#$%^&*+?:_/=<>]*)?)"
do
{
let
regex
=
try
NSRegularExpression
(
pattern
:
regulaStr
,
options
:
.
caseInsensitive
)
let
arrayOfAllMatches
=
regex
.
matches
(
in
:
self
,
options
:
NSRegularExpression
.
MatchingOptions
.
init
(
rawValue
:
0
),
range
:
NSMakeRange
(
0
,
self
.
count
))
return
arrayOfAllMatches
}
catch
{
return
nil
}
}
}
/// 打印
///
/// - Parameters:
/// - message: 打印内容
/// - file: 所在文件
/// - method: 所在方法
/// - line: 所在行
public
func
printLog
<
T
>
(
_
message
:
T
,
file
:
String
=
#file
,
method
:
String
=
#function
,
line
:
Int
=
#line
)
{
print
(
"
\(
(
file
as
NSString
)
.
lastPathComponent
)
[
\(
line
)
],
\(
method
)
:
\(
message
)
"
)
}
galaxy/galaxy/Classes/Tools/Extention/UIApplication-Extension.swift
0 → 100755
View file @
0b841956
//
// UIApplication-Extension.swift
// BaiSiSMApp
//
// Created by davidhuang on 2022/10/31.
// Copyright © 2022 www.davidhuang.com. All rights reserved.
//
import
UIKit
extension
UIApplication
{
func
bsKeyWindow
()
->
UIWindow
?
{
var
originalKeyWindow
:
UIWindow
?
#if swift(>=5.1)
if
#available(iOS 13, *)
{
originalKeyWindow
=
UIApplication
.
shared
.
connectedScenes
.
compactMap
{
$0
as?
UIWindowScene
}
.
flatMap
{
$0
.
windows
}
.
first
(
where
:
{
$0
.
isKeyWindow
})
}
else
{
originalKeyWindow
=
UIApplication
.
shared
.
keyWindow
}
#else
originalKeyWindow
=
UIApplication
.
shared
.
keyWindow
#endif
return
originalKeyWindow
}
}
galaxy/galaxy/Classes/Tools/Extention/UIButton-Extension.swift
0 → 100755
View file @
0b841956
//
// UIButton-Extension.swift
// BaiSiSMApp
//
// Created by DAVID on 2023/1/11.
// Copyright © 2023 www.sumian.com. All rights reserved.
//
import
UIKit
extension
UIButton
{
/// 图片在右位置
/// - Parameter spacing: 间距
func
iconInRight
(
with
spacing
:
CGFloat
)
{
let
img_w
=
self
.
imageView
?
.
frame
.
size
.
width
??
0
let
title_w
=
self
.
titleLabel
?
.
frame
.
size
.
width
??
0
self
.
titleEdgeInsets
=
UIEdgeInsets
(
top
:
0
,
left
:
-
(
img_w
+
spacing
/
2.0
),
bottom
:
0
,
right
:
(
img_w
+
spacing
/
2.0
))
self
.
imageEdgeInsets
=
UIEdgeInsets
(
top
:
0
,
left
:
(
title_w
+
spacing
/
2.0
),
bottom
:
0
,
right
:
-
(
title_w
+
spacing
/
2.0
))
}
/// 图片在左位置
/// - Parameter spacing: 间距
func
iconInLeft
(
spacing
:
CGFloat
)
{
self
.
titleEdgeInsets
=
UIEdgeInsets
(
top
:
0
,
left
:
spacing
/
2.0
,
bottom
:
0
,
right
:
-
spacing
/
2.0
)
self
.
imageEdgeInsets
=
UIEdgeInsets
(
top
:
0
,
left
:
-
spacing
/
2.0
,
bottom
:
0
,
right
:
spacing
/
2.0
)
}
/// 图片在上面
/// - Parameter spacing: 间距
func
iconInTop
(
spacing
:
CGFloat
)
{
let
img_W
=
self
.
imageView
?
.
frame
.
size
.
width
??
0
let
img_H
=
self
.
imageView
?
.
frame
.
size
.
height
??
0
let
tit_W
=
self
.
titleLabel
?
.
frame
.
size
.
width
??
0
let
tit_H
=
self
.
titleLabel
?
.
frame
.
size
.
height
??
0
self
.
titleEdgeInsets
=
UIEdgeInsets
(
top
:
(
tit_H
/
2
+
spacing
/
2
),
left
:
-
(
img_W
/
2
),
bottom
:
-
(
tit_H
/
2
+
spacing
/
2
),
right
:
(
img_W
/
2
))
self
.
imageEdgeInsets
=
UIEdgeInsets
(
top
:
-
(
img_H
/
2
+
spacing
/
2
),
left
:
(
tit_W
/
2
),
bottom
:
(
img_H
/
2
+
spacing
/
2
),
right
:
-
(
tit_W
/
2
))
}
/// 图片在 下面
/// - Parameter spacing: 间距
func
iconInBottom
(
spacing
:
CGFloat
)
{
let
img_W
=
self
.
imageView
?
.
frame
.
size
.
width
??
0
let
img_H
=
self
.
imageView
?
.
frame
.
size
.
height
??
0
let
tit_W
=
self
.
titleLabel
?
.
frame
.
size
.
width
??
0
let
tit_H
=
self
.
titleLabel
?
.
frame
.
size
.
height
??
0
self
.
titleEdgeInsets
=
UIEdgeInsets
(
top
:
-
(
tit_H
/
2
+
spacing
/
2
),
left
:
-
(
img_W
/
2
),
bottom
:
(
tit_H
/
2
+
spacing
/
2
),
right
:
(
img_W
/
2
))
self
.
imageEdgeInsets
=
UIEdgeInsets
(
top
:
(
img_H
/
2
+
spacing
/
2
),
left
:
(
tit_W
/
2
),
bottom
:
-
(
img_H
/
2
+
spacing
/
2
),
right
:
-
(
tit_W
/
2
))
}
}
// MARK: - Create 初始化
extension
UIButton
{
public
class
func
bs_button
(
title
:
String
?
=
nil
,
selectTitle
:
String
?
=
nil
,
font
:
UIFont
?
=
nil
,
normalColor
:
UIColor
?
=
nil
,
selectColor
:
UIColor
?
=
nil
,
bgNormalColor
:
UIColor
?
=
nil
,
bgSelectColor
:
UIColor
?
=
nil
,
lightNormalColor
:
UIColor
?
=
nil
,
lightSelectColor
:
UIColor
?
=
nil
,
bgLightNormalColor
:
UIColor
?
=
nil
,
bgLightSelectColor
:
UIColor
?
=
nil
)
->
UIButton
{
let
btn
=
UIButton
(
type
:
.
custom
)
btn
.
titleLabel
?
.
font
=
font
btn
.
setTitle
(
title
,
for
:
.
normal
)
btn
.
setTitle
(
selectTitle
,
for
:
.
selected
)
btn
.
setTitle
(
title
,
for
:
[
.
highlighted
,
.
normal
])
btn
.
setTitle
(
selectTitle
,
for
:
[
.
highlighted
,
.
selected
])
btn
.
setTitleColor
(
normalColor
,
for
:
.
normal
)
btn
.
setTitleColor
(
selectColor
,
for
:
.
selected
)
btn
.
setTitleColor
(
lightNormalColor
,
for
:
[
.
highlighted
,
.
normal
])
btn
.
setTitleColor
(
lightSelectColor
,
for
:
[
.
highlighted
,
.
selected
])
btn
.
setBackgroundImage
(
bgNormalColor
?
.
imageWithColor
(),
for
:
.
normal
)
btn
.
setBackgroundImage
(
bgSelectColor
?
.
imageWithColor
(),
for
:
.
selected
)
btn
.
setBackgroundImage
(
bgLightNormalColor
?
.
imageWithColor
(),
for
:
[
.
highlighted
,
.
normal
])
if
bgLightNormalColor
==
nil
{
btn
.
setBackgroundImage
(
bgNormalColor
?
.
withAlphaComponent
(
0.9
)
.
imageWithColor
(),
for
:
[
.
highlighted
,
.
normal
])
}
btn
.
setBackgroundImage
(
bgLightSelectColor
?
.
imageWithColor
(),
for
:
[
.
highlighted
,
.
selected
])
if
bgLightSelectColor
==
nil
{
btn
.
setBackgroundImage
(
bgSelectColor
?
.
withAlphaComponent
(
0.9
)
.
imageWithColor
(),
for
:
[
.
highlighted
,
.
selected
])
}
return
btn
}
}
galaxy/galaxy/Classes/Tools/Extention/UIColor-Extension.swift
0 → 100755
View file @
0b841956
//
// UIColor-Extension.swift
// DouYuUI
//
// Created by davidhuang on 2022/8/9.
// Copyright © 2022 davidhuang. All rights reserved.
//
import
UIKit
import
SwifterSwift
extension
UIColor
{
// MARK: - 当前 app 主颜色
static
let
mainColor
:
UIColor
=
UIColor
(
hexString
:
"#46E0BB"
)
!
static
let
commonColor100
:
UIColor
=
UIColor
(
hexString
:
"#333333"
,
transparency
:
1.0
)
!
static
let
commonColor90
:
UIColor
=
UIColor
(
hexString
:
"#333333"
,
transparency
:
0.9
)
!
static
let
commonColor65
:
UIColor
=
UIColor
(
hexString
:
"#333333"
,
transparency
:
0.65
)
!
static
let
commonColor45
:
UIColor
=
UIColor
(
hexString
:
"#333333"
,
transparency
:
0.45
)
!
static
let
commonColor25
:
UIColor
=
UIColor
(
hexString
:
"#333333"
,
transparency
:
0.25
)
!
static
let
commonColor15
:
UIColor
=
UIColor
(
hexString
:
"#333333"
,
transparency
:
0.15
)
!
static
let
commonColor10
:
UIColor
=
UIColor
(
hexString
:
"#333333"
,
transparency
:
0.10
)
!
static
let
commonColor6
:
UIColor
=
UIColor
(
hexString
:
"#333333"
,
transparency
:
0.06
)
!
static
let
commonColor4
:
UIColor
=
UIColor
(
hexString
:
"#333333"
,
transparency
:
0.04
)
!
static
let
commonColor3
:
UIColor
=
UIColor
(
hexString
:
"#333333"
,
transparency
:
0.03
)
!
static
let
backgroundColor
:
UIColor
=
UIColor
(
hexString
:
"#F2F7F6"
,
transparency
:
1.0
)
!
static
let
mainTextColor
:
UIColor
=
UIColor
(
hexString
:
"#00D19F"
)
!
static
let
selectBgColor
:
UIColor
=
UIColor
(
hexString
:
"#D9FCF7"
)
!
//黑色 50透明
static
let
black50Persent
:
UIColor
=
UIColor
.
black
.
withAlphaComponent
(
0.5
)
public
convenience
init
(
r
:
CGFloat
,
g
:
CGFloat
,
b
:
CGFloat
)
{
self
.
init
(
red
:
r
/
255.0
,
green
:
g
/
255.0
,
blue
:
b
/
255.0
,
alpha
:
1.0
)
}
public
func
imageWithColor
(
width
:
Double
=
1.0
,
height
:
Double
=
1.0
)
->
UIImage
{
let
rect
=
CGRect
(
x
:
0.0
,
y
:
0.0
,
width
:
width
,
height
:
height
)
UIGraphicsBeginImageContext
(
rect
.
size
)
let
ctx
=
UIGraphicsGetCurrentContext
()
ctx
!.
setFillColor
(
self
.
cgColor
)
ctx
!.
fill
(
rect
)
let
image
=
UIGraphicsGetImageFromCurrentImageContext
()
UIGraphicsEndImageContext
()
return
image
!
}
}
galaxy/galaxy/Classes/Tools/Extention/UIDevice-Extension.swift
0 → 100755
View file @
0b841956
//
// UIDevice-Extension.swift
// BaiSiSMApp
//
// Created by davidhuang on 2022/10/11.
// Copyright © 2022 www.davidhuang.com. All rights reserved.
//
import
UIKit
extension
UIDevice
{
// MARK: - 屏幕size
static
let
kScreenSize
:
CGRect
=
UIScreen
.
main
.
bounds
// MARK: - 屏幕宽度
static
let
kScreenW
:
CGFloat
=
UIScreen
.
main
.
bounds
.
width
// MARK: - 屏幕高度
static
let
kScreenH
:
CGFloat
=
UIScreen
.
main
.
bounds
.
height
// MARK: - iOS系统版本号
static
let
kSystemVersion
:
String
=
UIDevice
.
current
.
systemVersion
// MARK: - 顶部安全区高度
static
func
bs_safeDistanceTop
()
->
CGFloat
{
if
#available(iOS 13.0, *)
{
let
scene
=
UIApplication
.
shared
.
connectedScenes
.
first
guard
let
windowScene
=
scene
as?
UIWindowScene
else
{
return
0
}
guard
let
window
=
windowScene
.
windows
.
first
else
{
return
0
}
return
window
.
safeAreaInsets
.
top
}
// else if #available(iOS 11.0, *) {
// guard let window = UIApplication.shared.windows.first else { return 0 }
// return window.safeAreaInsets.top
// }
return
0
;
}
// MARK: - 底部安全区高度
static
func
bs_safeDistanceBottom
()
->
CGFloat
{
if
#available(iOS 13.0, *)
{
let
scene
=
UIApplication
.
shared
.
connectedScenes
.
first
guard
let
windowScene
=
scene
as?
UIWindowScene
else
{
return
0
}
guard
let
window
=
windowScene
.
windows
.
first
else
{
return
0
}
return
window
.
safeAreaInsets
.
bottom
}
// else if #available(iOS 11.0, *) {
// guard let window = UIApplication.shared.windows.first else { return 0 }
// return window.safeAreaInsets.bottom
// }
return
0
;
}
// MARK: - 顶部状态栏高度(包括安全区)
static
func
bs_statusBarHeight
()
->
CGFloat
{
var
statusBarHeight
:
CGFloat
=
0
if
#available(iOS 13.0, *)
{
let
scene
=
UIApplication
.
shared
.
connectedScenes
.
first
guard
let
windowScene
=
scene
as?
UIWindowScene
else
{
return
0
}
guard
let
statusBarManager
=
windowScene
.
statusBarManager
else
{
return
0
}
statusBarHeight
=
statusBarManager
.
statusBarFrame
.
height
}
// else {
// statusBarHeight = UIApplication.shared.statusBarFrame.height
// }
return
statusBarHeight
}
// MARK: - 导航栏高度
static
func
bs_navigationBarHeight
()
->
CGFloat
{
return
44.0
}
// MARK: - 状态栏+导航栏的高度
static
func
bs_navigationFullHeight
()
->
CGFloat
{
return
UIDevice
.
bs_statusBarHeight
()
+
UIDevice
.
bs_navigationBarHeight
()
}
// MARK: - 底部导航栏高度
static
func
bs_tabBarHeight
()
->
CGFloat
{
return
49.0
}
// MARK: - 底部导航栏高度(包括安全区)
static
func
bs_tabBarFullHeight
()
->
CGFloat
{
return
UIDevice
.
bs_tabBarHeight
()
+
UIDevice
.
bs_safeDistanceBottom
()
}
// MARK: - 版本号
static
func
appVersion
()
->
String
{
let
infoDictionary
=
Bundle
.
main
.
infoDictionary
if
let
infoDictionary
=
infoDictionary
{
let
appVersion
=
infoDictionary
[
"CFBundleShortVersionString"
]
return
appVersion
as!
String
}
return
" "
}
// MARK: - 内部编译版本号
static
func
appBuild
()
->
String
{
let
infoDictionary
=
Bundle
.
main
.
infoDictionary
if
let
infoDictionary
=
infoDictionary
{
let
appBuild
=
infoDictionary
[
"CFBundleVersion"
]
return
appBuild
as!
String
}
return
" "
}
}
galaxy/galaxy/Classes/Tools/Extention/UIFont-Extension.swift
0 → 100755
View file @
0b841956
//
// UIFont-Extension.swift
// BaiSiSMApp
//
// Created by davidhuang on 2022/10/16.
// Copyright © 2022 www.davidhuang.com. All rights reserved.
//
import
UIKit
extension
UIFont
{
// MARK: - 苹果字体
static
func
PFSCR
(
ofSize
size
:
CGFloat
=
15
)
->
UIFont
{
return
UIFont
(
name
:
"PingFangSC-Regular"
,
size
:
size
)
!
}
static
func
PFSCM
(
ofSize
size
:
CGFloat
=
15
)
->
UIFont
{
return
UIFont
(
name
:
"PingFangSC-Medium"
,
size
:
size
)
!
}
// static func PFSCB(ofSize size : CGFloat = 15) -> UIFont {
// return UIFont(name: "PingFangSC-Bold", size: size)!
// }
}
galaxy/galaxy/Classes/Tools/Extention/UIImage-Extension.swift
0 → 100755
View file @
0b841956
//
// UIImage-Extension.swift
// BaiSiSMApp
//
// Created by davidhuang on 2022/11/3.
// Copyright © 2022 www.davidhuang.com. All rights reserved.
//
import
UIKit
extension
UIImage
{
static
func
defaultHeadImage
()
->
UIImage
?
{
return
UIImage
(
named
:
"default-head-image"
)
}
static
func
from
(
color
:
UIColor
,
rect
:
CGRect
=
CGRect
(
origin
:
CGPoint
.
zero
,
size
:
CGSize
(
width
:
4
,
height
:
4
)))
->
UIImage
{
UIGraphicsBeginImageContext
(
rect
.
size
)
let
context
=
UIGraphicsGetCurrentContext
()
context
!.
setFillColor
(
color
.
cgColor
)
context
!.
fill
(
rect
)
let
img
=
UIGraphicsGetImageFromCurrentImageContext
()
UIGraphicsEndImageContext
()
return
img
!
}
// 修复图片旋转
func
fixOrientation
()
->
UIImage
{
if
self
.
imageOrientation
==
.
up
{
return
self
}
var
transform
=
CGAffineTransform
.
identity
switch
self
.
imageOrientation
{
case
.
down
,
.
downMirrored
:
transform
=
transform
.
translatedBy
(
x
:
self
.
size
.
width
,
y
:
self
.
size
.
height
)
transform
=
transform
.
rotated
(
by
:
.
pi
)
break
case
.
left
,
.
leftMirrored
:
transform
=
transform
.
translatedBy
(
x
:
self
.
size
.
width
,
y
:
0
)
transform
=
transform
.
rotated
(
by
:
.
pi
/
2
)
break
case
.
right
,
.
rightMirrored
:
transform
=
transform
.
translatedBy
(
x
:
0
,
y
:
self
.
size
.
height
)
transform
=
transform
.
rotated
(
by
:
-.
pi
/
2
)
break
default
:
break
}
switch
self
.
imageOrientation
{
case
.
upMirrored
,
.
downMirrored
:
transform
=
transform
.
translatedBy
(
x
:
self
.
size
.
width
,
y
:
0
)
transform
=
transform
.
scaledBy
(
x
:
-
1
,
y
:
1
)
break
case
.
leftMirrored
,
.
rightMirrored
:
transform
=
transform
.
translatedBy
(
x
:
self
.
size
.
height
,
y
:
0
);
transform
=
transform
.
scaledBy
(
x
:
-
1
,
y
:
1
)
break
default
:
break
}
let
ctx
=
CGContext
(
data
:
nil
,
width
:
Int
(
self
.
size
.
width
),
height
:
Int
(
self
.
size
.
height
),
bitsPerComponent
:
self
.
cgImage
!.
bitsPerComponent
,
bytesPerRow
:
0
,
space
:
self
.
cgImage
!.
colorSpace
!
,
bitmapInfo
:
self
.
cgImage
!.
bitmapInfo
.
rawValue
)
ctx
?
.
concatenate
(
transform
)
switch
self
.
imageOrientation
{
case
.
left
,
.
leftMirrored
,
.
right
,
.
rightMirrored
:
ctx
?
.
draw
(
self
.
cgImage
!
,
in
:
CGRect
(
x
:
CGFloat
(
0
),
y
:
CGFloat
(
0
),
width
:
CGFloat
(
size
.
height
),
height
:
CGFloat
(
size
.
width
)))
break
default
:
ctx
?
.
draw
(
self
.
cgImage
!
,
in
:
CGRect
(
x
:
CGFloat
(
0
),
y
:
CGFloat
(
0
),
width
:
CGFloat
(
size
.
width
),
height
:
CGFloat
(
size
.
height
)))
break
}
let
cgimg
:
CGImage
=
(
ctx
?
.
makeImage
())
!
let
img
=
UIImage
(
cgImage
:
cgimg
)
return
img
}
}
// MARK: - 图片大小编辑
extension
UIImage
{
//等比例放大(图片居中,增加边缘透明范围)
func
bs_scaled
(
toHeight
:
CGFloat
,
opaque
:
Bool
=
false
)
->
UIImage
?
{
let
scale
=
toHeight
/
size
.
height
let
newWidth
=
size
.
width
*
scale
UIGraphicsBeginImageContextWithOptions
(
CGSize
(
width
:
newWidth
,
height
:
toHeight
),
opaque
,
self
.
scale
)
draw
(
in
:
CGRect
(
x
:
(
newWidth
-
size
.
width
)
/
2
,
y
:
(
toHeight
-
size
.
height
)
/
2
,
width
:
size
.
width
,
height
:
size
.
height
))
let
newImage
=
UIGraphicsGetImageFromCurrentImageContext
()
UIGraphicsEndImageContext
()
return
newImage
}
func
withBackground
(
color
:
UIColor
,
opaque
:
Bool
=
true
)
->
UIImage
{
UIGraphicsBeginImageContextWithOptions
(
size
,
opaque
,
scale
)
guard
let
ctx
=
UIGraphicsGetCurrentContext
(),
let
image
=
cgImage
else
{
return
self
}
defer
{
UIGraphicsEndImageContext
()
}
let
rect
=
CGRect
(
origin
:
.
zero
,
size
:
size
)
ctx
.
setFillColor
(
color
.
cgColor
)
ctx
.
fill
(
rect
)
ctx
.
concatenate
(
CGAffineTransform
(
a
:
1
,
b
:
0
,
c
:
0
,
d
:
-
1
,
tx
:
0
,
ty
:
size
.
height
))
ctx
.
draw
(
image
,
in
:
rect
)
return
UIGraphicsGetImageFromCurrentImageContext
()
??
self
}
//等比例放大(图片居中,增加边缘透明范围)
func
bs_scaled
(
toWidth
:
CGFloat
,
opaque
:
Bool
=
false
)
->
UIImage
?
{
let
scale
=
toWidth
/
size
.
width
let
newHeight
=
size
.
height
*
scale
UIGraphicsBeginImageContextWithOptions
(
CGSize
(
width
:
toWidth
,
height
:
newHeight
),
opaque
,
self
.
scale
)
draw
(
in
:
CGRect
(
x
:
(
toWidth
-
size
.
width
)
/
2
,
y
:
(
newHeight
-
size
.
height
)
/
2
,
width
:
size
.
width
,
height
:
size
.
height
))
let
newImage
=
UIGraphicsGetImageFromCurrentImageContext
()
UIGraphicsEndImageContext
()
return
newImage
}
/// 放大画布大小(图片自定义,增加边缘透明范围)
/// - Parameters:
/// - toSize: 需要的画布大小
/// - rect: 图片在画布的位置
/// - opaque: 不透明/黑色背景
/// - Returns: 图片
func
bs_canvas
(
toSize
:
CGSize
,
rect
:
CGRect
,
opaque
:
Bool
=
false
)
->
UIImage
?
{
UIGraphicsBeginImageContextWithOptions
(
CGSize
(
width
:
toSize
.
width
,
height
:
toSize
.
height
),
opaque
,
self
.
scale
)
draw
(
in
:
rect
)
let
newImage
=
UIGraphicsGetImageFromCurrentImageContext
()
UIGraphicsEndImageContext
()
return
newImage
}
}
galaxy/galaxy/Classes/Tools/Extention/UILable-Extension.swift
0 → 100755
View file @
0b841956
//
// UILable-Extension.swift
// BaiSiSMApp
//
// Created by davidhuang on 2022/11/16.
// Copyright © 2022 www.davidhuang.com. All rights reserved.
//
import
UIKit
extension
UILabel
{
public
class
func
createBsTagLabel
()
->
UILabel
{
let
temp
=
UILabel
()
temp
.
textColor
=
UIColor
(
hexString
:
"#333333"
,
transparency
:
0.45
)
temp
.
textAlignment
=
.
center
temp
.
font
=
UIFont
.
PFSCM
(
ofSize
:
10
)
temp
.
backgroundColor
=
UIColor
(
hexString
:
"#333333"
,
transparency
:
0.04
)
temp
.
layer
.
cornerRadius
=
2
temp
.
clipsToBounds
=
true
return
temp
}
public
class
func
label
(
text
:
String
,
font
:
UIFont
,
color
:
UIColor
,
numberOfLines
:
Int
=
0
,
alignment
:
NSTextAlignment
=
.
left
)
->
UILabel
{
let
label
=
UILabel
()
label
.
text
=
text
label
.
font
=
font
label
.
textColor
=
color
label
.
numberOfLines
=
numberOfLines
label
.
textAlignment
=
alignment
return
label
}
convenience
init
(
text
:
String
,
font
:
UIFont
,
color
:
UIColor
,
numberOfLines
:
Int
=
0
,
alignment
:
NSTextAlignment
=
.
left
)
{
self
.
init
()
self
.
text
=
text
self
.
font
=
font
self
.
textColor
=
color
self
.
numberOfLines
=
numberOfLines
self
.
textAlignment
=
alignment
}
var
requiredWidth
:
CGFloat
{
let
label
=
UILabel
(
frame
:
CGRect
(
x
:
0
,
y
:
0
,
width
:
CGFloat
.
greatestFiniteMagnitude
,
height
:
frame
.
height
))
label
.
numberOfLines
=
0
label
.
lineBreakMode
=
NSLineBreakMode
.
byWordWrapping
label
.
font
=
font
label
.
text
=
text
label
.
attributedText
=
attributedText
label
.
sizeToFit
()
return
label
.
frame
.
width
}
}
galaxy/galaxy/Classes/Tools/Extention/UIView-Extension.swift
0 → 100755
View file @
0b841956
//
// UIView-Extension.swift
// BaiSiSMApp
//
// Created by davidhuang on 2022/10/16.
// Copyright © 2022 www.davidhuang.com. All rights reserved.
//
import
UIKit
extension
UIView
{
// MARK: - 旋转
func
rotate
(
begin
:
Bool
=
true
)
{
if
begin
==
true
{
let
rotation
:
CABasicAnimation
=
CABasicAnimation
(
keyPath
:
"transform.rotation.z"
)
rotation
.
toValue
=
NSNumber
(
value
:
Double
.
pi
*
2
)
rotation
.
duration
=
3
rotation
.
isCumulative
=
true
rotation
.
repeatCount
=
Float
.
greatestFiniteMagnitude
rotation
.
fillMode
=
CAMediaTimingFillMode
(
rawValue
:
"forwards"
)
layer
.
add
(
rotation
,
forKey
:
"rotationAnimation"
)
}
else
{
layer
.
removeAllAnimations
()
}
}
// MARK: - 获取当前UIview 所在的 UIViewController
func
getFirstViewController
()
->
UIViewController
?{
for
view
in
sequence
(
first
:
self
.
superview
,
next
:
{
$0
?
.
superview
}){
if
let
responder
=
view
?
.
next
{
if
responder
.
isKind
(
of
:
UIViewController
.
self
){
return
responder
as?
UIViewController
}
}
}
return
nil
}
// MARK: - UIView 晃动效果
public
func
shake2
(
direction
:
ShakeDirection
=
.
horizontal
,
times
:
Int
=
5
,
interval
:
TimeInterval
=
0.1
,
delta
:
CGFloat
=
5
,
completion
:(()
->
Void
)?
=
nil
){
if
times
==
0
{
self
.
layer
.
setAffineTransform
(
CGAffineTransform
.
identity
)
}
else
{
UIView
.
animate
(
withDuration
:
interval
)
{
switch
direction
{
case
.
horizontal
:
self
.
layer
.
setAffineTransform
(
CGAffineTransform
(
translationX
:
delta
,
y
:
0
))
break
case
.
vertical
:
self
.
layer
.
setAffineTransform
(
CGAffineTransform
(
translationX
:
0
,
y
:
delta
))
break
}
}
completion
:
{
(
finished
)
in
self
.
shake2
(
direction
:
direction
,
times
:
times
-
1
,
interval
:
interval
,
delta
:
delta
*
-
1
,
completion
:
completion
)
}
}
}
}
// MARK: - 阴影设置
extension
UIView
{
@objc
public
enum
ShadowType
:
Int
{
case
all
=
0
///四周
case
top
=
1
///上方
case
left
=
2
///左边
case
right
=
3
///右边
case
bottom
=
4
///下方
}
///默认设置:黑色阴影, 阴影所占视图的比例
// func shadow(_ type: ShadowType, percent: Float) {
// shadow(type: type, color: .black, opactiy: 0.4, //shadowSize: 4)
//}
///默认设置:黑色阴影
@objc
func
shadow
(
_
type
:
ShadowType
)
{
shadow
(
type
:
type
,
color
:
.
black
,
opactiy
:
0.1
,
shadowSize
:
4
)
}
///阴影设置
@objc
public
func
shadow
(
type
:
ShadowType
,
color
:
UIColor
,
opactiy
:
Float
,
shadowSize
:
CGFloat
)
->
Void
{
layer
.
masksToBounds
=
false
;
//必须要等于NO否则会把阴影切割隐藏掉
layer
.
shadowColor
=
color
.
cgColor
;
// 阴影颜色
layer
.
shadowOpacity
=
opactiy
;
// 阴影透明度,默认0
layer
.
shadowOffset
=
.
zero
;
//shadowOffset阴影偏移,默认(0, -3),这个跟shadowRadius配合使用
layer
.
shadowRadius
=
3
//阴影半径,默认3
var
shadowRect
:
CGRect
?
switch
type
{
case
.
all
:
shadowRect
=
CGRect
.
init
(
x
:
-
shadowSize
,
y
:
-
shadowSize
,
width
:
bounds
.
size
.
width
+
2
*
shadowSize
,
height
:
bounds
.
size
.
height
+
2
*
shadowSize
)
case
.
top
:
shadowRect
=
CGRect
.
init
(
x
:
-
shadowSize
,
y
:
-
shadowSize
,
width
:
bounds
.
size
.
width
+
2
*
shadowSize
,
height
:
2
*
shadowSize
)
case
.
bottom
:
shadowRect
=
CGRect
.
init
(
x
:
-
shadowSize
,
y
:
bounds
.
size
.
height
-
shadowSize
,
width
:
bounds
.
size
.
width
+
2
*
shadowSize
,
height
:
2
*
shadowSize
)
case
.
left
:
shadowRect
=
CGRect
.
init
(
x
:
-
shadowSize
,
y
:
-
shadowSize
,
width
:
2
*
shadowSize
,
height
:
bounds
.
size
.
height
+
2
*
shadowSize
)
case
.
right
:
shadowRect
=
CGRect
.
init
(
x
:
bounds
.
size
.
width
-
shadowSize
,
y
:
-
shadowSize
,
width
:
2
*
shadowSize
,
height
:
bounds
.
size
.
height
+
2
*
shadowSize
)
}
layer
.
shadowPath
=
UIBezierPath
.
init
(
rect
:
shadowRect
!
)
.
cgPath
}
///阴影 0.5
@objc
public
func
bs_shadow
(
color
:
UIColor
=
UIColor
(
red
:
0.87
,
green
:
0.87
,
blue
:
0.87
,
alpha
:
0.7
),
offset
:
CGSize
=
CGSize
(
width
:
0
,
height
:
1.5
),
opacity
:
Float
=
1
,
radius
:
CGFloat
=
3.5
)
{
self
.
layer
.
shadowColor
=
color
.
cgColor
self
.
layer
.
shadowOffset
=
offset
self
.
layer
.
shadowOpacity
=
opacity
self
.
layer
.
shadowRadius
=
radius
}
///内阴影
@objc
public
func
bs_innerShadow
()
{
self
.
layer
.
shadowColor
=
UIColor
(
red
:
0.87
,
green
:
0.87
,
blue
:
0.87
,
alpha
:
0.5
)
.
cgColor
self
.
layer
.
shadowOffset
=
CGSize
(
width
:
0
,
height
:
0
)
self
.
layer
.
shadowOpacity
=
1
self
.
layer
.
shadowRadius
=
3
}
}
// MARK: - 圆角设置
extension
UIView
{
public
func
setCorners
(
corners
:
UIRectCorner
,
radius
:
CGFloat
)
->
Void
{
self
.
setCorners
(
corners
:
corners
,
radius
:
radius
,
rect
:
self
.
bounds
)
}
public
func
setCorners
(
corners
:
UIRectCorner
,
radius
:
CGFloat
,
rect
:
CGRect
)
->
Void
{
let
path
=
UIBezierPath
.
init
(
roundedRect
:
rect
,
byRoundingCorners
:
corners
,
cornerRadii
:
CGSize
.
init
(
width
:
radius
,
height
:
radius
))
let
layer
=
CAShapeLayer
.
init
()
layer
.
frame
=
self
.
bounds
layer
.
path
=
path
.
cgPath
self
.
layer
.
mask
=
layer
}
///渐变颜色(frame需要有值)
@objc
public
func
bs_gradient
(
_
type
:
ShadowType
=
.
left
,
colors
:
[
UIColor
],
locations
:
[
NSNumber
]?
=
nil
)
{
let
gradientLayer
=
CAGradientLayer
()
gradientLayer
.
frame
=
self
.
bounds
//设置颜色
var
cgColors
:
[
CGColor
]
=
[]
for
color
in
colors
{
cgColors
.
append
(
color
.
cgColor
)
}
gradientLayer
.
colors
=
cgColors
//设置占比
if
locations
==
nil
{
let
num
=
1.0
/
(
Double
(
colors
.
count
)
-
1.0
)
var
locations
:
[
NSNumber
]
=
[]
for
i
in
0
..<
colors
.
count
{
locations
.
append
(
NSNumber
(
value
:
num
*
Double
(
i
)))
}
gradientLayer
.
locations
=
locations
}
else
{
gradientLayer
.
locations
=
locations
}
//设置位置
switch
type
{
case
.
all
:
gradientLayer
.
startPoint
=
CGPoint
(
x
:
0.5
,
y
:
0.5
)
gradientLayer
.
endPoint
=
CGPoint
(
x
:
0.5
,
y
:
0.5
)
case
.
top
:
gradientLayer
.
startPoint
=
CGPoint
(
x
:
0.5
,
y
:
0
)
gradientLayer
.
endPoint
=
CGPoint
(
x
:
0.5
,
y
:
1
)
break
case
.
left
:
gradientLayer
.
startPoint
=
CGPoint
(
x
:
0
,
y
:
0.5
)
gradientLayer
.
endPoint
=
CGPoint
(
x
:
1
,
y
:
0.5
)
break
case
.
right
:
gradientLayer
.
startPoint
=
CGPoint
(
x
:
1
,
y
:
0.5
)
gradientLayer
.
endPoint
=
CGPoint
(
x
:
0
,
y
:
0.5
)
break
case
.
bottom
:
gradientLayer
.
startPoint
=
CGPoint
(
x
:
0.5
,
y
:
1
)
gradientLayer
.
endPoint
=
CGPoint
(
x
:
0.5
,
y
:
0
)
break
}
self
.
layer
.
addSublayer
(
gradientLayer
)
}
/// 绘制虚线
/// - Parameters:
/// - lineLength: 长度
/// - lineSpacing: 间隔长度
/// - lineColor: 颜色
public
func
bs_drawDashLine
(
lineLength
:
Int
,
lineSpacing
:
Int
,
lineColor
:
UIColor
)
{
let
shapeLayer
=
CAShapeLayer
()
shapeLayer
.
bounds
=
self
.
bounds
shapeLayer
.
anchorPoint
=
CGPoint
(
x
:
0
,
y
:
0
)
shapeLayer
.
strokeColor
=
lineColor
.
cgColor
shapeLayer
.
lineWidth
=
1
//描边路径时使用的线宽。默认为1。
shapeLayer
.
lineJoin
=
CAShapeLayerLineJoin
.
round
shapeLayer
.
lineDashPattern
=
[
NSNumber
(
value
:
lineLength
),
NSNumber
(
value
:
lineSpacing
)]
let
path
=
CGMutablePath
()
path
.
move
(
to
:
CGPoint
(
x
:
0
,
y
:
0
))
path
.
addLine
(
to
:
CGPoint
(
x
:
self
.
bounds
.
size
.
width
,
y
:
0
))
shapeLayer
.
path
=
path
self
.
layer
.
addSublayer
(
shapeLayer
)
}
}
// MARK: - Frame
extension
UIView
{
//let cOrigin: CGPoint //!< 位置
//let cSize: CGSize //!< 大小
open
var
height
:
CGFloat
{
get
{
return
self
.
frame
.
height
}
set
{
var
frame
=
self
.
frame
frame
.
size
.
height
=
newValue
self
.
frame
=
frame
}
}
//!< 高度
open
var
width
:
CGFloat
{
get
{
return
self
.
frame
.
width
}
set
{
var
frame
=
self
.
frame
frame
.
size
.
width
=
newValue
self
.
frame
=
frame
}
}
//!< 宽度
open
var
top
:
CGFloat
{
get
{
return
self
.
frame
.
minY
}
set
{
var
frame
=
self
.
frame
frame
.
origin
.
y
=
newValue
self
.
frame
=
frame
}
}
//!< 上
open
var
left
:
CGFloat
{
get
{
return
self
.
frame
.
minX
}
set
{
var
frame
=
self
.
frame
frame
.
origin
.
x
=
newValue
self
.
frame
=
frame
}
}
//!< 左
open
var
bottom
:
CGFloat
{
get
{
return
self
.
frame
.
maxY
}
set
{
var
frame
=
self
.
frame
frame
.
origin
.
y
=
newValue
-
self
.
frame
.
height
self
.
frame
=
frame
}
}
//!< 下
open
var
right
:
CGFloat
{
get
{
return
self
.
frame
.
maxX
}
set
{
var
frame
=
self
.
frame
;
frame
.
origin
.
x
=
newValue
-
self
.
frame
.
width
self
.
frame
=
frame
}
}
//!< 右
}
galaxy/galaxy/Classes/Tools/Extention/UIViewController+Navigation.swift
0 → 100755
View file @
0b841956
//
// UIViewController+GDNavigation.swift
// GDKit
//
// Created by SJ on 2022/1/15.
//
import
UIKit
// MARK: - 获取当前控制器
extension
UIViewController
{
// 获取当前正呈现的UIViewController
static
var
current
:
UIViewController
?
{
let
delegate
=
UIApplication
.
shared
.
delegate
as?
AppDelegate
var
current
=
delegate
?
.
window
?
.
rootViewController
while
(
current
?
.
presentedViewController
!=
nil
)
{
current
=
current
?
.
presentedViewController
}
if
let
tabbar
=
current
as?
UITabBarController
,
tabbar
.
selectedViewController
!=
nil
{
current
=
tabbar
.
selectedViewController
}
while
let
navi
=
current
as?
UINavigationController
,
navi
.
topViewController
!=
nil
{
current
=
navi
.
topViewController
}
return
current
}
//获取UINavigationController的topViewController
static
var
navTopViewController
:
UIViewController
?
{
let
delegate
=
UIApplication
.
shared
.
delegate
as?
AppDelegate
var
current
=
delegate
?
.
window
?
.
rootViewController
if
let
tabbar
=
current
as?
UITabBarController
,
tabbar
.
selectedViewController
!=
nil
{
current
=
tabbar
.
selectedViewController
}
while
let
navi
=
current
as?
UINavigationController
,
navi
.
topViewController
!=
nil
{
current
=
navi
.
topViewController
}
return
current
}
class
func
classFromString
(
_
className
:
String
)
->
UIViewController
?
{
//1、获swift中的命名空间名
var
name
=
Bundle
.
main
.
object
(
forInfoDictionaryKey
:
"CFBundleExecutable"
)
as?
String
//2、如果包名中有'-'横线这样的字符,在拿到包名后,还需要把包名的'-'转换成'_'下横线
name
=
name
?
.
replacingOccurrences
(
of
:
"-"
,
with
:
"_"
)
//3、拼接命名空间和类名,”包名.类名“
let
fullClassName
=
name
!
+
"."
+
className
//通过NSClassFromString获取到最终的类,由于NSClassFromString返回的是AnyClass,这里要转换成UIViewController.Type类型
guard
let
classType
=
NSClassFromString
(
fullClassName
)
as?
UIViewController
.
Type
else
{
//fatalError("转换失败")
return
nil
}
return
classType
.
init
()
}
func
bs_popToRootViewController
(
animated
:
Bool
)
{
let
vcs
=
self
.
navigationController
?
.
popToRootViewController
(
animated
:
true
)
if
vcs
!=
nil
{
self
.
tabBarController
?
.
tabBar
.
isHidden
=
false
}
}
}
// MARK: - 创建RightBarButtonItem
extension
UIViewController
{
public
func
bs_setupRightButton
(
title
:
String
?
=
nil
,
color
:
UIColor
?
=
nil
,
image
:
UIImage
?
=
nil
,
font
:
UIFont
?
=
nil
,
imageColor
:
UIColor
?
=
nil
,
reset
:
Bool
=
false
)
{
var
button
:
UIButton
?
if
let
rightBarButtonItems
=
self
.
navigationItem
.
rightBarButtonItems
,
rightBarButtonItems
.
count
>
0
,
reset
==
false
{
for
view
in
rightBarButtonItems
{
if
let
rightButton
=
view
.
customView
as?
UIButton
{
button
=
rightButton
}
}
}
else
{
let
rightButton
=
UIButton
(
type
:
.
custom
)
rightButton
.
frame
=
CGRect
(
x
:
0
,
y
:
0
,
width
:
70
,
height
:
44
)
rightButton
.
addTarget
(
self
,
action
:
#selector(
clickedNavRight
)
,
for
:
.
touchUpInside
)
rightButton
.
contentHorizontalAlignment
=
.
right
let
rightItem
=
UIBarButtonItem
(
customView
:
rightButton
)
let
negativeSeperator
=
UIBarButtonItem
(
barButtonSystemItem
:
.
fixedSpace
,
target
:
nil
,
action
:
nil
)
negativeSeperator
.
width
=
-
0
self
.
navigationItem
.
rightBarButtonItems
=
[
negativeSeperator
,
rightItem
]
button
=
rightButton
}
if
font
==
nil
{
button
?
.
titleLabel
?
.
font
=
UIFont
.
PFSCM
(
ofSize
:
16
)
}
else
{
button
?
.
titleLabel
?
.
font
=
font
}
if
var
image
=
image
{
if
let
imageColor
=
imageColor
{
image
=
image
.
withRenderingMode
(
.
alwaysTemplate
)
button
?
.
tintColor
=
imageColor
}
else
{
image
=
image
.
withRenderingMode
(
.
alwaysOriginal
)
}
button
?
.
setImage
(
image
,
for
:
.
normal
)
button
?
.
setImage
(
image
,
for
:
.
highlighted
)
}
button
?
.
setTitle
(
title
,
for
:
.
normal
)
button
?
.
setTitleColor
(
color
,
for
:
.
normal
)
}
@objc
func
clickedNavRight
()
{
}
}
// MARK: - 配置导航栏
extension
UIViewController
{
public
func
bs_config
()
{
self
.
navigationController
?
.
navigationBar
.
isTranslucent
=
false
self
.
navigationController
?
.
setNavigationBarHidden
(
false
,
animated
:
true
)
self
.
bs_setupNavigationAttributed
(
.
white
)
self
.
bs_setupTitleAttributedAll
()
self
.
bs_setupLeftButton
()
self
.
bs_openPopGesture
()
}
///设置导航条属性
func
bs_setupNavigationAttributed
(
_
color
:
UIColor
=
UIColor
.
white
)
{
//设置状态栏
//UIApplication.shared.statusBarStyle = .default
//self.preferredStatusBarStyle = .default
self
.
navigationController
?
.
navigationBar
.
barTintColor
=
color
self
.
navigationController
?
.
navigationBar
.
setBackgroundImage
(
UIImage
.
from
(
color
:
color
),
for
:
.
default
)
self
.
navigationController
?
.
navigationBar
.
shadowImage
=
UIImage
()
//隐藏下划线
}
///设置全局标题属性
func
bs_setupTitleAttributedAll
(
font
:
UIFont
=
UIFont
.
PFSCM
(
ofSize
:
16
),
color
:
UIColor
=
.
black
)
{
let
titleDict
=
[
NSAttributedString
.
Key
.
font
:
font
,
NSAttributedString
.
Key
.
foregroundColor
:
color
]
self
.
navigationController
?
.
navigationBar
.
titleTextAttributes
=
titleDict
}
///设置独立标题属性
func
bs_setupTitleAttributed
(
title
:
String
,
font
:
UIFont
=
UIFont
.
PFSCM
(
ofSize
:
16
),
color
:
UIColor
=
.
black
,
reset
:
Bool
=
false
)
{
var
titleLabel
:
UILabel
?
if
let
label
=
self
.
navigationItem
.
titleView
as?
UILabel
,
reset
==
false
{
titleLabel
=
label
}
else
{
let
label
=
UILabel
()
titleLabel
=
label
}
titleLabel
?
.
font
=
font
titleLabel
?
.
textColor
=
color
titleLabel
?
.
text
=
title
self
.
navigationItem
.
titleView
=
titleLabel
}
///返回按钮
func
bs_setupLeftButton
(
title
:
String
?
=
nil
,
color
:
UIColor
?
=
nil
,
image
:
UIImage
?
=
UIImage
(
named
:
"back_icon"
),
reset
:
Bool
=
false
)
{
var
button
:
UIButton
?
if
let
leftBarButtonItems
=
self
.
navigationItem
.
leftBarButtonItems
,
leftBarButtonItems
.
count
>
0
,
reset
==
false
{
for
view
in
leftBarButtonItems
{
if
let
leftButton
=
view
.
customView
as?
UIButton
{
button
=
leftButton
}
}
}
else
{
let
leftButton
=
UIButton
(
type
:
.
custom
)
leftButton
.
frame
=
CGRect
(
x
:
0
,
y
:
0
,
width
:
44
,
height
:
44
)
leftButton
.
addTarget
(
self
,
action
:
#selector(
callBackAction
)
,
for
:
.
touchUpInside
)
leftButton
.
contentHorizontalAlignment
=
.
left
leftButton
.
contentEdgeInsets
=
UIEdgeInsets
(
top
:
0
,
left
:
-
4
,
bottom
:
0
,
right
:
0
)
let
leftItem
=
UIBarButtonItem
(
customView
:
leftButton
)
let
negativeSeperator
=
UIBarButtonItem
(
barButtonSystemItem
:
.
fixedSpace
,
target
:
nil
,
action
:
nil
)
negativeSeperator
.
width
=
-
0
self
.
navigationItem
.
leftBarButtonItems
=
[
negativeSeperator
,
leftItem
]
button
=
leftButton
}
var
image
=
image
if
color
!=
nil
{
image
=
image
?
.
withRenderingMode
(
.
alwaysTemplate
)
}
else
{
image
=
image
?
.
withRenderingMode
(
.
alwaysOriginal
)
}
button
?
.
setImage
(
image
,
for
:
.
normal
)
button
?
.
setImage
(
image
,
for
:
.
highlighted
)
button
?
.
titleLabel
?
.
font
=
UIFont
.
PFSCM
(
ofSize
:
16
)
button
?
.
setTitle
(
title
,
for
:
.
normal
)
button
?
.
setTitleColor
(
color
,
for
:
.
normal
)
button
?
.
tintColor
=
color
}
///返回按钮响应
@objc
func
callBackAction
()
{
let
selector
=
NSSelectorFromString
(
"onCallBackAction"
)
if
self
.
responds
(
to
:
selector
)
==
true
{
self
.
performSelector
(
onMainThread
:
selector
,
with
:
nil
,
waitUntilDone
:
false
)
}
else
{
self
.
navigationController
?
.
popViewController
(
animated
:
true
)
}
}
/**
打开系统手势返回
*/
@objc
func
bs_openPopGesture
()
{
self
.
navigationController
?
.
interactivePopGestureRecognizer
?
.
isEnabled
=
true
}
/**
关闭系统手势返回
*/
@objc
func
bs_closePopGesture
()
{
self
.
navigationController
?
.
interactivePopGestureRecognizer
?
.
isEnabled
=
false
}
///修改导航栏背景色(全局)
public
func
bs_navBackgroundColor
(
_
color
:
UIColor
)
{
self
.
navigationController
?
.
view
.
backgroundColor
=
color
//解决iOS13后backgroundColor设置无效的问题,参考https://developer.apple.com/forums/thread/682420
if
#available(iOS 13.0, *)
{
let
newAppearance
=
UINavigationBarAppearance
()
newAppearance
.
configureWithOpaqueBackground
()
newAppearance
.
backgroundColor
=
color
newAppearance
.
shadowImage
=
UIImage
()
newAppearance
.
shadowColor
=
nil
//newAppearance.titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.red, NSAttributedString.Key.font: UIFont.systemFont(ofSize: 20, weight: .medium)]
let
appearance
=
self
.
navigationController
?
.
navigationBar
??
UINavigationBar
.
appearance
()
appearance
.
standardAppearance
=
newAppearance
appearance
.
scrollEdgeAppearance
=
appearance
.
standardAppearance
}
else
{
bs_setupNavigationAttributed
(
color
)
}
}
}
galaxy/galaxy/Classes/Tools/Helper/BSJsonUtil.swift
0 → 100755
View file @
0b841956
//
// BSjsonUtil.swift
// BaiSiSMApp
//
// Created by davidhuang on 2022/11/18.
// Copyright © 2022 www.davidhuang.com. All rights reserved.
//
import
UIKit
import
HandyJSON
class
BSJsonUtil
:
NSObject
{
/**
* Json转对象
*/
static
func
jsonToModel
(
_
jsonStr
:
String
,
_
modelType
:
HandyJSON
.
Type
)
->
BsBaseModel
{
if
jsonStr
==
""
||
jsonStr
.
count
==
0
{
#if DEBUG
print
(
"jsonoModel:字符串为空"
)
#endif
return
BsBaseModel
()
}
return
modelType
.
deserialize
(
from
:
jsonStr
)
as!
BsBaseModel
}
/**
* Json转数组对象
*/
static
func
jsonArrayToModel
(
_
jsonArrayStr
:
String
,
_
modelType
:
HandyJSON
.
Type
)
->
[
BsBaseModel
]
{
if
jsonArrayStr
==
""
||
jsonArrayStr
.
count
==
0
{
#if DEBUG
print
(
"jsonToModelArray:字符串为空"
)
#endif
return
[]
}
var
modelArray
:[
BsBaseModel
]
=
[]
let
data
=
jsonArrayStr
.
data
(
using
:
String
.
Encoding
.
utf8
)
let
peoplesArray
=
try!
JSONSerialization
.
jsonObject
(
with
:
data
!
,
options
:
JSONSerialization
.
ReadingOptions
())
as?
[
AnyObject
]
for
people
in
peoplesArray
!
{
modelArray
.
append
(
dictionaryToModel
(
people
as!
[
String
:
Any
],
modelType
))
}
return
modelArray
}
/**
* 字典转对象
*/
static
func
dictionaryToModel
(
_
dictionStr
:[
String
:
Any
],
_
modelType
:
HandyJSON
.
Type
)
->
BsBaseModel
{
if
dictionStr
.
count
==
0
{
#if DEBUG
print
(
"dictionaryToModel:字符串为空"
)
#endif
return
BsBaseModel
()
}
return
modelType
.
deserialize
(
from
:
dictionStr
)
as!
BsBaseModel
}
/**
* 对象转JSON
*/
static
func
modelToJson
(
_
model
:
BsBaseModel
?)
->
String
{
if
model
==
nil
{
#if DEBUG
print
(
"modelToJson:model为空"
)
#endif
return
""
}
return
(
model
?
.
toJSONString
())
!
}
/**
* 对象转字典
*/
static
func
modelToDictionary
(
_
model
:
BsBaseModel
?)
->
[
String
:
Any
]
{
if
model
==
nil
{
#if DEBUG
print
(
"modelToJson:model为空"
)
#endif
return
[:]
}
return
(
model
?
.
toJSON
())
!
}
//数组转json
static
func
arrayToJson
(
_
array
:
NSArray
)
->
String
{
if
(
!
JSONSerialization
.
isValidJSONObject
(
array
))
{
print
(
"无法解析出JSONString"
)
return
""
}
let
data
:
NSData
!
=
try
?
JSONSerialization
.
data
(
withJSONObject
:
array
,
options
:
[])
as
NSData
let
JSONString
=
NSString
(
data
:
data
as
Data
,
encoding
:
String
.
Encoding
.
utf8
.
rawValue
)
return
JSONString
!
as
String
}
/**
* 字典转JSON
*/
static
func
dictionaryToJson
(
_
dictionary
:
NSDictionary
)
->
String
{
if
(
!
JSONSerialization
.
isValidJSONObject
(
dictionary
))
{
print
(
"无法解析出JSONString"
)
return
""
}
let
data
:
NSData
!
=
try
?
JSONSerialization
.
data
(
withJSONObject
:
dictionary
,
options
:
[])
as
NSData
let
JSONString
=
NSString
(
data
:
data
as
Data
,
encoding
:
String
.
Encoding
.
utf8
.
rawValue
)
return
JSONString
!
as
String
}
}
galaxy/galaxy/Classes/Tools/Helper/BsConstant.swift
0 → 100755
View file @
0b841956
//
// BsConstant.swift
// BaiSiSMApp
//
// Created by davidhuang on 2022/10/19.
// Copyright © 2022 www.davidhuang.com. All rights reserved.
//
import
UIKit
// MARK: - 工程中的 常量定义
class
BsConstant
{
// MARK: - 个人信息基本类型
enum
UserBaseInfoType
:
Int
{
case
unknow
//未知
case
sex
//性别
case
birthday
//生日
case
height
//身高
case
weight
//体重
case
education
//学历
case
profession
//职务
case
work_domain
//从事行业
case
income
//收入
func
title
()
->
String
{
switch
self
{
case
.
sex
:
return
"性别"
case
.
birthday
:
return
"生日"
case
.
height
:
return
"身高"
case
.
weight
:
return
"体重"
case
.
education
:
return
"学历"
case
.
profession
:
return
"职务"
case
.
work_domain
:
return
"从事行业"
case
.
income
:
return
"收入"
default
:
return
"--"
}
}
func
titleForSelectView
()
->
String
{
switch
self
{
case
.
sex
:
return
"性别"
case
.
birthday
:
return
"生日"
case
.
height
:
return
"身高(单位:cm)"
case
.
weight
:
return
"体重(单位:kg)"
case
.
education
:
return
"学历"
case
.
profession
:
return
"职务"
case
.
work_domain
:
return
"从事行业"
case
.
income
:
return
"收入(单位:k)"
default
:
return
"--"
}
}
/*
var id : String = ""//用户ID
var user_type : String = ""//用户类型 1:普通用户2.明星用户3.管理员
var sex : String = ""//性别 0其他, 1:男, 2女
var real_name : String = "" //真实姓名
var nick_name : String = "" //昵称
var avatar : String = ""//头像
var birthday : String = ""//生日
var status : String = ""//用户状态1:正常,0:已注销
var height : String = ""//身高
var weight : String = ""//体重
var user_name : String = ""//用户名
var phone : String = ""//手机号码
var marital_status : String = ""//婚姻情况
var profession : String = ""//职业ID
var profession_name : String = ""//职业名称
var education : String = ""//文化程度ID
var education_name : String = ""//文化程度名称
var work_domain : String = ""//行业领域ID
var work_domain_name : String = ""//行业领域名称
*/
func
key
()
->
String
{
switch
self
{
case
.
sex
:
return
"sex"
case
.
birthday
:
return
"birthday"
case
.
height
:
return
"height"
case
.
weight
:
return
"weight"
case
.
education
:
return
"education"
case
.
profession
:
return
"profession"
case
.
work_domain
:
return
"work_domain"
case
.
income
:
return
"monthly_income"
default
:
return
""
}
}
}
// MARK: - URL 相关
struct
URL
{
// MARK: - 帮助与反馈
static
let
userQAUrl
=
YHBaseUrlManager
.
shared
.
h5URL
()
+
"landing/index.html#/pages/my/index"
// MARK: - 优眠用户注销条款
static
let
userUnregisterURL
=
"https://www.baidu.com"
// MARK: - 隐私政策
static
let
privacyURL
=
YHBaseUrlManager
.
shared
.
h5URL
()
+
"landing/index.html#/subpages/personal/pages/protocol/index?classify=privacy"
// MARK: - 用户协议
static
let
userProtocalURL
=
YHBaseUrlManager
.
shared
.
h5URL
()
+
"landing/index.html#/subpages/personal/pages/protocol/index?classify=agreement"
// MARK: - 付费咨询服务协议
static
let
payProtocalURL
=
"https://www.baidu.com"
// MARK: - 官网地址
static
let
officialWebsite
=
"https://www.sumian.com"
// MARK: - 量表入口
static
let
liangBiaoEntryWebsite
=
YHBaseUrlManager
.
shared
.
h5URL
()
+
"landing/index.html#/pages/medicineCenter/index"
// MARK: - 通用链接,可以在 Safari 等 web 环境打开 APP,目前主要是提供给微信APP调用
static
let
universal_link
=
"https://sdapi.sumian.com/sleepdoctor/"
static
let
wx_universal_link
=
universal_link
+
"wx-sign-in/"
//#if DEBUG
// // MARK: - 医学中心
// static let medical_center_url = "http://10.168.3.41:10086/h5/#/pages/medicineCenter/index"
//#else
// MARK: - 医学中心
static
let
medical_center_url
=
YHBaseUrlManager
.
shared
.
h5URL
()
+
"landing/index.html#/pages/medicineCenter/index"
//#endif
// MARK: - 助眠专辑详情
//static let music_detail_url = BsBaseUrlManager.shared.h5URL() + "landing/index.html#/subpages/platform/pages/musicdetail/index?immerse=1"
// MARK: - 文章列表
//static let article_list_url = BsBaseUrlManager.shared.h5URL() + "landing/index.html#/subpages/platform/pages/articlelist/index?immerse=1"
// MARK: - 文章详情
static
let
article_detail_url
=
YHBaseUrlManager
.
shared
.
h5URL
()
+
"landing/index.html#/subpages/platform/pages/articledetail/index?immerse=1"
// MARK: - 科普视频列表
//static let video_list_url = BsBaseUrlManager.shared.h5URL() + "landing/index.html#/subpages/platform/pages/videolist/index?immerse=1"
}
// MARK: - 阿里云 手机号一键登录 秘钥信息
static
let
kAliOnePressPhoneLoginKey
=
"pjYDHIVE1Q4qu7QJNI8MaxfvqJQvn5j+Az8xHRlnctj+kUAGf2Hin6ONsTFu1yjCwWPvhmw5NlhFo5DuP1SabykuX1Dz/xl4aDDLQQ5oijBNqRtwmwFAHl/exvfLk6zndWdv3Hi+DUL6gRwAj2UWj1rNXAMP2YSlisC0NSrFFFpiKyHAd2dM2OpIiGh9lkGeihU5iOjv/IycVMW6l2Sx9QqcrKiAX44aPMp0/uS5+y0xYwy/CjV6bvpacHNstxtVFd2Vgi7p454="
// MARK: - 登录信息
static
let
KLoginedInfoKey
=
"KLoginedInfoKey"
// MARK: - 上次登录成功后的 手机号码
static
let
KLastLoginedSuccessPhoneKey
=
"KLastLoginedSuccessPhoneKey"
// MARK: - 登录用户 详情信息
static
let
kDetailInfo
=
"kDetailInfo"
}
extension
BsConstant
{
// MARK: - 友盟相关
struct
Wechat
{
static
let
appKey
=
"wx57b2a7469d15ff8f"
static
let
AppSecret
=
"e0a351290c66c05f85c54a31b213c1aa"
}
struct
UM
{
static
let
appKey
=
"5a77b807a40fa30f0300008b"
}
// MARK: - 支付宝
struct
Alipay
{
static
let
scheme
=
"com.usleep.health.alipay"
}
// MARK: - 通知相关 名称
class
BsNotification
{
public
static
let
didCancelTaskNotification
=
Notification
.
Name
(
rawValue
:
"org.alamofire.notification.name.request.didCancelTask"
)
//用户详细信息更改成功
public
static
let
didUpdateUserDetailInfoSuccessNotifiction
=
Notification
.
Name
(
rawValue
:
"com.usleep.health.updateUserDetailInfo.success"
)
//登录成功
public
static
let
didLoginSuccessNotifiction
=
Notification
.
Name
(
rawValue
:
"com.usleep.health.login.success"
)
//退出成功
public
static
let
didLoginoutSuccessNotifiction
=
Notification
.
Name
(
rawValue
:
"com.usleep.health.loginout.success"
)
//token 过期
public
static
let
tokenInvalidateNotifiction
=
Notification
.
Name
(
rawValue
:
"com.usleep.health.token.invalidate"
)
//用户注册 在完成登录、修改密码后需要 填写标签
public
static
let
needSelectTagsNotification
=
Notification
.
Name
(
rawValue
:
"com.usleep.health.selecte.tags"
)
//跳转安睡主页
public
static
let
goAnSleepNotification
=
Notification
.
Name
(
rawValue
:
"com.usleep.health.go.An.sleep"
)
//跳转填写量表列表界面
public
static
let
goFillScaleNotification
=
Notification
.
Name
(
rawValue
:
"com.usleep.health.go.Fill.Scale"
)
//支付结果回调
public
static
let
payResultNotification
=
Notification
.
Name
(
rawValue
:
"com.usleep.health.pay.result"
)
//隐藏tabBar
public
static
let
tabBarHideNotification
=
Notification
.
Name
(
rawValue
:
"com.usleep.health.tabBar.hide"
)
//显示tabBar
public
static
let
tabBarShowNotification
=
Notification
.
Name
(
rawValue
:
"com.usleep.health.tabBar.show"
)
//安睡主页切换Tab
public
static
let
sleepPageChangeTabNotification
=
Notification
.
Name
(
rawValue
:
"com.usleep.health.sleepPage.changeTab"
)
}
}
galaxy/galaxy/Classes/Tools/Helper/BsHUD/BsHUD.swift
0 → 100755
View file @
0b841956
//
// BsHUD.swift
// PKHUD Demo
//
// Created by ahao on 2018/3/20.
// Copyright © 2018年 NSExceptional. All rights reserved.
//
import
UIKit
import
PKHUD
public
enum
BsHUDType
{
case
success
(
message
:
String
?)
case
error
(
message
:
String
?)
case
warning
(
message
:
String
?)
case
progress
(
message
:
String
?)
case
image
(
image
:
UIImage
?,
message
:
String
?)
case
rotatingImage
(
image
:
UIImage
?,
message
:
String
?)
}
class
BsHUD
{
// MARK: Properties
public
static
var
dimsBackground
:
Bool
{
get
{
return
PKHUD
.
sharedHUD
.
dimsBackground
}
set
{
PKHUD
.
sharedHUD
.
dimsBackground
=
newValue
}
}
public
static
var
allowsInteraction
:
Bool
{
get
{
return
PKHUD
.
sharedHUD
.
userInteractionOnUnderlyingViewsEnabled
}
set
{
PKHUD
.
sharedHUD
.
userInteractionOnUnderlyingViewsEnabled
=
newValue
}
}
public
static
var
isVisible
:
Bool
{
return
PKHUD
.
sharedHUD
.
isVisible
}
// MARK: Public methods, PKHUD based
public
static
func
show
(
_
content
:
BsHUDType
,
onView
view
:
UIView
?
=
nil
)
{
PKHUD
.
sharedHUD
.
contentView
=
contentView
(
content
)
PKHUD
.
sharedHUD
.
show
(
onView
:
view
)
}
public
static
func
hide
(
_
completion
:
((
Bool
)
->
Void
)?
=
nil
)
{
PKHUD
.
sharedHUD
.
hide
(
animated
:
false
,
completion
:
completion
)
}
public
static
func
hide
(
animated
:
Bool
,
completion
:
((
Bool
)
->
Void
)?
=
nil
)
{
PKHUD
.
sharedHUD
.
hide
(
animated
:
animated
,
completion
:
completion
)
}
public
static
func
hide
(
afterDelay
delay
:
TimeInterval
,
completion
:
((
Bool
)
->
Void
)?
=
nil
)
{
PKHUD
.
sharedHUD
.
hide
(
afterDelay
:
delay
,
completion
:
completion
)
}
public
static
func
hideFlashMessage
()
{
let
keyWindow
=
UIApplication
.
shared
.
windows
.
first
{
$0
.
isKeyWindow
}
if
keyWindow
!=
nil
{
while
(
keyWindow
!.
viewWithTag
(
BsHUD
.
flashMessageTag
)
!=
nil
){
keyWindow
!.
viewWithTag
(
BsHUD
.
flashMessageTag
)?
.
removeFromSuperview
()
}
}
}
// MARK: Public methods, HUD based
public
static
func
flash
(
_
content
:
BsHUDType
,
onView
view
:
UIView
?
=
nil
)
{
BsHUD
.
flash
(
content
,
onView
:
view
,
delay
:
1
,
completion
:
nil
)
}
public
static
func
flash
(
_
content
:
BsHUDType
,
onView
view
:
UIView
?
=
nil
,
delay
:
TimeInterval
,
completion
:
((
Bool
)
->
Void
)?
=
nil
)
{
BsHUD
.
show
(
content
,
onView
:
view
)
BsHUD
.
hide
(
afterDelay
:
delay
,
completion
:
completion
)
}
// MARK: Private methods
static
func
contentView
(
_
content
:
BsHUDType
)
->
UIView
{
let
todoView
:
UIView
switch
content
{
case
let
.
progress
(
message
):
todoView
=
BsHUDProgressView
(
title
:
message
)
case
let
.
success
(
message
):
todoView
=
BsHUDSuccessView
(
title
:
message
)
case
let
.
error
(
message
):
todoView
=
BsHUDErrorView
(
title
:
message
)
case
let
.
warning
(
message
):
todoView
=
BsHUDWariningView
(
title
:
message
)
case
let
.
rotatingImage
(
image
,
message
):
todoView
=
BsHUDSquareBaseView
(
image
:
image
,
title
:
message
)
case
let
.
image
(
image
,
message
):
todoView
=
BsHUDSquareBaseView
(
image
:
image
,
title
:
message
)
}
return
todoView
}
}
extension
BsHUD
{
static
func
setup
(){
PKHUD
.
sharedHUD
.
effect
=
nil
// PKHUD.sharedHUD.gracePeriod = 0.5
}
}
extension
BsHUD
{
static
let
flashMessageTag
=
61535
static
func
flash
(
message
:
String
,
dismissAfter
:
TimeInterval
=
1.5
,
duration
:
TimeInterval
=
0.5
,
isRemoveBefore
:
Bool
=
true
,
insets
:
UIEdgeInsets
=
UIEdgeInsets
(
top
:
0
,
left
:
20
,
bottom
:
120
,
right
:
20
),
contentInsets
:
UIEdgeInsets
=
UIEdgeInsets
(
top
:
5
,
left
:
10
,
bottom
:
5
,
right
:
10
),
containerWindow
:
UIWindow
?
=
nil
,
walk
:((
UILabel
)
->
Void
)?
=
nil
){
if
isRemoveBefore
{
hideFlashMessage
()
}
if
message
.
isEmpty
{
return
}
let
containerView
=
UIView
()
containerView
.
backgroundColor
=
UIColor
.
black
.
withAlphaComponent
(
0.7
)
containerView
.
layer
.
cornerRadius
=
4
containerView
.
alpha
=
0
containerView
.
tag
=
flashMessageTag
let
label
=
UILabel
()
label
.
text
=
message
label
.
numberOfLines
=
5
label
.
textColor
=
UIColor
.
white
label
.
font
=
UIFont
.
systemFont
(
ofSize
:
14
)
containerView
.
addSubview
(
label
)
walk
?(
label
)
let
keyW
=
UIApplication
.
shared
.
windows
.
first
{
$0
.
isKeyWindow
}
if
let
keyWindow
=
(
containerWindow
??
keyW
){
let
labelWidth
=
keyWindow
.
bounds
.
width
-
insets
.
left
-
insets
.
right
-
contentInsets
.
left
-
contentInsets
.
right
label
.
frame
=
CGRect
(
x
:
contentInsets
.
left
,
y
:
contentInsets
.
top
,
width
:
labelWidth
,
height
:
30
)
label
.
sizeToFit
()
let
containerViewSize
=
CGSize
(
width
:
label
.
frame
.
width
+
contentInsets
.
left
+
contentInsets
.
right
,
height
:
label
.
frame
.
height
+
contentInsets
.
top
+
contentInsets
.
bottom
)
containerView
.
frame
=
CGRect
(
x
:
(
keyWindow
.
bounds
.
width
-
containerViewSize
.
width
)
/
2.0
,
y
:
(
keyWindow
.
bounds
.
height
-
containerViewSize
.
height
)
/
2.0
,
width
:
containerViewSize
.
width
,
height
:
containerViewSize
.
height
)
keyWindow
.
addSubview
(
containerView
)
UIView
.
animate
(
withDuration
:
duration
,
animations
:
{
containerView
.
alpha
=
1
},
completion
:
{
(
_
)
in
UIView
.
animate
(
withDuration
:
duration
,
delay
:
dismissAfter
,
options
:
[],
animations
:
{
containerView
.
alpha
=
0
},
completion
:
{
(
_
)
in
containerView
.
removeFromSuperview
()
})
})
}
}
}
galaxy/galaxy/Classes/Tools/Helper/BsHUD/BsHUDContainerView.swift
0 → 100755
View file @
0b841956
//
// BsHUDContainerView.swift
// PKHUD Demo
//
// Created by ahao on 2018/3/20.
// Copyright © 2018年 NSExceptional. All rights reserved.
//
import
UIKit
class
BsHUDContainerView
:
UIView
{
static
let
defaultFrame
=
CGRect
(
origin
:
CGPoint
.
zero
,
size
:
CGSize
(
width
:
156.0
,
height
:
156.0
))
private
let
offSet
:
CGFloat
var
contentView
:
UIView
init
(
contentView
:
UIView
,
offSet
:
CGFloat
=
0
)
{
self
.
contentView
=
contentView
self
.
offSet
=
offSet
super
.
init
(
frame
:
BsHUDContainerView
.
adjustFrame
(
contentViewFrame
:
contentView
.
frame
,
offSet
:
offSet
))
addSubview
(
contentView
)
}
func
adjustFrame
()
->
CGRect
{
return
BsHUDContainerView
.
adjustFrame
(
contentViewFrame
:
contentView
.
frame
,
offSet
:
offSet
)
}
class
func
adjustFrame
(
contentViewFrame
:
CGRect
,
offSet
:
CGFloat
)
->
CGRect
{
let
height
=
contentViewFrame
.
height
+
abs
(
offSet
)
*
2
let
adjustSize
=
CGSize
(
width
:
contentViewFrame
.
width
,
height
:
height
)
return
CGRect
(
origin
:
CGPoint
.
zero
,
size
:
adjustSize
)
}
override
func
layoutSubviews
()
{
super
.
layoutSubviews
()
let
contentSize
=
contentView
.
frame
.
size
contentView
.
frame
=
CGRect
(
origin
:
CGPoint
.
zero
,
size
:
contentSize
)
contentView
.
center
=
CGPoint
(
x
:
bounds
.
width
/
2.0
,
y
:
bounds
.
height
/
2.0
+
offSet
)
}
required
init
?(
coder
aDecoder
:
NSCoder
)
{
fatalError
(
"init(coder:) has not been implemented"
)
}
}
galaxy/galaxy/Classes/Tools/Helper/BsHUD/BsHUDErrorView.swift
0 → 100755
View file @
0b841956
//
// BsHUDErrorView.swift
// PKHUD Demo
//
// Created by ahao on 2018/3/20.
// Copyright © 2018年 NSExceptional. All rights reserved.
//
import
UIKit
import
PKHUD
class
BsHUDErrorView
:
BsHUDSquareBaseView
{
public
init
(
title
:
String
?
=
nil
)
{
super
.
init
(
image
:
UIImage
(
named
:
"float_icon_error"
),
title
:
title
)
}
public
required
init
?(
coder
aDecoder
:
NSCoder
)
{
super
.
init
(
coder
:
aDecoder
)
}
}
galaxy/galaxy/Classes/Tools/Helper/BsHUD/BsHUDProgressView.swift
0 → 100755
View file @
0b841956
//
// BsHUDProgressView.swift
// PKHUD Demo
//
// Created by ahao on 2018/4/19.
// Copyright © 2018年 NSExceptional. All rights reserved.
//
import
UIKit
import
PKHUD
class
BsHUDProgressView
:
BsHUDSquareBaseView
,
PKHUDAnimating
{
public
init
(
title
:
String
?
=
nil
)
{
super
.
init
(
image
:
UIImage
(
named
:
"float_icon_loading"
),
title
:
title
)
}
public
required
init
?(
coder
aDecoder
:
NSCoder
)
{
super
.
init
(
coder
:
aDecoder
)
}
public
func
startAnimation
()
{
imageView
.
layer
.
add
(
PKHUDAnimation
.
discreteRotation
,
forKey
:
"progressAnimation"
)
}
public
func
stopAnimation
()
{
imageView
.
layer
.
removeAnimation
(
forKey
:
"progressAnimation"
)
}
}
galaxy/galaxy/Classes/Tools/Helper/BsHUD/BsHUDRotatingImageView.swift
0 → 100755
View file @
0b841956
//
// BsHUDRotatingImageView.swift
// PKHUD Demo
//
// Created by ahao on 2018/4/19.
// Copyright © 2018年 NSExceptional. All rights reserved.
//
import
UIKit
import
PKHUD
class
BsHUDRotatingImageView
:
BsHUDSquareBaseView
,
PKHUDAnimating
{
public
func
startAnimation
()
{
imageView
.
layer
.
add
(
PKHUDAnimation
.
discreteRotation
,
forKey
:
"progressAnimation"
)
}
public
func
stopAnimation
()
{
}
}
galaxy/galaxy/Classes/Tools/Helper/BsHUD/BsHUDSquareBaseView.swift
0 → 100755
View file @
0b841956
//
// BsHUDSquareBaseView.swift
// PKHUD Demo
//
// Created by ahao on 2018/4/19.
// Copyright © 2018年 NSExceptional. All rights reserved.
//
import
UIKit
import
PKHUD
class
BsHUDSquareBaseView
:
UIView
{
static
let
defaultSquareBaseViewFrame
=
CGRect
(
origin
:
CGPoint
.
zero
,
size
:
CGSize
(
width
:
120
,
height
:
120
))
override
init
(
frame
:
CGRect
)
{
super
.
init
(
frame
:
frame
)
}
required
init
?(
coder
aDecoder
:
NSCoder
)
{
super
.
init
(
coder
:
aDecoder
)
}
init
(
image
:
UIImage
?
=
nil
,
title
:
String
?
=
nil
)
{
super
.
init
(
frame
:
BsHUDSquareBaseView
.
defaultSquareBaseViewFrame
)
backgroundColor
=
UIColor
.
black
imageView
.
image
=
image
titleLabel
.
text
=
title
titleLabel
.
sizeToFit
()
addSubview
(
containerView
)
containerView
.
addSubview
(
imageView
)
containerView
.
addSubview
(
titleLabel
)
}
let
imageView
:
UIImageView
=
{
let
imageView
=
UIImageView
()
imageView
.
clipsToBounds
=
true
imageView
.
contentMode
=
.
scaleAspectFit
return
imageView
}()
let
titleLabel
:
UILabel
=
{
let
label
=
UILabel
()
label
.
textAlignment
=
.
center
label
.
font
=
UIFont
.
boldSystemFont
(
ofSize
:
14.0
)
label
.
textColor
=
UIColor
.
white
label
.
adjustsFontSizeToFitWidth
=
true
label
.
minimumScaleFactor
=
0.25
return
label
}()
let
containerView
:
UIView
=
{
let
temp
=
UIView
()
return
temp
}()
open
override
func
layoutSubviews
()
{
super
.
layoutSubviews
()
let
viewWidth
=
bounds
.
size
.
width
let
viewHeight
=
bounds
.
size
.
height
let
labelHeight
=
titleLabel
.
bounds
.
height
let
imageViewHeight
:
CGFloat
=
max
(
imageView
.
image
?
.
size
.
height
??
28
,
30
)
let
padding
:
CGFloat
=
labelHeight
>
0
?
8
:
0
let
containerWidth
=
viewWidth
-
5
-
5
let
containerHeight
=
imageViewHeight
+
padding
+
labelHeight
containerView
.
frame
.
size
=
CGSize
(
width
:
containerWidth
,
height
:
containerHeight
)
containerView
.
center
=
CGPoint
(
x
:
viewWidth
/
2.0
,
y
:
viewHeight
/
2.0
)
imageView
.
frame
=
CGRect
(
origin
:
CGPoint
.
zero
,
size
:
CGSize
(
width
:
containerWidth
,
height
:
imageViewHeight
))
titleLabel
.
frame
=
CGRect
(
origin
:
CGPoint
(
x
:
0
,
y
:
imageView
.
frame
.
maxY
+
padding
),
size
:
CGSize
(
width
:
viewWidth
-
8
,
height
:
titleLabel
.
frame
.
height
))
}
}
galaxy/galaxy/Classes/Tools/Helper/BsHUD/BsHUDSuccessView.swift
0 → 100755
View file @
0b841956
//
// BsHUDSuccessView.swift
// PKHUD Demo
//
// Created by ahao on 2018/3/20.
// Copyright © 2018年 NSExceptional. All rights reserved.
//
import
UIKit
import
PKHUD
class
BsHUDSuccessView
:
BsHUDSquareBaseView
{
public
init
(
title
:
String
?
=
nil
)
{
super
.
init
(
image
:
UIImage
(
named
:
"float_icon_success"
),
title
:
title
)
}
public
required
init
?(
coder
aDecoder
:
NSCoder
)
{
super
.
init
(
coder
:
aDecoder
)
}
}
galaxy/galaxy/Classes/Tools/Helper/BsHUD/BsHUDWariningView.swift
0 → 100755
View file @
0b841956
//
// BsHUDWariningView.swift
// PKHUD Demo
//
// Created by ahao on 2018/4/19.
// Copyright © 2018年 NSExceptional. All rights reserved.
//
import
UIKit
class
BsHUDWariningView
:
BsHUDSquareBaseView
{
public
init
(
title
:
String
?
=
nil
)
{
super
.
init
(
image
:
UIImage
(
named
:
"float_icon_caveat"
),
title
:
title
)
}
public
required
init
?(
coder
aDecoder
:
NSCoder
)
{
super
.
init
(
coder
:
aDecoder
)
}
}
galaxy/galaxy/Classes/Tools/Helper/BsKVOHelper.swift
0 → 100755
View file @
0b841956
//
// 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
()
}
}
}
galaxy/galaxy/Classes/Tools/Helper/BsMapManager.swift
0 → 100755
View file @
0b841956
//
// BsMapManager.swift
// BaiSiSMApp
//
// Created by DAVID 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
)
!
)
}
}
}
galaxy/galaxy/Classes/Tools/Helper/BsPageView/BsPageContentView.swift
0 → 100755
View file @
0b841956
//
// 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
)
}
}
galaxy/galaxy/Classes/Tools/Helper/BsPageView/BsPageTitleView.swift
0 → 100755
View file @
0b841956
//
// 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
)
}
}
}
}
}
}
galaxy/galaxy/Classes/Tools/Helper/BsPresentView.swift
0 → 100755
View file @
0b841956
//
// BsPresentView.swift
// BaiSiSMApp
//
// Created by DAVID 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
()
}
}
}
galaxy/galaxy/Classes/Tools/Helper/BsWebViewPreloadManager.swift
0 → 100755
View file @
0b841956
//
// 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
}
}
}
galaxy/galaxy/Classes/Tools/Helper/ClipImage(裁切图片)/Images/ClipImage_cancel.png
0 → 100755
View file @
0b841956
1.14 KB
galaxy/galaxy/Classes/Tools/Helper/ClipImage(裁切图片)/Images/ClipImage_rotating.png
0 → 100755
View file @
0b841956
1.33 KB
galaxy/galaxy/Classes/Tools/Helper/ClipImage(裁切图片)/Images/ClipImage_sure.png
0 → 100755
View file @
0b841956
993 Bytes
galaxy/galaxy/Classes/Tools/Helper/ClipImage(裁切图片)/MCClipImageTool.swift
0 → 100755
View file @
0b841956
//
// 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
!
}
}
galaxy/galaxy/Classes/Tools/Helper/ClipImage(裁切图片)/MCClipImageViewController.swift
0 → 100755
View file @
0b841956
//
// 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
galaxy/galaxy/Classes/Tools/NetWork/YHAllApiName.swift
0 → 100755
View file @
0b841956
//
// BsAllApiName.swift
// BaiSiSMApp
//
// Created by davidhuang on 2022/10/18.
// Copyright © 2022 www.davidhuang.com. All rights reserved.
//
class
YHAllApiName
{
//===============登录相关 开始===============
//手机号码、密码 登录
static
let
loginByPwd
=
"user/UserLoginV2/loginByPwd"
//手机号码、验证码 登录
static
let
loginByVerifyCode
=
"user/UserLoginV2/loginByPhone"
//更改手机号
static
let
changedPhone
=
"user/User/changeUserPhone"
//获取验证码
static
let
verifyCode
=
"user/VerificationCodeV2/sendCode"
//手机一键登录
static
let
loginByOnePress
=
"user/UserLoginV2/oneClickPhoneLogin"
//苹果登录
static
let
appleLogin
=
"user/UserLoginV2/appleLogin"
//苹果登录绑定手机号
static
let
appleLoginBindPhone
=
"user/UserLoginV2/appleLoginBindPhone"
//手机号码是否注册
static
let
checkPhoneReigster
=
"user/UserLoginV2/checkPhoneRegister"
//修改密码
static
let
resetPwd
=
"user/user/editUserPassword"
//用户注销
static
let
unRegister
=
"user/user/destroy"
//检查更新
static
let
checkAppLastVersion
=
"system/AppVersion/getLastestVersion"
//===============登录相关 结束===============
//===============用户信息相关 开始===============
//用户详细信息
static
let
userDetailInfo
=
"user/user/userDetail"
//更新 用户详细信息
static
let
updateUserInfo
=
"user/user/updateUserInfo"
//上传图片
static
let
uploadImage
=
"system/Media/uploadBase64Image"
//确认用户是否有未读信息
static
let
reqUnreadMsgNum
=
"message/officialNotification/latestMonthUnreadNum"
//===============用户信息相关 结束===============
//===============用户反馈 开始===============
//用户反馈
static
let
userFeedBack
=
"user/Feedback/feedback"
//===============用户反馈 结束===============
//===============我的档案 开始===============
//用户额外信息
static
let
userExtInfo
=
"user/user/getUserExtInfo"
//获取用户信息选择项目
static
let
userSelection
=
"dictionary/DataDictionary/getUserDataList"
//获取用户提交过的健康状态详情
static
let
userHealthConditionDetail
=
"health/HealthCondition/getUserHealthConditionDetail"
//获取用户相关的健康状态问题列表
static
let
userHealthConditionList
=
"health/HealthCondition/getHealthConditionList"
//提交健康状态
static
let
submitHealthConditionReport
=
"health/HealthCondition/submitHealthConditionReport"
//===============我的档案 结束===============
//===============站内消息 开始===============
//获取站内信 通知列表
static
let
reqMsgList
=
"message/officialNotification/getNotificationList"
//更新信息为已读状态
static
let
updateMsgReadedStatus
=
"message/officialNotification/addReadRecord"
//查询用户是否有未读消息 --- for test hjl 还没有定义
static
let
queryMsgReadedStatus
=
"user/user/getUserExtInfo"
//===============站内消息 结束===============
//===============我的订单 开始===============
//获取 我的订单列表数据
static
let
reqMyOrderListData
=
"order/order/getOrderList"
//获取 订单详情
static
let
reqGetOrderDetail
=
"order/order/getOrderDetail"
//创建订单
static
let
reqCreateOrder
=
"order/order/createOrderV1"
//取消订单(只有待支付的才能取消)
static
let
reqCancelOrder
=
"order/order/cancelOrder"
//支付宝获取支付orderStr
static
let
reqAliPayOrderStr
=
"pay/pay/aliPayOrderStr"
//申请退款
static
let
reqApplyRefund
=
"order/order/applyRefund"
//===============我的订单 结束===============
//===============量表 开始===============
//获取已测评历史记录列表
static
let
reqCpHistoryList
=
"jiankang/JkRiskCheck/getUserCheckHistoryList"
//测评结果选项详情
static
let
cpResultOptionDetail
=
"jiankang/JkRiskCheck/getUserCheckHistoryQuestionSnapshot"
//获取量表测评分类
static
let
reqScaleCategory
=
"jiankang/JkRiskCheck/getCategory"
//获取量表测评列表
static
let
reqScaleCategoryList
=
"jiankang/JkRiskCheck/getSubject"
//量表详情(不含问题)
static
let
reqScaleDetail
=
"jiankang/JkRiskCheck/getRiskCheckSubjectDetail"
//量表详情&问题列表
static
let
reqScaleQuestions
=
"jiankang/JkRiskCheck/getRiskCheckQuestion"
//根据标签获取量表详情&问题列表(自我评估)
static
let
reqScaleQuestionsForSelf
=
"jiankang/JkRiskCheck/getRiskCheckQuestionByTag"
//提交测评数据
static
let
submitScaleInfo
=
"jiankang/JkRiskCheck/submit"
//获取已测评历史记录详情
static
let
reqGetUserCheckHistoryInfo
=
"jiankang/JkRiskCheck/getUserCheckHistoryInfo"
//获取是否已经做过自我评估(即是否填写过量表)
static
let
checkHasFillScale
=
"jiankang/JkRiskCheck/getSelfCheckStatus"
//===============量表 结束===============
//===============主页 开始===============
//获取banner列表
static
let
reqGetBanner
=
"banner/banner/getBanner"
//助眠专辑列表
static
let
reqGetSleepAlbumList
=
"album/album/getSleepAlbumList"
//===============主页 结束===============
//===============商品 开始===============
//获取上架的商品列表
static
let
reqGetProductList
=
"product/product/getProductList"
//获取指定商品详情
static
let
reqGetProduct
=
"product/product/getProduct"
//咨询服务展示选取的时间段
static
let
reqGetConsultTimePeriod
=
"product/consult/getConsultTimePeriod"
//===============商品 结束===============
//===============标签 开始===============
//全部的标签
static
let
allTagsApi
=
"user/tag/getRisk"
//已选标签
static
let
selectedTagsApi
=
"user/tag/getTags"
//设置标签
static
let
setTagsApi
=
"user/tag/set"
//===============标签 结束===============
//===============睡眠曲 开始===============
//睡眠曲分类列表
static
let
getSleepMusicCategorys
=
"sleep/SleepMusic/getAllCategorys"
//睡眠曲列表
static
let
getSleepMusicList
=
"sleep/SleepMusic/list"
//===============睡眠曲 结束===============
//===============科普视频 开始===============
//科普视频分类列表
static
let
getSleepVideoCategorys
=
"sleep/SleepVideo/getAllCategorys"
//科普视频列表
static
let
reqGetSleepVideoList
=
"sleep/SleepVideo/list"
//科普视频首页列表
static
let
reqGetIndexVideoList
=
"sleep/SleepVideo/getIndexVideoList"
//===============科普视频 结束===============
//===============公开讲座 开始===============
//公开讲座列表
static
let
getOpenLectureList
=
"lecture/OpenLecture/list"
//===============公开讲座 结束===============
//===============行业资讯 开始===============
//资讯首页列表数据
static
let
getIndexKnowledgeList
=
"jiankang/JkKnowledge/getIndexKnowledgeList"
//文章列表
static
let
reqGetKnowledgeList
=
"jiankang/JkKnowledge/getKnowledgeList"
//===============行业资讯 结束===============
//===============安睡 开始===============
//专辑详情
static
let
albumDetail
=
"album/album/getDetail"
//专辑中音乐列表
static
let
albumMusicList
=
"album/album/getAlbumMusicList"
//增加专辑浏览量
static
let
addAlbumLookCount
=
"album/album/addLookCount"
//视频或音乐点击播放埋点
static
let
addPlayCount
=
"sleep/SleepPlayHistory/play"
//===============安睡 开始===============
//===============门诊 开始===============
//获取门诊列表
static
let
getClinicList
=
"clinic/clinic/getClinicList"
//门诊详情
static
let
getClinicDetail
=
"clinic/clinic/getDetail"
//门诊绑定医生医生列表
static
let
getBindDoctorList
=
"clinic/clinic/getBindDoctorList"
//===============门诊 结束===============
//===============医生 开始===============
//医生列表
static
let
getDoctorList
=
"sleep/Doctor/getDoctorList"
//医生详情
static
let
getDoctorDetail
=
"sleep/Doctor/detail"
//医生直播及采访视频列表
static
let
getDoctorVideoList
=
"sleep/Doctor/getDoctorVideoList"
//首页搜索
static
let
searchClinicDoctorList
=
"clinic/clinic/searchClinicDoctorList"
//===============医生 结束===============
//===============用户-跳转链接 开始===============
//获取睡眠日记跳转链接
static
let
getSleepDiaryUrl
=
"user/user/getSleepDiaryUrl"
//获取cbti训练跳转链接
static
let
getCBTIJumpUrl
=
"user/user/getCBTIJumpUrl"
//===============用户-跳转链接 结束===============
}
galaxy/galaxy/Classes/Tools/NetWork/YHBaseUrlManager.swift
0 → 100755
View file @
0b841956
//
// BsBaseurlManager.swift
// BaiSiSMApp
//
// Created by davidhuang on 2022/10/17.
// Copyright © 2022 www.davidhuang.com. All rights reserved.
//
// MARK: - 管理项目开发中需要使用到的域名地址
class
YHBaseUrlManager
{
static
let
shared
=
YHBaseUrlManager
()
//开发环境
static
let
baseUrlDev
:
String
=
"http://test.api.health.sleep321.com/"
//测试环境
//static let baseUrlTest : String = ""
//正式环境
static
let
baseUrlRelease
:
String
=
"https://api.health.sleep321.com/"
//h5开发环境
static
let
h5UrlDev
:
String
=
"https://cdn.sleep321.com/trial/"
//h5正式环境
static
let
h5UrlRelease
:
String
=
"https://cdn.sleep321.com/production/"
//用于外部编辑的
var
urlForEditing
:
String
?
// MARK: - 当前使用的url
func
curURL
()
->
String
{
#if DEBUG
return
urlForEditing
??
YHBaseUrlManager
.
baseUrlDev
#else
return
urlForEditing
??
YHBaseUrlManager
.
baseUrlRelease
#endif
}
// MARK: - 当前使用的url
func
h5URL
()
->
String
{
#if DEBUG
return
YHBaseUrlManager
.
h5UrlDev
#else
return
YHBaseUrlManager
.
h5UrlRelease
#endif
}
}
galaxy/galaxy/Classes/Tools/NetWork/YHNetworkStatusManager.swift
0 → 100755
View file @
0b841956
//
// BsNetworkStatusManager.swift
// BaiSiSMApp
//
// Created by davidhuang on 2022/11/8.
// Copyright © 2022 www.davidhuang.com. All rights reserved.
//
import
UIKit
import
Reachability
//网络状况 检测
class
YHNetworkStatusManager
{
static
let
shared
=
YHNetworkStatusManager
()
var
reachability
:
Reachability
!
init
(){
do
{
reachability
=
try
Reachability
()
reachability
.
whenReachable
=
{
reachability
in
if
reachability
.
connection
==
.
wifi
{
print
(
"Reachable via WiFi2"
)
BsHUD
.
flash
(
message
:
"当前网络: wifi"
)
}
else
{
print
(
"Reachable via Cellular"
)
BsHUD
.
flash
(
message
:
"当前网络: Cellular"
)
}
}
reachability
.
whenUnreachable
=
{
_
in
print
(
"Not reachable"
)
BsHUD
.
flash
(
message
:
"当前网络不可用"
)
}
}
catch
{
print
(
"Unable to create Reachability"
)
return
}
}
var
isNetWorkOK
:
Bool
{
if
reachability
.
connection
!=
.
unavailable
{
return
true
}
else
{
print
(
"网络连接:不可用"
)
return
false
}
}
var
netType
:
Reachability
.
Connection
{
return
reachability
.
connection
}
func
listenNetWorkStatus
()
{
NotificationCenter
.
default
.
addObserver
(
self
,
selector
:
#selector(
reachabilityChanged(note:)
)
,
name
:
.
reachabilityChanged
,
object
:
reachability
)
do
{
try
reachability
.
startNotifier
()
}
catch
{
print
(
"could not start reachability notifier"
)
}
}
@objc
func
reachabilityChanged
(
note
:
Notification
)
{
switch
reachability
.
connection
{
case
.
wifi
:
print
(
"Reachable via WiFi1"
)
case
.
cellular
:
print
(
"Reachable via Cellular"
)
case
.
unavailable
:
print
(
"Network not reachable"
)
case
.
none
:
print
(
".none"
)
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment