├── .DS_Store ├── .gitignore ├── FunIOS.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ │ └── redli.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── redli.xcuserdatad │ └── xcschemes │ └── xcschememanagement.plist ├── FunIOS.xcworkspace ├── contents.xcworkspacedata ├── xcshareddata │ └── IDEWorkspaceChecks.plist └── xcuserdata │ └── redli.xcuserdatad │ ├── UserInterfaceState.xcuserstate │ └── xcdebugger │ └── Breakpoints_v2.xcbkptlist ├── FunIOS ├── .DS_Store ├── AppDelegate.swift ├── Assets.xcassets │ ├── .DS_Store │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── ios-marketing-1024x1024.png │ │ ├── iphone-20x20@2x.png │ │ ├── iphone-20x20@3x.png │ │ ├── iphone-29x29@2x.png │ │ ├── iphone-29x29@3x.png │ │ ├── iphone-40x40@2x.png │ │ ├── iphone-40x40@3x.png │ │ ├── iphone-60x60@2x.png │ │ └── iphone-60x60@3x.png │ ├── Common │ │ ├── .DS_Store │ │ ├── Contents.json │ │ ├── ic_collect.imageset │ │ │ ├── Contents.json │ │ │ ├── ic_collect@2x.png │ │ │ └── ic_collect@3x.png │ │ ├── ic_top.imageset │ │ │ ├── Contents.json │ │ │ ├── ic_top-1.png │ │ │ └── ic_top.png │ │ ├── ic_uncollect.imageset │ │ │ ├── Contents.json │ │ │ ├── ic_uncollect@2x.png │ │ │ └── ic_uncollect@3x.png │ │ ├── normal_placeholder_h.imageset │ │ │ ├── Contents.json │ │ │ └── normal_placeholder_h@2x.png │ │ └── normal_placeholder_v.imageset │ │ │ ├── Contents.json │ │ │ └── normal_placeholder_v@2x.png │ ├── Contents.json │ ├── dropdown │ │ ├── Contents.json │ │ ├── dropdown_loading_00.imageset │ │ │ ├── Contents.json │ │ │ └── dropdown_loading_00@2x.png │ │ ├── dropdown_loading_01.imageset │ │ │ ├── Contents.json │ │ │ └── dropdown_loading_01@2x.png │ │ ├── dropdown_loading_010.imageset │ │ │ ├── Contents.json │ │ │ └── dropdown_loading_10@2x.png │ │ ├── dropdown_loading_011.imageset │ │ │ ├── Contents.json │ │ │ └── dropdown_loading_11@2x.png │ │ ├── dropdown_loading_012.imageset │ │ │ ├── Contents.json │ │ │ └── dropdown_loading_12@2x.png │ │ ├── dropdown_loading_013.imageset │ │ │ ├── Contents.json │ │ │ └── dropdown_loading_13@2x.png │ │ ├── dropdown_loading_014.imageset │ │ │ ├── Contents.json │ │ │ └── dropdown_loading_14@2x.png │ │ ├── dropdown_loading_015.imageset │ │ │ ├── Contents.json │ │ │ └── dropdown_loading_15@2x.png │ │ ├── dropdown_loading_02.imageset │ │ │ ├── Contents.json │ │ │ └── dropdown_loading_02@2x.png │ │ ├── dropdown_loading_03.imageset │ │ │ ├── Contents.json │ │ │ └── dropdown_loading_03@2x.png │ │ ├── dropdown_loading_04.imageset │ │ │ ├── Contents.json │ │ │ └── dropdown_loading_04@2x.png │ │ ├── dropdown_loading_05.imageset │ │ │ ├── Contents.json │ │ │ └── dropdown_loading_05@2x.png │ │ ├── dropdown_loading_06.imageset │ │ │ ├── Contents.json │ │ │ └── dropdown_loading_06@2x.png │ │ ├── dropdown_loading_07.imageset │ │ │ ├── Contents.json │ │ │ └── dropdown_loading_07@2x.png │ │ ├── dropdown_loading_08.imageset │ │ │ ├── Contents.json │ │ │ └── dropdown_loading_08@2x.png │ │ └── dropdown_loading_09.imageset │ │ │ ├── Contents.json │ │ │ └── dropdown_loading_09@2x.png │ ├── loading │ │ ├── Contents.json │ │ ├── sendloading_18x18_0.imageset │ │ │ ├── Contents.json │ │ │ ├── sendloading_18x18_0@2x.png │ │ │ └── sendloading_18x18_0@3x.png │ │ ├── sendloading_18x18_1.imageset │ │ │ ├── Contents.json │ │ │ ├── sendloading_18x18_1@2x.png │ │ │ └── sendloading_18x18_1@3x.png │ │ ├── sendloading_18x18_2.imageset │ │ │ ├── Contents.json │ │ │ ├── sendloading_18x18_2@2x.png │ │ │ └── sendloading_18x18_2@3x.png │ │ ├── sendloading_18x18_3.imageset │ │ │ ├── Contents.json │ │ │ ├── sendloading_18x18_3@2x.png │ │ │ └── sendloading_18x18_3@3x.png │ │ ├── sendloading_18x18_4.imageset │ │ │ ├── Contents.json │ │ │ ├── sendloading_18x18_4@2x.png │ │ │ └── sendloading_18x18_4@3x.png │ │ ├── sendloading_18x18_5.imageset │ │ │ ├── Contents.json │ │ │ ├── sendloading_18x18_5@2x.png │ │ │ └── sendloading_18x18_5@3x.png │ │ ├── sendloading_18x18_6.imageset │ │ │ ├── Contents.json │ │ │ ├── sendloading_18x18_6@2x.png │ │ │ └── sendloading_18x18_6@3x.png │ │ └── sendloading_18x18_7.imageset │ │ │ ├── Contents.json │ │ │ ├── sendloading_18x18_7@2x.png │ │ │ └── sendloading_18x18_7@3x.png │ ├── login │ │ ├── .DS_Store │ │ ├── Contents.json │ │ ├── ic_close.imageset │ │ │ ├── Contents.json │ │ │ ├── ic_close-1.png │ │ │ └── ic_close.png │ │ ├── ic_logout.imageset │ │ │ ├── Contents.json │ │ │ ├── ic_logout-1.png │ │ │ └── ic_logout.png │ │ ├── ic_password.imageset │ │ │ ├── Contents.json │ │ │ ├── ic_password-1.png │ │ │ └── ic_password.png │ │ └── ic_user.imageset │ │ │ ├── Contents.json │ │ │ ├── ic_user-1.png │ │ │ └── ic_user.png │ ├── mine │ │ ├── Contents.json │ │ ├── ic_browsing.imageset │ │ │ ├── Contents.json │ │ │ ├── ic_browsing-1.png │ │ │ └── ic_browsing.png │ │ ├── ic_calendar.imageset │ │ │ ├── Contents.json │ │ │ ├── ic_calendar-1.png │ │ │ └── ic_calendar.png │ │ ├── ic_collection.imageset │ │ │ ├── Contents.json │ │ │ ├── ic_collection-1.png │ │ │ └── ic_collection.png │ │ ├── ic_courier.imageset │ │ │ ├── Contents.json │ │ │ ├── ic_courier-1.png │ │ │ └── ic_courier.png │ │ ├── ic_google.imageset │ │ │ ├── Contents.json │ │ │ ├── ic_google-1.png │ │ │ └── ic_google.png │ │ ├── ic_integral.imageset │ │ │ ├── Contents.json │ │ │ ├── ic_integral-1.png │ │ │ └── ic_integral.png │ │ ├── ic_ranking.imageset │ │ │ ├── Contents.json │ │ │ ├── ic_ranking-1.png │ │ │ └── ic_ranking.png │ │ ├── ic_share.imageset │ │ │ ├── Contents.json │ │ │ ├── ic_share-1.png │ │ │ └── ic_share.png │ │ ├── ic_todo.imageset │ │ │ ├── Contents.json │ │ │ ├── ic_todo-1.png │ │ │ └── ic_todo.png │ │ └── ic_weather.imageset │ │ │ ├── Contents.json │ │ │ ├── ic_weather-1.png │ │ │ └── ic_weather.png │ └── tabbar │ │ ├── .DS_Store │ │ ├── Contents.json │ │ ├── home_tabbar_night_32x32_.imageset │ │ ├── Contents.json │ │ ├── Icon-60@2x.png │ │ └── Icon-60@3x.png │ │ ├── home_tabbar_press_32x32_.imageset │ │ ├── Contents.json │ │ ├── Icon-60@3x.png │ │ └── icon-60@2x.png │ │ ├── mine_tabbar_night_32x32_.imageset │ │ ├── Contents.json │ │ ├── Icon-60@2x.png │ │ └── Icon-60@3x.png │ │ ├── mine_tabbar_press_32x32_.imageset │ │ ├── Contents.json │ │ ├── icon-60@2x.png │ │ └── icon-60@3x.png │ │ ├── project_tabbar_night_32x32_.imageset │ │ ├── Contents.json │ │ ├── Icon-60@2x.png │ │ └── Icon-60@3x.png │ │ ├── project_tabbar_press_32x32_.imageset │ │ ├── Contents.json │ │ ├── icon-60@2x.png │ │ └── icon-60@3x.png │ │ ├── structure_tabbar_night_32x32_.imageset │ │ ├── Contents.json │ │ ├── Icon-60@2x.png │ │ └── Icon-60@3x.png │ │ ├── structure_tabbar_press_32x32_.imageset │ │ ├── .DS_Store │ │ ├── Contents.json │ │ └── icon-60@2x.png │ │ ├── wechat_tabbar_night_32x32_.imageset │ │ ├── Contents.json │ │ ├── Icon-60@2x.png │ │ └── Icon-60@3x.png │ │ └── wechat_tabbar_press_32x32_.imageset │ │ ├── Contents.json │ │ └── icon-60@2x.png ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Base │ ├── BaseResponse.swift │ ├── BaseTableViewCell.swift │ └── BaseVController.swift ├── Cell-列表item样式 │ ├── ArticleCell.swift │ ├── CollectCell.swift │ ├── MenuCell.swift │ ├── ProjectCell.swift │ ├── RankingCell.swift │ ├── StructureCell.swift │ ├── UserCell.swift │ └── WechatCell.swift ├── Const.swift ├── Extension │ ├── MBProgressHUD+Extension.swift │ ├── UIColor+Extension.swift │ ├── UIView+Extension.swift │ └── UIViewController+Extension.swift ├── IndexVController.swift ├── Info.plist ├── Models │ ├── ArticleModel.swift │ ├── BannerModel.swift │ ├── IntegralModel.swift │ ├── NavigationModel.swift │ ├── RankingModel.swift │ ├── StructureModel.swift │ ├── UserCoinLevelModel.swift │ └── UserModel.swift ├── SceneDelegate.swift ├── Services │ └── Api.swift ├── Tools │ ├── HttpUtils.swift │ └── LogUtils.swift ├── UI │ ├── Home │ │ └── HomeVController.swift │ ├── Login │ │ └── LoginVController.swift │ ├── Project │ │ ├── ProjectArticlesVController.swift │ │ └── ProjectVController.swift │ ├── Structure │ │ ├── StructureListVController.swift │ │ └── StructureVController.swift │ ├── StructureDetail │ │ └── StructureDetailVController.swift │ ├── User │ │ ├── Collect │ │ │ └── CollectVController.swift │ │ ├── Integral │ │ │ └── IntegralVController.swift │ │ ├── Ranking │ │ │ └── RankingVController.swift │ │ └── UserVController.swift │ ├── Web │ │ └── WebVController.swift │ └── Wechat │ │ ├── WechatArticlesVController.swift │ │ └── WechatVController.swift ├── View │ ├── FloatButtonTableView.swift │ └── RefreshView.swift └── icon-60@3x.png ├── Podfile └── README.md /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## User settings 6 | xcuserdata/ 7 | 8 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) 9 | *.xcscmblueprint 10 | *.xccheckout 11 | 12 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) 13 | Pods/ 14 | build/ 15 | DerivedData/ 16 | Podfile.lock 17 | *.moved-aside 18 | *.pbxuser 19 | !default.pbxuser 20 | *.mode1v3 21 | !default.mode1v3 22 | *.mode2v3 23 | !default.mode2v3 24 | *.perspectivev3 25 | !default.perspectivev3 26 | 27 | ## Obj-C/Swift specific 28 | *.hmap 29 | 30 | ## App packaging 31 | *.ipa 32 | *.dSYM.zip 33 | *.dSYM 34 | 35 | ## Playgrounds 36 | timeline.xctimeline 37 | playground.xcworkspace 38 | 39 | # Swift Package Manager 40 | # 41 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 42 | # Packages/ 43 | # Package.pins 44 | # Package.resolved 45 | # *.xcodeproj 46 | # 47 | # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata 48 | # hence it is not needed unless you have added a package configuration file to your project 49 | # .swiftpm 50 | 51 | .build/ 52 | 53 | # CocoaPods 54 | # 55 | # We recommend against adding the Pods directory to your .gitignore. However 56 | # you should judge for yourself, the pros and cons are mentioned at: 57 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 58 | # 59 | # Pods/ 60 | # 61 | # Add this line if you want to avoid checking in source code from the Xcode workspace 62 | # *.xcworkspace 63 | 64 | # Carthage 65 | # 66 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 67 | # Carthage/Checkouts 68 | 69 | Carthage/Build/ 70 | 71 | # Accio dependency management 72 | Dependencies/ 73 | .accio/ 74 | 75 | # fastlane 76 | # 77 | # It is recommended to not store the screenshots in the git repo. 78 | # Instead, use fastlane to re-generate the screenshots whenever they are needed. 79 | # For more information about the recommended setup visit: 80 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 81 | 82 | fastlane/report.xml 83 | fastlane/Preview.html 84 | fastlane/screenshots/**/*.png 85 | fastlane/test_output 86 | 87 | # Code Injection 88 | # 89 | # After new code Injection tools there's a generated folder /iOSInjectionProject 90 | # https://github.com/johnno1962/injectionforxcode 91 | 92 | iOSInjectionProject/ 93 | -------------------------------------------------------------------------------- /FunIOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /FunIOS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /FunIOS.xcodeproj/project.xcworkspace/xcuserdata/redli.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS.xcodeproj/project.xcworkspace/xcuserdata/redli.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /FunIOS.xcodeproj/xcuserdata/redli.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | FunIOS.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 20 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /FunIOS.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /FunIOS.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /FunIOS.xcworkspace/xcuserdata/redli.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS.xcworkspace/xcuserdata/redli.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /FunIOS/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/.DS_Store -------------------------------------------------------------------------------- /FunIOS/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // FunIOS 4 | // 5 | // Created by redli on 2021/7/21. 6 | // 7 | 8 | import UIKit 9 | 10 | @main 11 | class AppDelegate: UIResponder, UIApplicationDelegate { 12 | 13 | 14 | 15 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 16 | // Override point for customization after application launch. 17 | return true 18 | } 19 | 20 | // MARK: UISceneSession Lifecycle 21 | 22 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { 23 | // Called when a new scene session is being created. 24 | // Use this method to select a configuration to create the new scene with. 25 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) 26 | } 27 | 28 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { 29 | // Called when the user discards a scene session. 30 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. 31 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return. 32 | } 33 | 34 | 35 | } 36 | 37 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/.DS_Store -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "iphone-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "iphone-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "iphone-29x29@2x.png", 19 | "scale" : "2x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "iphone-29x29@3x.png", 25 | "scale" : "3x" 26 | }, 27 | { 28 | "size" : "40x40", 29 | "idiom" : "iphone", 30 | "filename" : "iphone-40x40@2x.png", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "iphone-40x40@3x.png", 37 | "scale" : "3x" 38 | }, 39 | { 40 | "size" : "60x60", 41 | "idiom" : "iphone", 42 | "filename" : "iphone-60x60@2x.png", 43 | "scale" : "2x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "iphone-60x60@3x.png", 49 | "scale" : "3x" 50 | }, 51 | { 52 | "size" : "1024x1024", 53 | "idiom" : "ios-marketing", 54 | "filename" : "ios-marketing-1024x1024.png", 55 | "scale" : "1x" 56 | } 57 | ], 58 | "info" : { 59 | "version" : 1, 60 | "author" : "xcode" 61 | } 62 | } -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/AppIcon.appiconset/ios-marketing-1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/AppIcon.appiconset/ios-marketing-1024x1024.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/AppIcon.appiconset/iphone-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/AppIcon.appiconset/iphone-20x20@2x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/AppIcon.appiconset/iphone-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/AppIcon.appiconset/iphone-20x20@3x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/AppIcon.appiconset/iphone-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/AppIcon.appiconset/iphone-29x29@2x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/AppIcon.appiconset/iphone-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/AppIcon.appiconset/iphone-29x29@3x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/AppIcon.appiconset/iphone-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/AppIcon.appiconset/iphone-40x40@2x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/AppIcon.appiconset/iphone-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/AppIcon.appiconset/iphone-40x40@3x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/AppIcon.appiconset/iphone-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/AppIcon.appiconset/iphone-60x60@2x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/AppIcon.appiconset/iphone-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/AppIcon.appiconset/iphone-60x60@3x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/Common/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/Common/.DS_Store -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/Common/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/Common/ic_collect.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "ic_collect@2x.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "filename" : "ic_collect@3x.png", 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/Common/ic_collect.imageset/ic_collect@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/Common/ic_collect.imageset/ic_collect@2x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/Common/ic_collect.imageset/ic_collect@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/Common/ic_collect.imageset/ic_collect@3x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/Common/ic_top.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "ic_top-1.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "filename" : "ic_top.png", 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/Common/ic_top.imageset/ic_top-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/Common/ic_top.imageset/ic_top-1.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/Common/ic_top.imageset/ic_top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/Common/ic_top.imageset/ic_top.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/Common/ic_uncollect.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "ic_uncollect@2x.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "filename" : "ic_uncollect@3x.png", 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/Common/ic_uncollect.imageset/ic_uncollect@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/Common/ic_uncollect.imageset/ic_uncollect@2x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/Common/ic_uncollect.imageset/ic_uncollect@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/Common/ic_uncollect.imageset/ic_uncollect@3x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/Common/normal_placeholder_h.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "normal_placeholder_h@2x.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/Common/normal_placeholder_h.imageset/normal_placeholder_h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/Common/normal_placeholder_h.imageset/normal_placeholder_h@2x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/Common/normal_placeholder_v.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "normal_placeholder_v@2x.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/Common/normal_placeholder_v.imageset/normal_placeholder_v@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/Common/normal_placeholder_v.imageset/normal_placeholder_v@2x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/dropdown/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/dropdown/dropdown_loading_00.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "dropdown_loading_00@2x.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/dropdown/dropdown_loading_00.imageset/dropdown_loading_00@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/dropdown/dropdown_loading_00.imageset/dropdown_loading_00@2x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/dropdown/dropdown_loading_01.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "dropdown_loading_01@2x.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/dropdown/dropdown_loading_01.imageset/dropdown_loading_01@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/dropdown/dropdown_loading_01.imageset/dropdown_loading_01@2x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/dropdown/dropdown_loading_010.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "dropdown_loading_10@2x.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/dropdown/dropdown_loading_010.imageset/dropdown_loading_10@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/dropdown/dropdown_loading_010.imageset/dropdown_loading_10@2x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/dropdown/dropdown_loading_011.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "dropdown_loading_11@2x.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/dropdown/dropdown_loading_011.imageset/dropdown_loading_11@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/dropdown/dropdown_loading_011.imageset/dropdown_loading_11@2x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/dropdown/dropdown_loading_012.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "dropdown_loading_12@2x.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/dropdown/dropdown_loading_012.imageset/dropdown_loading_12@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/dropdown/dropdown_loading_012.imageset/dropdown_loading_12@2x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/dropdown/dropdown_loading_013.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "dropdown_loading_13@2x.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/dropdown/dropdown_loading_013.imageset/dropdown_loading_13@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/dropdown/dropdown_loading_013.imageset/dropdown_loading_13@2x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/dropdown/dropdown_loading_014.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "dropdown_loading_14@2x.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/dropdown/dropdown_loading_014.imageset/dropdown_loading_14@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/dropdown/dropdown_loading_014.imageset/dropdown_loading_14@2x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/dropdown/dropdown_loading_015.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "dropdown_loading_15@2x.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/dropdown/dropdown_loading_015.imageset/dropdown_loading_15@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/dropdown/dropdown_loading_015.imageset/dropdown_loading_15@2x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/dropdown/dropdown_loading_02.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "dropdown_loading_02@2x.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/dropdown/dropdown_loading_02.imageset/dropdown_loading_02@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/dropdown/dropdown_loading_02.imageset/dropdown_loading_02@2x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/dropdown/dropdown_loading_03.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "dropdown_loading_03@2x.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/dropdown/dropdown_loading_03.imageset/dropdown_loading_03@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/dropdown/dropdown_loading_03.imageset/dropdown_loading_03@2x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/dropdown/dropdown_loading_04.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "dropdown_loading_04@2x.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/dropdown/dropdown_loading_04.imageset/dropdown_loading_04@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/dropdown/dropdown_loading_04.imageset/dropdown_loading_04@2x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/dropdown/dropdown_loading_05.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "dropdown_loading_05@2x.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/dropdown/dropdown_loading_05.imageset/dropdown_loading_05@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/dropdown/dropdown_loading_05.imageset/dropdown_loading_05@2x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/dropdown/dropdown_loading_06.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "dropdown_loading_06@2x.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/dropdown/dropdown_loading_06.imageset/dropdown_loading_06@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/dropdown/dropdown_loading_06.imageset/dropdown_loading_06@2x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/dropdown/dropdown_loading_07.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "dropdown_loading_07@2x.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/dropdown/dropdown_loading_07.imageset/dropdown_loading_07@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/dropdown/dropdown_loading_07.imageset/dropdown_loading_07@2x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/dropdown/dropdown_loading_08.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "dropdown_loading_08@2x.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/dropdown/dropdown_loading_08.imageset/dropdown_loading_08@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/dropdown/dropdown_loading_08.imageset/dropdown_loading_08@2x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/dropdown/dropdown_loading_09.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "dropdown_loading_09@2x.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/dropdown/dropdown_loading_09.imageset/dropdown_loading_09@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/dropdown/dropdown_loading_09.imageset/dropdown_loading_09@2x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/loading/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/loading/sendloading_18x18_0.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "sendloading_18x18_0@2x.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "filename" : "sendloading_18x18_0@3x.png", 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/loading/sendloading_18x18_0.imageset/sendloading_18x18_0@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/loading/sendloading_18x18_0.imageset/sendloading_18x18_0@2x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/loading/sendloading_18x18_0.imageset/sendloading_18x18_0@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/loading/sendloading_18x18_0.imageset/sendloading_18x18_0@3x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/loading/sendloading_18x18_1.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "sendloading_18x18_1@2x.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "filename" : "sendloading_18x18_1@3x.png", 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/loading/sendloading_18x18_1.imageset/sendloading_18x18_1@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/loading/sendloading_18x18_1.imageset/sendloading_18x18_1@2x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/loading/sendloading_18x18_1.imageset/sendloading_18x18_1@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/loading/sendloading_18x18_1.imageset/sendloading_18x18_1@3x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/loading/sendloading_18x18_2.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "sendloading_18x18_2@2x.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "filename" : "sendloading_18x18_2@3x.png", 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/loading/sendloading_18x18_2.imageset/sendloading_18x18_2@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/loading/sendloading_18x18_2.imageset/sendloading_18x18_2@2x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/loading/sendloading_18x18_2.imageset/sendloading_18x18_2@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/loading/sendloading_18x18_2.imageset/sendloading_18x18_2@3x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/loading/sendloading_18x18_3.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "sendloading_18x18_3@2x.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "filename" : "sendloading_18x18_3@3x.png", 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/loading/sendloading_18x18_3.imageset/sendloading_18x18_3@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/loading/sendloading_18x18_3.imageset/sendloading_18x18_3@2x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/loading/sendloading_18x18_3.imageset/sendloading_18x18_3@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/loading/sendloading_18x18_3.imageset/sendloading_18x18_3@3x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/loading/sendloading_18x18_4.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "sendloading_18x18_4@2x.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "filename" : "sendloading_18x18_4@3x.png", 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/loading/sendloading_18x18_4.imageset/sendloading_18x18_4@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/loading/sendloading_18x18_4.imageset/sendloading_18x18_4@2x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/loading/sendloading_18x18_4.imageset/sendloading_18x18_4@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/loading/sendloading_18x18_4.imageset/sendloading_18x18_4@3x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/loading/sendloading_18x18_5.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "sendloading_18x18_5@2x.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "filename" : "sendloading_18x18_5@3x.png", 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/loading/sendloading_18x18_5.imageset/sendloading_18x18_5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/loading/sendloading_18x18_5.imageset/sendloading_18x18_5@2x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/loading/sendloading_18x18_5.imageset/sendloading_18x18_5@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/loading/sendloading_18x18_5.imageset/sendloading_18x18_5@3x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/loading/sendloading_18x18_6.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "sendloading_18x18_6@2x.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "filename" : "sendloading_18x18_6@3x.png", 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/loading/sendloading_18x18_6.imageset/sendloading_18x18_6@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/loading/sendloading_18x18_6.imageset/sendloading_18x18_6@2x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/loading/sendloading_18x18_6.imageset/sendloading_18x18_6@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/loading/sendloading_18x18_6.imageset/sendloading_18x18_6@3x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/loading/sendloading_18x18_7.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "sendloading_18x18_7@2x.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "filename" : "sendloading_18x18_7@3x.png", 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/loading/sendloading_18x18_7.imageset/sendloading_18x18_7@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/loading/sendloading_18x18_7.imageset/sendloading_18x18_7@2x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/loading/sendloading_18x18_7.imageset/sendloading_18x18_7@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/loading/sendloading_18x18_7.imageset/sendloading_18x18_7@3x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/login/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/login/.DS_Store -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/login/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/login/ic_close.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "ic_close-1.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "filename" : "ic_close.png", 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/login/ic_close.imageset/ic_close-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/login/ic_close.imageset/ic_close-1.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/login/ic_close.imageset/ic_close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/login/ic_close.imageset/ic_close.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/login/ic_logout.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "ic_logout-1.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "filename" : "ic_logout.png", 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/login/ic_logout.imageset/ic_logout-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/login/ic_logout.imageset/ic_logout-1.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/login/ic_logout.imageset/ic_logout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/login/ic_logout.imageset/ic_logout.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/login/ic_password.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "ic_password-1.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "filename" : "ic_password.png", 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/login/ic_password.imageset/ic_password-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/login/ic_password.imageset/ic_password-1.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/login/ic_password.imageset/ic_password.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/login/ic_password.imageset/ic_password.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/login/ic_user.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "ic_user-1.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "filename" : "ic_user.png", 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/login/ic_user.imageset/ic_user-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/login/ic_user.imageset/ic_user-1.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/login/ic_user.imageset/ic_user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/login/ic_user.imageset/ic_user.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/mine/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/mine/ic_browsing.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "ic_browsing-1.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "filename" : "ic_browsing.png", 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/mine/ic_browsing.imageset/ic_browsing-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/mine/ic_browsing.imageset/ic_browsing-1.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/mine/ic_browsing.imageset/ic_browsing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/mine/ic_browsing.imageset/ic_browsing.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/mine/ic_calendar.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "ic_calendar-1.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "filename" : "ic_calendar.png", 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/mine/ic_calendar.imageset/ic_calendar-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/mine/ic_calendar.imageset/ic_calendar-1.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/mine/ic_calendar.imageset/ic_calendar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/mine/ic_calendar.imageset/ic_calendar.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/mine/ic_collection.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "ic_collection.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "filename" : "ic_collection-1.png", 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/mine/ic_collection.imageset/ic_collection-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/mine/ic_collection.imageset/ic_collection-1.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/mine/ic_collection.imageset/ic_collection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/mine/ic_collection.imageset/ic_collection.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/mine/ic_courier.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "ic_courier-1.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "filename" : "ic_courier.png", 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/mine/ic_courier.imageset/ic_courier-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/mine/ic_courier.imageset/ic_courier-1.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/mine/ic_courier.imageset/ic_courier.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/mine/ic_courier.imageset/ic_courier.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/mine/ic_google.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "ic_google-1.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "filename" : "ic_google.png", 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/mine/ic_google.imageset/ic_google-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/mine/ic_google.imageset/ic_google-1.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/mine/ic_google.imageset/ic_google.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/mine/ic_google.imageset/ic_google.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/mine/ic_integral.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "ic_integral-1.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "filename" : "ic_integral.png", 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/mine/ic_integral.imageset/ic_integral-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/mine/ic_integral.imageset/ic_integral-1.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/mine/ic_integral.imageset/ic_integral.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/mine/ic_integral.imageset/ic_integral.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/mine/ic_ranking.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "ic_ranking-1.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "filename" : "ic_ranking.png", 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/mine/ic_ranking.imageset/ic_ranking-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/mine/ic_ranking.imageset/ic_ranking-1.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/mine/ic_ranking.imageset/ic_ranking.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/mine/ic_ranking.imageset/ic_ranking.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/mine/ic_share.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "ic_share-1.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "filename" : "ic_share.png", 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/mine/ic_share.imageset/ic_share-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/mine/ic_share.imageset/ic_share-1.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/mine/ic_share.imageset/ic_share.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/mine/ic_share.imageset/ic_share.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/mine/ic_todo.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "ic_todo-1.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "filename" : "ic_todo.png", 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/mine/ic_todo.imageset/ic_todo-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/mine/ic_todo.imageset/ic_todo-1.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/mine/ic_todo.imageset/ic_todo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/mine/ic_todo.imageset/ic_todo.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/mine/ic_weather.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "ic_weather-1.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "filename" : "ic_weather.png", 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/mine/ic_weather.imageset/ic_weather-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/mine/ic_weather.imageset/ic_weather-1.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/mine/ic_weather.imageset/ic_weather.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/mine/ic_weather.imageset/ic_weather.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/tabbar/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/tabbar/.DS_Store -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/tabbar/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/tabbar/home_tabbar_night_32x32_.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "Icon-60@2x.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "filename" : "Icon-60@3x.png", 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | }, 22 | "properties" : { 23 | "template-rendering-intent" : "original" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/tabbar/home_tabbar_night_32x32_.imageset/Icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/tabbar/home_tabbar_night_32x32_.imageset/Icon-60@2x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/tabbar/home_tabbar_night_32x32_.imageset/Icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/tabbar/home_tabbar_night_32x32_.imageset/Icon-60@3x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/tabbar/home_tabbar_press_32x32_.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "icon-60@2x.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "filename" : "icon-60@3x.png", 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | }, 22 | "properties" : { 23 | "template-rendering-intent" : "original" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/tabbar/home_tabbar_press_32x32_.imageset/Icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/tabbar/home_tabbar_press_32x32_.imageset/Icon-60@3x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/tabbar/home_tabbar_press_32x32_.imageset/icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/tabbar/home_tabbar_press_32x32_.imageset/icon-60@2x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/tabbar/mine_tabbar_night_32x32_.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "Icon-60@2x.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "filename" : "Icon-60@3x.png", 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | }, 22 | "properties" : { 23 | "template-rendering-intent" : "original" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/tabbar/mine_tabbar_night_32x32_.imageset/Icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/tabbar/mine_tabbar_night_32x32_.imageset/Icon-60@2x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/tabbar/mine_tabbar_night_32x32_.imageset/Icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/tabbar/mine_tabbar_night_32x32_.imageset/Icon-60@3x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/tabbar/mine_tabbar_press_32x32_.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "icon-60@2x.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "filename" : "icon-60@3x.png", 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | }, 22 | "properties" : { 23 | "template-rendering-intent" : "original" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/tabbar/mine_tabbar_press_32x32_.imageset/icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/tabbar/mine_tabbar_press_32x32_.imageset/icon-60@2x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/tabbar/mine_tabbar_press_32x32_.imageset/icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/tabbar/mine_tabbar_press_32x32_.imageset/icon-60@3x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/tabbar/project_tabbar_night_32x32_.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "Icon-60@2x.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "filename" : "Icon-60@3x.png", 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | }, 22 | "properties" : { 23 | "template-rendering-intent" : "original" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/tabbar/project_tabbar_night_32x32_.imageset/Icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/tabbar/project_tabbar_night_32x32_.imageset/Icon-60@2x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/tabbar/project_tabbar_night_32x32_.imageset/Icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/tabbar/project_tabbar_night_32x32_.imageset/Icon-60@3x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/tabbar/project_tabbar_press_32x32_.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "icon-60@2x.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "filename" : "icon-60@3x.png", 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | }, 22 | "properties" : { 23 | "template-rendering-intent" : "original" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/tabbar/project_tabbar_press_32x32_.imageset/icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/tabbar/project_tabbar_press_32x32_.imageset/icon-60@2x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/tabbar/project_tabbar_press_32x32_.imageset/icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/tabbar/project_tabbar_press_32x32_.imageset/icon-60@3x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/tabbar/structure_tabbar_night_32x32_.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "Icon-60@2x.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "filename" : "Icon-60@3x.png", 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/tabbar/structure_tabbar_night_32x32_.imageset/Icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/tabbar/structure_tabbar_night_32x32_.imageset/Icon-60@2x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/tabbar/structure_tabbar_night_32x32_.imageset/Icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/tabbar/structure_tabbar_night_32x32_.imageset/Icon-60@3x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/tabbar/structure_tabbar_press_32x32_.imageset/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/tabbar/structure_tabbar_press_32x32_.imageset/.DS_Store -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/tabbar/structure_tabbar_press_32x32_.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "icon-60@2x.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "filename" : "icon-60@3x.png", 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/tabbar/structure_tabbar_press_32x32_.imageset/icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/tabbar/structure_tabbar_press_32x32_.imageset/icon-60@2x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/tabbar/wechat_tabbar_night_32x32_.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "Icon-60@2x.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "filename" : "Icon-60@3x.png", 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/tabbar/wechat_tabbar_night_32x32_.imageset/Icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/tabbar/wechat_tabbar_night_32x32_.imageset/Icon-60@2x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/tabbar/wechat_tabbar_night_32x32_.imageset/Icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/tabbar/wechat_tabbar_night_32x32_.imageset/Icon-60@3x.png -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/tabbar/wechat_tabbar_press_32x32_.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "icon-60@2x.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "filename" : "icon-60@3x.png", 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /FunIOS/Assets.xcassets/tabbar/wechat_tabbar_press_32x32_.imageset/icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/Assets.xcassets/tabbar/wechat_tabbar_press_32x32_.imageset/icon-60@2x.png -------------------------------------------------------------------------------- /FunIOS/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /FunIOS/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /FunIOS/Base/BaseResponse.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BaseResponse.swift 3 | // FunIOS 4 | // 5 | // Created by redli on 2021/7/21. 6 | // 7 | 8 | import Foundation 9 | import HandyJSON 10 | 11 | class BaseResponse: HandyJSON { 12 | 13 | var errorCode : Int? //服务返回码 14 | 15 | var errorMsg : String? 16 | 17 | var data : T? 18 | 19 | required init() {} 20 | } 21 | -------------------------------------------------------------------------------- /FunIOS/Base/BaseTableViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BaseTableViewCell.swift 3 | // FunIOS 4 | // 5 | // Created by redli on 2021/7/22. 6 | // 7 | 8 | import UIKit 9 | import Reusable 10 | 11 | 12 | // Reusable 是用回收的 13 | 14 | /** 15 | 收藏功能提到basecell 。这个项目每个列表都有收藏功能。可加可不加 16 | */ 17 | 18 | class BaseTableViewCell: UITableViewCell, Reusable { 19 | 20 | weak open var collectDelegate: CollectDelegate? 21 | 22 | //是否收藏 23 | var isCollect = false 24 | 25 | lazy var imgCollect = UIButton().then({attr in 26 | attr.setImage(UIImage(named: "ic_uncollect"), for: .normal) 27 | }) 28 | 29 | override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { 30 | super.init(style: style, reuseIdentifier: reuseIdentifier) 31 | selectionStyle = .none 32 | configUI() 33 | } 34 | 35 | open func configUI() { 36 | 37 | } 38 | 39 | func refreshCollect(isCollect collect: Bool) { 40 | if collect { 41 | imgCollect.setImage(UIImage(named: "ic_collect"), for: .normal) 42 | } else { 43 | imgCollect.setImage(UIImage(named: "ic_uncollect"), for: .normal) 44 | } 45 | self.isCollect = collect 46 | } 47 | 48 | @objc func collect(btn: UIButton) { 49 | if self.isCollect { 50 | collectDelegate?.uncollectAirticle(cid: btn.tag, tabCell: self) 51 | } else { 52 | collectDelegate?.collectAirticle(cid: btn.tag, tabCell: self) 53 | } 54 | } 55 | 56 | required init?(coder: NSCoder) { 57 | fatalError("init(coder:) has not been implemented") 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /FunIOS/Base/BaseVController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BaseVController.swift 3 | // FunIOS 4 | // 5 | // Created by redli on 2021/9/6. 6 | // 7 | 8 | import Foundation 9 | import UIKit 10 | import LGButton 11 | 12 | 13 | class BaseCVontroller: UIViewController{ 14 | 15 | var floatAnimal = false 16 | 17 | var floatButton = UIButton().then({attr in 18 | attr.setImage(UIImage(named: "ic_top"), for: .normal) 19 | attr.contentMode = .scaleToFill 20 | attr.isHidden = true 21 | }) 22 | 23 | func error(error: String?) { 24 | // view.makeToast(error) 25 | showHUDWithError(error: error) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /FunIOS/Cell-列表item样式/ArticleCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ArticleCell.swift 3 | // FunIOS 4 | // 5 | // Created by redli on 2021/7/22. 6 | // 7 | 8 | import UIKit 9 | import SnapKitExtend 10 | 11 | public protocol CollectDelegate : NSObjectProtocol{ 12 | 13 | //收藏 文章 14 | func collectAirticle(cid id: Int, tabCell tabviewCell: UITableViewCell) -> Void 15 | 16 | //取消收藏 文章 17 | func uncollectAirticle(cid id: Int, tabCell tabviewCell: UITableViewCell) -> Void 18 | } 19 | 20 | 21 | class ArticleCell: BaseTableViewCell { 22 | 23 | private lazy var labelAuthor = UILabel().then({ (attr) in 24 | attr.text = "author" 25 | attr.font = UIFont.systemFont(ofSize: 12) 26 | attr.numberOfLines = 0 //相当于不限制行数 27 | attr.lineBreakMode = .byWordWrapping 28 | attr.sizeToFit() 29 | attr.backgroundColor = UIColor.white 30 | }) 31 | 32 | private lazy var labelTime = UILabel().then({ (attr) in 33 | attr.text = "Time" 34 | attr.textColor = .gray 35 | attr.font = UIFont.systemFont(ofSize: 12) 36 | attr.numberOfLines = 0 //相当于不限制行数 37 | attr.lineBreakMode = .byWordWrapping 38 | attr.sizeToFit() 39 | attr.backgroundColor = UIColor.white 40 | }) 41 | 42 | 43 | private lazy var labelTitle: UILabel = UILabel().then {(attr) in 44 | attr.text = "Titile" 45 | attr.textColor = .black 46 | attr.font = UIFont.systemFont(ofSize: 14) 47 | attr.numberOfLines = 2 //相当于不限制行数 48 | attr.lineBreakMode = .byWordWrapping 49 | attr.sizeToFit() 50 | attr.backgroundColor = UIColor.white 51 | } 52 | 53 | 54 | private lazy var labelChapterName = UILabel().then({(attr) in 55 | attr.text = "ChapterName" 56 | attr.textColor = .gray 57 | attr.font = UIFont.systemFont(ofSize: 10) 58 | attr.numberOfLines = 0 //相当于不限制行数 59 | attr.lineBreakMode = .byWordWrapping 60 | attr.sizeToFit() 61 | attr.backgroundColor = UIColor.white 62 | }) 63 | 64 | private lazy var labelSuperChapterName = UILabel().then({(attr) in 65 | attr.text = "SuperChapterName" 66 | attr.textColor = .gray 67 | attr.font = UIFont.systemFont(ofSize: 10) 68 | attr.numberOfLines = 0 //相当于不限制行数 69 | attr.lineBreakMode = .byWordWrapping 70 | attr.sizeToFit() 71 | attr.backgroundColor = UIColor.white 72 | }) 73 | 74 | var model: ArticleItemModel?{ 75 | didSet { 76 | guard model == nil else { 77 | labelAuthor.text = (model?.author.isEmpty)! ? model?.shareUser : model?.author 78 | labelTime.text = model?.niceShareDate 79 | labelTitle.text = model?.title 80 | labelSuperChapterName.text = model?.superChapterName 81 | labelChapterName.text = " · \(model?.chapterName ?? "")" 82 | 83 | isCollect = model?.collect ?? false 84 | 85 | refreshCollect(isCollect: isCollect) 86 | 87 | imgCollect.tag = model?.id ?? 0 88 | return 89 | } 90 | } 91 | } 92 | 93 | override func configUI() { 94 | contentView.addSubview(labelAuthor) 95 | labelAuthor.snp.makeConstraints {maker in 96 | maker.leading.equalToSuperview().offset(10) 97 | maker.top.equalToSuperview().offset(10) 98 | } 99 | 100 | contentView.addSubview(labelTime) 101 | labelTime.snp.makeConstraints({maker in 102 | maker.trailing.equalToSuperview().offset(-10) 103 | maker.top.equalToSuperview().offset(10) 104 | }) 105 | 106 | contentView.addSubview(labelTitle) 107 | labelTitle.snp.makeConstraints({maker in 108 | maker.top.equalTo(labelAuthor.snp.bottom).offset(10) 109 | maker.leading.equalToSuperview().offset(10) 110 | maker.trailing.equalToSuperview().offset(-10) 111 | 112 | }) 113 | 114 | contentView.addSubview(labelSuperChapterName) 115 | labelSuperChapterName.snp.makeConstraints {maker in 116 | maker.leading.equalToSuperview().offset(10) 117 | maker.top.equalTo(labelTitle.snp.bottom).offset(10) 118 | maker.bottom.equalToSuperview().offset(-10) 119 | } 120 | 121 | contentView.addSubview(labelChapterName) 122 | labelChapterName.snp.makeConstraints({maker in 123 | maker.leading.equalTo(labelSuperChapterName.snp.trailing) 124 | maker.top.equalTo(labelTitle.snp.bottom).offset(10) 125 | maker.bottom.equalToSuperview().offset(-10) 126 | }) 127 | 128 | contentView.addSubview(imgCollect) 129 | imgCollect.snp.makeConstraints { maker in 130 | maker.height.equalTo(20) 131 | maker.width.equalTo(20) 132 | maker.trailing.equalToSuperview().offset(-10) 133 | maker.bottom.equalToSuperview().offset(-5) 134 | } 135 | 136 | imgCollect.addTarget(self, action: #selector(self.collect(btn:)), for: .touchUpInside) 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /FunIOS/Cell-列表item样式/CollectCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CollectCell.swift 3 | // FunIOS 4 | // 5 | // Created by redli on 2021/8/10. 6 | // 7 | 8 | import Foundation 9 | import UIKit 10 | 11 | class CollectCell: BaseTableViewCell { 12 | private lazy var labelAuthor = UILabel().then({ (attr) in 13 | attr.text = "author" 14 | attr.font = UIFont.systemFont(ofSize: 15) 15 | attr.numberOfLines = 0 //相当于不限制行数 16 | attr.lineBreakMode = .byWordWrapping 17 | attr.sizeToFit() 18 | attr.backgroundColor = UIColor.white 19 | }) 20 | 21 | private lazy var labelTime = UILabel().then({ (attr) in 22 | attr.text = "Time" 23 | attr.textColor = .gray 24 | attr.font = UIFont.systemFont(ofSize: 14) 25 | attr.numberOfLines = 0 //相当于不限制行数 26 | attr.lineBreakMode = .byWordWrapping 27 | attr.sizeToFit() 28 | attr.backgroundColor = UIColor.white 29 | }) 30 | 31 | 32 | private lazy var labelTitle: UILabel = UILabel().then {(attr) in 33 | attr.text = "Titile" 34 | attr.textColor = .black 35 | attr.font = UIFont.boldSystemFont(ofSize: 15) 36 | attr.numberOfLines = 2 //相当于不限制行数 37 | attr.lineBreakMode = .byWordWrapping 38 | attr.sizeToFit() 39 | attr.backgroundColor = UIColor.white 40 | } 41 | 42 | private lazy var labelDesc: UILabel = UILabel().then { (attr) in 43 | attr.text = "desc" 44 | attr.font = UIFont.systemFont(ofSize: 14) 45 | attr.numberOfLines = 2 //相当于不限制行数 46 | attr.lineBreakMode = .byTruncatingTail 47 | attr.sizeToFit() 48 | attr.isHidden = true 49 | attr.backgroundColor = UIColor.white 50 | } 51 | 52 | 53 | private lazy var labelChapterName = UILabel().then({(attr) in 54 | attr.text = "ChapterName" 55 | attr.textColor = .gray 56 | attr.font = UIFont.boldSystemFont(ofSize: 12) 57 | attr.numberOfLines = 0 //相当于不限制行数 58 | attr.lineBreakMode = .byWordWrapping 59 | attr.sizeToFit() 60 | attr.backgroundColor = UIColor.white 61 | }) 62 | 63 | private lazy var labelSuperChapterName = UILabel().then({(attr) in 64 | attr.text = "SuperChapterName" 65 | attr.textColor = .gray 66 | attr.font = UIFont.boldSystemFont(ofSize: 12) 67 | attr.numberOfLines = 0 //相当于不限制行数 68 | attr.lineBreakMode = .byWordWrapping 69 | attr.sizeToFit() 70 | attr.backgroundColor = UIColor.white 71 | }) 72 | 73 | private lazy var line = UIView().then({ (attr) in 74 | attr.backgroundColor = UIColor.lightGray.withAlphaComponent(0.2) 75 | }) 76 | 77 | var model: ArticleItemModel?{ 78 | didSet { 79 | guard model == nil else { 80 | labelAuthor.text = (model?.author.isEmpty)! ? model?.shareUser : model?.author 81 | labelTime.text = model?.niceDate 82 | labelTitle.text = model?.title 83 | labelDesc.text = model?.desc 84 | labelSuperChapterName.text = model?.superChapterName 85 | labelChapterName.text = " · \(model?.chapterName ?? "")" 86 | return 87 | } 88 | } 89 | } 90 | 91 | 92 | override func configUI() { 93 | contentView.addSubview(labelAuthor) 94 | labelAuthor.snp.makeConstraints {(maker) in 95 | maker.leading.equalToSuperview().offset(10) 96 | maker.top.equalToSuperview().offset(10) 97 | 98 | } 99 | 100 | contentView.addSubview(labelTime) 101 | labelTime.snp.makeConstraints({(maker) in 102 | maker.trailing.equalToSuperview().offset(-10) 103 | maker.top.equalToSuperview().offset(10) 104 | }) 105 | 106 | contentView.addSubview(labelTitle) 107 | labelTitle.snp.makeConstraints({(maker) in 108 | maker.top.equalTo(labelAuthor.snp.bottom).offset(10) 109 | maker.top.equalTo(labelTime.snp.bottom).offset(10) 110 | maker.leading.equalToSuperview().offset(10) 111 | maker.trailing.equalToSuperview().offset(-10) 112 | }) 113 | 114 | // contentView.addSubview(labelDesc) 115 | // labelDesc.snp.makeConstraints { (maker) in 116 | // maker.top.equalTo(labelTitle.snp.bottom).offset(10) 117 | // maker.leading.equalToSuperview().offset(10) 118 | // maker.trailing.equalToSuperview().offset(-10) 119 | // } 120 | 121 | contentView.addSubview(labelSuperChapterName) 122 | labelSuperChapterName.snp.makeConstraints {(maker) in 123 | maker.leading.equalToSuperview().offset(10) 124 | maker.top.equalTo(labelTitle.snp.bottom).offset(10) 125 | } 126 | 127 | contentView.addSubview(labelChapterName) 128 | labelChapterName.snp.makeConstraints({(maker) in 129 | maker.leading.equalTo(labelSuperChapterName.snp.trailing) 130 | maker.top.equalTo(labelTitle.snp.bottom).offset(10) 131 | }) 132 | 133 | contentView.addSubview(line) 134 | line.snp.makeConstraints { (maker) in 135 | maker.top.equalTo(labelSuperChapterName.snp.bottom).offset(10) 136 | maker.top.equalTo(labelChapterName.snp.bottom).offset(10) 137 | maker.bottom.equalToSuperview() 138 | maker.leading.equalToSuperview().offset(10) 139 | maker.trailing.equalToSuperview().offset(-10) 140 | maker.height.equalTo(1) 141 | } 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /FunIOS/Cell-列表item样式/MenuCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MenuCell.swift 3 | // FunIOS 4 | // 5 | // Created by redli on 2021/7/29. 6 | // 7 | 8 | import UIKit 9 | import Reusable 10 | 11 | class MenuCell: UICollectionViewCell, Reusable { 12 | 13 | var labelTitle: UILabel! 14 | var imgIcon: UIImageView! 15 | 16 | override init(frame: CGRect) { 17 | super.init(frame: frame) 18 | self.labelTitle = UILabel().then({ (attr) in 19 | attr.textAlignment = .center 20 | attr.font = UIFont.systemFont(ofSize: 12) 21 | }) 22 | 23 | self.imgIcon = UIImageView().then({ (attr) in 24 | attr.contentMode = .scaleAspectFit 25 | }) 26 | 27 | contentView.addSubview(self.imgIcon) 28 | self.imgIcon.snp.makeConstraints { (maker) in 29 | maker.top.equalToSuperview().offset(7) 30 | // maker.leading.equalToSuperview() 31 | // maker.trailing.equalToSuperview() 32 | maker.centerX.equalToSuperview() 33 | } 34 | 35 | contentView.addSubview(self.labelTitle) 36 | self.labelTitle.snp.makeConstraints { (maker) in 37 | maker.top.equalTo(self.imgIcon.snp.bottom).offset(5) 38 | // maker.leading.equalToSuperview() 39 | // maker.trailing.equalToSuperview() 40 | maker.centerX.equalToSuperview() 41 | } 42 | } 43 | 44 | 45 | required init?(coder: NSCoder) { 46 | fatalError("init(coder:) has not been implemented") 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /FunIOS/Cell-列表item样式/ProjectCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ProjectCell.swift 3 | // FunIOS 4 | // 5 | // Created by redli on 2021/7/25. 6 | // 7 | 8 | import UIKit 9 | import Kingfisher 10 | 11 | class ProjectCell: BaseTableViewCell { 12 | 13 | private lazy var labelAuthor = UILabel().then({ (attr) in 14 | attr.text = "author" 15 | attr.font = UIFont.systemFont(ofSize: 12) 16 | attr.numberOfLines = 0 //相当于不限制行数 17 | attr.lineBreakMode = .byWordWrapping 18 | attr.sizeToFit() 19 | attr.backgroundColor = UIColor.white 20 | }) 21 | 22 | private lazy var labelTime = UILabel().then({ (attr) in 23 | attr.text = "Time" 24 | attr.textColor = .gray 25 | attr.font = UIFont.systemFont(ofSize: 12) 26 | attr.numberOfLines = 0 //相当于不限制行数 27 | attr.lineBreakMode = .byWordWrapping 28 | attr.sizeToFit() 29 | attr.backgroundColor = UIColor.white 30 | }) 31 | 32 | 33 | private lazy var labelTitle: UILabel = UILabel().then {(attr) in 34 | attr.text = "Titile" 35 | attr.textColor = .black 36 | attr.font = UIFont.systemFont(ofSize: 15) 37 | attr.numberOfLines = 2 //相当于不限制行数 38 | attr.lineBreakMode = .byWordWrapping 39 | attr.sizeToFit() 40 | attr.backgroundColor = UIColor.white 41 | } 42 | 43 | private lazy var labelDesc: UILabel = UILabel().then { (attr) in 44 | attr.text = "desc" 45 | attr.font = UIFont.systemFont(ofSize: 12) 46 | attr.numberOfLines = 2 //相当于不限制行数 47 | attr.lineBreakMode = .byTruncatingTail 48 | attr.sizeToFit() 49 | attr.backgroundColor = UIColor.white 50 | } 51 | 52 | private lazy var imageContainer = UIImageView().then { (attr) in 53 | 54 | } 55 | 56 | private lazy var labelChapterName = UILabel().then({(attr) in 57 | attr.text = "ChapterName" 58 | attr.textColor = .gray 59 | attr.font = UIFont.systemFont(ofSize: 10) 60 | attr.numberOfLines = 0 //相当于不限制行数 61 | attr.lineBreakMode = .byWordWrapping 62 | attr.sizeToFit() 63 | attr.backgroundColor = UIColor.white 64 | }) 65 | 66 | private lazy var labelSuperChapterName = UILabel().then({(attr) in 67 | attr.text = "SuperChapterName" 68 | attr.textColor = .gray 69 | attr.font = UIFont.systemFont(ofSize: 10) 70 | attr.numberOfLines = 0 //相当于不限制行数 71 | attr.lineBreakMode = .byWordWrapping 72 | attr.sizeToFit() 73 | attr.backgroundColor = UIColor.white 74 | }) 75 | 76 | var model: ArticleItemModel?{ 77 | didSet { 78 | guard model == nil else { 79 | labelAuthor.text = (model?.author.isEmpty)! ? model?.shareUser : model?.author 80 | labelTime.text = model?.niceShareDate 81 | labelTitle.text = model?.title 82 | labelDesc.text = model?.desc 83 | imageContainer.kf.setImage(with: URL(string: model!.envelopePic), placeholder: UIImage(named: "normal_placeholder_h")) 84 | labelSuperChapterName.text = model?.superChapterName 85 | labelChapterName.text = " · \(model?.chapterName ?? "")" 86 | 87 | isCollect = model?.collect ?? false 88 | 89 | refreshCollect(isCollect: isCollect) 90 | 91 | imgCollect.tag = model?.id ?? 0 92 | 93 | return 94 | } 95 | } 96 | } 97 | 98 | override func configUI() { 99 | contentView.addSubview(labelAuthor) 100 | labelAuthor.snp.makeConstraints {(maker) in 101 | maker.leading.equalToSuperview().offset(10) 102 | maker.top.equalToSuperview().offset(10) 103 | 104 | } 105 | 106 | contentView.addSubview(labelTime) 107 | labelTime.snp.makeConstraints({(maker) in 108 | maker.trailing.equalToSuperview().offset(-10) 109 | maker.top.equalToSuperview().offset(10) 110 | }) 111 | 112 | contentView.addSubview(labelTitle) 113 | labelTitle.snp.makeConstraints({(maker) in 114 | maker.top.equalTo(labelAuthor.snp.bottom).offset(10) 115 | maker.top.equalTo(labelTime.snp.bottom).offset(10) 116 | maker.leading.equalToSuperview().offset(10) 117 | // maker.trailing.equalToSuperview().offset(-10) 118 | }) 119 | 120 | contentView.addSubview(labelDesc) 121 | labelDesc.snp.makeConstraints { (maker) in 122 | maker.top.equalTo(labelTitle.snp.bottom).offset(10) 123 | maker.leading.equalToSuperview().offset(10) 124 | // maker.trailing.equalToSuperview().offset(-10) 125 | } 126 | 127 | contentView.addSubview(imageContainer) 128 | imageContainer.snp.makeConstraints { (maker) in 129 | maker.top.equalTo(labelAuthor.snp.bottom).offset(10) 130 | maker.top.equalTo(labelTime.snp.bottom).offset(10) 131 | maker.trailing.equalToSuperview().offset(-10) 132 | maker.leading.equalTo(labelTitle.snp.trailing).offset(10) 133 | maker.leading.equalTo(labelDesc.snp.trailing).offset(10) 134 | maker.height.equalTo(60) 135 | maker.width.equalTo(60) 136 | } 137 | 138 | contentView.addSubview(labelSuperChapterName) 139 | labelSuperChapterName.snp.makeConstraints {(maker) in 140 | maker.leading.equalToSuperview().offset(10) 141 | maker.top.equalTo(labelDesc.snp.bottom).offset(10) 142 | maker.bottom.equalToSuperview().offset(-10) 143 | } 144 | 145 | contentView.addSubview(labelChapterName) 146 | labelChapterName.snp.makeConstraints({(maker) in 147 | maker.leading.equalTo(labelSuperChapterName.snp.trailing) 148 | maker.top.equalTo(labelDesc.snp.bottom).offset(10) 149 | maker.bottom.equalToSuperview().offset(-10) 150 | }) 151 | 152 | contentView.addSubview(imgCollect) 153 | imgCollect.snp.makeConstraints { maker in 154 | maker.height.equalTo(20) 155 | maker.width.equalTo(20) 156 | maker.trailing.equalToSuperview().offset(-10) 157 | maker.bottom.equalToSuperview().offset(-5) 158 | } 159 | 160 | imgCollect.addTarget(self, action: #selector(self.collect(btn:)), for: .touchUpInside) 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /FunIOS/Cell-列表item样式/RankingCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RankingCell.swift 3 | // FunIOS 4 | // 5 | // Created by redli on 2021/8/10. 6 | // 7 | 8 | import Foundation 9 | import UIKit 10 | 11 | class RankingCell: BaseTableViewCell { 12 | 13 | private let labelLeading = UILabel().then { attr in 14 | attr.textColor = UIColor.white 15 | attr.layer.cornerRadius = 20 16 | attr.layer.masksToBounds = true 17 | attr.backgroundColor = UIColor.randomColor 18 | attr.font = .boldSystemFont(ofSize: 12) 19 | attr.textAlignment = .center 20 | } 21 | 22 | private let labelTitle = UILabel().then { attr in 23 | attr.font = .boldSystemFont(ofSize: 16) 24 | attr.textColor = UIColor.black 25 | } 26 | 27 | private let labelSubTitle = UILabel().then { attr in 28 | attr.font = .systemFont(ofSize: 14) 29 | } 30 | 31 | private let labelTrailing = UILabel().then { attr in 32 | 33 | } 34 | 35 | var model: UserCoinLevelModel? { 36 | didSet { 37 | guard model == nil else { 38 | labelTitle.text = model?.username 39 | labelSubTitle.text = "\(model?.level ?? 0)" 40 | labelTrailing.text = "\(model?.coinCount ?? 0)" 41 | return 42 | } 43 | } 44 | } 45 | 46 | var index: Int? { 47 | didSet { 48 | guard model == nil else { 49 | labelLeading.text = "\(index ?? 0)" 50 | return 51 | } 52 | } 53 | } 54 | 55 | override func configUI() { 56 | contentView.addSubview(labelLeading) 57 | labelLeading.snp.makeConstraints { maker in 58 | maker.leading.equalToSuperview().offset(20) 59 | maker.centerY.equalToSuperview() 60 | maker.height.equalTo(40) 61 | maker.width.equalTo(40) 62 | } 63 | 64 | contentView.addSubview(labelTitle) 65 | labelTitle.snp.makeConstraints { maker in 66 | maker.leading.equalTo(labelLeading.snp.trailing).offset(10) 67 | maker.top.equalToSuperview().offset(10) 68 | } 69 | 70 | contentView.addSubview(labelSubTitle) 71 | labelSubTitle.snp.makeConstraints { maker in 72 | maker.leading.equalTo(labelLeading.snp.trailing).offset(10) 73 | // maker.top.equalTo(labelTitle.snp.bottom).offset(5) 74 | maker.bottom.equalToSuperview().offset(-10) 75 | } 76 | 77 | contentView.addSubview(labelTrailing) 78 | labelTrailing.snp.makeConstraints { maker in 79 | maker.trailing.equalToSuperview().offset(-20) 80 | maker.centerY.equalToSuperview() 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /FunIOS/Cell-列表item样式/StructureCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StructureCell.swift 3 | // FunIOS 4 | // 5 | // Created by redli on 2021/7/25. 6 | // 7 | 8 | import UIKit 9 | import SnapKitExtend 10 | import TagListView 11 | 12 | public protocol TagViewDelegate : NSObjectProtocol{ 13 | 14 | //体系Tag点击事件 15 | func tagStructureClick(parentModel model: StructureModel, childClickIndex clickIndex: Int) -> Void 16 | 17 | //导航Tag点击事件 18 | func tagNavigationClick(parentModel model: NavigationModel, childClickIndex clickIndex: Int) -> Void 19 | } 20 | 21 | 22 | class StructureCell: BaseTableViewCell { 23 | 24 | weak open var tagDelegate: TagViewDelegate? 25 | 26 | private var tagListView: TagListView = TagListView().then { (attr) in 27 | attr.textFont = UIFont.systemFont(ofSize: 14) 28 | attr.textColor = UIColor.white 29 | attr.cornerRadius = 10 30 | attr.paddingX = 10 31 | attr.paddingY = 5 32 | attr.marginX = 10 33 | attr.marginY = 5 34 | } 35 | 36 | 37 | override func configUI() { 38 | contentView.addSubview(tagListView) 39 | tagListView.snp.makeConstraints { (make) in 40 | make.top.equalTo(contentView.snp.top).offset(15) 41 | make.bottom.equalTo(contentView.snp.bottom).offset(-15) 42 | make.leading.equalToSuperview().offset(15) 43 | make.trailing.equalToSuperview().offset(-15) 44 | } 45 | } 46 | 47 | func setModel(type: Int, model: Any) { 48 | tagListView.removeAllTags(); 49 | if type == 1 { 50 | let structure = model as! StructureModel 51 | for (index, value) in structure.children.enumerated() { 52 | let tagView = self.tagListView.addTag(value.name) 53 | tagView.tagBackgroundColor = UIColor.randomColor 54 | tagView.onTap = { tagView in 55 | self.tagDelegate?.tagStructureClick(parentModel: structure, childClickIndex: index) 56 | } 57 | } 58 | } else { 59 | let navigation = model as! NavigationModel 60 | for (index, value) in navigation.articles.enumerated() { 61 | let tagView = self.tagListView.addTag(value.title) 62 | tagView.tagBackgroundColor = UIColor.randomColor 63 | tagView.onTap = { tagView in 64 | self.tagDelegate?.tagNavigationClick(parentModel: navigation, childClickIndex: index) 65 | } 66 | } 67 | } 68 | contentView.frame.size.height = self.tagListView.height 69 | contentView.layoutIfNeeded() 70 | contentView.setNeedsLayout() 71 | } 72 | 73 | var model: StructureModel? { 74 | didSet { 75 | guard model == nil else { 76 | return 77 | } 78 | } 79 | } 80 | } 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /FunIOS/Cell-列表item样式/UserCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UserCell.swift 3 | // FunIOS 4 | // 5 | // Created by redli on 2021/8/9. 6 | // 7 | 8 | import UIKit 9 | 10 | class UserCell: BaseTableViewCell { 11 | 12 | private let icon = UIImageView().then { attr in 13 | attr.contentMode = .scaleAspectFit 14 | } 15 | 16 | private let title = UILabel().then { attr in 17 | 18 | } 19 | 20 | private lazy var line = UIView().then({ attr in 21 | attr.backgroundColor = UIColor.lightGray.withAlphaComponent(0.2) 22 | }) 23 | 24 | var model: MenuItem? { 25 | didSet { 26 | guard model == nil else { 27 | title.text = model?.title 28 | icon.image = UIImage(named: model?.icon ?? "") 29 | return 30 | } 31 | } 32 | } 33 | 34 | override func configUI() { 35 | contentView.addSubview(line) 36 | line.snp.makeConstraints { maker in 37 | maker.top.equalToSuperview() 38 | maker.leading.equalToSuperview().offset(10) 39 | maker.trailing.equalToSuperview().offset(-10) 40 | maker.height.equalTo(1) 41 | } 42 | contentView.addSubview(icon) 43 | icon.snp.makeConstraints { maker in 44 | maker.centerY.equalToSuperview() 45 | maker.leading.equalToSuperview().offset(20) 46 | } 47 | 48 | contentView.addSubview(title) 49 | title.snp.makeConstraints { maker in 50 | maker.centerY.equalToSuperview() 51 | maker.leading.equalTo(icon.snp.trailing).offset(10) 52 | } 53 | 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /FunIOS/Cell-列表item样式/WechatCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WechatCell.swift 3 | // FunIOS 4 | // 5 | // Created by redli on 2021/7/25. 6 | // 7 | 8 | import UIKit 9 | import Kingfisher 10 | 11 | class WechatCell: BaseTableViewCell { 12 | 13 | private lazy var labelAuthor = UILabel().then({ (attr) in 14 | attr.text = "author" 15 | attr.font = UIFont.systemFont(ofSize: 12) 16 | attr.numberOfLines = 0 //相当于不限制行数 17 | attr.lineBreakMode = .byWordWrapping 18 | attr.sizeToFit() 19 | attr.backgroundColor = UIColor.white 20 | }) 21 | 22 | private lazy var labelTime = UILabel().then({ (attr) in 23 | attr.text = "Time" 24 | attr.textColor = .gray 25 | attr.font = UIFont.systemFont(ofSize: 12) 26 | attr.numberOfLines = 0 //相当于不限制行数 27 | attr.lineBreakMode = .byWordWrapping 28 | attr.sizeToFit() 29 | attr.backgroundColor = UIColor.white 30 | }) 31 | 32 | 33 | private lazy var labelTitle: UILabel = UILabel().then {(attr) in 34 | attr.text = "Titile" 35 | attr.textColor = .black 36 | attr.font = UIFont.systemFont(ofSize: 15) 37 | attr.numberOfLines = 2 //相当于不限制行数 38 | attr.lineBreakMode = .byWordWrapping 39 | attr.sizeToFit() 40 | attr.backgroundColor = UIColor.white 41 | } 42 | 43 | private lazy var labelDesc: UILabel = UILabel().then { (attr) in 44 | attr.text = "desc" 45 | attr.font = UIFont.systemFont(ofSize: 12) 46 | attr.numberOfLines = 2 //相当于不限制行数 47 | attr.lineBreakMode = .byTruncatingTail 48 | attr.sizeToFit() 49 | attr.backgroundColor = UIColor.white 50 | } 51 | 52 | 53 | private lazy var labelChapterName = UILabel().then({(attr) in 54 | attr.text = "ChapterName" 55 | attr.textColor = .gray 56 | attr.font = UIFont.systemFont(ofSize: 10) 57 | attr.numberOfLines = 0 //相当于不限制行数 58 | attr.lineBreakMode = .byWordWrapping 59 | attr.sizeToFit() 60 | attr.backgroundColor = UIColor.white 61 | }) 62 | 63 | private lazy var labelSuperChapterName = UILabel().then({(attr) in 64 | attr.text = "SuperChapterName" 65 | attr.textColor = .gray 66 | attr.font = UIFont.systemFont(ofSize: 10) 67 | attr.numberOfLines = 0 //相当于不限制行数 68 | attr.lineBreakMode = .byWordWrapping 69 | attr.sizeToFit() 70 | attr.backgroundColor = UIColor.white 71 | }) 72 | 73 | private lazy var line = UIView().then({ (attr) in 74 | attr.backgroundColor = UIColor.lightGray.withAlphaComponent(0.2) 75 | }) 76 | 77 | var model: ArticleItemModel?{ 78 | didSet { 79 | guard model == nil else { 80 | labelAuthor.text = (model?.author.isEmpty)! ? model?.shareUser : model?.author 81 | labelTime.text = model?.niceShareDate 82 | labelTitle.text = model?.title 83 | labelDesc.text = model?.desc 84 | labelSuperChapterName.text = model?.superChapterName 85 | labelChapterName.text = " · \(model?.chapterName ?? "")" 86 | 87 | isCollect = model?.collect ?? false 88 | 89 | refreshCollect(isCollect: isCollect) 90 | 91 | imgCollect.tag = model?.id ?? 0 92 | 93 | return 94 | } 95 | } 96 | } 97 | 98 | 99 | override func configUI() { 100 | contentView.addSubview(labelAuthor) 101 | labelAuthor.snp.makeConstraints {(maker) in 102 | maker.leading.equalToSuperview().offset(10) 103 | maker.top.equalToSuperview().offset(10) 104 | 105 | } 106 | 107 | contentView.addSubview(labelTime) 108 | labelTime.snp.makeConstraints({(maker) in 109 | maker.trailing.equalToSuperview().offset(-10) 110 | maker.top.equalToSuperview().offset(10) 111 | }) 112 | 113 | contentView.addSubview(labelTitle) 114 | labelTitle.snp.makeConstraints({(maker) in 115 | maker.top.equalTo(labelAuthor.snp.bottom).offset(10) 116 | maker.top.equalTo(labelTime.snp.bottom).offset(10) 117 | maker.leading.equalToSuperview().offset(10) 118 | maker.trailing.equalToSuperview().offset(-10) 119 | }) 120 | 121 | contentView.addSubview(labelDesc) 122 | labelDesc.snp.makeConstraints { (maker) in 123 | maker.top.equalTo(labelTitle.snp.bottom).offset(10) 124 | maker.leading.equalToSuperview().offset(10) 125 | maker.trailing.equalToSuperview().offset(-10) 126 | } 127 | 128 | contentView.addSubview(labelSuperChapterName) 129 | labelSuperChapterName.snp.makeConstraints {(maker) in 130 | maker.leading.equalToSuperview().offset(10) 131 | maker.top.equalTo(labelDesc.snp.bottom).offset(10) 132 | } 133 | 134 | contentView.addSubview(labelChapterName) 135 | labelChapterName.snp.makeConstraints({(maker) in 136 | maker.leading.equalTo(labelSuperChapterName.snp.trailing) 137 | maker.top.equalTo(labelDesc.snp.bottom).offset(10) 138 | }) 139 | 140 | contentView.addSubview(line) 141 | line.snp.makeConstraints { (maker) in 142 | maker.top.equalTo(labelSuperChapterName.snp.bottom).offset(10) 143 | maker.top.equalTo(labelChapterName.snp.bottom).offset(10) 144 | maker.bottom.equalToSuperview() 145 | maker.leading.equalToSuperview().offset(10) 146 | maker.trailing.equalToSuperview().offset(-10) 147 | maker.height.equalTo(1) 148 | } 149 | 150 | contentView.addSubview(imgCollect) 151 | imgCollect.snp.makeConstraints { maker in 152 | maker.height.equalTo(20) 153 | maker.width.equalTo(20) 154 | maker.trailing.equalToSuperview().offset(-10) 155 | maker.bottom.equalToSuperview().offset(-5) 156 | } 157 | 158 | imgCollect.addTarget(self, action: #selector(self.collect(btn:)), for: .touchUpInside) 159 | } 160 | 161 | } 162 | -------------------------------------------------------------------------------- /FunIOS/Const.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Const.swift 3 | // FunIOS 4 | // 5 | // Created by redli on 2021/7/21. 6 | // 7 | 8 | import Foundation 9 | import UIKit 10 | 11 | 12 | let screenWidth = UIScreen.main.bounds.width 13 | let screenHeight = UIScreen.main.bounds.height 14 | 15 | let statusBarHeight = UIApplication.shared.statusBarFrame.height 16 | 17 | let baseUrl = "https://www.wanandroid.com/" 18 | 19 | let userKey = "user_key" 20 | 21 | let userEvent = "user_event" 22 | -------------------------------------------------------------------------------- /FunIOS/Extension/MBProgressHUD+Extension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MBProgressHUD+Extension.swift 3 | // FunIOS 4 | // 5 | // Created by redli on 2021/8/4. 6 | // 7 | 8 | import UIKit 9 | import MBProgressHUD 10 | let HUD_Duration_Infinite = -1 11 | let HUD_Duration_Normal = 1.5 12 | let HUD_Duration_Short = 0.5 13 | 14 | extension MBProgressHUD { 15 | @discardableResult 16 | class func showAdded(view: UIView, duration showTime: Double, animated: Bool) -> (MBProgressHUD) { 17 | var animated = animated 18 | let existHUD:MBProgressHUD = MBProgressHUD(view: view) 19 | if existHUD != nil{ 20 | // 如果有HUD先隐藏掉,保证始终只有一个HUD 21 | MBProgressHUD.hide(for: view, animated: false) 22 | // 如果有HUD,则不做animation 23 | animated = false 24 | } 25 | 26 | let showView = self.showAdded(to: view, animated: animated) 27 | 28 | if Int(showTime) != HUD_Duration_Infinite { 29 | DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + Double(Int64(showTime * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC), execute: { 30 | MBProgressHUD.hide(for: view, animated: false) 31 | }) 32 | } 33 | return showView 34 | } 35 | 36 | @discardableResult 37 | class func showAdded(view: UIView, duration showTime: TimeInterval, withText text: String?, animated: Bool) -> (MBProgressHUD) { 38 | let showView = self.showAdded(view: view, duration: showTime, animated: animated) 39 | MBProgressHUD(view: view).isUserInteractionEnabled = false 40 | MBProgressHUD(view: view).mode = .text 41 | MBProgressHUD(view: view).label.text = text 42 | return showView 43 | } 44 | 45 | @discardableResult 46 | class func showAdded(view: UIView, icon image: UIImage?, duration showTime: TimeInterval, withText text: String?, animated: Bool) -> (MBProgressHUD) { 47 | let showView = self.showAdded(view: view, duration: showTime, animated: animated) 48 | MBProgressHUD(view: view).isUserInteractionEnabled = false 49 | MBProgressHUD(view: view).mode = .customView 50 | return showView 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /FunIOS/Extension/UIColor+Extension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // File.swift 3 | // FunIOS 4 | // 5 | // Created by redli on 2021/7/28. 6 | // 7 | 8 | import Foundation 9 | import UIKit 10 | 11 | extension UIColor { 12 | //返回随机颜色 13 | class var randomColor: UIColor { 14 | get { 15 | let red = CGFloat (arc4random()%256)/255.0 16 | let green = CGFloat (arc4random()%256)/255.0 17 | let blue = CGFloat (arc4random()%256)/255.0 18 | return UIColor (red: red, green: green, blue: blue, alpha: 1.0) 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /FunIOS/Extension/UIView+Extension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+Extension.swift 3 | // FunIOS 4 | // 5 | // Created by redli on 2021/7/25. 6 | // 7 | 8 | import UIKit 9 | 10 | extension UIView { 11 | var x: CGFloat { 12 | get { 13 | return frame.origin.x 14 | } 15 | set(x) { 16 | var frame = self.frame 17 | frame.origin.x = x 18 | self.frame = frame 19 | } 20 | } 21 | 22 | var y: CGFloat { 23 | get { 24 | return frame.origin.y 25 | } 26 | set(y) { 27 | var frame = self.frame 28 | frame.origin.y = y 29 | self.frame = frame 30 | } 31 | } 32 | 33 | var centerX: CGFloat { 34 | get { 35 | return center.x 36 | } 37 | set(centerX) { 38 | var center = self.center 39 | center.x = centerX 40 | self.center = center 41 | } 42 | } 43 | 44 | var centerY: CGFloat { 45 | get { 46 | return center.y 47 | } 48 | set(centerY) { 49 | var center = self.center 50 | center.y = centerY 51 | self.center = center 52 | } 53 | } 54 | 55 | var width: CGFloat { 56 | get { 57 | return frame.size.width 58 | } 59 | set(width) { 60 | var frame = self.frame 61 | frame.size.width = width 62 | self.frame = frame 63 | } 64 | } 65 | 66 | var height: CGFloat { 67 | get { 68 | return frame.size.height 69 | } 70 | set(height) { 71 | var frame = self.frame 72 | frame.size.height = height 73 | self.frame = frame 74 | } 75 | } 76 | 77 | var size: CGSize { 78 | get { 79 | return frame.size 80 | } 81 | set(size) { 82 | var frame = self.frame 83 | frame.size = size 84 | self.frame = frame 85 | } 86 | } 87 | 88 | var origin: CGPoint { 89 | get { 90 | return frame.origin 91 | } 92 | set(origin) { 93 | var frame = self.frame 94 | frame.origin = origin 95 | self.frame = frame 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /FunIOS/Extension/UIViewController+Extension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+Extension.swift 3 | // FunIOS 4 | // 5 | // Created by redli on 2021/8/4. 6 | // 7 | 8 | import UIKit 9 | import Foundation 10 | import MBProgressHUD 11 | 12 | private let minHUDWidth: CGFloat = 0.0 13 | 14 | extension UIViewController { 15 | @discardableResult 16 | func showWaitHUD() -> MBProgressHUD { 17 | return showWaitHUD(title: "加载中…") 18 | } 19 | 20 | @discardableResult 21 | func showWaitHUD(title: String?) -> MBProgressHUD { 22 | let HUD = showHUD(title: title, duration: TimeInterval(HUD_Duration_Infinite)) 23 | HUD.isUserInteractionEnabled = true 24 | return HUD 25 | } 26 | 27 | @discardableResult 28 | func showHUDWithError(error: String?) -> MBProgressHUD { 29 | return showHUD(title: error, duration: HUD_Duration_Normal) 30 | } 31 | 32 | @discardableResult 33 | func showHUD(title: String?) -> MBProgressHUD { 34 | return showHUD(title: title, duration: HUD_Duration_Normal) 35 | } 36 | 37 | @discardableResult 38 | func showHUD(title: String?, detail: String?) -> MBProgressHUD { 39 | return showHUD(title: title, detail: detail, duration: HUD_Duration_Normal) 40 | } 41 | 42 | @discardableResult 43 | func showHUD(title: String?, duration: TimeInterval) -> MBProgressHUD { 44 | return showHUD(title: "", detail: title, duration: duration) 45 | } 46 | 47 | @discardableResult 48 | func showHUD(title: String?, detail: String?, duration: TimeInterval) -> MBProgressHUD { 49 | var HUD:MBProgressHUD = MBProgressHUD() 50 | if hudContainerView() != nil { 51 | HUD = MBProgressHUD.showAdded(view: hudContainerView()!, duration: duration, withText: title, animated: true) 52 | HUD.detailsLabel.text = detail 53 | setHUDBelowNavigationBar() 54 | HUD.minSize = CGSize(width: minHUDWidth, height: 0.0) 55 | 56 | } 57 | return HUD 58 | } 59 | 60 | @discardableResult 61 | func showHUD(withTitle title: String?, detail: String?, topIcon iconImage: UIImage?, duration: TimeInterval) -> MBProgressHUD { 62 | let HUD = showHUD(title: title, detail: detail, duration: duration) 63 | HUD.mode = .customView 64 | HUD.customView = UIImageView(image: iconImage) 65 | return HUD 66 | } 67 | 68 | @discardableResult 69 | func showHUD(withTitle title: String?, error: Error?) -> MBProgressHUD { 70 | 71 | let errorDetail = error?.localizedDescription 72 | return showHUD(title: title, detail: errorDetail) 73 | } 74 | 75 | 76 | func hideHUD() { 77 | if hudContainerView() != nil { 78 | MBProgressHUD.hide(for: hudContainerView()!, animated: true) 79 | } 80 | } 81 | 82 | @discardableResult 83 | func hudContainerView() -> UIView? { 84 | if isViewLoaded { 85 | if parent != nil && parent != navigationController { 86 | return parent?.hudContainerView() 87 | } else if navigationController?.parent != nil && navigationController?.parent != tabBarController { 88 | return navigationController?.parent?.hudContainerView() 89 | } else { 90 | return view 91 | } 92 | } else { 93 | return nil 94 | } 95 | } 96 | 97 | func setHUDBelowNavigationBar() { 98 | if navigationController?.view == hudContainerView() { 99 | if let navigationBar = navigationController?.navigationBar { 100 | if let hud = MBProgressHUD.forView((navigationController?.view)!) { 101 | navigationController?.view.insertSubview(hud, belowSubview: navigationBar) 102 | } 103 | 104 | } 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /FunIOS/IndexVController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // FunIOS 4 | // 5 | // Created by redli on 2021/7/21. 6 | // 7 | 8 | import UIKit 9 | 10 | class IndexVController: UITabBarController { 11 | 12 | override func viewDidLoad() { 13 | super.viewDidLoad() 14 | initTab() 15 | UITabBar.appearance().tintColor = UIColor.red.withAlphaComponent(0.5) 16 | } 17 | 18 | private func initTab() { 19 | let home = HomeVController() 20 | let project = ProjectVController() 21 | let wechat = WechatVController() 22 | let structure = StructrureVController() 23 | let user = UserVController() 24 | 25 | home.tabBarItem = UITabBarItem(title: "主页", image: UIImage(named: "home_tabbar_night_32x32_"), selectedImage: UIImage(named: "home_tabbar_press_32x32_")) 26 | 27 | project.tabBarItem = UITabBarItem(title: "项目", image: UIImage(named: "project_tabbar_night_32x32_"), selectedImage: UIImage(named: "project_tabbar_press_32x32_")) 28 | 29 | wechat.tabBarItem = UITabBarItem(title: "公众号", image: UIImage(named: "wechat_tabbar_night_32x32_"), selectedImage: UIImage(named: "wechat_tabbar_press_32x32_")) 30 | 31 | structure.tabBarItem = UITabBarItem(title: "体系", image: UIImage(named: "structure_tabbar_night_32x32_"), selectedImage: UIImage(named: "structure_tabbar_press_32x32_")) 32 | 33 | user.tabBarItem = UITabBarItem(title: "我的", image: UIImage(named: "mine_tabbar_night_32x32_"), selectedImage: UIImage(named: "mine_tabbar_press_32x32_")) 34 | 35 | self.viewControllers = [home, project, wechat, structure, user] 36 | } 37 | 38 | } 39 | 40 | -------------------------------------------------------------------------------- /FunIOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | $(MARKETING_VERSION) 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | LSRequiresIPhoneOS 22 | 23 | UIApplicationSceneManifest 24 | 25 | UIApplicationSupportsMultipleScenes 26 | 27 | UISceneConfigurations 28 | 29 | UIWindowSceneSessionRoleApplication 30 | 31 | 32 | UISceneConfigurationName 33 | Default Configuration 34 | UISceneDelegateClassName 35 | $(PRODUCT_MODULE_NAME).SceneDelegate 36 | 37 | 38 | 39 | 40 | UIApplicationSupportsIndirectInputEvents 41 | 42 | UILaunchStoryboardName 43 | LaunchScreen 44 | UIMainStoryboardFile 45 | Main 46 | UIRequiredDeviceCapabilities 47 | 48 | armv7 49 | 50 | UISupportedInterfaceOrientations 51 | 52 | UIInterfaceOrientationPortrait 53 | UIInterfaceOrientationLandscapeLeft 54 | UIInterfaceOrientationLandscapeRight 55 | 56 | UISupportedInterfaceOrientations~ipad 57 | 58 | UIInterfaceOrientationPortrait 59 | UIInterfaceOrientationPortraitUpsideDown 60 | UIInterfaceOrientationLandscapeLeft 61 | UIInterfaceOrientationLandscapeRight 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /FunIOS/Models/ArticleModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AirticleModel.swift 3 | // FunIOS 4 | // 5 | // Created by redli on 2021/7/22. 6 | // 7 | 8 | import HandyJSON 9 | 10 | 11 | import HandyJSON 12 | 13 | 14 | class ArticleModel : HandyJSON { 15 | 16 | var curPage : Int = 0 17 | var datas : [ArticleItemModel] = [] 18 | var offset : Int = 0 19 | var over : Bool = false 20 | var pageCount : Int = 0 21 | var size : Int = 0 22 | var total : Int = 0 23 | 24 | 25 | required init() {} 26 | 27 | } 28 | 29 | class ArticleItemModel : HandyJSON { 30 | 31 | var apkLink : String = "" 32 | var audit : Int = 0 33 | var author : String = "" 34 | var canEdit : Bool = false 35 | var chapterId : Int = 0 36 | var chapterName : String = "" 37 | var collect : Bool = false 38 | var courseId : Int = 0 39 | var desc : String = "" 40 | var descMd : String = "" 41 | var envelopePic : String = "" 42 | var fresh : Bool = false 43 | var host : String = "" 44 | var id : Int = 0 45 | var link : String = "" 46 | var niceDate : String = "" 47 | var niceShareDate : String = "" 48 | var origin : String = "" 49 | var prefix : String = "" 50 | var projectLink : String = "" 51 | var publishTime : Int = 0 52 | var realSuperChapterId : Int = 0 53 | var selfVisible : Int = 0 54 | var shareDate : Int = 0 55 | var shareUser : String = "" 56 | var superChapterId : Int = 0 57 | var superChapterName : String = "" 58 | var tags : [Tag] = [] 59 | var title : String = "" 60 | var type : Int = 0 61 | var userId : Int = 0 62 | var visible : Int = 0 63 | var zan : Int = 0 64 | 65 | 66 | required init() {} 67 | 68 | } 69 | 70 | class Tag : HandyJSON { 71 | 72 | var name : String = "" 73 | var url : String = "" 74 | 75 | 76 | required init() {} 77 | 78 | } 79 | -------------------------------------------------------------------------------- /FunIOS/Models/BannerModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BannerModel.swift 3 | // Model file generated using JSONExport: https://github.com/Ahmed-Ali/JSONExport 4 | 5 | import HandyJSON 6 | 7 | 8 | class BannerModel : HandyJSON { 9 | 10 | var desc : String = "" 11 | var id : Int = 0 12 | var imagePath : String = "" 13 | var isVisible : Int = 0 14 | var order : Int = 0 15 | var title : String = "" 16 | var type : Int = 0 17 | var url : String = "" 18 | 19 | 20 | required init() {} 21 | 22 | } 23 | -------------------------------------------------------------------------------- /FunIOS/Models/IntegralModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CoinModel.swift 3 | // FunIOS 4 | // 5 | // Created by redli on 2021/8/9. 6 | // 7 | 8 | /** 9 | {"curPage":1,"datas":[{"coinCount":13,"date":1628475372000,"desc":"2021-08-09 10:16:12 签到 , 积分:13 + 0","id":478599,"reason":"签到","type":1,"userId":45070,"userName":"redli"}],"offset":0,"over":false,"pageCount":5,"size":20,"total":91} 10 | */ 11 | 12 | import HandyJSON 13 | 14 | class IntegralModel : HandyJSON { 15 | 16 | var curPage : Int = 0 17 | var datas : [IntegralItemModel] = [] 18 | var offset : Int = 0 19 | var over : Bool = false 20 | var pageCount : Int = 0 21 | var size : Int = 0 22 | var total : Int = 0 23 | 24 | required init() {} 25 | 26 | } 27 | 28 | class IntegralItemModel: HandyJSON { 29 | var coinCount : Int = 0 30 | var date : Int = 0 31 | var desc : String = "" 32 | var id : Int = 0 33 | var reason : String = "" 34 | var type : Int = 0 35 | var userId : Int = 0 36 | var userName : String = "" 37 | 38 | 39 | required init() {} 40 | } 41 | -------------------------------------------------------------------------------- /FunIOS/Models/NavigationModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NavigationModel.swift 3 | // FunIOS 4 | // 5 | // Created by redli on 2021/7/27. 6 | // 7 | 8 | import HandyJSON 9 | 10 | open class NavigationModel: HandyJSON { 11 | 12 | var articles: [ArticleItemModel] = [] 13 | var cid: Int = 0 14 | var name: String = "" 15 | 16 | required public init() {} 17 | } 18 | -------------------------------------------------------------------------------- /FunIOS/Models/RankingModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RankingModel.swift 3 | // FunIOS 4 | // 5 | // Created by redli on 2021/8/10. 6 | // 7 | /** 8 | {"curPage":1,"datas":[{"coinCount":48606,"level":487,"nickname":"","rank":"1","userId":20382,"username":"g**eii"}],"offset":0,"over":false,"pageCount":2685,"size":30,"total":80540} 9 | */ 10 | 11 | 12 | import Foundation 13 | import HandyJSON 14 | 15 | class RankingModel : HandyJSON { 16 | 17 | var curPage : Int = 0 18 | var datas : [UserCoinLevelModel] = [] 19 | var offset : Int = 0 20 | var over : Bool = false 21 | var pageCount : Int = 0 22 | var size : Int = 0 23 | var total : Int = 0 24 | 25 | 26 | required init() {} 27 | 28 | } 29 | -------------------------------------------------------------------------------- /FunIOS/Models/StructureModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StructureModel.swift 3 | // FunIOS 4 | // 5 | // Created by redli on 2021/7/25. 6 | // 7 | 8 | import HandyJSON 9 | 10 | 11 | open class StructureModel : HandyJSON { 12 | 13 | var children : [StructureModel] = [] 14 | var courseId : Int = 0 15 | var id : Int = 0 16 | var name : String = "" 17 | var order : Int = 0 18 | var parentChapterId : Int = 0 19 | var userControlSetTop : Bool = false 20 | var visible : Int = 0 21 | 22 | 23 | required public init() {} 24 | 25 | } 26 | -------------------------------------------------------------------------------- /FunIOS/Models/UserCoinLevelModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CoinModel.swift 3 | // FunIOS 4 | // 5 | // Created by redli on 2021/8/9. 6 | // 7 | 8 | /** 9 | {"coinCount":2308,"level":24,"nickname":"","rank":"782","userId":45070,"username":"r**li"} 10 | */ 11 | 12 | import HandyJSON 13 | 14 | class UserCoinLevelModel : HandyJSON { 15 | 16 | var coinCount : Int = 0 17 | var level : Int = 0 18 | var nickname : String = "" 19 | var rank : String = "" 20 | var userId : Int = 0 21 | var username : String = "" 22 | 23 | 24 | required init() {} 25 | 26 | } 27 | -------------------------------------------------------------------------------- /FunIOS/Models/UserModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UserModel.swift 3 | // FunIOS 4 | // 5 | // Created by redli on 2021/8/4. 6 | // 7 | 8 | import HandyJSON 9 | 10 | class UserModel : HandyJSON { 11 | 12 | var admin : Bool = false 13 | var chapterTops : [AnyObject] = [] 14 | var coinCount : Int = 0 15 | var collectIds : [Int] = [] 16 | var email : String = "" 17 | var icon : String = "" 18 | var id : Int = 0 19 | var nickname : String = "" 20 | var password : String = "" 21 | var publicName : String = "" 22 | var token : String = "" 23 | var type : Int = 0 24 | var username : String = "" 25 | 26 | 27 | required init() {} 28 | 29 | } 30 | -------------------------------------------------------------------------------- /FunIOS/SceneDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.swift 3 | // FunIOS 4 | // 5 | // Created by redli on 2021/7/21. 6 | // 7 | 8 | import UIKit 9 | 10 | class SceneDelegate: UIResponder, UIWindowSceneDelegate { 11 | 12 | var window: UIWindow? 13 | 14 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { 15 | guard let windowScene = (scene as? UIWindowScene) else { return } 16 | let contentView = IndexVController() 17 | self.window = UIWindow(windowScene: windowScene) 18 | self.window?.backgroundColor = UIColor.white 19 | self.window?.rootViewController = UINavigationController.init(rootViewController: contentView) 20 | self.window?.makeKeyAndVisible() 21 | } 22 | 23 | func sceneDidDisconnect(_ scene: UIScene) { 24 | // Called as the scene is being released by the system. 25 | // This occurs shortly after the scene enters the background, or when its session is discarded. 26 | // Release any resources associated with this scene that can be re-created the next time the scene connects. 27 | // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead). 28 | } 29 | 30 | func sceneDidBecomeActive(_ scene: UIScene) { 31 | // Called when the scene has moved from an inactive state to an active state. 32 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. 33 | } 34 | 35 | func sceneWillResignActive(_ scene: UIScene) { 36 | // Called when the scene will move from an active state to an inactive state. 37 | // This may occur due to temporary interruptions (ex. an incoming phone call). 38 | } 39 | 40 | func sceneWillEnterForeground(_ scene: UIScene) { 41 | // Called as the scene transitions from the background to the foreground. 42 | // Use this method to undo the changes made on entering the background. 43 | } 44 | 45 | func sceneDidEnterBackground(_ scene: UIScene) { 46 | // Called as the scene transitions from the foreground to the background. 47 | // Use this method to save data, release shared resources, and store enough scene-specific state information 48 | // to restore the scene back to its current state. 49 | } 50 | 51 | 52 | } 53 | 54 | -------------------------------------------------------------------------------- /FunIOS/Services/Api.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Api.swift 3 | // FunIOS 4 | // 5 | // Created by redli on 2021/7/22. 6 | // 7 | 8 | import Foundation 9 | import HandyJSON 10 | 11 | class Api { 12 | 13 | //获取轮播图列表 14 | static func fetchBanners(success: @escaping(_ result: Array?) -> (), error: @escaping(_ error: String?) -> ()) { 15 | HttpUtils.request(url: "banner/json", success: success, error: error) 16 | } 17 | 18 | //获取置顶文章列表 19 | static func fetchTopArticles(success: @escaping(_ result: Array?) -> (), error: @escaping(_ error: String?) -> ()) { 20 | HttpUtils.request(url: "article/top/json", success: success, error: error) 21 | } 22 | 23 | //获取文章列表 24 | static func fetchArticles(page: Int, success: @escaping(_ result: ArticleModel?) -> (), error: @escaping(_ error: String?) -> ()) { 25 | HttpUtils.request(url: "article/list/\(page)/json", success: success, error: error) 26 | } 27 | 28 | //获取项目分类 29 | static func fetchProjectSegmented(success: @escaping(_ result: Array?) -> (), error: @escaping(_ error: String?) -> ()) { 30 | HttpUtils.request(url: "project/tree/json", success: success, error: error) 31 | } 32 | 33 | //获取项目文章列表 34 | static func fetchProjectArticles(page: Int, cid: Int, success: @escaping(_ result: ArticleModel?) -> (), error: @escaping(_ error: String?) -> ()) { 35 | HttpUtils.request(url: "article/list/\(page)/json?cid=\(cid)", success: success, error: error) 36 | } 37 | 38 | //获取公众号分类 39 | static func fetchWechatSegmented(success: @escaping(_ result: Array?) -> (), error: @escaping(_ error: String?) -> ()) { 40 | HttpUtils.request(url: "wxarticle/chapters/json", success: success, error: error) 41 | } 42 | 43 | //获取公众号文章列表 44 | static func fetchWechatArticles(page: Int, cid: Int, success: @escaping(_ result: ArticleModel?) -> (), error: @escaping(_ error: String?) -> ()) { 45 | HttpUtils.request(url: "wxarticle/list/\(cid)/\(page)/json", success: success, error: error) 46 | } 47 | 48 | //获取navigation item 体系中的体系列表 49 | static func fetchStructures(success: @escaping(_ result: Array?) -> (), error: @escaping(_ error: String?) -> ()) { 50 | HttpUtils.request(url: "tree/json", success: success, error: error) 51 | } 52 | 53 | //获取navigation item 体系中的导航列表 54 | static func fetchNavigations(success: @escaping(_ result: Array?) -> (), error: @escaping(_ error: String?) -> ()) { 55 | HttpUtils.request(url: "navi/json", success: success, error: error) 56 | } 57 | 58 | //登录 59 | static func login(username: String, password: String, success: @escaping(_ result: UserModel?) -> (), error: @escaping(_ error: String?) -> ()) { 60 | HttpUtils.request(url: "user/login", type: MethodType.post, params: ["username": username, "password" : password], success: success, error: error) 61 | } 62 | 63 | //获取用户等级和积分 64 | static func fetchUserCoinLevel(success: @escaping(_ result: UserCoinLevelModel?) -> (), error: @escaping(_ error: String?) -> ()) { 65 | HttpUtils.request(url: "lg/coin/userinfo/json", success: success, error: error) 66 | } 67 | 68 | //获取收藏文章列表 69 | static func fetchCollectArticles(page: Int, success: @escaping(_ result: ArticleModel?) -> (), error: @escaping(_ error: String?) -> ()) { 70 | HttpUtils.request(url: "/lg/collect/list/\(page)/json", success: success, error: error) 71 | } 72 | 73 | //获取个人积分 74 | static func fetchMyIntegral(page: Int, success: @escaping(_ result: IntegralModel?) -> (), error: @escaping(_ error: String?) -> ()) { 75 | HttpUtils.request(url: "lg/coin/list/\(page)/json", success: success, error: error) 76 | } 77 | 78 | //获取积分排行榜 79 | static func fetchRanking(page: Int, success: @escaping(_ result: RankingModel?) -> (), error: @escaping(_ error: String?) -> ()) { 80 | HttpUtils.request(url: "coin/rank/\(page)/json", success: success, error: error) 81 | } 82 | 83 | //收藏文章 84 | static func collect(cid: Int, success: @escaping(_ result: Any?) -> (), error: @escaping(_ error: String?) -> ()) { 85 | HttpUtils.request(url: "lg/collect/\(cid)/json", type: MethodType.post, success: success, error: error) 86 | } 87 | 88 | //收藏网址 89 | static func collectUrl(name: String, link: String, success: @escaping(_ result: Any?) -> (), error: @escaping(_ error: String?) -> ()) { 90 | HttpUtils.request(url: "lg/collect/addtool/json", params: ["name": name, "link": link], success: success, error: error) 91 | } 92 | 93 | //取消收藏文章 94 | static func uncollect(cid: Int, success: @escaping(_ result: Any?) -> (), error: @escaping(_ error: String?) -> ()) { 95 | HttpUtils.request(url: "lg/uncollect_originId/\(cid)/json", type: MethodType.post, success: success, error: error) 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /FunIOS/Tools/HttpUtils.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HttpUtils.swift 3 | // FunIOS 4 | // 5 | // Created by redli on 2021/7/21. 6 | // 7 | 8 | import Foundation 9 | import HandyJSON 10 | import Alamofire 11 | 12 | enum MethodType { 13 | case get 14 | case post 15 | } 16 | 17 | class HttpUtils { 18 | 19 | // static 也可以用 class 替代 效果是一样的 20 | static func request(url: String, type: MethodType? = MethodType.get, params: [String: Any]? = nil, success: @escaping(_ result: T?) -> (), error: @escaping(_ error: String?) -> ()) { 21 | 22 | let method = type == .get ? HTTPMethod.get : HTTPMethod.post 23 | // let headers: HTTPHeaders = ["Cookie": ""] 24 | 25 | print("请求地址 ---> \(baseUrl + url)") 26 | 27 | AF.request(baseUrl + url, method: method, parameters: params).responseJSON { response in 28 | 29 | guard let data = response.value else { 30 | error(response.error?.errorDescription ?? "请求错误") 31 | log(log: "请求错误 ---> \(response.error?.errorDescription ?? "")") 32 | return 33 | } 34 | 35 | let result = JSONDeserializer>.deserializeFrom(dict: data as? [String: Any]) 36 | 37 | if result?.errorCode == 0 { 38 | success(result?.data) 39 | print("请求成功 ---> \(baseUrl + url)") 40 | } else{ 41 | error(result?.errorMsg) 42 | print("请求失败 ---> \(baseUrl + url)") 43 | } 44 | print(response.value ?? "") 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /FunIOS/Tools/LogUtils.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LogUtil.swift 3 | // WanAndroid_IOS 4 | // 5 | // Created by 雷富 on 2020/4/7. 6 | // Copyright © 2020 雷富. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | func log(log: T, fileName: String = #file, methodName: String = #function, lineNumber: Int = #line) { 12 | //print(#file) //获取当前print所在的文件路径 13 | //print(#function) //获取当前print所在的方法名称 14 | //print(#line) //获取当前print所在的行数 15 | //判断是否打印debug 16 | #if DEBUG 17 | print("\((fileName as NSString).pathComponents.last!)_\(methodName)[行: \(lineNumber)]: \(log)") 18 | 19 | #endif 20 | } 21 | 22 | 23 | -------------------------------------------------------------------------------- /FunIOS/UI/Home/HomeVController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MainVController.swift 3 | // FunIOS 4 | // 5 | // Created by redli on 2021/7/21. 6 | // 7 | 8 | import UIKit 9 | import Then 10 | import LLCycleScrollView 11 | import SnapKit 12 | import SVProgressHUD 13 | import MBProgressHUD 14 | import HandyJSON 15 | 16 | class HomeVController: BaseCVontroller { 17 | 18 | var page = 0 19 | 20 | private var articleList = Array() 21 | 22 | private var bannerLists = Array() 23 | 24 | private lazy var dispatchGroup = { return DispatchGroup.init() }() 25 | 26 | private lazy var tableView: FloatButtonTableView = FloatButtonTableView(frame: .zero, style: .plain).then({ (attr) in 27 | attr.backgroundColor = UIColor.white 28 | attr.delegate = self 29 | attr.dataSource = self 30 | attr.floatButtonDelegate = self 31 | attr.alwaysBounceVertical = true 32 | // attr.separatorStyle = .none 33 | attr.register(ArticleCell.self, forCellReuseIdentifier: "ArticleCell") 34 | }) 35 | 36 | private lazy var bannerView = LLCycleScrollView().then({ (attr) in 37 | attr.backgroundColor = UIColor.yellow 38 | attr.autoScrollTimeInterval = 5 39 | attr.placeHolderImage = UIImage(named: "normal_placeholder_h") 40 | attr.coverImage = UIImage(named: "normal_placeholder_h") 41 | attr.imageViewContentMode = .scaleToFill 42 | attr.pageControlPosition = .right 43 | attr.frame = CGRect(x: 0, y: 0, width: screenWidth, height: screenWidth / 2) 44 | attr.lldidSelectItemAtIndex = self.didSelectBanner(index:) 45 | }) 46 | 47 | private func didSelectBanner(index: NSInteger) { 48 | let bannerModel = self.bannerLists[index] 49 | let webVController = WebVController(title: bannerModel.title, url: bannerModel.url) 50 | navigationController?.pushViewController(webVController, animated: true) 51 | } 52 | 53 | override func viewWillAppear(_ animated: Bool) { 54 | self.navigationController?.navigationBar.isHidden = true 55 | } 56 | 57 | override func viewDidDisappear(_ animated: Bool) { 58 | // self.navigationController?.navigationBar.isHidden = false 59 | } 60 | 61 | override func viewDidLoad() { 62 | self.view.addSubview(tableView) 63 | tableView.snp.makeConstraints { maker in 64 | maker.top.equalToSuperview().offset(statusBarHeight) 65 | maker.left.equalToSuperview() 66 | maker.right.equalToSuperview() 67 | maker.bottom.equalToSuperview().offset(-40) 68 | } 69 | 70 | tableView.tableHeaderView = bannerView 71 | 72 | self.view.addSubview(floatButton) 73 | floatButton.snp.makeConstraints { maker in 74 | maker.bottom.equalToSuperview().offset(-80) 75 | maker.right.equalToSuperview().offset(-30) 76 | } 77 | 78 | floatButton.addTarget(self, action: #selector(topOffset), for: .touchUpInside) 79 | 80 | if #available(iOS 11.0, *) { 81 | UIScrollView.appearance().contentInsetAdjustmentBehavior = .never 82 | } else { 83 | automaticallyAdjustsScrollViewInsets = false 84 | } 85 | setRefresh() 86 | } 87 | 88 | @objc func topOffset() { 89 | self.tableView.scrollToRow(at: IndexPath.init(row: 0, section: 0), at: .bottom, animated: floatAnimal) 90 | } 91 | 92 | private func setRefresh() { 93 | 94 | let refreshHeader = RefreshHeader{ [weak self] in 95 | self?.page = 0 96 | self?.getData(false) 97 | } 98 | 99 | refreshHeader.isAutomaticallyChangeAlpha = true 100 | refreshHeader.lastUpdatedTimeLabel?.isHidden = true 101 | tableView.mj_header = refreshHeader 102 | refreshHeader.beginRefreshing() 103 | 104 | tableView.mj_footer = RefreshFooter{ [weak self] in 105 | self?.getData(true) 106 | } 107 | tableView.mj_footer?.isAutomaticallyChangeAlpha = true 108 | } 109 | 110 | 111 | private func getData(_ loadMore: Bool = false) { 112 | if !loadMore { 113 | page = 0 114 | } else { 115 | page += 1 116 | } 117 | 118 | if !loadMore { 119 | Api.fetchBanners(success: {(value:Array?) in 120 | self.bannerLists = value ?? [] 121 | self.bannerView.imagePaths = value?.map{$0.imagePath} ?? [] 122 | self.bannerView.titles = value?.map{ $0.title} ?? [] 123 | }, error: error(error:)) 124 | 125 | self.dispatchGroup.enter() 126 | Api.fetchTopArticles(success: {(value: Array?) in 127 | self.articleList = value ?? [] 128 | self.dispatchGroup.leave() 129 | }, error: error(error:)) 130 | } 131 | 132 | self.dispatchGroup.enter() 133 | Api.fetchArticles(page: page, success: { (value: ArticleModel?) in 134 | //结束刷新 135 | if self.tableView.mj_header!.isRefreshing { self.tableView.mj_header?.endRefreshing() 136 | } 137 | 138 | if self.tableView.mj_footer!.isRefreshing { self.tableView.mj_footer?.endRefreshing() 139 | } 140 | 141 | //是否加载更多 142 | if loadMore { 143 | if value?.datas.count ?? 0 <= 0 { 144 | self.tableView.mj_footer?.endRefreshingWithNoMoreData() } else { 145 | self.articleList.append(contentsOf: value!.datas) 146 | } 147 | } else { 148 | if value?.datas.count ?? 0 < (loadMore ? 20 : 19) { 149 | self.tableView.mj_footer?.endRefreshingWithNoMoreData() 150 | } 151 | self.articleList.append(contentsOf: value!.datas) 152 | } 153 | self.dispatchGroup.leave() 154 | }, error: error(error:)) 155 | 156 | self.dispatchGroup.notify(queue: DispatchQueue.main) { 157 | self.tableView.reloadData() 158 | } 159 | } 160 | 161 | } 162 | 163 | extension HomeVController: UITableViewDataSource, UITableViewDelegate, CollectDelegate , FloatButtonDelegate{ 164 | //数据 165 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 166 | return articleList.count 167 | } 168 | 169 | //每行行高 170 | func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 171 | 100 172 | } 173 | 174 | //每行加载样式 175 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 176 | let tableViewCell = tableView.dequeueReusableCell(for: indexPath, cellType: ArticleCell.self) 177 | tableViewCell.collectDelegate = self 178 | tableViewCell.model = articleList[indexPath.row] 179 | return tableViewCell 180 | } 181 | 182 | //item点击事件 183 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 184 | let model = self.articleList[indexPath.row] 185 | let webVController = WebVController(title: model.title, url: model.link) 186 | navigationController?.pushViewController(webVController, animated: true) 187 | } 188 | 189 | //收藏文章 190 | func collectAirticle(cid id: Int, tabCell tabviewCell: UITableViewCell) { 191 | Api.collect(cid: id, success: { value in 192 | let cell = tabviewCell as! ArticleCell 193 | cell.refreshCollect(isCollect: true) 194 | self.view.makeToast("收藏成功") 195 | }, error: error(error:)) 196 | } 197 | 198 | //取消收藏文章 199 | func uncollectAirticle(cid id: Int, tabCell tabviewCell: UITableViewCell) { 200 | Api.uncollect(cid: id, success: { value in 201 | let cell = tabviewCell as! ArticleCell 202 | cell.refreshCollect(isCollect: false) 203 | self.view.makeToast("取消收藏成功") 204 | }, error: error(error:)) 205 | } 206 | 207 | func floatStatus(forHide hide: Bool, withAnimal animal: Bool) { 208 | floatButton.isHidden = hide 209 | floatAnimal = animal 210 | } 211 | } 212 | -------------------------------------------------------------------------------- /FunIOS/UI/Login/LoginVController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LoginVController.swift 3 | // FunIOS 4 | // 5 | // Created by redli on 2021/7/30. 6 | // 7 | 8 | import UIKit 9 | import LGButton 10 | import Toast_Swift 11 | import MBProgressHUD 12 | import SwiftEventBus 13 | 14 | class LoginVController: BaseCVontroller { 15 | 16 | private let closeImage = UIImageView().then { (attr) in 17 | attr.image = UIImage(named: "ic_close") 18 | attr.isUserInteractionEnabled = true 19 | } 20 | 21 | private let labelTitle = UILabel().then { (attr) in 22 | attr.text = "Fun IOS" 23 | attr.font = UIFont.boldSystemFont(ofSize: 20) 24 | attr.textColor = UIColor.black 25 | } 26 | 27 | private let textFieldUser = UITextField().then { (attr) in 28 | attr.borderStyle = .roundedRect 29 | attr.placeholder = "请输入账户" 30 | attr.clearButtonMode = .always 31 | attr.leftViewMode = .always 32 | attr.leftView = UIImageView(image: UIImage(named: "ic_user")) 33 | } 34 | 35 | private let textFieldPwd = UITextField().then { (attr) in 36 | attr.borderStyle = .roundedRect 37 | attr.placeholder = "请输入密码" 38 | attr.isSecureTextEntry = true 39 | attr.clearButtonMode = .always 40 | attr.leftViewMode = .always 41 | attr.leftView = UIImageView(image: UIImage(named: "ic_password")) 42 | } 43 | 44 | private let btnLogin = LGButton().then { (attr) in 45 | attr.cornerRadius = 10 46 | attr.titleString = "登录" 47 | attr.titleFontSize = 16 48 | attr.titleColor = UIColor.white 49 | attr.bgColor = UIColor.red.withAlphaComponent(0.6) 50 | } 51 | 52 | override func viewDidAppear(_ animated: Bool) { 53 | 54 | } 55 | 56 | override func viewDidLoad() { 57 | view.backgroundColor = UIColor.white 58 | 59 | let barHight = navigationController?.navigationBar.frame.height 60 | 61 | view.addSubview(closeImage) 62 | closeImage.snp.makeConstraints { (maker) in 63 | maker.top.equalToSuperview().offset(statusBarHeight + barHight!) 64 | maker.leading.equalToSuperview().offset(30) 65 | maker.height.equalTo(20) 66 | maker.width.equalTo(20) 67 | } 68 | let closeTap = UITapGestureRecognizer.init(target: self, action: #selector(close)) 69 | closeImage.addGestureRecognizer(closeTap) 70 | 71 | view.addSubview(labelTitle) 72 | labelTitle.snp.makeConstraints { (maker) in 73 | maker.top.equalToSuperview().offset(statusBarHeight + barHight! + screenWidth / 3) 74 | maker.centerX.equalToSuperview() 75 | } 76 | 77 | view.addSubview(textFieldUser) 78 | textFieldUser.snp.makeConstraints { (maker) in 79 | maker.top.equalTo(labelTitle.snp.bottom).offset(30) 80 | maker.leading.equalToSuperview().offset(20) 81 | maker.trailing.equalToSuperview().offset(-20) 82 | maker.height.equalTo(50) 83 | } 84 | 85 | view.addSubview(textFieldPwd) 86 | textFieldPwd.snp.makeConstraints { (maker) in 87 | maker.top.equalTo(textFieldUser.snp.bottom).offset(20) 88 | maker.leading.equalToSuperview().offset(20) 89 | maker.trailing.equalToSuperview().offset(-20) 90 | maker.height.equalTo(50) 91 | } 92 | 93 | view.addSubview(btnLogin) 94 | btnLogin.snp.makeConstraints { (maker) in 95 | maker.top.equalTo(textFieldPwd.snp.bottom).offset(20) 96 | maker.centerX.equalToSuperview() 97 | maker.width.equalTo(screenWidth / 3 * 2) 98 | maker.height.equalTo(50) 99 | } 100 | btnLogin.addTarget(self, action: #selector(login), for: .touchUpInside) 101 | } 102 | 103 | @objc func login() { 104 | let username = textFieldUser.text 105 | let password = textFieldPwd.text 106 | 107 | if ((username?.isEmpty) == nil) { 108 | view.makeToast("请输入用户名") 109 | return 110 | } 111 | 112 | if ((password?.isEmpty) == nil) { 113 | view.makeToast("请输入密码") 114 | return 115 | } 116 | 117 | self.showHUD(title: "登录中") 118 | 119 | Api.login(username: username!, password: password!, success: { (value: UserModel?) in 120 | UserDefaults.standard.setValue(value?.toJSONString(prettyPrint:true), forKey: userKey) 121 | self.hideHUD() 122 | self.close() 123 | SwiftEventBus.post(userEvent, sender: value) 124 | }, error: error(error:)) 125 | } 126 | 127 | @objc func close() { 128 | navigationController?.popViewController(animated: true) 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /FunIOS/UI/Project/ProjectArticlesVController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ProjectArticlesVController.swift 3 | // FunIOS 4 | // 5 | // Created by redli on 2021/7/25. 6 | // 7 | 8 | import UIKit 9 | import JXSegmentedView 10 | 11 | class ProjectArticlesVController: BaseCVontroller { 12 | 13 | 14 | // 当前页面 15 | var page = 0 16 | //文章id 17 | var cid : Int = 0 18 | //实体类数组 19 | private var articleList = [ArticleItemModel]() 20 | 21 | private lazy var tableView: UITableView = UITableView(frame: .zero, style: .plain).then({ (attr) in 22 | attr.backgroundColor = UIColor.white 23 | attr.delegate = self 24 | attr.dataSource = self 25 | attr.alwaysBounceVertical = true 26 | // attr.separatorStyle = .none 27 | attr.register(cellType: ProjectCell.self) 28 | // attr.rowHeight = 150 29 | }) 30 | 31 | 32 | 33 | convenience init(cid: Int) { 34 | self.init() 35 | self.cid = cid 36 | } 37 | 38 | 39 | override func viewDidLoad() { 40 | self.view.addSubview(tableView) 41 | tableView.snp.makeConstraints { (maker) in 42 | maker.edges.equalToSuperview() 43 | } 44 | 45 | tableView.register(ArticleCell.self, forCellReuseIdentifier: "ArticleCell") 46 | 47 | 48 | if #available(iOS 11.0, *) { 49 | UIScrollView.appearance().contentInsetAdjustmentBehavior = .never 50 | } else { 51 | automaticallyAdjustsScrollViewInsets = false 52 | } 53 | 54 | setRefresh() 55 | } 56 | 57 | private func setRefresh() { 58 | 59 | let refreshHeader = RefreshHeader{ [weak self] in 60 | self?.page = 0 61 | self?.getData(false) 62 | } 63 | 64 | refreshHeader.isAutomaticallyChangeAlpha = true 65 | refreshHeader.lastUpdatedTimeLabel?.isHidden = true 66 | tableView.mj_header = refreshHeader 67 | refreshHeader.beginRefreshing() 68 | 69 | tableView.mj_footer = RefreshFooter{ [weak self] in 70 | self?.getData(true) 71 | } 72 | tableView.mj_footer?.isAutomaticallyChangeAlpha = true 73 | 74 | } 75 | 76 | 77 | private func getData(_ loadMore: Bool = false) { 78 | if !loadMore { 79 | page = 0 80 | } else { 81 | page += 1 82 | } 83 | 84 | Api.fetchProjectArticles(page: page, cid: cid, success: { (value: ArticleModel?) in 85 | //结束刷新 86 | if self.tableView.mj_header!.isRefreshing { self.tableView.mj_header?.endRefreshing() 87 | } 88 | 89 | if self.tableView.mj_footer!.isRefreshing { self.tableView.mj_footer?.endRefreshing() 90 | } 91 | 92 | //是否加载更多 93 | if loadMore { 94 | if value?.datas.count ?? 0 <= 0 { 95 | self.tableView.mj_footer?.endRefreshingWithNoMoreData() } else { 96 | self.articleList.append(contentsOf: value!.datas) 97 | } 98 | } else { 99 | if value?.datas.count ?? 0 < 20 { 100 | self.tableView.mj_footer?.endRefreshingWithNoMoreData() 101 | } 102 | self.articleList = value?.datas ?? [] 103 | } 104 | 105 | self.tableView.reloadData() 106 | }, error: error(error:)) 107 | } 108 | } 109 | 110 | extension ProjectArticlesVController: JXSegmentedListContainerViewListDelegate, UITableViewDataSource, UITableViewDelegate, CollectDelegate { 111 | func listView() -> UIView { 112 | view 113 | } 114 | 115 | //数据 116 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 117 | return articleList.count 118 | } 119 | 120 | //每行加载样式 121 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 122 | let tableViewCell = tableView.dequeueReusableCell(for: indexPath, cellType: ProjectCell.self) 123 | tableViewCell.collectDelegate = self 124 | tableViewCell.model = articleList[indexPath.row] 125 | return tableViewCell 126 | } 127 | 128 | //item点击事件 129 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 130 | let model = self.articleList[indexPath.row] 131 | let webVController = WebVController(title: model.title, url: model.link) 132 | navigationController?.pushViewController(webVController, animated: true) 133 | } 134 | 135 | //收藏文章 136 | func collectAirticle(cid id: Int, tabCell tabviewCell: UITableViewCell) { 137 | Api.collect(cid: id, success: { value in 138 | let cell = tabviewCell as! ProjectCell 139 | cell.refreshCollect(isCollect: true) 140 | self.view.makeToast("收藏成功") 141 | }, error: error(error:)) 142 | } 143 | 144 | //取消收藏文章 145 | func uncollectAirticle(cid id: Int, tabCell tabviewCell: UITableViewCell) { 146 | Api.uncollect(cid: id, success: { value in 147 | let cell = tabviewCell as! ProjectCell 148 | cell.refreshCollect(isCollect: false) 149 | self.view.makeToast("取消收藏成功") 150 | }, error: error(error:)) 151 | } 152 | } 153 | 154 | -------------------------------------------------------------------------------- /FunIOS/UI/Project/ProjectVController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ProjectVController.swift 3 | // FunIOS 4 | // 5 | // Created by redli on 2021/7/21. 6 | // 7 | 8 | import UIKit 9 | import SnapKitExtend 10 | import JXSegmentedView 11 | 12 | class ProjectVController: BaseCVontroller { 13 | 14 | 15 | private let segmentedView = JXSegmentedView() 16 | 17 | private let segmentedDataSource = JXSegmentedTitleDataSource() 18 | 19 | private lazy var divLine = UIView().then({ (attr) in 20 | attr.backgroundColor = UIColor.lightGray.withAlphaComponent(0.2) 21 | }) 22 | 23 | //配置指示器 24 | private let indicator = JXSegmentedIndicatorLineView() 25 | 26 | private lazy var listContainerView:JXSegmentedListContainerView = { 27 | return JXSegmentedListContainerView(dataSource: self) 28 | }() 29 | 30 | //指示器内容 31 | private var tabTitles : [String] = [] 32 | 33 | private var viewControllers: [ProjectArticlesVController] = [] 34 | 35 | override func viewWillAppear(_ animated: Bool) { 36 | self.navigationController?.navigationBar.isHidden = true 37 | } 38 | 39 | override func viewDidLoad() { 40 | Api.fetchProjectSegmented(success: { (value:Array?) in 41 | value?.forEach({ (item: StructureModel) in 42 | self.tabTitles.append(item.name) 43 | self.viewControllers.append(ProjectArticlesVController(cid: item.id)) 44 | }) 45 | self.loadUI() 46 | }, error: error(error:)) 47 | } 48 | 49 | private func loadUI() { 50 | self.segmentedDataSource.titles = self.tabTitles 51 | self.segmentedView.dataSource = self.segmentedDataSource 52 | self.view.addSubview(self.segmentedView) 53 | self.view.addSubview(self.divLine) 54 | self.indicator.indicatorWidth = 20 55 | self.segmentedView.indicators = [self.indicator] 56 | self.segmentedView.listContainer = self.listContainerView 57 | self.view.addSubview(self.listContainerView) 58 | } 59 | 60 | override func viewDidLayoutSubviews() { 61 | super.viewDidLayoutSubviews() 62 | segmentedView.frame = CGRect(x: 0, y: statusBarHeight, width: screenWidth, height: 50) 63 | 64 | divLine.frame = CGRect(x: 0, y: statusBarHeight + 50, width: screenWidth, height: 1) 65 | 66 | listContainerView.frame = CGRect(x: 0, y: statusBarHeight + 50 + 1, width: screenWidth, height: screenHeight - statusBarHeight - 50 - 1) 67 | } 68 | } 69 | 70 | extension ProjectVController: JXSegmentedListContainerViewDataSource { 71 | func numberOfLists(in listContainerView: JXSegmentedListContainerView) -> Int { 72 | return viewControllers.count 73 | } 74 | 75 | func listContainerView(_ listContainerView: JXSegmentedListContainerView, initListAt index: Int) -> JXSegmentedListContainerViewListDelegate { 76 | return viewControllers[index] 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /FunIOS/UI/Structure/StructureListVController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StructureListVController.swift 3 | // FunIOS 4 | // 5 | // Created by redli on 2021/7/27. 6 | // 7 | 8 | import UIKit 9 | import JXSegmentedView 10 | 11 | 12 | class StructureListVController: BaseCVontroller { 13 | 14 | //type = 1 体系, type = 2 导航 15 | private var type = 1 16 | 17 | private var list = [Any]() 18 | 19 | private lazy var tableView: UITableView = UITableView(frame: .zero, style: .plain).then({ (attr) in 20 | attr.backgroundColor = UIColor.white 21 | attr.delegate = self 22 | attr.dataSource = self 23 | attr.alwaysBounceVertical = true 24 | attr.separatorStyle = .none 25 | }) 26 | 27 | convenience init(type: Int) { 28 | self.init() 29 | self.type = type 30 | 31 | if type == 1 { 32 | self.list = [StructureModel]() 33 | } else { 34 | self.list = [NavigationModel]() 35 | } 36 | } 37 | 38 | 39 | override func viewDidLoad() { 40 | tableView.register(cellType: StructureCell.self) 41 | self.view.addSubview(tableView) 42 | tableView.snp.makeConstraints { (maker) in 43 | maker.edges.equalToSuperview() 44 | } 45 | 46 | setRefresh() 47 | } 48 | 49 | private func setRefresh() { 50 | 51 | let refreshHeader = RefreshHeader{ [weak self] in 52 | self?.getData() 53 | } 54 | 55 | refreshHeader.isAutomaticallyChangeAlpha = true 56 | refreshHeader.lastUpdatedTimeLabel?.isHidden = true 57 | tableView.mj_header = refreshHeader 58 | refreshHeader.beginRefreshing() 59 | } 60 | 61 | 62 | private func getData() { 63 | if type == 1 { 64 | Api.fetchStructures(success: { (value: Array?) in 65 | self.reloadTable(value: value) 66 | }, error: error(error:)) 67 | } else { 68 | Api.fetchNavigations(success: { (value: Array?) in 69 | self.reloadTable(value: value) 70 | }, error: error(error:)) 71 | } 72 | } 73 | 74 | private func reloadTable(value: Array?) { 75 | self.list.append(contentsOf: value ?? []) 76 | self.tableView.reloadData() 77 | //结束刷新 78 | if self.tableView.mj_header!.isRefreshing { self.tableView.mj_header?.endRefreshing() 79 | } 80 | 81 | //刷新一下tableview布局 82 | DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {[weak self] in 83 | self?.tableView.beginUpdates() 84 | self?.tableView.endUpdates() 85 | } 86 | } 87 | } 88 | 89 | extension StructureListVController: UITableViewDelegate, UITableViewDataSource, JXSegmentedListContainerViewListDelegate, TagViewDelegate { 90 | 91 | func tagStructureClick(parentModel model: StructureModel, childClickIndex clickIndex: Int) { 92 | let structureDetailVController = StructureDetailVController.init(parentModel: model, childClickIndex: clickIndex) 93 | navigationController?.pushViewController(structureDetailVController, animated: true) 94 | } 95 | 96 | func tagNavigationClick(parentModel model: NavigationModel, childClickIndex clickIndex: Int) { 97 | let item = model.articles[clickIndex] 98 | let webVController = WebVController(title: item.title, url: item.link) 99 | navigationController?.pushViewController(webVController, animated: true) 100 | } 101 | 102 | func listView() -> UIView { 103 | view 104 | } 105 | 106 | func numberOfSections(in tableView: UITableView) -> Int { 107 | return self.list.count 108 | } 109 | 110 | func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { 111 | return 30 112 | } 113 | 114 | func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { 115 | let view = UIView() 116 | view.backgroundColor = UIColor(red:0.94, green:0.94, blue:0.94, alpha:1.0) 117 | let viewLabel = UILabel(frame: CGRect(x: 10, y: 0, width: UIScreen.main.bounds.size.width, height: 30)) 118 | if self.type == 1 { 119 | viewLabel.text = (self.list[section] as! StructureModel).name 120 | } else { 121 | viewLabel.text = (self.list[section] as! NavigationModel).name 122 | } 123 | 124 | viewLabel.textColor = UIColor(red:0.31, green:0.31, blue:0.31, alpha:1.0) 125 | view.addSubview(viewLabel) 126 | tableView.addSubview(view) 127 | return view 128 | } 129 | 130 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 131 | // if self.type == 1 { 132 | // return (self.list[section] as! StructureModel).children.count 133 | // } else { 134 | // return (self.list[section] as! NavigationModel).articles.count 135 | // } 136 | return 1 137 | } 138 | 139 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 140 | let tableViewCell = tableView.dequeueReusableCell(for: indexPath, cellType: StructureCell.self) 141 | tableViewCell.tagDelegate = self 142 | if self.type == 1 { 143 | // tableViewCell.setModel(type: 1, model: (self.list[indexPath.section] as! StructureModel).children[indexPath.row]) 144 | tableViewCell.setModel(type: 1, model: (self.list[indexPath.section] as! StructureModel)) 145 | } else { 146 | // tableViewCell.setModel(type: 2, model: (self.list[indexPath.section] as! NavigationModel).articles[indexPath.row]) 147 | tableViewCell.setModel(type: 2, model: (self.list[indexPath.section] as! NavigationModel)) 148 | } 149 | return tableViewCell 150 | } 151 | 152 | // func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 153 | // if type == 1 { 154 | // let model = (self.list[indexPath.section] as! StructureModel).children[indexPath.row] 155 | // } else { 156 | // let model = (self.list[indexPath.section] as! NavigationModel).articles[indexPath.row] 157 | // let webVController = WebVController(title: model.title, url: model.link) 158 | // navigationController?.pushViewController(webVController, animated: true) 159 | // } 160 | // } 161 | } 162 | -------------------------------------------------------------------------------- /FunIOS/UI/Structure/StructureVController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StructureVController.swift 3 | // FunIOS 4 | // 5 | // Created by redli on 2021/7/21. 6 | // 7 | 8 | import UIKit 9 | import JXSegmentedView 10 | import SnapKitExtend 11 | 12 | class StructrureVController: UIViewController { 13 | 14 | private let titles = ["体系", "导航"] 15 | 16 | private let segmentedView = JXSegmentedView() 17 | 18 | private let segmentedDataSource = JXSegmentedTitleDataSource() 19 | 20 | //配置指示器 21 | private let indicator = JXSegmentedIndicatorBackgroundView() 22 | 23 | private lazy var divLine = UIView().then({ (attr) in 24 | attr.backgroundColor = UIColor.lightGray.withAlphaComponent(0.2) 25 | }) 26 | 27 | private lazy var listContainerView:JXSegmentedListContainerView = { 28 | return JXSegmentedListContainerView(dataSource: self) 29 | }() 30 | 31 | private var viewControllers: [StructureListVController] = [] 32 | 33 | var totalItemWidth: CGFloat = 0 34 | 35 | override func viewWillAppear(_ animated: Bool) { 36 | self.navigationController?.navigationBar.isHidden = true 37 | } 38 | 39 | override func viewDidLoad() { 40 | totalItemWidth = UIScreen.main.bounds.size.width - 30 * 2 41 | segmentedDataSource.itemWidth = totalItemWidth / CGFloat(titles.count) / 2 42 | segmentedDataSource.titles = titles 43 | segmentedDataSource.isTitleMaskEnabled = true 44 | segmentedDataSource.titleNormalColor = UIColor.red 45 | segmentedDataSource.titleSelectedColor = UIColor.white 46 | segmentedDataSource.itemSpacing = 0 47 | segmentedView.dataSource = segmentedDataSource 48 | segmentedView.layer.masksToBounds = true 49 | segmentedView.layer.cornerRadius = 15 50 | segmentedView.layer.borderColor = UIColor.red.cgColor 51 | segmentedView.layer.borderWidth = 1 / UIScreen.main.scale 52 | 53 | indicator.indicatorHeight = 30 54 | indicator.indicatorWidthIncrement = 0 55 | indicator.indicatorColor = UIColor.red 56 | 57 | segmentedView.indicators = [indicator] 58 | 59 | titles.forEach { (title) in 60 | viewControllers.append(StructureListVController(type: title == self.titles[0] ? 1 : 2)) 61 | } 62 | 63 | segmentedView.listContainer = listContainerView 64 | 65 | view.addSubview(segmentedView) 66 | view.addSubview(listContainerView) 67 | } 68 | 69 | override func viewDidLayoutSubviews() { 70 | super.viewDidLayoutSubviews() 71 | 72 | segmentedView.frame = CGRect(x:screenWidth / 2 - (totalItemWidth / 4), y: statusBarHeight, width: totalItemWidth / 2, height: 30) 73 | 74 | divLine.frame = CGRect(x: 0, y: statusBarHeight + 50, width: screenWidth, height: 1) 75 | 76 | listContainerView.frame = CGRect(x: 0, y: statusBarHeight + 30, width: screenWidth, height: screenHeight - statusBarHeight - 30) 77 | } 78 | 79 | } 80 | 81 | extension StructrureVController: JXSegmentedListContainerViewDataSource { 82 | func numberOfLists(in listContainerView: JXSegmentedListContainerView) -> Int { 83 | return viewControllers.count 84 | } 85 | 86 | func listContainerView(_ listContainerView: JXSegmentedListContainerView, initListAt index: Int) -> JXSegmentedListContainerViewListDelegate { 87 | return viewControllers[index] 88 | } 89 | 90 | 91 | } 92 | -------------------------------------------------------------------------------- /FunIOS/UI/StructureDetail/StructureDetailVController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StructureDetailVController.swift 3 | // FunIOS 4 | // 5 | // Created by redli on 2021/7/28. 6 | // 7 | 8 | import UIKit 9 | import JXSegmentedView 10 | 11 | class StructureDetailVController: UIViewController { 12 | 13 | private var model: StructureModel? 14 | 15 | private var clickIndex: Int? 16 | 17 | private let segmentedView = JXSegmentedView() 18 | 19 | private let segmentedDataSource = JXSegmentedTitleDataSource() 20 | 21 | private lazy var divLine = UIView().then({ (attr) in 22 | attr.backgroundColor = UIColor.lightGray.withAlphaComponent(0.2) 23 | }) 24 | 25 | //配置指示器 26 | private let indicator = JXSegmentedIndicatorLineView() 27 | 28 | private lazy var listContainerView:JXSegmentedListContainerView = { 29 | return JXSegmentedListContainerView(dataSource: self) 30 | }() 31 | 32 | //指示器内容 33 | private var tabTitles : [String] = [] 34 | 35 | private var viewControllers: [WechatArticlesVController] = [] 36 | 37 | convenience init(parentModel model: StructureModel, childClickIndex clickIndex: Int) { 38 | self.init() 39 | self.model = model 40 | self.clickIndex = clickIndex 41 | } 42 | 43 | override func viewWillAppear(_ animated: Bool) { 44 | self.navigationController?.navigationBar.isHidden = false 45 | //设置背景色,防止跳转界面视图重叠 46 | self.view.backgroundColor = UIColor.white 47 | } 48 | 49 | override func viewDidLoad() { 50 | super.viewDidLoad() 51 | self.navigationItem.title = model?.name 52 | self.model?.children.forEach({ (value: StructureModel) in 53 | self.tabTitles.append(value.name) 54 | self.viewControllers.append(WechatArticlesVController(cid: value.id)) 55 | }) 56 | self.segmentedDataSource.titles = self.tabTitles 57 | self.segmentedView.dataSource = self.segmentedDataSource 58 | self.view.addSubview(self.segmentedView) 59 | self.view.addSubview(self.divLine) 60 | self.indicator.indicatorWidth = 20 61 | self.segmentedView.indicators = [self.indicator] 62 | self.segmentedView.defaultSelectedIndex = self.clickIndex ?? 0 63 | self.segmentedView.listContainer = self.listContainerView 64 | self.view.addSubview(self.listContainerView) 65 | } 66 | 67 | override func viewDidLayoutSubviews() { 68 | super.viewDidLayoutSubviews() 69 | 70 | let navigationHeight = navigationController?.navigationBar.frame.size.height ?? 40 71 | 72 | segmentedView.frame = CGRect(x: 0, y: statusBarHeight + navigationHeight, width: screenWidth, height: 50) 73 | 74 | divLine.frame = CGRect(x: 0, y: statusBarHeight + navigationHeight + 50, width: screenWidth, height: 1) 75 | 76 | listContainerView.frame = CGRect(x: 0, y: statusBarHeight + navigationHeight + 50 + 1, width: screenWidth, height: screenHeight - statusBarHeight - 50 - 1) 77 | } 78 | } 79 | 80 | extension StructureDetailVController: JXSegmentedListContainerViewDataSource { 81 | 82 | func numberOfLists(in listContainerView: JXSegmentedListContainerView) -> Int { 83 | return viewControllers.count 84 | } 85 | 86 | func listContainerView(_ listContainerView: JXSegmentedListContainerView, initListAt index: Int) -> JXSegmentedListContainerViewListDelegate { 87 | return viewControllers[index] 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /FunIOS/UI/User/Collect/CollectVController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CollectVController.swift 3 | // FunIOS 4 | // 5 | // Created by redli on 2021/8/10. 6 | // 7 | 8 | import Foundation 9 | import UIKit 10 | 11 | class CollectVController: BaseCVontroller { 12 | 13 | // 当前页面 14 | var page = 0 15 | 16 | private var data = [ArticleItemModel]() 17 | 18 | private lazy var tableView: UITableView = UITableView(frame: .zero, style: .plain).then({ (attr) in 19 | attr.backgroundColor = UIColor.white 20 | attr.delegate = self 21 | attr.dataSource = self 22 | attr.alwaysBounceVertical = true 23 | attr.separatorStyle = .none 24 | attr.register(cellType: CollectCell.self) 25 | }) 26 | 27 | 28 | override func viewWillAppear(_ animated: Bool) { 29 | navigationController?.navigationBar.isHidden = false 30 | navigationItem.title = "我的收藏" 31 | } 32 | 33 | override func viewDidLoad() { 34 | let navigationHeight = navigationController?.navigationBar.frame.height ?? 0 35 | self.view.addSubview(tableView) 36 | tableView.snp.makeConstraints { (maker) in 37 | maker.top.equalToSuperview().offset(statusBarHeight + navigationHeight) 38 | maker.leading.equalToSuperview() 39 | maker.trailing.equalToSuperview() 40 | maker.bottom.equalToSuperview() 41 | } 42 | setRefresh() 43 | } 44 | 45 | private func setRefresh() { 46 | 47 | let refreshHeader = RefreshHeader{ [weak self] in 48 | self?.page = 0 49 | self?.getData(false) 50 | } 51 | 52 | refreshHeader.isAutomaticallyChangeAlpha = true 53 | refreshHeader.lastUpdatedTimeLabel?.isHidden = true 54 | tableView.mj_header = refreshHeader 55 | refreshHeader.beginRefreshing() 56 | 57 | tableView.mj_footer = RefreshFooter{ [weak self] in 58 | self?.getData(true) 59 | } 60 | tableView.mj_footer?.isAutomaticallyChangeAlpha = true 61 | } 62 | 63 | private func getData(_ loadMore: Bool = false) { 64 | if !loadMore { 65 | page = 0 66 | } else { 67 | page += 1 68 | } 69 | 70 | Api.fetchCollectArticles(page: page, success: { (value: ArticleModel?) in 71 | //结束刷新 72 | if self.tableView.mj_header!.isRefreshing { self.tableView.mj_header?.endRefreshing() 73 | } 74 | 75 | if self.tableView.mj_footer!.isRefreshing { self.tableView.mj_footer?.endRefreshing() 76 | } 77 | 78 | //是否加载更多 79 | if loadMore { 80 | if value?.datas.count ?? 0 <= 0 { 81 | self.tableView.mj_footer?.endRefreshingWithNoMoreData() } else { 82 | self.data.append(contentsOf: value!.datas) 83 | } 84 | } else { 85 | if value?.datas.count ?? 0 < 20 { 86 | self.tableView.mj_footer?.endRefreshingWithNoMoreData() 87 | } 88 | self.data = value?.datas ?? [] 89 | } 90 | 91 | self.tableView.reloadData() 92 | }, error: error(error:)) 93 | } 94 | 95 | } 96 | 97 | extension CollectVController: UITableViewDelegate, UITableViewDataSource { 98 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 99 | return data.count 100 | } 101 | 102 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 103 | let tableViewCell = tableView.dequeueReusableCell(for: indexPath, cellType: CollectCell.self) 104 | tableViewCell.model = self.data[indexPath.row] 105 | return tableViewCell 106 | } 107 | 108 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 109 | let model = self.data[indexPath.row] 110 | let webVController = WebVController(title: model.title, url: model.link) 111 | navigationController?.pushViewController(webVController, animated: true) 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /FunIOS/UI/User/Integral/IntegralVController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // IntegralVController.swift 3 | // FunIOS 4 | // 5 | // Created by redli on 2021/8/10. 6 | // 7 | 8 | import Foundation 9 | import UIKit 10 | 11 | class IntegralVController: BaseCVontroller { 12 | 13 | 14 | // 当前页面 15 | var page = 0 16 | 17 | private var data = [IntegralItemModel]() 18 | 19 | private lazy var tableView: UITableView = UITableView(frame: .zero, style: .plain).then({ (attr) in 20 | attr.backgroundColor = UIColor.white 21 | attr.delegate = self 22 | attr.dataSource = self 23 | attr.alwaysBounceVertical = true 24 | 25 | }) 26 | 27 | 28 | override func viewWillAppear(_ animated: Bool) { 29 | navigationController?.navigationBar.isHidden = false 30 | navigationItem.title = "积分列表" 31 | } 32 | 33 | override func viewDidLoad() { 34 | let navigationHeight = navigationController?.navigationBar.frame.height ?? 0 35 | self.view.addSubview(tableView) 36 | tableView.snp.makeConstraints { (maker) in 37 | maker.top.equalToSuperview().offset(statusBarHeight + navigationHeight) 38 | maker.leading.equalToSuperview() 39 | maker.trailing.equalToSuperview() 40 | maker.bottom.equalToSuperview() 41 | } 42 | setRefresh() 43 | } 44 | 45 | private func setRefresh() { 46 | 47 | let refreshHeader = RefreshHeader{ [weak self] in 48 | self?.page = 0 49 | self?.getData(false) 50 | } 51 | 52 | refreshHeader.isAutomaticallyChangeAlpha = true 53 | refreshHeader.lastUpdatedTimeLabel?.isHidden = true 54 | tableView.mj_header = refreshHeader 55 | refreshHeader.beginRefreshing() 56 | 57 | tableView.mj_footer = RefreshFooter{ [weak self] in 58 | self?.getData(true) 59 | } 60 | tableView.mj_footer?.isAutomaticallyChangeAlpha = true 61 | } 62 | 63 | private func getData(_ loadMore: Bool = false) { 64 | if !loadMore { 65 | page = 0 66 | } else { 67 | page += 1 68 | } 69 | 70 | Api.fetchMyIntegral(page: page, success: { (value: IntegralModel?) in 71 | //结束刷新 72 | if self.tableView.mj_header!.isRefreshing { self.tableView.mj_header?.endRefreshing() 73 | } 74 | 75 | if self.tableView.mj_footer!.isRefreshing { self.tableView.mj_footer?.endRefreshing() 76 | } 77 | 78 | //是否加载更多 79 | if loadMore { 80 | if value?.datas.count ?? 0 <= 0 { 81 | self.tableView.mj_footer?.endRefreshingWithNoMoreData() } else { 82 | self.data.append(contentsOf: value!.datas) 83 | } 84 | } else { 85 | if value?.datas.count ?? 0 < 20 { 86 | self.tableView.mj_footer?.endRefreshingWithNoMoreData() 87 | } 88 | self.data = value?.datas ?? [] 89 | } 90 | 91 | self.tableView.reloadData() 92 | }, error: error(error:)) 93 | } 94 | 95 | } 96 | 97 | 98 | extension IntegralVController: UITableViewDataSource, UITableViewDelegate { 99 | 100 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 101 | return self.data.count 102 | } 103 | 104 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 105 | 106 | let tabelCell = UITableViewCell.init(style: .subtitle, reuseIdentifier: "integral_cell") 107 | tabelCell.textLabel?.text = self.data[indexPath.row].reason 108 | tabelCell.detailTextLabel?.text = self.data[indexPath.row 109 | ].desc 110 | tabelCell.selectedBackgroundView = UIView() 111 | return tabelCell 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /FunIOS/UI/User/Ranking/RankingVController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RankingVController.swift 3 | // FunIOS 4 | // 5 | // Created by redli on 2021/8/10. 6 | // 7 | 8 | import Foundation 9 | import UIKit 10 | 11 | 12 | class RankingVController: BaseCVontroller { 13 | // 当前页面 14 | var page = 1 15 | 16 | private var data = [UserCoinLevelModel]() 17 | 18 | private lazy var tableView: UITableView = UITableView(frame: .zero, style: .plain).then({ (attr) in 19 | attr.backgroundColor = UIColor.white 20 | attr.delegate = self 21 | attr.dataSource = self 22 | attr.alwaysBounceVertical = true 23 | attr.rowHeight = 60 24 | attr.register(cellType: RankingCell.self) 25 | }) 26 | 27 | override func viewWillAppear(_ animated: Bool) { 28 | navigationController?.navigationBar.isHidden = false 29 | navigationItem.title = "排行榜" 30 | } 31 | 32 | override func viewDidLoad() { 33 | let navigationHeight = navigationController?.navigationBar.frame.height ?? 0 34 | self.view.addSubview(tableView) 35 | tableView.snp.makeConstraints { (maker) in 36 | maker.top.equalToSuperview().offset(statusBarHeight + navigationHeight) 37 | maker.leading.equalToSuperview() 38 | maker.trailing.equalToSuperview() 39 | maker.bottom.equalToSuperview() 40 | } 41 | setRefresh() 42 | } 43 | 44 | private func setRefresh() { 45 | 46 | let refreshHeader = RefreshHeader{ [weak self] in 47 | self?.page = 1 48 | self?.getData(false) 49 | } 50 | 51 | refreshHeader.isAutomaticallyChangeAlpha = true 52 | refreshHeader.lastUpdatedTimeLabel?.isHidden = true 53 | tableView.mj_header = refreshHeader 54 | refreshHeader.beginRefreshing() 55 | 56 | tableView.mj_footer = RefreshFooter{ [weak self] in 57 | self?.getData(true) 58 | } 59 | tableView.mj_footer?.isAutomaticallyChangeAlpha = true 60 | } 61 | 62 | private func getData(_ loadMore: Bool = false) { 63 | if !loadMore { 64 | page = 0 65 | } else { 66 | page += 1 67 | } 68 | 69 | Api.fetchRanking(page: page, success: { (value: RankingModel?) in 70 | //结束刷新 71 | if self.tableView.mj_header!.isRefreshing { self.tableView.mj_header?.endRefreshing() 72 | } 73 | 74 | if self.tableView.mj_footer!.isRefreshing { self.tableView.mj_footer?.endRefreshing() 75 | } 76 | 77 | //是否加载更多 78 | if loadMore { 79 | if value?.datas.count ?? 0 <= 0 { 80 | self.tableView.mj_footer?.endRefreshingWithNoMoreData() } else { 81 | self.data.append(contentsOf: value!.datas) 82 | } 83 | } else { 84 | if value?.datas.count ?? 0 < 20 { 85 | self.tableView.mj_footer?.endRefreshingWithNoMoreData() 86 | } 87 | self.data = value?.datas ?? [] 88 | } 89 | 90 | self.tableView.reloadData() 91 | }, error: error(error:)) 92 | } 93 | } 94 | 95 | extension RankingVController: UITableViewDataSource, UITableViewDelegate { 96 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 97 | return self.data.count 98 | } 99 | 100 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 101 | let cell = tableView.dequeueReusableCell(for: indexPath, cellType: RankingCell.self) 102 | cell.model = self.data[indexPath.row] 103 | cell.index = indexPath.row + 1 104 | return cell 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /FunIOS/UI/Web/WebVController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WebVController.swift 3 | // FunIOS 4 | // 5 | // Created by redli on 2021/7/25. 6 | // 7 | 8 | import UIKit 9 | import WebKit 10 | 11 | class WebVController: UIViewController { 12 | var url : String? 13 | 14 | convenience init(title: String? , url: String?) { 15 | self.init() 16 | self.title = title 17 | self.url = url 18 | } 19 | 20 | override func viewWillAppear(_ animated: Bool) { 21 | // let barButton = UIBarButtonItem() 22 | // barButton.title = "" 23 | // self.navigationItem.backBarButtonItem = barButton 24 | self.navigationController?.navigationBar.isHidden = false 25 | } 26 | 27 | override func viewDidLoad() { 28 | super.viewDidLoad() 29 | self.navigationItem.title = title ?? "网页" 30 | //添加webview 31 | let webView = WKWebView.init(frame: view.frame) 32 | 33 | if url != nil { 34 | webView.load(URLRequest.init(url:URL.init(string: url!)!)) 35 | } 36 | 37 | self.view.addSubview(webView) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /FunIOS/UI/Wechat/WechatArticlesVController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WechatArticlesVController.swift 3 | // FunIOS 4 | // 5 | // Created by redli on 2021/7/25. 6 | // 7 | 8 | import UIKit 9 | import JXSegmentedView 10 | 11 | class WechatArticlesVController: BaseCVontroller { 12 | 13 | // 当前页面 14 | var page = 0 15 | //文章id 16 | var cid : Int = 0 17 | //实体类数组 18 | private var articleList = [ArticleItemModel]() 19 | 20 | private lazy var tableView: UITableView = UITableView(frame: .zero, style: .plain).then({ (attr) in 21 | attr.backgroundColor = UIColor.white 22 | attr.delegate = self 23 | attr.dataSource = self 24 | attr.alwaysBounceVertical = true 25 | attr.separatorStyle = .none 26 | attr.register(cellType: WechatCell.self) 27 | // attr.rowHeight = 150 28 | }) 29 | 30 | 31 | 32 | convenience init(cid: Int) { 33 | self.init() 34 | self.cid = cid 35 | } 36 | 37 | override func viewWillAppear(_ animated: Bool) { 38 | self.view.backgroundColor = UIColor.white 39 | } 40 | 41 | override func viewDidLoad() { 42 | self.view.addSubview(tableView) 43 | tableView.snp.makeConstraints { (maker) in 44 | maker.edges.equalToSuperview() 45 | } 46 | 47 | tableView.register(ArticleCell.self, forCellReuseIdentifier: "ArticleCell") 48 | 49 | if #available(iOS 11.0, *) { 50 | UIScrollView.appearance().contentInsetAdjustmentBehavior = .never 51 | } else { 52 | automaticallyAdjustsScrollViewInsets = false 53 | } 54 | 55 | setRefresh() 56 | } 57 | 58 | private func setRefresh() { 59 | let refreshHeader = RefreshHeader{ [weak self] in 60 | self?.getData(false) 61 | } 62 | 63 | refreshHeader.isAutomaticallyChangeAlpha = true 64 | refreshHeader.lastUpdatedTimeLabel?.isHidden = true 65 | tableView.mj_header = refreshHeader 66 | refreshHeader.beginRefreshing() 67 | 68 | tableView.mj_footer = RefreshFooter{ [weak self] in 69 | self?.getData(true) 70 | } 71 | tableView.mj_footer?.isAutomaticallyChangeAlpha = true 72 | } 73 | 74 | 75 | private func getData(_ loadMore: Bool = false) { 76 | if !loadMore { 77 | page = 0 78 | } else { 79 | page += 1 80 | } 81 | 82 | Api.fetchWechatArticles(page: page, cid: cid, success: { (value: ArticleModel?) in 83 | //结束刷新 84 | if self.tableView.mj_header!.isRefreshing { self.tableView.mj_header?.endRefreshing() 85 | } 86 | if self.tableView.mj_footer!.isRefreshing { self.tableView.mj_footer?.endRefreshing() 87 | } 88 | //是否加载更多 89 | if loadMore { 90 | if value?.datas.count ?? 0 <= 0 { 91 | self.tableView.mj_footer?.endRefreshingWithNoMoreData() } else { 92 | self.articleList.append(contentsOf: value!.datas) 93 | } 94 | } else { 95 | if value?.datas.count ?? 0 < 20 { 96 | self.tableView.mj_footer?.endRefreshingWithNoMoreData() 97 | } 98 | self.articleList = value?.datas ?? [] 99 | } 100 | 101 | self.tableView.reloadData() 102 | }, error: error(error:)) 103 | } 104 | } 105 | 106 | extension WechatArticlesVController: JXSegmentedListContainerViewListDelegate, UITableViewDataSource, UITableViewDelegate, CollectDelegate { 107 | func listView() -> UIView { 108 | view 109 | } 110 | 111 | //数据 112 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 113 | return articleList.count 114 | } 115 | 116 | //每行加载样式 117 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 118 | let tableViewCell = tableView.dequeueReusableCell(for: indexPath, cellType: WechatCell.self) 119 | tableViewCell.collectDelegate = self 120 | tableViewCell.model = articleList[indexPath.row] 121 | return tableViewCell 122 | } 123 | 124 | //item点击事件 125 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 126 | let model = self.articleList[indexPath.row] 127 | let webVController = WebVController(title: model.title, url: model.link) 128 | navigationController?.pushViewController(webVController, animated: true) 129 | } 130 | 131 | //收藏文章 132 | func collectAirticle(cid id: Int, tabCell tabviewCell: UITableViewCell) { 133 | Api.collect(cid: id, success: { value in 134 | let cell = tabviewCell as! WechatCell 135 | cell.refreshCollect(isCollect: true) 136 | self.view.makeToast("收藏成功") 137 | }, error: error(error:)) 138 | } 139 | 140 | //取消收藏文章 141 | func uncollectAirticle(cid id: Int, tabCell tabviewCell: UITableViewCell) { 142 | Api.uncollect(cid: id, success: { value in 143 | let cell = tabviewCell as! WechatCell 144 | cell.refreshCollect(isCollect: false) 145 | self.view.makeToast("取消收藏成功") 146 | }, error: error(error:)) 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /FunIOS/UI/Wechat/WechatVController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WechatAccountVController.swift 3 | // FunIOS 4 | // 5 | // Created by redli on 2021/7/21. 6 | // 7 | 8 | import UIKit 9 | import SnapKitExtend 10 | import JXSegmentedView 11 | 12 | class WechatVController: BaseCVontroller { 13 | 14 | private let segmentedView = JXSegmentedView() 15 | 16 | private let segmentedDataSource = JXSegmentedTitleDataSource() 17 | 18 | private lazy var divLine = UIView().then({ (attr) in 19 | attr.backgroundColor = UIColor.lightGray.withAlphaComponent(0.2) 20 | }) 21 | 22 | //配置指示器 23 | private let indicator = JXSegmentedIndicatorLineView() 24 | 25 | private lazy var listContainerView:JXSegmentedListContainerView = { 26 | return JXSegmentedListContainerView(dataSource: self) 27 | }() 28 | 29 | //指示器内容 30 | private var tabTitles : [String] = [] 31 | 32 | private var viewControllers: [WechatArticlesVController] = [] 33 | 34 | override func viewWillAppear(_ animated: Bool) { 35 | self.navigationController?.navigationBar.isHidden = true 36 | } 37 | 38 | override func viewDidLoad() { 39 | Api.fetchWechatSegmented(success: { (value:Array?) in 40 | value?.forEach({ (item: StructureModel) in 41 | self.tabTitles.append(item.name) 42 | self.viewControllers.append(WechatArticlesVController(cid: item.id)) 43 | }) 44 | self.loadUI() 45 | }, error: error(error:)) 46 | } 47 | 48 | private func loadUI() { 49 | self.segmentedDataSource.titles = self.tabTitles 50 | self.segmentedView.dataSource = self.segmentedDataSource 51 | self.view.addSubview(self.segmentedView) 52 | self.view.addSubview(self.divLine) 53 | self.indicator.indicatorWidth = 20 54 | self.segmentedView.indicators = [self.indicator] 55 | self.segmentedView.listContainer = self.listContainerView 56 | self.view.addSubview(self.listContainerView) 57 | } 58 | 59 | override func viewDidLayoutSubviews() { 60 | super.viewDidLayoutSubviews() 61 | segmentedView.frame = CGRect(x: 0, y: statusBarHeight, width: screenWidth, height: 50) 62 | 63 | divLine.frame = CGRect(x: 0, y: statusBarHeight + 50, width: screenWidth, height: 1) 64 | 65 | listContainerView.frame = CGRect(x: 0, y: statusBarHeight + 50 + 1, width: screenWidth, height: screenHeight - statusBarHeight - 50 - 1) 66 | } 67 | } 68 | 69 | extension WechatVController: JXSegmentedListContainerViewDataSource { 70 | func numberOfLists(in listContainerView: JXSegmentedListContainerView) -> Int { 71 | return viewControllers.count 72 | } 73 | 74 | func listContainerView(_ listContainerView: JXSegmentedListContainerView, initListAt index: Int) -> JXSegmentedListContainerViewListDelegate { 75 | return viewControllers[index] 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /FunIOS/View/FloatButtonTableView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BaseUITableView.swift 3 | // FunIOS 4 | // 5 | // Created by redli on 2021/9/7. 6 | // 7 | 8 | import Foundation 9 | import UIKit 10 | import MEVFloatingButton 11 | 12 | public protocol FloatButtonDelegate: NSObjectProtocol { 13 | func floatStatus(forHide hide: Bool, withAnimal animal: Bool) 14 | } 15 | 16 | class FloatButtonTableView: UITableView { 17 | 18 | weak open var floatButtonDelegate: FloatButtonDelegate? 19 | 20 | override init(frame: CGRect, style: UITableView.Style) { 21 | super.init(frame: frame, style: style) 22 | self.addObserver(self, forKeyPath: "contentOffset", options: .new, context: nil) 23 | } 24 | 25 | override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { 26 | let offset = change?[NSKeyValueChangeKey.newKey] as! CGPoint 27 | 28 | print("\(offset.y)") 29 | 30 | if offset.y > 400.0 && offset.y < 1000.0 { 31 | floatButtonDelegate?.floatStatus(forHide: false, withAnimal: true) 32 | } else if offset.y > 1000.0 { 33 | floatButtonDelegate?.floatStatus(forHide: false, withAnimal: false) 34 | } else { 35 | floatButtonDelegate?.floatStatus(forHide: true, withAnimal: false) 36 | } 37 | } 38 | 39 | 40 | required init?(coder: NSCoder) { 41 | fatalError("init(coder:) has not been implemented") 42 | } 43 | } 44 | 45 | extension FloatButtonTableView { 46 | 47 | } 48 | -------------------------------------------------------------------------------- /FunIOS/View/RefreshView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RefreshView.swift 3 | // FunIOS 4 | // 5 | // Created by redli on 2021/7/23. 6 | // 7 | 8 | import MJRefresh 9 | 10 | class RefreshHeader: MJRefreshGifHeader { 11 | 12 | override func prepare() { 13 | super.prepare() 14 | var images = [UIImage]() 15 | for index in 0..<16 { 16 | let image = UIImage(named: "dropdown_loading_0\(index)") 17 | images.append(image!) 18 | } 19 | setImages(images, for: .idle) 20 | setImages(images, for: .refreshing) 21 | setTitle("下拉刷新", for: .idle) 22 | setTitle("松开刷新", for: .pulling) 23 | setTitle("刷新中", for: .refreshing) 24 | } 25 | 26 | override func placeSubviews() { 27 | super.placeSubviews() 28 | gifView?.contentMode = .center 29 | gifView?.frame = CGRect(x: 0, y: 4, width: mj_w, height: 25) 30 | stateLabel?.font = UIFont.systemFont(ofSize: 12) 31 | stateLabel?.frame = CGRect(x: 0, y: 35, width: mj_w, height: 14) 32 | } 33 | 34 | } 35 | 36 | 37 | class RefreshFooter: MJRefreshAutoGifFooter { 38 | 39 | override func prepare() { 40 | super.prepare() 41 | // 设置控件的高度 42 | mj_h = 50 43 | // 图片数组 44 | var images = [UIImage]() 45 | // 遍历 46 | for index in 0..<8 { 47 | let image = UIImage(named: "sendloading_18x18_\(index)") 48 | images.append(image!) 49 | } 50 | // 设置空闲状态的图片 51 | setImages(images, for: .idle) 52 | // 设置刷新状态的图片 53 | setImages(images, for: .refreshing) 54 | setTitle("上拉加载数据", for: .idle) 55 | setTitle("正在努力加载", for: .pulling) 56 | setTitle("正在努力加载", for: .refreshing) 57 | setTitle("没有更多数据啦", for: .noMoreData) 58 | } 59 | 60 | override func placeSubviews() { 61 | super.placeSubviews() 62 | gifView?.mj_x = 135 63 | } 64 | } 65 | 66 | -------------------------------------------------------------------------------- /FunIOS/icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanklee9820/FunIOS/6023b32af72b85e977b5307c8f166577fe800fe3/FunIOS/icon-60@3x.png -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | source 'https://github.com/CocoaPods/Specs.git' 2 | platform :ios, '10.0' 3 | use_frameworks! 4 | 5 | target 'FunIOS' do 6 | 7 | # pod 'Moya'//网络二次封装 8 | # pod 'HYBUnicodeReadable', '~> 1.1' 9 | pod 'PrintBeautifulLog' 10 | pod 'Alamofire' #网络, '~> 4.7' 11 | pod 'MJRefresh' #刷新 12 | pod 'LLCycleScrollView' #轮播 13 | # pod 'EmptyDataSet-Swift' 14 | pod 'HandyJSON' 15 | pod 'Kingfisher' #图片 16 | pod 'Then' #语法糖 17 | #pod 'SnapKit', '~> 4.2.0' 18 | pod 'SnapKitExtend' #自动布局扩展 19 | pod 'SVProgressHUD' 20 | pod 'MBProgressHUD' 21 | pod 'Reusable' #可复用 22 | #pod 'Tabman' #tab导航 23 | pod 'JXSegmentedView' 24 | pod 'LGButton' 25 | pod 'Toast-Swift', '~> 5.0.1' 26 | pod 'TagListView', '~> 1.0' #tag标签栏 27 | pod 'SwiftEventBus', :tag => '5.1.0', :git => 'https://github.com/cesarferreira/SwiftEventBus.git' 28 | # pod 'MEVFloatingButton' #UITableView,UICollectionView和UIScrollView超类,用于在它上面显示一个可定制的浮动按钮 29 | 30 | end 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FunIOS - [玩Android](https://www.wanandroid.com/index) IOS Swift 版本 2 | 3 | ## 介绍 4 | 5 | **我一直都是做Android开发的,一直以来在断断续续的学习IOS,学了Object-C,可以看懂,写就不太习惯,后来直接上手了swift,突然觉得太舒服了,跟kotlin,dart差不多,本项目是纯代目撸布局。使用SnapKit 拘束布局搭建** 6 | 7 | ## 改善 8 | **有需求欢迎issue,空余时间会持续更新中** 9 | 10 | ## 依赖第三方 11 | 12 | ``` 13 | pod 'PrintBeautifulLog' #日志 14 | pod 'Alamofire' , '~> 4.7' #网络 15 | pod 'MJRefresh' #刷新 16 | pod 'LLCycleScrollView' #轮播 17 | pod 'HandyJSON' #序列化 反序列 18 | pod 'Kingfisher' #图片 19 | pod 'Then' #语法糖 20 | pod 'SnapKitExtend' #自动布局扩展 21 | pod 'SVProgressHUD' #加载框 22 | pod 'MBProgressHUD' #加载框 23 | pod 'Reusable' #可复用 24 | pod 'JXSegmentedView' #顶部tab 25 | pod 'LGButton' #按钮 26 | pod 'Toast-Swift', '~> 5.0.1' #吐司 27 | pod 'TagListView', '~> 1.0' #tag标签栏 28 | pod 'SwiftEventBus', :tag => '5.1.0', :git => 'https://github.com/cesarferreira/SwiftEventBus.git' #跨界面通信 29 | 30 | ``` 31 | 32 | ## 版本号 33 | ***V1.0*** 34 | *基本模块的实现 主页 项目 公众号 体系 我的 数据获取显示,登录等* 35 | 36 | ***V1.1*** 37 | *更新app logo 图标,删除没必要的png,增加收藏功能,网络请求增加失败回调统一处理* 38 | 39 | ***V1.2*** 40 | *删除不必要的文件,首页列表增加置顶功能(置顶功能冗余度有点高,不方便移植,后续慢慢琢磨一下)* 41 | 42 | ## 使用方法 43 | **下载源码,根目录执行 pod install 用 xcode 打开 FunIOS.xcworkspace 即可** 44 | 45 | ## 截图 46 | 47 | 48 | 49 | 50 | 51 | 52 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | --------------------------------------------------------------------------------