Skip to content
切换导航条
切换导航条
当前项目
正在载入...
登录
陈高翔
/
AoleiSports
转到一个项目
切换导航栏
切换导航栏固定状态
项目
群组
代码片段
帮助
项目
活动
版本库
流水线
图表
问题
0
合并请求
0
维基
网络
创建新的问题
作业
提交
问题看板
文件
提交
网络
比较
分支
标签
Commit 8613f641
由
ilCode
编写于
2024-06-19 11:28:09 +0800
浏览文件
选项
浏览文件
标签
下载
电子邮件补丁
差异文件
刷新加载等基础框架搭建
1 个父辈
4b21ff31
全部展开
隐藏空白字符变更
内嵌
并排
正在显示
26 个修改的文件
包含
505 行增加
和
116 行删除
AoleiSports.xcodeproj/project.pbxproj
AoleiSports/Config/en.lproj/Localizable.strings
AoleiSports/Config/zh-Hans.lproj/Localizable.strings
AoleiSports/Res/Assets.xcassets/default/refresh_icon.imageset/Contents.json
AoleiSports/Res/Assets.xcassets/default/refresh_icon.imageset/refresh_icon.png
AoleiSports/Res/Assets.xcassets/default/refresh_icon.imageset/refresh_icon@2x.png
AoleiSports/Res/Assets.xcassets/default/refresh_icon.imageset/refresh_icon@3x.png
AoleiSports/Src/Base/AsEmptyView.swift
AoleiSports/Src/Base/BaseController.swift
AoleiSports/Src/Ext/UIImage+Ext.swift
AoleiSports/Src/Ext/UIView+Ext.swift
AoleiSports/Src/Information/InfoController.swift
AoleiSports/Src/Information/InfoDetailController.swift
AoleiSports/Src/Information/InfoModel.swift
AoleiSports/Src/Information/InfoProvider.swift
AoleiSports/Src/Information/MatchInfoCell.swift
AoleiSports/Src/Root/RootController.swift
AoleiSports/Src/Root/en.lproj/LaunchScreen.strings
AoleiSports/Src/Root/zh-Hans.lproj/LaunchScreen.strings
AoleiSports/Src/Utils/ImportTools.swift
AoleiSports/Src/Utils/NetworkTools.swift
AoleiSports/Src/Vendors/Refresh/RefreshFooterAnimator.swift
AoleiSports/Src/Vendors/Refresh/RefreshHeaderAnimator.swift
Podfile
Podfile.lock
R.generated.swift
AoleiSports.xcodeproj/project.pbxproj
查看文件 @
8613f64
此文件的差异被折叠,
点击展开。
AoleiSports/Config/en.lproj/Localizable.strings
0 → 100644
查看文件 @
8613f64
/*
Localizable.strings
AoleiSports
Created by ilCode on 2024/6/19.
*/
"Loading more" = "Loading more";
"No more data" = "No more data";
"Loading..." = "Loading...";
AoleiSports/Config/zh-Hans.lproj/Localizable.strings
0 → 100644
查看文件 @
8613f64
/*
Localizable.strings
AoleiSports
Created by ilCode on 2024/6/19.
*/
"Loading more" = "加载更多";
"No more data" = "没有更多数据";
"Loading..." = "加载中...";
AoleiSports/Res/Assets.xcassets/default/refresh_icon.imageset/Contents.json
0 → 100644
查看文件 @
8613f64
{
"images"
:
[
{
"filename"
:
"refresh_icon.png"
,
"idiom"
:
"universal"
,
"scale"
:
"1x"
},
{
"filename"
:
"refresh_icon@2x.png"
,
"idiom"
:
"universal"
,
"scale"
:
"2x"
},
{
"filename"
:
"refresh_icon@3x.png"
,
"idiom"
:
"universal"
,
"scale"
:
"3x"
}
],
"info"
:
{
"author"
:
"xcode"
,
"version"
:
1
}
}
AoleiSports/Res/Assets.xcassets/default/refresh_icon.imageset/refresh_icon.png
0 → 100644
查看文件 @
8613f64
3.4 KB
AoleiSports/Res/Assets.xcassets/default/refresh_icon.imageset/refresh_icon@2x.png
0 → 100644
查看文件 @
8613f64
8.4 KB
AoleiSports/Res/Assets.xcassets/default/refresh_icon.imageset/refresh_icon@3x.png
0 → 100644
查看文件 @
8613f64
12.7 KB
AoleiSports/Src/Base/AsEmptyView.swift
查看文件 @
8613f64
...
...
@@ -11,6 +11,7 @@ import UIKit
enum
EmptyType
{
case
netErr
// 网络问题
case
noData
// 无数据
case
other
// 其他错误
}
// 缺省页
...
...
@@ -22,21 +23,13 @@ class AsEmptyView: UIView {
return
iv
}()
private
lazy
var
net
Lab
:
UILabel
=
{
private
lazy
var
message
Lab
:
UILabel
=
{
let
lab
=
UILabel
()
lab
.
text
=
"请检查您的网络设置或刷新重试"
lab
.
textColor
=
kSubTitleColor
lab
.
textAlignment
=
.
center
lab
.
font
=
kFontSize
(
14
)
return
lab
}()
private
lazy
var
noDataLab
:
UILabel
=
{
let
lab
=
UILabel
()
lab
.
text
=
"暂无数据"
lab
.
text
=
""
lab
.
textColor
=
kSubTitleColor
lab
.
textAlignment
=
.
center
lab
.
font
=
kFontSize
(
14
)
lab
.
numberOfLines
=
0
return
lab
}()
...
...
@@ -51,26 +44,8 @@ class AsEmptyView: UIView {
return
btn
}()
private
lazy
var
netStackView
:
UIStackView
=
{
let
stackView
=
UIStackView
(
arrangedSubviews
:
[
netLab
,
refreshBtn
])
stackView
.
axis
=
.
vertical
stackView
.
alignment
=
.
center
stackView
.
distribution
=
.
equalSpacing
stackView
.
spacing
=
15
return
stackView
}()
private
lazy
var
noDataStackView
:
UIStackView
=
{
let
stackView
=
UIStackView
(
arrangedSubviews
:
[
noDataLab
])
stackView
.
axis
=
.
vertical
stackView
.
alignment
=
.
center
stackView
.
distribution
=
.
equalSpacing
stackView
.
spacing
=
20
return
stackView
}()
private
lazy
var
containerStackView
:
UIStackView
=
{
let
stackView
=
UIStackView
(
arrangedSubviews
:
[
placeHolder
,
netStackView
,
noDataStackView
])
let
stackView
=
UIStackView
(
arrangedSubviews
:
[
placeHolder
,
messageLab
,
refreshBtn
])
stackView
.
axis
=
.
vertical
stackView
.
alignment
=
.
center
stackView
.
distribution
=
.
equalSpacing
...
...
@@ -87,6 +62,8 @@ class AsEmptyView: UIView {
containerStackView
.
snp
.
makeConstraints
{
make
in
make
.
center
.
equalToSuperview
()
make
.
left
.
equalToSuperview
()
.
offset
(
10
)
make
.
right
.
equalToSuperview
()
.
offset
(
-
10
)
}
refreshBtn
.
snp
.
makeConstraints
{
make
in
...
...
@@ -105,14 +82,15 @@ extension AsEmptyView {
if
type
==
.
netErr
{
placeHolder
.
image
=
R
.
image
.
net_err
()
netStackView
.
isHidden
=
false
noDataStackView
.
isHidden
=
true
netLab
.
text
=
message
??
"请检查您的网络设置或刷新重试"
messageLab
.
text
=
message
??
"请检查您的网络设置或刷新重试"
}
else
if
type
==
.
noData
{
placeHolder
.
image
=
R
.
image
.
no_data
()
netStackView
.
isHidden
=
true
noDataStackView
.
isHidden
=
false
messageLab
.
text
=
"暂无数据,请刷新重试"
}
else
if
type
==
.
other
{
placeHolder
.
image
=
R
.
image
.
no_data
()
messageLab
.
text
=
message
??
""
}
}
...
...
@@ -124,3 +102,40 @@ extension AsEmptyView {
refreshAction
?()
}
}
////MARK: - UIView+EmptyView
//extension UITableView {
// private enum AssociatedKeys {
// static var emptyViewKey: Void?
// }
//
// private var emptyView: AsEmptyView? {
// get {
// return objc_getAssociatedObject(self, &AssociatedKeys.emptyViewKey) as? AsEmptyView
// }
// set {
// objc_setAssociatedObject(self, &AssociatedKeys.emptyViewKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
// }
// }
//
// // 显示空视图
// func showEmptyView(type: EmptyType, message: String? = nil, refreshAction: (() -> Void)? = nil) {
// if emptyView == nil {
// let ev = AsEmptyView(frame: .zero)
// addSubview(ev)
// ev.snp.makeConstraints { make in
// make.center.equalToSuperview()
// }
// emptyView = ev
// }
// emptyView?.refreshAction = refreshAction
// emptyView?.show(type: type, message: message)
// }
//
// // 隐藏空视图
// func hideEmptyView() {
// emptyView?.dismiss()
// emptyView?.removeFromSuperview()
// emptyView = nil
// }
//}
AoleiSports/Src/Base/BaseController.swift
查看文件 @
8613f64
...
...
@@ -31,6 +31,7 @@ class BaseController: UIViewController {
}
}
//MARK: - Empty处理
extension
BaseController
{
func
showEmpty
(
type
:
EmptyType
,
message
:
String
?
=
nil
)
{
emptyView
.
show
(
type
:
type
,
message
:
message
)
...
...
@@ -41,6 +42,6 @@ extension BaseController {
}
@objc
func
handleRefresh
()
{
dismissEmpty
()
}
}
AoleiSports/Src/Ext/UIImage+Ext.swift
查看文件 @
8613f64
...
...
@@ -16,3 +16,14 @@ extension UIImage {
return
resizedImage
}
}
extension
UIImage
{
convenience
init
(
color
:
UIColor
,
size
:
CGSize
)
{
UIGraphicsBeginImageContextWithOptions
(
size
,
false
,
0.0
)
color
.
setFill
()
UIRectFill
(
CGRect
(
origin
:
.
zero
,
size
:
size
))
let
image
=
UIGraphicsGetImageFromCurrentImageContext
()
UIGraphicsEndImageContext
()
self
.
init
(
cgImage
:
image
!.
cgImage
!
)
}
}
AoleiSports/Src/Ext/UIView+Ext.swift
查看文件 @
8613f64
...
...
@@ -21,8 +21,8 @@ extension UIView {
}
// 分割线
static
func
divider
(
color
:
UIColor
=
kDividerColor
)
->
UIView
{
let
line
=
UIView
()
static
func
divider
(
frame
:
CGRect
=
.
zero
,
color
:
UIColor
=
kDividerColor
)
->
UIView
{
let
line
=
UIView
(
frame
:
frame
)
line
.
backgroundColor
=
color
return
line
}
...
...
AoleiSports/Src/Information/InfoController.swift
查看文件 @
8613f64
...
...
@@ -9,6 +9,8 @@ import UIKit
// 赛事情报页面
class
InfoController
:
BaseController
{
private
let
MatchInfoCellId
=
"MatchInfoCell"
var
provider
:
InfoProvider
<
InfoTarget
>
?
private
lazy
var
infoListView
:
UITableView
=
{
...
...
@@ -17,7 +19,10 @@ class InfoController: BaseController {
tv
.
dataSource
=
self
tv
.
rowHeight
=
100
tv
.
backgroundColor
=
kMainBgColor
tv
.
register
(
MatchInfoCell
.
self
,
forCellReuseIdentifier
:
"MatchInfoCell"
)
tv
.
register
(
MatchInfoCell
.
self
,
forCellReuseIdentifier
:
MatchInfoCellId
)
tv
.
es
.
addPullToRefresh
(
animator
:
RefreshHeaderAnimator
(
frame
:
.
zero
))
{
[
weak
self
]
in
self
?
.
handleRefresh
()
}
return
tv
}()
...
...
@@ -25,49 +30,65 @@ class InfoController: BaseController {
super
.
viewDidLoad
()
gk_navTitle
=
"赛事情报"
provider
=
InfoProvider
(
vc
:
self
,
showErr
:
false
)
view
.
addSubview
(
infoListView
)
initProvider
()
handleRefresh
()
}
deinit
{
infoListView
.
es
.
removeRefreshHeader
()
}
private
func
initProvider
()
{
provider
=
InfoProvider
(
vc
:
self
,
showErr
:
false
)
provider
?
.
infoDataList
.
asObservable
()
.
subscribe
(
onNext
:
{
infoModels
in
print
(
"InfoDataList changed:
\(
infoModels
)
"
)
self
.
infoListView
.
reloadData
()
if
infoModels
.
isEmpty
{
self
.
infoListView
.
isHidden
=
true
self
.
showEmpty
(
type
:
.
noData
)
}
else
{
// 数据不为空后面刷新操作换成下拉刷新
self
.
dismissEmpty
()
self
.
provider
?
.
initLoading
=
false
self
.
infoListView
.
isHidden
=
false
}
})
.
disposed
(
by
:
disposeBag
)
}
override
func
touchesBegan
(
_
touches
:
Set
<
UITouch
>
,
with
event
:
UIEvent
?)
{
handleRefresh
()
}
override
func
handleRefresh
()
{
super
.
handleRefresh
()
dismissEmpty
()
provider
?
.
liveScoreRequest
(
completion
:
{
logicResult
in
if
self
.
provider
!.
initLoading
==
false
{
self
.
infoListView
.
es
.
stopPullToRefresh
()
}
if
case
.
failure
(
let
err
)
=
logicResult
{
if
case
AsError
.
netErr
(
let
message
)
=
err
{
if
self
.
provider
!.
infoDataList
.
value
.
isEmpty
&&
self
.
provider
!.
initLoading
==
true
{
self
.
infoListView
.
isHidden
=
true
self
.
showEmpty
(
type
:
.
netErr
,
message
:
message
)
if
case
AsError
.
netErr
(
let
message
)
=
err
{
self
.
showEmpty
(
type
:
.
netErr
,
message
:
message
)
}
else
{
self
.
showEmpty
(
type
:
.
other
,
message
:
err
.
localizedDescription
)
}
}
else
{
self
.
view
.
makeToast
(
err
.
localizedDescription
,
position
:
.
center
)
}
return
}
})
}
}
//MARK: UITableViewDelegate, UITableViewDataSource
extension
InfoController
:
UITableViewDelegate
,
UITableViewDataSource
{
func
tableView
(
_
tableView
:
UITableView
,
numberOfRowsInSection
section
:
Int
)
->
Int
{
return
provider
?
.
infoDataList
.
value
.
count
??
0
...
...
@@ -75,51 +96,15 @@ extension InfoController: UITableViewDelegate, UITableViewDataSource {
func
tableView
(
_
tableView
:
UITableView
,
cellForRowAt
indexPath
:
IndexPath
)
->
UITableViewCell
{
let
model
=
provider
?
.
infoDataList
.
value
[
indexPath
.
row
]
let
cell
=
tableView
.
dequeueReusableCell
(
withIdentifier
:
"MatchInfoCell"
,
for
:
indexPath
)
as!
MatchInfoCell
model
?
.
isLast
=
indexPath
.
row
==
(
provider
?
.
infoDataList
.
value
.
count
??
0
)
-
1
let
cell
=
tableView
.
dequeueReusableCell
(
withIdentifier
:
MatchInfoCellId
,
for
:
indexPath
)
as!
MatchInfoCell
cell
.
model
=
model
return
cell
}
}
class
MatchInfoCell
:
BaseTableViewCell
{
private
lazy
var
cornerBgView
:
UIView
=
{
let
view
=
UIView
()
view
.
backgroundColor
=
kWhite
view
.
corners
(
radius
:
10
)
return
view
}()
private
lazy
var
teamLab
:
UILabel
=
{
let
lab
=
UILabel
()
lab
.
textColor
=
kMainTitleColor
lab
.
font
=
kFontSize
(
16
)
return
lab
}()
var
model
:
InfoModel
?
{
didSet
{
teamLab
.
text
=
(
model
?
.
hostName
??
""
)
+
"VS"
+
(
model
?
.
guestName
??
""
)
}
}
override
init
(
style
:
UITableViewCell
.
CellStyle
,
reuseIdentifier
:
String
?)
{
super
.
init
(
style
:
style
,
reuseIdentifier
:
reuseIdentifier
)
contentView
.
addSubview
(
cornerBgView
)
cornerBgView
.
addSubview
(
teamLab
)
cornerBgView
.
snp
.
makeConstraints
{
make
in
make
.
left
.
top
.
equalToSuperview
()
.
offset
(
5
)
make
.
right
.
equalToSuperview
()
.
offset
(
-
5
)
make
.
bottom
.
equalToSuperview
()
}
teamLab
.
snp
.
makeConstraints
{
make
in
make
.
left
.
top
.
equalToSuperview
()
.
offset
(
5
)
}
}
required
init
?(
coder
:
NSCoder
)
{
fatalError
(
"init(coder:) has not been implemented"
)
func
tableView
(
_
tableView
:
UITableView
,
didSelectRowAt
indexPath
:
IndexPath
)
{
let
infoDetail
=
InfoDetailController
()
infoDetail
.
model
=
provider
?
.
infoDataList
.
value
[
indexPath
.
row
]
navigationController
?
.
pushViewController
(
infoDetail
,
animated
:
true
)
}
}
AoleiSports/Src/Information/InfoDetailController.swift
查看文件 @
8613f64
...
...
@@ -9,15 +9,11 @@ import UIKit
// 情报详情页面
class
InfoDetailController
:
BaseController
{
var
model
:
InfoModel
?
{
didSet
{
gk_navTitle
=
(
model
?
.
hostName
??
""
)
+
"VS"
+
(
model
?
.
guestName
??
""
)
}
}
var
model
:
InfoModel
?
override
func
viewDidLoad
()
{
super
.
viewDidLoad
()
gk_navTitle
=
(
model
?
.
hostName
??
""
)
+
"VS"
+
(
model
?
.
guestName
??
""
)
}
}
AoleiSports/Src/Information/InfoModel.swift
查看文件 @
8613f64
...
...
@@ -27,6 +27,8 @@ class InfoModel: Mappable {
var
sportsInfoCount
:
Int
?
var
jcInfo
:
String
?
var
isLast
:
Bool
?
required
init
?(
map
:
ObjectMapper
.
Map
)
{
}
...
...
AoleiSports/Src/Information/InfoProvider.swift
查看文件 @
8613f64
...
...
@@ -58,18 +58,18 @@ enum InfoTarget: TargetType {
class
InfoProvider
<
Target
:
TargetType
>
:
BaseMoyaProvider
<
Target
>
{
var
infoDataList
=
BehaviorRelay
<
[
InfoModel
]
>
(
value
:
[])
func
liveScoreRequest
(
completion
:
@escaping
(
Result
<
Bool
,
AsError
>
)
->
Void
)
{
moyaPost
(
api
:
APIs
.
kLiveScore
,
target
:
InfoTarget
.
info
)
{
midResult
in
DDLogInfo
(
"赛事情报接口数据:
\(
midResult
)
"
)
//
DDLogInfo("赛事情报接口数据:\(midResult)")
switch
midResult
{
case
let
.
success
(
midSuccessResult
):
guard
let
matchs
=
midSuccessResult
[
"matchs"
]
as?
[[
String
:
Any
]]
else
{
guard
let
matchs
=
midSuccessResult
[
"matchs"
]
as?
[[
String
:
Any
]]
,
!
matchs
.
isEmpty
else
{
self
.
infoDataList
.
accept
([])
return
}
// 过滤出
JcInfo
非空的项
// 过滤出
JcInfo
非空的项
let
filteredMatchs
=
matchs
.
filter
{
match
in
guard
let
jcInfo
=
match
[
"JcInfo"
]
as?
String
,
!
jcInfo
.
isEmpty
else
{
return
false
...
...
@@ -78,7 +78,6 @@ class InfoProvider<Target: TargetType>: BaseMoyaProvider<Target> {
}
let
infoModels
=
Mapper
<
InfoModel
>
()
.
mapArray
(
JSONArray
:
filteredMatchs
)
self
.
infoDataList
.
accept
(
infoModels
)
completion
(
.
success
(
true
))
case
.
failure
(
let
err
):
completion
(
.
failure
(
err
))
...
...
AoleiSports/Src/Information/MatchInfoCell.swift
0 → 100644
查看文件 @
8613f64
//
// MatchInfoCell.swift
// AoleiSports
//
// Created by ilCode on 2024/6/18.
//
import
UIKit
class
MatchInfoCell
:
BaseTableViewCell
{
private
lazy
var
cornerBgView
:
UIView
=
{
let
view
=
UIView
()
view
.
backgroundColor
=
kWhite
view
.
corners
(
radius
:
5
)
return
view
}()
private
lazy
var
teamLab
:
UILabel
=
{
let
lab
=
UILabel
()
lab
.
textColor
=
kMainTitleColor
lab
.
font
=
kFontSize
(
16
)
return
lab
}()
var
model
:
InfoModel
?
{
didSet
{
teamLab
.
text
=
(
model
?
.
hostName
??
""
)
+
"VS"
+
(
model
?
.
guestName
??
""
)
cornerBgView
.
snp
.
remakeConstraints
{
make
in
make
.
left
.
top
.
equalToSuperview
()
.
offset
(
8
)
make
.
right
.
equalToSuperview
()
.
offset
(
-
8
)
make
.
bottom
.
equalToSuperview
()
.
offset
((
model
?
.
isLast
??
false
)
?
-
8
:
0
)
}
}
}
override
init
(
style
:
UITableViewCell
.
CellStyle
,
reuseIdentifier
:
String
?)
{
super
.
init
(
style
:
style
,
reuseIdentifier
:
reuseIdentifier
)
contentView
.
backgroundColor
=
kMainBgColor
contentView
.
addSubview
(
cornerBgView
)
cornerBgView
.
addSubview
(
teamLab
)
cornerBgView
.
snp
.
makeConstraints
{
make
in
make
.
left
.
top
.
equalToSuperview
()
.
offset
(
8
)
make
.
right
.
equalToSuperview
()
.
offset
(
-
8
)
make
.
bottom
.
equalToSuperview
()
}
teamLab
.
snp
.
makeConstraints
{
make
in
make
.
left
.
top
.
equalToSuperview
()
.
offset
(
5
)
}
}
required
init
?(
coder
:
NSCoder
)
{
fatalError
(
"init(coder:) has not been implemented"
)
}
}
AoleiSports/Src/Root/RootController.swift
查看文件 @
8613f64
...
...
@@ -23,6 +23,9 @@ class RootController: UITabBarController {
// 设置tabbar选中及未选中的文字颜色
tabBar
.
tintColor
=
kMasterColor
tabBar
.
unselectedItemTintColor
=
kSubTitleColor
// 自定义分割线
tabBar
.
addSubview
(
UIView
.
divider
(
frame
:
CGRect
(
x
:
0
,
y
:
0
,
width
:
kScreenW
,
height
:
1
)))
addController
(
rootVC
:
HomeController
(),
title
:
"赛事比分"
,
image
:
R
.
image
.
home
(),
selectedImage
:
R
.
image
.
home_selected
())
addController
(
rootVC
:
InfoController
(),
title
:
"赛事情报"
,
image
:
R
.
image
.
ssqb
(),
selectedImage
:
R
.
image
.
ssqb_selected
())
...
...
AoleiSports/Src/Root/en.lproj/LaunchScreen.strings
查看文件 @
8613f64
AoleiSports/Src/Root/zh-Hans.lproj/LaunchScreen.strings
0 → 100644
查看文件 @
8613f64
AoleiSports/Src/Utils/ImportTools.swift
查看文件 @
8613f64
...
...
@@ -15,3 +15,4 @@
@_exported
import
SwiftyJSON
@_exported
import
RxGesture
@_exported
import
ObjectMapper
@_exported
import
ESPullToRefresh
AoleiSports/Src/Utils/NetworkTools.swift
查看文件 @
8613f64
...
...
@@ -73,13 +73,15 @@ extension TargetType {
final
class
BaseMoyaPlugin
:
PluginType
{
var
vc
:
UIViewController
?
private
var
spinner
:
NVActivityIndicatorView
!
var
initLoading
:
Bool
=
true
var
showErr
:
Bool
=
true
init
(
vc
:
UIViewController
?,
show
Loading
:
Bool
=
true
,
showErr
:
Bool
=
true
)
{
init
(
vc
:
UIViewController
?,
init
Loading
:
Bool
=
true
,
showErr
:
Bool
=
true
)
{
self
.
vc
=
vc
self
.
initLoading
=
initLoading
self
.
showErr
=
showErr
if
let
tmpVC
=
self
.
vc
,
show
Loading
{
if
let
tmpVC
=
self
.
vc
,
init
Loading
{
spinner
=
NVActivityIndicatorView
(
frame
:
CGRect
(
x
:
0
,
y
:
0
,
width
:
60
,
height
:
55
),
type
:
.
ballSpinFadeLoader
,
color
:
kMasterColor
)
spinner
.
center
=
tmpVC
.
view
.
center
}
...
...
@@ -96,7 +98,7 @@ final class BaseMoyaPlugin: PluginType {
}
func
willSend
(
_
request
:
any
RequestType
,
target
:
any
TargetType
)
{
if
let
tmpVC
=
self
.
vc
,
let
spinner
=
spinner
{
if
let
tmpVC
=
self
.
vc
,
initLoading
,
let
spinner
=
spinner
{
DispatchQueue
.
main
.
async
{
tmpVC
.
view
.
addSubview
(
spinner
)
spinner
.
startAnimating
()
...
...
@@ -106,7 +108,7 @@ final class BaseMoyaPlugin: PluginType {
func
didReceive
(
_
result
:
Result
<
Response
,
MoyaError
>
,
target
:
any
TargetType
)
{
// 移除界面中央的活动状态指示器
if
let
spinner
=
spinner
{
if
let
spinner
=
spinner
,
initLoading
{
DispatchQueue
.
main
.
async
{
spinner
.
removeFromSuperview
()
spinner
.
stopAnimating
()
...
...
@@ -132,10 +134,16 @@ final class BaseMoyaPlugin: PluginType {
class
BaseMoyaProvider
<
Target
:
TargetType
>
:
MoyaProvider
<
Target
>
{
let
disposeBag
=
DisposeBag
()
var
basePlugin
:
BaseMoyaPlugin
var
initLoading
:
Bool
=
true
{
didSet
{
basePlugin
.
initLoading
=
initLoading
}
}
init
(
vc
:
UIViewController
?
=
nil
,
show
Loading
:
Bool
=
true
,
showErr
:
Bool
=
true
)
{
self
.
basePlugin
=
BaseMoyaPlugin
(
vc
:
vc
,
showLoading
:
show
Loading
,
showErr
:
showErr
)
init
(
vc
:
UIViewController
?
=
nil
,
init
Loading
:
Bool
=
true
,
showErr
:
Bool
=
true
)
{
self
.
basePlugin
=
BaseMoyaPlugin
(
vc
:
vc
,
initLoading
:
init
Loading
,
showErr
:
showErr
)
super
.
init
(
plugins
:
[
self
.
basePlugin
])
self
.
initLoading
=
initLoading
}
/// Moya Post
...
...
AoleiSports/Src/Vendors/Refresh/RefreshFooterAnimator.swift
0 → 100644
查看文件 @
8613f64
//
// RefreshFooterAnimator.swift
// AoleiSports
//
// Created by ilCode on 2024/6/19.
//
import
UIKit
//MARK: - 自定义刷新尾
public
class
RefreshFooterAnimator
:
UIView
,
ESRefreshProtocol
,
ESRefreshAnimatorProtocol
{
public
let
loadingMoreDescription
:
String
=
"Loading more"
public
let
noMoreDataDescription
:
String
=
"No more data"
public
let
loadingDescription
:
String
=
"Loading..."
public
var
view
:
UIView
{
return
self
}
public
var
insets
:
UIEdgeInsets
=
UIEdgeInsets
.
zero
public
var
trigger
:
CGFloat
=
48.0
public
var
executeIncremental
:
CGFloat
=
48.0
public
var
state
:
ESRefreshViewState
=
.
pullToRefresh
private
let
topLine
:
UIView
=
{
let
topLine
=
UIView
.
init
(
frame
:
CGRect
.
zero
)
topLine
.
backgroundColor
=
UIColor
.
init
(
red
:
214
/
255.0
,
green
:
211
/
255.0
,
blue
:
206
/
255.0
,
alpha
:
1.0
)
return
topLine
}()
private
let
bottomLine
:
UIView
=
{
let
bottomLine
=
UIView
.
init
(
frame
:
CGRect
.
zero
)
bottomLine
.
backgroundColor
=
UIColor
.
init
(
red
:
214
/
255.0
,
green
:
211
/
255.0
,
blue
:
206
/
255.0
,
alpha
:
1.0
)
return
bottomLine
}()
private
let
titleLabel
:
UILabel
=
{
let
label
=
UILabel
.
init
(
frame
:
CGRect
.
zero
)
label
.
font
=
UIFont
.
systemFont
(
ofSize
:
14.0
)
label
.
textColor
=
UIColor
.
init
(
white
:
160.0
/
255.0
,
alpha
:
1.0
)
label
.
textAlignment
=
.
center
return
label
}()
private
let
indicatorView
:
UIActivityIndicatorView
=
{
let
indicatorView
=
UIActivityIndicatorView
.
init
(
style
:
.
medium
)
indicatorView
.
isHidden
=
true
return
indicatorView
}()
override
init
(
frame
:
CGRect
)
{
super
.
init
(
frame
:
frame
)
self
.
backgroundColor
=
UIColor
.
white
titleLabel
.
text
=
loadingMoreDescription
addSubview
(
titleLabel
)
addSubview
(
indicatorView
)
addSubview
(
topLine
)
addSubview
(
bottomLine
)
}
public
required
init
(
coder
aDecoder
:
NSCoder
)
{
fatalError
(
"init(coder:) has not been implemented"
)
}
public
func
refreshAnimationBegin
(
view
:
ESRefreshComponent
)
{
indicatorView
.
startAnimating
()
indicatorView
.
isHidden
=
false
}
public
func
refreshAnimationEnd
(
view
:
ESRefreshComponent
)
{
indicatorView
.
stopAnimating
()
indicatorView
.
isHidden
=
true
}
public
func
refresh
(
view
:
ESRefreshComponent
,
progressDidChange
progress
:
CGFloat
)
{
// do nothing
}
public
func
refresh
(
view
:
ESRefreshComponent
,
stateDidChange
state
:
ESRefreshViewState
)
{
switch
state
{
case
.
refreshing
:
titleLabel
.
text
=
loadingDescription
break
case
.
autoRefreshing
:
titleLabel
.
text
=
loadingDescription
break
case
.
noMoreData
:
titleLabel
.
text
=
noMoreDataDescription
break
default
:
titleLabel
.
text
=
loadingMoreDescription
break
}
}
public
override
func
layoutSubviews
()
{
super
.
layoutSubviews
()
let
s
=
self
.
bounds
.
size
let
w
=
s
.
width
let
h
=
s
.
height
titleLabel
.
frame
=
self
.
bounds
indicatorView
.
center
=
CGPoint
.
init
(
x
:
32.0
,
y
:
h
/
2.0
)
topLine
.
frame
=
CGRect
.
init
(
x
:
0.0
,
y
:
0.0
,
width
:
w
,
height
:
0.5
)
bottomLine
.
frame
=
CGRect
.
init
(
x
:
0.0
,
y
:
h
-
1.0
,
width
:
w
,
height
:
1.0
)
}
}
AoleiSports/Src/Vendors/Refresh/RefreshHeaderAnimator.swift
0 → 100755
查看文件 @
8613f64
//
// RefreshHeaderAnimator.swift
// LittleDreamSleep
//
// Created by peter on 2022/8/24.
//
import
UIKit
//MARK: - 自定义刷新头
class
RefreshHeaderAnimator
:
UIView
,
ESRefreshAnimatorProtocol
{
public
var
view
:
UIView
{
return
self
}
public
var
insets
:
UIEdgeInsets
=
UIEdgeInsets
.
zero
public
var
trigger
:
CGFloat
=
60.0
public
var
executeIncremental
:
CGFloat
=
60.0
public
var
state
:
ESRefreshViewState
=
.
pullToRefresh
let
aniImageView
=
UIImageView
(
image
:
R
.
image
.
refresh_icon
())
override
init
(
frame
:
CGRect
)
{
super
.
init
(
frame
:
frame
)
aniImageView
.
frame
=
CGRect
(
x
:
(
kScreenW
-
30
)
/
2.0
,
y
:
(
60
-
30
)
/
2.0
,
width
:
30
,
height
:
30
)
addSubview
(
aniImageView
)
}
public
required
init
(
coder
aDecoder
:
NSCoder
)
{
fatalError
(
"init(coder:) has not been implemented"
)
}
}
//MARK: - ESRefreshProtocol
extension
RefreshHeaderAnimator
:
ESRefreshProtocol
{
public
func
refreshAnimationBegin
(
view
:
ESRefreshComponent
)
{
aniImageView
.
frame
=
CGRect
(
x
:
(
self
.
bounds
.
size
.
width
-
30
)
/
2.0
,
y
:
(
self
.
bounds
.
size
.
height
-
30
)
/
2.0
,
width
:
30
,
height
:
30
)
startAnimation
()
}
public
func
refreshAnimationEnd
(
view
:
ESRefreshComponent
)
{
stopAnimation
()
}
public
func
refresh
(
view
:
ESRefreshComponent
,
progressDidChange
progress
:
CGFloat
)
{
}
public
func
refresh
(
view
:
ESRefreshComponent
,
stateDidChange
state
:
ESRefreshViewState
)
{
guard
self
.
state
!=
state
else
{
return
}
self
.
state
=
state
switch
state
{
case
.
pullToRefresh
:
break
case
.
releaseToRefresh
:
break
default
:
break
}
}
}
extension
RefreshHeaderAnimator
{
@objc
func
startAnimation
()
{
let
animation
=
CABasicAnimation
(
keyPath
:
"transform.rotation.z"
)
animation
.
toValue
=
NSNumber
(
value
:
Double
.
pi
*
2
)
animation
.
duration
=
2.0
animation
.
repeatCount
=
Float
.
infinity
aniImageView
.
layer
.
add
(
animation
,
forKey
:
"rotationAnimation"
)
}
@objc
func
stopAnimation
()
{
aniImageView
.
layer
.
removeAnimation
(
forKey
:
"rotationAnimation"
)
}
}
//MARK: - 3D动画
extension
RefreshHeaderAnimator
{
// import SceneKit
// var sceneView: SCNView!
// 创建旋转动画
// let animation = CABasicAnimation(keyPath: "transform.rotation.z")
// animation.toValue = NSNumber(value: Double.pi * 2)
// animation.duration = 3.0
// animation.repeatCount = Float.infinity
// aniImageView.layer.add(animation, forKey: nil)
// 创建 SceneKit 视图
// sceneView = SCNView(frame: CGRect(x: (kScreenW - w)/2.0, y: 0, width: 60, height: 60))
// addSubview(sceneView)
// sceneView.border()
// 创建场景
// let scene = SCNScene()
// sceneView.scene = scene
// sceneView.allowsCameraControl = true
// sceneView.autoenablesDefaultLighting = true
// 创建球体几何体
// let sphere = SCNSphere(radius: 1.5)
//
// // 添加球体材质
// let material = SCNMaterial()
// material.diffuse.contents = UIImage(named: "football_texture.jpg")
// sphere.firstMaterial = material
//
// // 创建球体节点
// let sphereNode = SCNNode(geometry: sphere)
// sphereNode.position = SCNVector3(0, 0, 0)
// scene.rootNode.addChildNode(sphereNode)
//
// // 创建绕球体旋转的动画
// let rotateAction = SCNAction.rotateBy(x: 0, y: CGFloat(2 * Double.pi), z: 0, duration: 3)
// let repeatAction = SCNAction.repeatForever(rotateAction)
// sphereNode.runAction(repeatAction)
//
// // 添加相机
// let cameraNode = SCNNode()
// cameraNode.camera = SCNCamera()
// cameraNode.position = SCNVector3(0, 0, 5)
// scene.rootNode.addChildNode(cameraNode)
}
Podfile
查看文件 @
8613f64
...
...
@@ -15,6 +15,7 @@ target 'AoleiSports' do
pod
'Toast-Swift'
,
'~> 5.1.1'
pod
'ObjectMapper'
,
'~> 4.4.2'
pod
'RxGesture'
,
'~> 4.0.4'
pod
'ESPullToRefresh'
,
'~> 2.9.3'
end
...
...
Podfile.lock
查看文件 @
8613f64
...
...
@@ -3,6 +3,7 @@ PODS:
- CocoaLumberjack/Core (3.8.5)
- CocoaLumberjack/Swift (3.8.5):
- CocoaLumberjack/Core
- ESPullToRefresh (2.9.3)
- Moya/Core (15.0.0):
- Alamofire (~> 5.0)
- Moya/RxSwift (15.0.0):
...
...
@@ -29,6 +30,7 @@ PODS:
DEPENDENCIES:
- Alamofire (~> 5.9.1)
- CocoaLumberjack/Swift
- ESPullToRefresh (~> 2.9.3)
- Moya/RxSwift (~> 15.0)
- NVActivityIndicatorView (~> 5.2.0)
- ObjectMapper (~> 4.4.2)
...
...
@@ -44,6 +46,7 @@ SPEC REPOS:
trunk:
- Alamofire
- CocoaLumberjack
- ESPullToRefresh
- Moya
- NVActivityIndicatorView
- ObjectMapper
...
...
@@ -59,6 +62,7 @@ SPEC REPOS:
SPEC CHECKSUMS:
Alamofire: f36a35757af4587d8e4f4bfa223ad10be2422b8c
CocoaLumberjack: 6a459bc897d6d80bd1b8c78482ec7ad05dffc3f0
ESPullToRefresh: 0d68daa602b343c81753a1b95e09fd0bfcddfd40
Moya: 138f0573e53411fb3dc17016add0b748dfbd78ee
NVActivityIndicatorView: fe52a6a68664c2df8991d7d9e3d86d8d19453c53
ObjectMapper: e6e4d91ff7f2861df7aecc536c92d8363f4c9677
...
...
@@ -71,6 +75,6 @@ SPEC CHECKSUMS:
SwiftyJSON: f5b1bf1cd8dd53cd25887ac0eabcfd92301c6a5a
Toast-Swift: 7a03a532afe3a560d4044bc7c237e2864d295173
PODFILE CHECKSUM:
0ed9736004dd278591ebfa22937383fb27c4e17f
PODFILE CHECKSUM:
aaab2dc38f3bdf57b45edf6252d34b03cda60517
COCOAPODS: 1.15.2
R.generated.swift
查看文件 @
8613f64
...
...
@@ -44,25 +44,55 @@ struct _R {
}
struct
project
{
let
developmentRegion
=
"
en
"
let
developmentRegion
=
"
zh-Hans
"
}
/// This `_R.string` struct is generated, and contains static references to
1
localization tables.
/// This `_R.string` struct is generated, and contains static references to
2
localization tables.
struct
string
{
let
bundle
:
Foundation
.
Bundle
let
preferredLanguages
:
[
String
]?
let
locale
:
Locale
?
var
launchScreen
:
launchScreen
{
.
init
(
source
:
.
init
(
bundle
:
bundle
,
tableName
:
"LaunchScreen"
,
preferredLanguages
:
preferredLanguages
,
locale
:
locale
))
}
var
localizable
:
localizable
{
.
init
(
source
:
.
init
(
bundle
:
bundle
,
tableName
:
"Localizable"
,
preferredLanguages
:
preferredLanguages
,
locale
:
locale
))
}
func
launchScreen
(
preferredLanguages
:
[
String
])
->
launchScreen
{
.
init
(
source
:
.
init
(
bundle
:
bundle
,
tableName
:
"LaunchScreen"
,
preferredLanguages
:
preferredLanguages
,
locale
:
locale
))
}
func
localizable
(
preferredLanguages
:
[
String
])
->
localizable
{
.
init
(
source
:
.
init
(
bundle
:
bundle
,
tableName
:
"Localizable"
,
preferredLanguages
:
preferredLanguages
,
locale
:
locale
))
}
/// This `_R.string.launchScreen` struct is generated, and contains static references to 0 localization keys.
struct
launchScreen
{
let
source
:
RswiftResources
.
StringResource
.
Source
}
/// This `_R.string.localizable` struct is generated, and contains static references to 3 localization keys.
struct
localizable
{
let
source
:
RswiftResources
.
StringResource
.
Source
/// zh-Hans translation: 加载更多
///
/// Key: Loading more
///
/// Locales: en, zh-Hans
var
loadingMore
:
RswiftResources
.
StringResource
{
.
init
(
key
:
"Loading more"
,
tableName
:
"Localizable"
,
source
:
source
,
developmentValue
:
"加载更多"
,
comment
:
nil
)
}
/// zh-Hans translation: 加载中...
///
/// Key: Loading...
///
/// Locales: en, zh-Hans
var
loading
:
RswiftResources
.
StringResource
{
.
init
(
key
:
"Loading..."
,
tableName
:
"Localizable"
,
source
:
source
,
developmentValue
:
"加载中..."
,
comment
:
nil
)
}
/// zh-Hans translation: 没有更多数据
///
/// Key: No more data
///
/// Locales: en, zh-Hans
var
noMoreData
:
RswiftResources
.
StringResource
{
.
init
(
key
:
"No more data"
,
tableName
:
"Localizable"
,
source
:
source
,
developmentValue
:
"没有更多数据"
,
comment
:
nil
)
}
}
}
/// This `_R.color` struct is generated, and contains static references to 1 colors.
...
...
@@ -73,7 +103,7 @@ struct _R {
var
accentColor
:
RswiftResources
.
ColorResource
{
.
init
(
name
:
"AccentColor"
,
path
:
[],
bundle
:
bundle
)
}
}
/// This `_R.image` struct is generated, and contains static references to 2
2
images.
/// This `_R.image` struct is generated, and contains static references to 2
3
images.
struct
image
{
let
bundle
:
Foundation
.
Bundle
...
...
@@ -134,6 +164,9 @@ struct _R {
/// Image `profile_selected`.
var
profile_selected
:
RswiftResources
.
ImageResource
{
.
init
(
name
:
"profile_selected"
,
path
:
[],
bundle
:
bundle
,
locale
:
nil
,
onDemandResourceTags
:
nil
)
}
/// Image `refresh_icon`.
var
refresh_icon
:
RswiftResources
.
ImageResource
{
.
init
(
name
:
"refresh_icon"
,
path
:
[],
bundle
:
bundle
,
locale
:
nil
,
onDemandResourceTags
:
nil
)
}
/// Image `right_arrow_icon`.
var
right_arrow_icon
:
RswiftResources
.
ImageResource
{
.
init
(
name
:
"right_arrow_icon"
,
path
:
[],
bundle
:
bundle
,
locale
:
nil
,
onDemandResourceTags
:
nil
)
}
...
...
编写
预览
支持
Markdown
格式
附加文件
你添加了
0
人
到此讨论。请谨慎行事。
Finish editing this message first!
Cancel
请
注册
或
登录
后发表评论