Commit e9c9b92a ilCode

框架搭建

1 个父辈 8af6555d
正在显示 69 个修改的文件 包含 1231 行增加62 行删除
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>_XCCurrentVersionName</key>
<string>AoleiSports.xcdatamodel</string>
</dict>
</plist>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="22757" systemVersion="23E224" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
<entity name="FilterCompetition" representedClassName="FilterCompetition" syncable="YES" codeGenerationType="class">
<attribute name="first_letter" optional="YES" attributeType="String"/>
<attribute name="id" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="is_hot" optional="YES" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="is_selected" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="leisu_competition_id" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="level" optional="YES" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="match_count" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="type" optional="YES" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="update_time" optional="YES" attributeType="String"/>
<attribute name="yiqiu_id" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="yiqiu_name" optional="YES" attributeType="String"/>
<attribute name="yiqiu_short_name" optional="YES" attributeType="String"/>
</entity>
<entity name="NmCompetition" representedClassName=".NmCompetition" syncable="YES" codeGenerationType="class">
<attribute name="area_id" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="area_name" optional="YES" attributeType="String"/>
<attribute name="end_date" optional="YES" attributeType="String"/>
<attribute name="first_letter" optional="YES" attributeType="String"/>
<attribute name="hot_order" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="id" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="is_hot" optional="YES" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="is_league" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="is_selected" optional="YES" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
<attribute name="leisu_competition_id" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="level" optional="YES" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="rank_memo" optional="YES" attributeType="String"/>
<attribute name="sort_id" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="start_date" optional="YES" attributeType="String"/>
<attribute name="status" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="yiqiu_competition_mode" optional="YES" attributeType="String"/>
<attribute name="yiqiu_competition_round" optional="YES" attributeType="String"/>
<attribute name="yiqiu_competition_season" optional="YES" attributeType="String"/>
<attribute name="yiqiu_en_name" optional="YES" attributeType="String"/>
<attribute name="yiqiu_id" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="yiqiu_logo" optional="YES" attributeType="String"/>
<attribute name="yiqiu_name" optional="YES" attributeType="String"/>
<attribute name="yiqiu_short_name" optional="YES" attributeType="String"/>
</entity>
<entity name="NmMatch" representedClassName="NmMatch" syncable="YES" codeGenerationType="class">
<attribute name="away_name" optional="YES" attributeType="String"/>
<attribute name="away_photo" optional="YES" attributeType="String"/>
<attribute name="away_rank" optional="YES" attributeType="String"/>
<attribute name="away_short_name" optional="YES" attributeType="String"/>
<attribute name="beidan_number" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="competition_color" optional="YES" attributeType="String"/>
<attribute name="competition_name" optional="YES" attributeType="String"/>
<attribute name="competition_short_name" optional="YES" attributeType="String"/>
<attribute name="corner_kicks" optional="YES" attributeType="Binary" valueTransformerName="ScoreValueTransformer" customClassName="[NSNumber]"/>
<attribute name="diff_kq_timestamp" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="diff_update_timestamp" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="experts_count" optional="YES" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="guest_formation" optional="YES" attributeType="String" defaultValueString=""/>
<attribute name="half" optional="YES" attributeType="Binary" valueTransformerName="ScoreValueTransformer" customClassName="[NSNumber]"/>
<attribute name="host_formation" optional="YES" attributeType="String" defaultValueString=""/>
<attribute name="host_name" optional="YES" attributeType="String"/>
<attribute name="host_photo" optional="YES" attributeType="String"/>
<attribute name="host_rank" optional="YES" attributeType="String"/>
<attribute name="host_short_name" optional="YES" attributeType="String"/>
<attribute name="hot_count" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="id" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="incidents" optional="YES" attributeType="Binary"/>
<attribute name="info_count" optional="YES" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="is_all" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="is_beidan" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="is_expanded" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="is_focused" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="is_jingcai" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="is_zucai" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="kaiqiu_timestamp" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="leisu_competition_id" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="leisu_match_id" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="local_update_time" optional="YES" attributeType="String"/>
<attribute name="match_playing_time" optional="YES" attributeType="String" defaultValueString=""/>
<attribute name="match_time" optional="YES" attributeType="String"/>
<attribute name="n" optional="YES" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="nm_match_detail_stats" optional="YES" attributeType="Binary"/>
<attribute name="position" optional="YES" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="red_card" optional="YES" attributeType="Binary" valueTransformerName="ScoreValueTransformer" customClassName="[NSNumber]"/>
<attribute name="score" optional="YES" attributeType="Binary" valueTransformerName="ScoreValueTransformer" customClassName="[NSNumber]"/>
<attribute name="score_all" optional="YES" attributeType="Binary" valueTransformerName="ScoreValueTransformer" customClassName="[NSNumber]"/>
<attribute name="score_point" optional="YES" attributeType="Binary" valueTransformerName="ScoreValueTransformer" customClassName="[NSNumber]"/>
<attribute name="show_ball_message" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="sporttery_issue_name" optional="YES" attributeType="String"/>
<attribute name="sporttery_number" optional="YES" attributeType="String"/>
<attribute name="status" optional="YES" attributeType="Integer 16" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="yellow_card" optional="YES" attributeType="Binary" valueTransformerName="ScoreValueTransformer" customClassName="[NSNumber]"/>
<attribute name="yiqiu_competition_id" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="zucai_number" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
</entity>
</model>
\ No newline at end of file
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "apple_icon.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "apple_icon@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "apple_icon@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "default_user.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "guest_icon.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "guest_icon@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "guest_icon@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "ic_banben.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "ic_banben@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "ic_banben@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "ic_clear_cache.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "ic_clear_cache@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "ic_clear_cache@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "ic_yinsi.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "ic_yinsi@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "ic_yinsi@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "icon_close.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "icon_close@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "icon_close@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "icon_selected.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "icon_selected@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "icon_selected@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "icon_un_select.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "icon_un_select@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "icon_un_select@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "right_arrow_icon.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "right_arrow_icon@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "right_arrow_icon@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
......@@ -6,6 +6,9 @@
//
import UIKit
import CoreData
let viewContext = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
......@@ -15,36 +18,60 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
Thread.sleep(forTimeInterval: 3)
initLogger()
initNaviBar()
initOthers()
initWindow()
return true
}
// MARK: - Core Data stack
lazy var persistentContainer: NSPersistentContainer = {
/*
The persistent container for the application. This implementation
creates and returns a container, having loaded the store for the
application to it. This property is optional since there are legitimate
error conditions that could cause the creation of the store to fail.
*/
let container = NSPersistentContainer(name: "AoleiSports")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
/*
Typical reasons for an error here include:
* The parent directory does not exist, cannot be created, or disallows writing.
* The persistent store is not accessible, due to permissions or data protection when the device is locked.
* The device is out of space.
* The store could not be migrated to the current model version.
Check the error message to determine what the actual problem was.
*/
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()
// MARK: - Core Data Saving support
func saveContext () {
let context = persistentContainer.viewContext
if context.hasChanges {
do {
try context.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
let nserror = error as NSError
fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
}
}
}
}
extension AppDelegate {
private func initLogger() {
// 使用默认的OS Logger
DDLog.add(DDOSLogger.sharedInstance)
// 使用File Logger
let fileLogger = DDFileLogger()
fileLogger.rollingFrequency = 60 * 60 * 24
fileLogger.logFileManager.maximumNumberOfLogFiles = 7
DDLog.add(fileLogger)
// 创建并设置自定义的 LogFormatter
let customFormatter = CustomLogFormatter()
if let osLogger = DDLog.allLoggers.first(where: { $0 is DDOSLogger }) as? DDOSLogger {
osLogger.logFormatter = customFormatter
}
// 设置远程日志记录器
// if let remoteLoggingURL = URL(string: "https://your-remote-server.com/logs") {
// let remoteLogger = RemoteLogger(remoteLoggingURL: remoteLoggingURL)
// DDLog.add(remoteLogger)
// }
_ = LoggerTools()
}
private func initNaviBar() {
......@@ -60,8 +87,8 @@ extension AppDelegate {
// 状态栏样式
$0.statusBarStyle = .darkContent
// 导航栏左右item间距
$0.gk_navItemLeftSpace = 10
$0.gk_navItemRightSpace = 10
$0.gk_navItemLeftSpace = 15
$0.gk_navItemRightSpace = 15
// 是否恢复系统导航
$0.gk_restoreSystemNavBar = true
......@@ -71,9 +98,16 @@ extension AppDelegate {
// 开启全局UIScrollView处理
$0.gk_openScrollViewGestureHandle = true
// 跳转的时候隐藏标签栏
$0.gk_hidesBottomBarWhenPushed = true
}
}
private func initOthers() {
UITableView.appearance().separatorStyle = .none
}
private func initWindow() {
window = UIWindow.init(frame: UIScreen.main.bounds)
window?.backgroundColor = .white
......
//
// BaseTableViewCell.swift
// AoleiSports
//
// Created by ilCode on 2024/6/13.
//
import UIKit
class BaseTableViewCell: UITableViewCell {
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
selectionStyle = .none
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
//
// UIButton+Ext.swift
// AoleiSports
//
// Created by ilCode on 2024/6/14.
//
import UIKit
extension UIButton {
enum ImagePosition {
case left
case right
case top
case bottom
}
/// 调整图片位置,返回调整后所需要的size
/// 调用本方法前,请先确保imageView和titleLabel有值。
@discardableResult
func adjustImage(position: ImagePosition, spacing: CGFloat) -> CGSize {
guard imageView != nil && titleLabel != nil else {
return CGSize.zero
}
let imageSize = self.imageView!.intrinsicContentSize
let titleSize = self.titleLabel!.intrinsicContentSize
// 布局
switch (position) {
case .left:
imageEdgeInsets = UIEdgeInsets(top: 0, left: -spacing / 2, bottom: 0, right: spacing / 2)
titleEdgeInsets = UIEdgeInsets(top: 0, left: spacing / 2, bottom: 0, right: -spacing / 2)
contentEdgeInsets = UIEdgeInsets(top: 0, left: spacing / 2, bottom: 0, right: spacing / 2)
case .right:
imageEdgeInsets = UIEdgeInsets(top: 0, left: (titleSize.width + spacing / 2), bottom: 0, right: -(titleSize.width + spacing / 2))
titleEdgeInsets = UIEdgeInsets(top: 0, left: -(imageSize.width + spacing / 2), bottom: 0, right: (imageSize.width + spacing / 2))
contentEdgeInsets = UIEdgeInsets(top: 0, left: spacing / 2, bottom: 0, right: spacing / 2);
case .top, .bottom:
let imageOffsetX = (imageSize.width + titleSize.width) / 2 - imageSize.width / 2
let imageOffsetY = imageSize.height / 2 + spacing / 2
let titleOffsetX = (imageSize.width + titleSize.width / 2) - (imageSize.width + titleSize.width) / 2
let titleOffsetY = titleSize.height / 2 + spacing / 2
let changedWidth = titleSize.width + imageSize.width - max(titleSize.width, imageSize.width)
let changedHeight = titleSize.height + imageSize.height + spacing - max(imageSize.height, imageSize.height)
if position == .top {
imageEdgeInsets = UIEdgeInsets(top: -imageOffsetY, left: imageOffsetX, bottom: imageOffsetY, right: -imageOffsetX)
titleEdgeInsets = UIEdgeInsets(top: titleOffsetY, left: -titleOffsetX, bottom: -titleOffsetY, right: titleOffsetX)
self.contentEdgeInsets = UIEdgeInsets(top: imageOffsetY, left: -changedWidth / 2, bottom: changedHeight - imageOffsetY, right: -changedWidth / 2);
} else {
imageEdgeInsets = UIEdgeInsets(top: imageOffsetY, left: imageOffsetX, bottom: -imageOffsetY, right: -imageOffsetX)
titleEdgeInsets = UIEdgeInsets(top: -titleOffsetY, left: -titleOffsetX, bottom: titleOffsetY, right: titleOffsetX)
self.contentEdgeInsets = UIEdgeInsets(top: changedHeight - imageOffsetY, left: -changedWidth / 2, bottom: imageOffsetY, right: -changedWidth / 2);
}
}
return self.intrinsicContentSize
}
}
//
// UIImage+Ext.swift
// AoleiSports
//
// Created by ilCode on 2024/6/14.
//
import UIKit
extension UIImage {
func resize(to size: CGSize) -> UIImage? {
UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
draw(in: CGRect(origin: .zero, size: size))
let resizedImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return resizedImage
}
}
//
// UIView+Ext.swift
// AoleiSports
//
// Created by ilCode on 2024/6/11.
//
import UIKit
extension UIView {
// 设置边框
func border(borderColor: UIColor = .red, borderWidth: CGFloat = 1.0) {
self.layer.borderWidth = borderWidth
self.layer.borderColor = borderColor.cgColor
}
// 设置圆角
func corners(radius: CGFloat) -> Void {
self.layer.cornerRadius = radius
self.clipsToBounds = true
}
// 分割线
static func divider(color: UIColor = kDividerColor) -> UIView {
let line = UIView()
line.backgroundColor = color
return line
}
}
extension UIView {
var x: CGFloat {
get {
return frame.origin.x
}
set(newVal) {
var tmpFrame = frame
tmpFrame.origin.x = newVal
frame = tmpFrame
}
}
var y: CGFloat {
get {
return frame.origin.y
}
set(newVal) {
var tmpFrame = frame
tmpFrame.origin.y = newVal
frame = tmpFrame
}
}
var width: CGFloat {
get {
return frame.size.width
}
set(newVal) {
var tmpFrame = frame
tmpFrame.size.width = newVal
frame = tmpFrame
}
}
var height: CGFloat {
get {
return frame.size.height
}
set(newVal) {
var tmpFrame = frame
tmpFrame.size.height = newVal
frame = tmpFrame
}
}
var origin : CGPoint {
get {
return frame.origin
}
set(newVal) {
var tmpFrame = frame
tmpFrame.origin = newVal
frame = tmpFrame
}
}
var size: CGSize {
get {
return frame.size
}
set(newVal) {
var tmpFrame = frame
tmpFrame.size = newVal
frame = tmpFrame
}
}
}
extension UIView {
func shakeAnimation() {
let animation = CAKeyframeAnimation(keyPath: "position.x")
animation.values = [0, 8, -8, 8, 0]
animation.keyTimes = [0, 0.2, 0.4, 0.6, 1]
animation.duration = 0.4
animation.isAdditive = true
layer.add(animation, forKey: "shake")
}
}
//
// UIViewController+Ext.swift
// AoleiSports
//
// Created by ilCode on 2024/6/13.
//
import UIKit
extension UIViewController {
func al_present(_ target: UIViewController, modelStyle: UIModalPresentationStyle = .fullScreen, animated: Bool = true, completion: (() -> Void)? = nil) {
target.modalPresentationStyle = modelStyle
present(target, animated: animated, completion: completion)
}
}
......@@ -23,7 +23,6 @@ class HomeController: BaseController {
btn.titleLabel?.font = kFontSize(14)
btn.imageEdgeInsets = UIEdgeInsets(top: 0, left: -5, bottom: 0, right: 0)
btn.setImage(R.image.match_filter(), for: .normal)
isHiddenRelay.asObservable()
.bind(to: btn.rx.isHidden)
.disposed(by: disposeBag)
......@@ -35,7 +34,7 @@ class HomeController: BaseController {
let btn = UIButton()
btn.frame = CGRect(x: 0, y: 0, width: 44, height: 44)
btn.setImage(R.image.match_setting(), for: .normal)
btn.contentHorizontalAlignment = .right
// 方法1
// btn.rx.tap.do(onNext: {
// print("点击了设置按钮")
......@@ -57,6 +56,7 @@ class HomeController: BaseController {
switch result {
case let .success(list):
print("变化了", list.count)
self.view.makeToast("加载成功", position: .center)
case .failure(_):
print("出错了...")
}
......
......@@ -14,3 +14,20 @@ class LeagueController: BaseController {
gk_navTitle = "赛事筛选"
}
}
protocol Mabable {
func test()
static func goto()
}
extension Mabable {
func test() {
}
}
struct Piggy: Mabable {
static func goto() {
}
}
......@@ -42,14 +42,25 @@ class ScoreProvider<Target: TargetType>: BaseMoyaProvider<Target> {
self.rx.request(target as! Target).subscribe { event in
switch event {
case let .success(response):
guard let json = try? JSONSerialization.jsonObject(with: response.data, options: []) as? [String: Any],
let dataDict = json["data"] as? [String: Any],
let nmMatchList = dataDict["nm_match_list"] as? [[String: Any]] else {
DDLogError("Error: Failed to parse JSON data")
return
}
DDLogDebug("\(nmMatchList)")
completion(.success(nmMatchList))
let json = JSON(response.data)
let matchList = json["data"]["nm_match_list"].arrayValue
let jsonModel = matchList.first!
DDLogInfo("\(jsonModel["yellow_card"].arrayValue), \(jsonModel["yiqiu_competition_short_name"].stringValue)")
DDLogDebug("\(matchList)")
// let json = try? JSON(data: response.data)
// if let matchList = json?["data"]["nm_match_list"].array {
// DDLogDebug("\(matchList)")
// }
// guard let json = try? JSONSerialization.jsonObject(with: response.data, options: []) as? [String: Any],
// let dataDict = json["data"] as? [String: Any],
// let nmMatchList = dataDict["nm_match_list"] as? [[String: Any]] else {
// DDLogError("Error: Failed to parse JSON data")
// return
// }
// DDLogDebug("\(nmMatchList)")
// completion(.success(nmMatchList))
case let .failure(error):
completion(.failure(error))
}
......
//
// LoginTools.swift
// AoleiSports
//
// Created by ilCode on 2024/6/13.
//
import Foundation
struct LoginTools {
static func toLogin(target: UIViewController) {
target.al_present(UINavigationController(rootVC: LoginController()))
}
}
//
// PrivacyController.swift
// AoleiSports
//
// Created by ilCode on 2024/6/13.
//
import UIKit
class PrivacyController: BaseController {
override func viewDidLoad() {
super.viewDidLoad()
gk_navTitle = "隐私协议"
}
}
//
// ProfileController.swift
// AoleiSports
//
// Created by ilCode on 2024/6/4.
//
import UIKit
class ProfileController: BaseController {
lazy var profileView: ProfileView = {
let view = ProfileView()
view.delegate = self
return view
}()
override func loadView() {
view = profileView
}
override func viewDidLoad() {
super.viewDidLoad()
gk_navigationBar.isHidden = true
}
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
}
extension ProfileController: ProfileViewDelegate {
func tapHeader() {
// navigationController?.pushViewController(UpdateProfileController(), animated: true)
// let loginVC = LoginController()
// loginVC.modalPresentationStyle = .fullScreen
// present(loginVC, animated: true)
LoginTools.toLogin(target: self)
}
func didSelectRow(indexPath: IndexPath) {
let model = ProfileModel.profileModels[indexPath.row]
switch model.itemType {
case .privacy:
navigationController?.pushViewController(PrivacyController(), animated: true)
case .cache:
view.makeToast("清除成功")
break
default:
break
}
}
func tapLogout() {
}
}
//
// ProfileModel.swift
// AoleiSports
//
// Created by ilCode on 2024/6/12.
//
import Foundation
struct ProfileModel {
enum ProfileItemType {
case myOrder
case myCare
case privacy
case version
case cache
}
let itemType: ProfileItemType
let icon: UIImage?
let title: String
let detail: String?
static var profileModels: [ProfileModel] {
return [
ProfileModel(itemType: .privacy, icon: R.image.ic_yinsi(), title: "隐私协议", detail: ""),
ProfileModel(itemType: .version, icon: R.image.ic_banben(), title: "当前版本", detail: "v" + AppInfo.appVersion()),
ProfileModel(itemType: .cache, icon: R.image.ic_clear_cache(), title: "清除缓存", detail: "")
]
}
}
//
// ProfileView.swift
// AoleiSports
//
// Created by ilCode on 2024/6/12.
//
import UIKit
@objc protocol ProfileViewDelegate {
func tapHeader()
func didSelectRow(indexPath: IndexPath)
func tapLogout()
}
class ProfileView: UIView {
weak var delegate: ProfileViewDelegate?
private let disposeBag = DisposeBag()
private lazy var userIV: UIImageView = {
let iv = UIImageView(image: R.image.default_user())
iv.border(borderColor: kWhite, borderWidth: 1)
iv.corners(radius: 40)
return iv
}()
private lazy var nameLab: UILabel = {
let lab = UILabel()
lab.font = kFontSize(18)
lab.textColor = kWhite
lab.text = "chengx"
return lab
}()
private lazy var welLab: UILabel = {
let lab = UILabel()
lab.font = kFontSize(14)
lab.textColor = kWhite
lab.text = "欢迎来到傲雷体育"
return lab
}()
private lazy var gradientLayer: CAGradientLayer = {
let layer = CAGradientLayer()
let colorTop = UIColor.colorWith(hexString: "4EA6FF").cgColor
let colorBottom = UIColor.colorWith(hexString: "7CD4FF").cgColor
layer.colors = [colorTop, colorBottom]
layer.startPoint = CGPoint(x: 0, y: 0)
layer.endPoint = CGPoint(x: 1, y: 0)
return layer
}()
private lazy var headView: UIView = {
let view = UIView()
view.rx.tapGesture()
.subscribe { _ in
self.delegate?.tapHeader()
}
.disposed(by: disposeBag)
return view
}()
private lazy var logoutBtn: UIButton = {
let btn = UIButton(frame: CGRect(x: 15, y: 20, width: kScreenW - 30, height: 40))
btn.setTitle("退出登录", for: .normal)
btn.setTitleColor(kMainTitleColor, for: .normal)
btn.backgroundColor = kWhite
btn.rx.tap.subscribe(onNext: {
self.delegate?.tapLogout()
}).disposed(by: disposeBag)
btn.corners(radius: 5)
return btn
}()
private lazy var footView: UIView = {
let view = UIView(frame: CGRect(x: 0, y: 0, width: kScreenW, height: 80))
view.addSubview(logoutBtn)
return view
}()
private lazy var profileTV: UITableView = {
let tv = UITableView.init(frame: CGRectZero, style: .plain)
tv.backgroundColor = kMainBgColor
tv.contentInsetAdjustmentBehavior = .never
tv.rowHeight = 60
tv.dataSource = self
tv.delegate = self
tv.tableFooterView = footView
tv.register(ProfileItemCell.self, forCellReuseIdentifier: "ProfileItemCell")
return tv
}()
override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
gradientLayer.frame = headView.bounds
}
}
extension ProfileView {
private func setupView() {
addSubview(headView)
addSubview(profileTV)
headView.layer.addSublayer(gradientLayer)
headView.addSubview(userIV)
headView.addSubview(nameLab)
headView.addSubview(welLab)
layoutUI()
}
private func layoutUI() {
headView.snp.makeConstraints { make in
make.top.left.right.equalToSuperview()
make.height.equalTo(160)
}
profileTV.snp.makeConstraints { make in
make.top.equalTo(headView.snp.bottom).offset(10)
make.left.right.equalToSuperview()
make.bottom.equalTo(safeAreaLayoutGuide)
}
userIV.snp.makeConstraints { make in
make.top.equalToSuperview().offset(kStatusBarH + (160 - kStatusBarH - 80)/2.0)
make.size.equalTo(CGSize(width: 80, height: 80))
make.left.equalToSuperview().offset(30)
}
nameLab.snp.makeConstraints { make in
make.left.equalTo(userIV.snp.right).offset(20)
make.top.equalTo(userIV).offset(15)
}
welLab.snp.makeConstraints { make in
make.left.equalTo(userIV.snp.right).offset(20)
make.bottom.equalTo(userIV).offset(-15)
}
}
}
extension ProfileView: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return ProfileModel.profileModels.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let model = ProfileModel.profileModels[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "ProfileItemCell", for: indexPath) as! ProfileItemCell
cell.model = model
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
delegate?.didSelectRow(indexPath: indexPath)
}
}
//MARK: - ProfileItemCell
class ProfileItemCell: BaseTableViewCell {
private lazy var typeIcon: UIImageView = {
let iv = UIImageView()
return iv
}()
private lazy var titleLab: UILabel = {
let lab = UILabel()
return lab
}()
private lazy var detailLab: UILabel = {
let lab = UILabel()
lab.textAlignment = .right
return lab
}()
private lazy var rightIcon: UIImageView = {
let iv = UIImageView(image: R.image.right_arrow_icon())
return iv
}()
private lazy var sepLine: UIView = {
let line = UIView.divider()
return line
}()
var model: ProfileModel? {
didSet {
typeIcon.image = model?.icon
titleLab.text = model?.title
detailLab.text = model?.detail
rightIcon.isHidden = model?.itemType != .privacy
sepLine.isHidden = model?.itemType == .cache
}
}
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
selectionStyle = .default
contentView.addSubview(typeIcon)
contentView.addSubview(titleLab)
contentView.addSubview(detailLab)
contentView.addSubview(rightIcon)
contentView.addSubview(sepLine)
layoutUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func layoutUI() {
typeIcon.snp.makeConstraints { make in
make.centerY.equalToSuperview()
make.left.equalToSuperview().offset(15)
make.size.equalTo(CGSize(width: 30, height: 30))
}
titleLab.snp.makeConstraints { make in
make.centerY.equalToSuperview()
make.left.equalTo(typeIcon.snp.right).offset(10)
}
rightIcon.snp.makeConstraints { make in
make.centerY.equalToSuperview()
make.right.equalToSuperview().offset(-15)
make.size.equalTo(CGSize(width: 19, height: 19))
}
detailLab.snp.makeConstraints { make in
make.centerY.equalToSuperview()
make.right.equalToSuperview().offset(-15)
}
sepLine.snp.makeConstraints { make in
make.bottom.equalToSuperview()
make.left.right.equalToSuperview()
make.height.equalTo(1)
}
}
}
//
// ProfileController.swift
// RegisterController.swift
// AoleiSports
//
// Created by ilCode on 2024/6/4.
// Created by ilCode on 2024/6/13.
//
import UIKit
class ProfileController: BaseController {
class RegisterController: BaseController {
override func viewDidLoad() {
super.viewDidLoad()
}
}
//
// UpdateProfileController.swift
// AoleiSports
//
// Created by ilCode on 2024/6/12.
//
import UIKit
class UpdateProfileController: BaseController {
override func viewDidLoad() {
super.viewDidLoad()
gk_navTitle = "个人信息"
}
}
......@@ -14,6 +14,10 @@ struct AppInfo: Codable {
var packageName: String = "AoleiSports"
var uniqueId: String
static func appVersion() -> String {
Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? ""
}
static func getAppInfo() -> String {
let info = AppInfo(uniqueId:getUKey())
return "{\"packageName\":\"\(info.packageName)\",\"os\":\"\(info.os)\",\"uniqueId\":\"\(info.uniqueId)\",\"version\":\"\(info.version)\",\"promoterId\":\"\(info.promoterId)\"}"
......
......@@ -25,4 +25,6 @@ let kMainTitleColor = kHexColor("333333")
let kSubTitleColor = kHexColor("AAAAAA")
/// 主背景色
let kMainBgColor = kHexColor("EFEFEF")
/// 分割线颜色
let kDividerColor = kHexColor("F5F7FC")
......@@ -10,3 +10,7 @@
@_exported import RxSwift
@_exported import RxCocoa
@_exported import Moya
@_exported import NVActivityIndicatorView
@_exported import Toast_Swift
@_exported import SwiftyJSON
@_exported import RxGesture
//
// LayoutTools.swift
// AoleiSports
//
// Created by ilCode on 2024/6/12.
//
import UIKit
/// 屏幕高
let kScreenH = UIScreen.main.bounds.height
/// 屏幕宽
let kScreenW = UIScreen.main.bounds.width
/// 状态栏高度
let kStatusBarH = STATUSBAR_HEIGHT()
/// 导航栏内容高度
let kNavBarContentH = 44.0
/// 导航栏整体高度: 状态栏高 + 导航栏内容高
let kNavBarH = (kStatusBarH + kNavBarContentH)
/// 底部导航内容高度
let kTabBarContentH = 49.0
/// 屏幕底部安全距离
let kBottomSafeH = TABBAR_INDICATOR_HEIGHT()
/// 底部导航菜单高度:内容高 + 底部安全距离
let kTabBarH = (kTabBarContentH + kBottomSafeH)
/// 获取状态栏高度
private func STATUSBAR_HEIGHT() -> CGFloat {
// 适配灵动岛状态栏高度
var statusBarHeight: CGFloat = 0
if #available(iOS 13.0, *) {
let window = UIApplication.shared.windows.first
let topPadding = window?.safeAreaInsets.top
statusBarHeight = topPadding ?? 20.0
} else {
statusBarHeight = UIApplication.shared.statusBarFrame.height
}
return statusBarHeight
}
/// 底部指示条
private func TABBAR_INDICATOR_HEIGHT() -> CGFloat {
if #available(iOS 11.0, *) {
return kWindow()?.safeAreaInsets.bottom ?? 0
} else {
return 0
}
}
/// 获取window
private func kWindow() -> UIWindow? {
if #available(iOS 13.0, *) {
let winScene = UIApplication.shared.connectedScenes.first as? UIWindowScene
return winScene?.windows.first
} else {
return UIApplication.shared.delegate?.window ?? UIApplication.shared.keyWindow
}
}
......@@ -10,17 +10,17 @@ import Foundation
// 自定义日志输出格式
class CustomLogFormatter: NSObject, DDLogFormatter {
let dateFormatter: DateFormatter
override init() {
dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss.SSS"
super.init()
}
func format(message logMessage: DDLogMessage) -> String? {
let _ = dateFormatter.string(from: logMessage.timestamp)
let logLevel: String
switch logMessage.flag {
case .error:
logLevel = "❗️[ERROR]"
......@@ -35,7 +35,7 @@ class CustomLogFormatter: NSObject, DDLogFormatter {
default:
logLevel = "[UNKNOWN]"
}
return "\(logLevel) [\(logMessage.fileName) \(logMessage.function ?? ""):\(logMessage.line)] =>\n\(logMessage.message)"
}
}
......@@ -43,22 +43,22 @@ class CustomLogFormatter: NSObject, DDLogFormatter {
// 将日志存储到远程服务器
class RemoteLogger: DDAbstractLogger {
private let remoteLoggingURL: URL
init(remoteLoggingURL: URL) {
self.remoteLoggingURL = remoteLoggingURL
super.init()
}
override func log(message logMessage: DDLogMessage) {
let formattedMessage = format(logMessage: logMessage)
sendLogToServer(formattedMessage)
}
private func format(logMessage: DDLogMessage) -> String {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss.SSS"
let dateAndTime = dateFormatter.string(from: logMessage.timestamp)
let logLevel: String
switch logMessage.flag {
case .error: logLevel = "ERROR"
......@@ -68,16 +68,16 @@ class RemoteLogger: DDAbstractLogger {
case .verbose: logLevel = "VERBOSE"
default: logLevel = "UNKNOWN"
}
return "\(dateAndTime) \(logLevel) [\(logMessage.fileName) \(logMessage.function ?? ""):\(logMessage.line)]: \(logMessage.message)"
}
private func sendLogToServer(_ message: String) {
var request = URLRequest(url: remoteLoggingURL)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: ["log": message], options: [])
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print("Failed to send log to server: \(error)")
......@@ -89,3 +89,28 @@ class RemoteLogger: DDAbstractLogger {
}
}
struct LoggerTools {
init() {
// 使用默认的OS Logger
DDLog.add(DDOSLogger.sharedInstance)
// 使用File Logger
let fileLogger = DDFileLogger()
fileLogger.rollingFrequency = 60 * 60 * 24
fileLogger.logFileManager.maximumNumberOfLogFiles = 7
DDLog.add(fileLogger)
// 创建并设置自定义的 LogFormatter
let customFormatter = CustomLogFormatter()
if let osLogger = DDLog.allLoggers.first(where: { $0 is DDOSLogger }) as? DDOSLogger {
osLogger.logFormatter = customFormatter
}
// 设置远程日志记录器
// if let remoteLoggingURL = URL(string: "https://your-remote-server.com/logs") {
// let remoteLogger = RemoteLogger(remoteLoggingURL: remoteLoggingURL)
// DDLog.add(remoteLogger)
// }
}
}
......@@ -36,12 +36,14 @@ extension TargetType {
// 自定义Plugin
final class BaseMoyaPlugin: PluginType {
var vc: UIViewController
private var spinner: UIActivityIndicatorView!
private var spinner: NVActivityIndicatorView!
init(vc: UIViewController) {
init(vc: UIViewController, showLoading: Bool = true) {
self.vc = vc
spinner = UIActivityIndicatorView(style: UIActivityIndicatorView.Style.medium)
spinner.center = self.vc.view.center
if showLoading {
spinner = NVActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 60, height: 55), type: .ballSpinFadeLoader, color: kMasterColor)
spinner.center = self.vc.view.center
}
}
func prepare(_ request: URLRequest, target: any TargetType) -> URLRequest {
......@@ -55,18 +57,23 @@ final class BaseMoyaPlugin: PluginType {
}
func willSend(_ request: any RequestType, target: any TargetType) {
DispatchQueue.main.async { [weak self] in
self?.vc.view.addSubview(self!.spinner)
self?.spinner.startAnimating()
if let spinner = spinner {
DispatchQueue.main.async { [weak self] in
self?.vc.view.addSubview(spinner)
spinner.startAnimating()
}
}
}
func didReceive(_ result: Result<Response, MoyaError>, target: any TargetType) {
// 移除界面中央的活动状态指示器
DispatchQueue.main.async { [weak self] in
self?.spinner.removeFromSuperview()
self?.spinner.stopAnimating()
if let spinner = spinner {
DispatchQueue.main.async {
spinner.removeFromSuperview()
spinner.stopAnimating()
}
}
// 只有请求错误时会继续往下执行
guard case let Result.failure(error) = result else { return }
......@@ -86,8 +93,8 @@ class BaseMoyaProvider<Target: TargetType>: MoyaProvider<Target> {
let disposeBag = DisposeBag()
var basePlugin: BaseMoyaPlugin
init(vc: UIViewController) {
self.basePlugin = BaseMoyaPlugin(vc: vc)
init(vc: UIViewController, showLoading: Bool = true) {
self.basePlugin = BaseMoyaPlugin(vc: vc, showLoading: showLoading)
super.init(plugins: [self.basePlugin])
}
}
......@@ -856,7 +856,13 @@ extension UIViewController {
if backImage == nil { return }
self.gk_navigationItem.leftBarButtonItem = UIBarButtonItem.gk_item(image: backImage, target: self, action: #selector(backItemClick(_:)))
let btn = UIButton()
btn.setImage(backImage, for: .normal)
btn.width = 40
btn.contentHorizontalAlignment = .left
btn.addTarget(self, action: #selector(backItemClick(_:)), for: .touchUpInside)
self.gk_navigationItem.leftBarButtonItem = UIBarButtonItem(customView: btn)
// self.gk_navigationItem.leftBarButtonItem = UIBarButtonItem.gk_item(image: backImage, target: self, action: #selector(backItemClick(_:)))
}
fileprivate func setNavBackground(_ image: UIImage?) {
......
......@@ -11,6 +11,10 @@ target 'AoleiSports' do
pod 'RxSwift', '~> 6.7.1'
pod 'RxCocoa', '~> 6.7.1',:inhibit_warnings => true
pod 'SwiftyJSON', '~> 5.0.2'
pod 'NVActivityIndicatorView', '~> 5.2.0'
pod 'Toast-Swift', '~> 5.1.1'
pod 'ObjectMapper', '~> 4.4.2'
pod 'RxGesture', '~> 4.0.4'
end
......
......@@ -8,49 +8,69 @@ PODS:
- Moya/RxSwift (15.0.0):
- Moya/Core
- RxSwift (~> 6.0)
- NVActivityIndicatorView (5.2.0):
- NVActivityIndicatorView/Base (= 5.2.0)
- NVActivityIndicatorView/Base (5.2.0)
- ObjectMapper (4.4.2)
- R.swift (7.3.2)
- RxCocoa (6.7.1):
- RxRelay (= 6.7.1)
- RxSwift (= 6.7.1)
- RxGesture (4.0.4):
- RxCocoa (~> 6.0)
- RxSwift (~> 6.0)
- RxRelay (6.7.1):
- RxSwift (= 6.7.1)
- RxSwift (6.7.1)
- SnapKit (5.7.1)
- SwiftyJSON (5.0.2)
- Toast-Swift (5.1.1)
DEPENDENCIES:
- Alamofire (~> 5.9.1)
- CocoaLumberjack/Swift
- Moya/RxSwift (~> 15.0)
- NVActivityIndicatorView (~> 5.2.0)
- ObjectMapper (~> 4.4.2)
- R.swift (~> 7.3.2)
- RxCocoa (~> 6.7.1)
- RxGesture (~> 4.0.4)
- RxSwift (~> 6.7.1)
- SnapKit (~> 5.7.1)
- SwiftyJSON (~> 5.0.2)
- Toast-Swift (~> 5.1.1)
SPEC REPOS:
trunk:
- Alamofire
- CocoaLumberjack
- Moya
- NVActivityIndicatorView
- ObjectMapper
- R.swift
- RxCocoa
- RxGesture
- RxRelay
- RxSwift
- SnapKit
- SwiftyJSON
- Toast-Swift
SPEC CHECKSUMS:
Alamofire: f36a35757af4587d8e4f4bfa223ad10be2422b8c
CocoaLumberjack: 6a459bc897d6d80bd1b8c78482ec7ad05dffc3f0
Moya: 138f0573e53411fb3dc17016add0b748dfbd78ee
NVActivityIndicatorView: fe52a6a68664c2df8991d7d9e3d86d8d19453c53
ObjectMapper: e6e4d91ff7f2861df7aecc536c92d8363f4c9677
R.swift: 0af0d882f49f03711415cb4e5215daa977d8a480
RxCocoa: f5609cb4637587a7faa99c5d5787e3ad582b75a4
RxGesture: f3efb47ed2d26a8082f7b660d4a59970e275a7f8
RxRelay: 4151ba01152436b08271e08410135e099880eae5
RxSwift: b9a93a26031785159e11abd40d1a55bcb8057e52
SnapKit: d612e99e678a2d3b95bf60b0705ed0a35c03484a
SwiftyJSON: f5b1bf1cd8dd53cd25887ac0eabcfd92301c6a5a
Toast-Swift: 7a03a532afe3a560d4044bc7c237e2864d295173
PODFILE CHECKSUM: ba331d23fa7a277b9fb3ecb12535749b08a25bb2
PODFILE CHECKSUM: 0ed9736004dd278591ebfa22937383fb27c4e17f
COCOAPODS: 1.15.2
......@@ -73,16 +73,43 @@ struct _R {
var accentColor: RswiftResources.ColorResource { .init(name: "AccentColor", path: [], bundle: bundle) }
}
/// This `_R.image` struct is generated, and contains static references to 8 images.
/// This `_R.image` struct is generated, and contains static references to 18 images.
struct image {
let bundle: Foundation.Bundle
/// Image `apple_icon`.
var apple_icon: RswiftResources.ImageResource { .init(name: "apple_icon", path: [], bundle: bundle, locale: nil, onDemandResourceTags: nil) }
/// Image `default_user`.
var default_user: RswiftResources.ImageResource { .init(name: "default_user", path: [], bundle: bundle, locale: nil, onDemandResourceTags: nil) }
/// Image `guest_icon`.
var guest_icon: RswiftResources.ImageResource { .init(name: "guest_icon", path: [], bundle: bundle, locale: nil, onDemandResourceTags: nil) }
/// Image `home`.
var home: RswiftResources.ImageResource { .init(name: "home", path: [], bundle: bundle, locale: nil, onDemandResourceTags: nil) }
/// Image `home_selected`.
var home_selected: RswiftResources.ImageResource { .init(name: "home_selected", path: [], bundle: bundle, locale: nil, onDemandResourceTags: nil) }
/// Image `ic_banben`.
var ic_banben: RswiftResources.ImageResource { .init(name: "ic_banben", path: [], bundle: bundle, locale: nil, onDemandResourceTags: nil) }
/// Image `ic_clear_cache`.
var ic_clear_cache: RswiftResources.ImageResource { .init(name: "ic_clear_cache", path: [], bundle: bundle, locale: nil, onDemandResourceTags: nil) }
/// Image `ic_yinsi`.
var ic_yinsi: RswiftResources.ImageResource { .init(name: "ic_yinsi", path: [], bundle: bundle, locale: nil, onDemandResourceTags: nil) }
/// Image `icon_close`.
var icon_close: RswiftResources.ImageResource { .init(name: "icon_close", path: [], bundle: bundle, locale: nil, onDemandResourceTags: nil) }
/// Image `icon_selected`.
var icon_selected: RswiftResources.ImageResource { .init(name: "icon_selected", path: [], bundle: bundle, locale: nil, onDemandResourceTags: nil) }
/// Image `icon_un_select`.
var icon_un_select: RswiftResources.ImageResource { .init(name: "icon_un_select", path: [], bundle: bundle, locale: nil, onDemandResourceTags: nil) }
/// Image `launch_bg`.
var launch_bg: RswiftResources.ImageResource { .init(name: "launch_bg", path: [], bundle: bundle, locale: LocaleReference.none, onDemandResourceTags: nil) }
......@@ -100,6 +127,9 @@ struct _R {
/// Image `profile_selected`.
var profile_selected: RswiftResources.ImageResource { .init(name: "profile_selected", 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) }
}
/// This `_R.file` struct is generated, and contains static references to 6 resource files.
......
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!