├── .gitignore ├── README.md ├── Resources ├── AppIcon.png ├── AppIcon@2x.png ├── AppIcon@3x.png ├── Design.sketch ├── Image-Failed.png ├── Image-Failed@2x.png ├── Image-Failed@3x.png ├── Image-Placeholder.png ├── Image-Placeholder@2x.png ├── Image-Placeholder@3x.png ├── Logo-Text.png ├── Logo-Text@2x.png ├── Logo-Text@3x.png ├── Logo.png ├── Logo@2x.png ├── Logo@3x.png ├── Up.png ├── Up@2x.png ├── Up@3x.png └── juejin-logo.white.svg ├── XituGold.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── unixzii.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── unixzii.xcuserdatad │ └── xcschemes │ ├── XituGold.xcscheme │ └── xcschememanagement.plist ├── XituGold.xcworkspace ├── contents.xcworkspacedata └── xcuserdata │ └── unixzii.xcuserdatad │ ├── UserInterfaceState.xcuserstate │ └── xcdebugger │ └── Breakpoints_v2.xcbkptlist └── XituGold ├── AppDelegate.swift ├── Assets.xcassets ├── AppIcon.appiconset │ ├── AppIcon@2x.png │ ├── AppIcon@3x.png │ └── Contents.json ├── Contents.json ├── Image-Failed.imageset │ ├── Contents.json │ ├── Image-Failed.png │ ├── Image-Failed@2x.png │ └── Image-Failed@3x.png ├── Image-Placeholder.imageset │ ├── Contents.json │ ├── Image-Placeholder.png │ ├── Image-Placeholder@2x.png │ └── Image-Placeholder@3x.png ├── Logo-Text.imageset │ ├── Contents.json │ ├── Logo-Text.png │ ├── Logo-Text@2x.png │ └── Logo-Text@3x.png ├── Logo.imageset │ ├── Contents.json │ ├── Logo.png │ ├── Logo@2x.png │ └── Logo@3x.png ├── Up.imageset │ ├── Contents.json │ ├── Up.png │ ├── Up@2x.png │ └── Up@3x.png ├── icon_explore.imageset │ ├── Contents.json │ └── icon_explore.pdf ├── icon_explore_active.imageset │ ├── Contents.json │ └── icon_explore_active.pdf ├── icon_tags.imageset │ ├── Contents.json │ └── icon_feeds.pdf └── icon_tags_active.imageset │ ├── Contents.json │ └── icon_feeds_active.pdf ├── Base.lproj └── LaunchScreen.storyboard ├── Info.plist ├── NSDate+Helpers.swift ├── SMNetworkActivityController.swift ├── UIImage+Helpers.swift ├── UIViewController+Alert.swift ├── XGConfig.swift ├── XGEntry.swift ├── XGEntryAPI.swift ├── XGEntryCell.swift ├── XGEntryCell.xib ├── XGEntryTableViewController.swift ├── XGExplorerViewController.swift ├── XGFilterCell.swift ├── XGFilterCell.xib ├── XGFilterViewController.swift ├── XGGroupTitleReusableView.swift ├── XGGroupTitleReusableView.xib ├── XGImageCacheController.swift ├── XGLoadableImageView.swift ├── XGNavigationController.swift ├── XGTabBarController.swift ├── XGTag.swift ├── XGTagAPI.swift ├── XGTagCell.swift ├── XGTagCell.xib └── XGTagViewController.swift /.gitignore: -------------------------------------------------------------------------------- 1 | *.framework/* 2 | *.dylib 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 稀土掘金客户端 for iOS 2 | 3 | 本 App 将持续开发,现阶段可能存在少量 Bug,欢迎大家测试。 4 | 5 | ## 功能 6 | 7 | * 提供所有浏览功能(暂不支持需要登录的操作) 8 | * 支持应用内搜索 9 | * 支持按不同排序方式和分类浏览 10 | * 支持 **3D Touch** 预览 11 | * 支持使用内建 **Safari View Controller** 打开文章链接 12 | 13 | ## 项目依赖 14 | 15 | * [RxSwift](https://github.com/ReactiveX/RxSwift) 16 | * [LeanCloud SDK](https://leancloud.cn) 17 | 18 | ## 版权声明 19 | 20 | * 使用本 App 浏览的所有资源均属 [稀土掘金](http://gold.xitu.io/) 所有。 21 | * 本 App 中 Tab Bar 的图标来自 [Yep](https://github.com/CatchChat/Yep) ,如有版权问题请原作者提交 **Issue** ,本人会尽快处理。 22 | 23 | ## 关于我 24 | 25 | 我是一名大一学生,热爱苹果产品,喜欢各种开发。 26 | 27 | > #### 我的相关链接 28 | > Weibo: [@Cyandev](http://weibo.com/2834711045/profile)
29 | > 简书: [Cyandev](http://www.jianshu.com/users/c49454e0ae54/latest_articles) 30 | 31 | 欢迎大家关注! 32 | -------------------------------------------------------------------------------- /Resources/AppIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unixzii/XituGold-iOS/a326d427fff2bb509bb73b88a9b64f347f0f6b9b/Resources/AppIcon.png -------------------------------------------------------------------------------- /Resources/AppIcon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unixzii/XituGold-iOS/a326d427fff2bb509bb73b88a9b64f347f0f6b9b/Resources/AppIcon@2x.png -------------------------------------------------------------------------------- /Resources/AppIcon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unixzii/XituGold-iOS/a326d427fff2bb509bb73b88a9b64f347f0f6b9b/Resources/AppIcon@3x.png -------------------------------------------------------------------------------- /Resources/Design.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unixzii/XituGold-iOS/a326d427fff2bb509bb73b88a9b64f347f0f6b9b/Resources/Design.sketch -------------------------------------------------------------------------------- /Resources/Image-Failed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unixzii/XituGold-iOS/a326d427fff2bb509bb73b88a9b64f347f0f6b9b/Resources/Image-Failed.png -------------------------------------------------------------------------------- /Resources/Image-Failed@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unixzii/XituGold-iOS/a326d427fff2bb509bb73b88a9b64f347f0f6b9b/Resources/Image-Failed@2x.png -------------------------------------------------------------------------------- /Resources/Image-Failed@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unixzii/XituGold-iOS/a326d427fff2bb509bb73b88a9b64f347f0f6b9b/Resources/Image-Failed@3x.png -------------------------------------------------------------------------------- /Resources/Image-Placeholder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unixzii/XituGold-iOS/a326d427fff2bb509bb73b88a9b64f347f0f6b9b/Resources/Image-Placeholder.png -------------------------------------------------------------------------------- /Resources/Image-Placeholder@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unixzii/XituGold-iOS/a326d427fff2bb509bb73b88a9b64f347f0f6b9b/Resources/Image-Placeholder@2x.png -------------------------------------------------------------------------------- /Resources/Image-Placeholder@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unixzii/XituGold-iOS/a326d427fff2bb509bb73b88a9b64f347f0f6b9b/Resources/Image-Placeholder@3x.png -------------------------------------------------------------------------------- /Resources/Logo-Text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unixzii/XituGold-iOS/a326d427fff2bb509bb73b88a9b64f347f0f6b9b/Resources/Logo-Text.png -------------------------------------------------------------------------------- /Resources/Logo-Text@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unixzii/XituGold-iOS/a326d427fff2bb509bb73b88a9b64f347f0f6b9b/Resources/Logo-Text@2x.png -------------------------------------------------------------------------------- /Resources/Logo-Text@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unixzii/XituGold-iOS/a326d427fff2bb509bb73b88a9b64f347f0f6b9b/Resources/Logo-Text@3x.png -------------------------------------------------------------------------------- /Resources/Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unixzii/XituGold-iOS/a326d427fff2bb509bb73b88a9b64f347f0f6b9b/Resources/Logo.png -------------------------------------------------------------------------------- /Resources/Logo@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unixzii/XituGold-iOS/a326d427fff2bb509bb73b88a9b64f347f0f6b9b/Resources/Logo@2x.png -------------------------------------------------------------------------------- /Resources/Logo@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unixzii/XituGold-iOS/a326d427fff2bb509bb73b88a9b64f347f0f6b9b/Resources/Logo@3x.png -------------------------------------------------------------------------------- /Resources/Up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unixzii/XituGold-iOS/a326d427fff2bb509bb73b88a9b64f347f0f6b9b/Resources/Up.png -------------------------------------------------------------------------------- /Resources/Up@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unixzii/XituGold-iOS/a326d427fff2bb509bb73b88a9b64f347f0f6b9b/Resources/Up@2x.png -------------------------------------------------------------------------------- /Resources/Up@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unixzii/XituGold-iOS/a326d427fff2bb509bb73b88a9b64f347f0f6b9b/Resources/Up@3x.png -------------------------------------------------------------------------------- /Resources/juejin-logo.white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | xitu_logo 5 | Created with sketchtool. 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 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /XituGold.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 9D0504D91CC34E39005C4339 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D0504D81CC34E39005C4339 /* AppDelegate.swift */; }; 11 | 9D0504E01CC34E39005C4339 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9D0504DF1CC34E39005C4339 /* Assets.xcassets */; }; 12 | 9D0504E31CC34E39005C4339 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9D0504E11CC34E39005C4339 /* LaunchScreen.storyboard */; }; 13 | 9D0504EE1CC3528C005C4339 /* XGTabBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D0504ED1CC3528C005C4339 /* XGTabBarController.swift */; }; 14 | 9D0505061CC35573005C4339 /* AVOSCloud.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D0505041CC35533005C4339 /* AVOSCloud.framework */; }; 15 | 9D0505071CC35573005C4339 /* AVOSCloud.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9D0505041CC35533005C4339 /* AVOSCloud.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 16 | 9D05050C1CC35580005C4339 /* RxBlocking.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D0505091CC35580005C4339 /* RxBlocking.framework */; }; 17 | 9D05050E1CC35580005C4339 /* RxSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D05050B1CC35580005C4339 /* RxSwift.framework */; }; 18 | 9D0505101CC35588005C4339 /* RxBlocking.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9D0505091CC35580005C4339 /* RxBlocking.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 19 | 9D0505111CC35588005C4339 /* RxCocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D05050A1CC35580005C4339 /* RxCocoa.framework */; }; 20 | 9D0505121CC35588005C4339 /* RxCocoa.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9D05050A1CC35580005C4339 /* RxCocoa.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 21 | 9D0505141CC35588005C4339 /* RxSwift.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9D05050B1CC35580005C4339 /* RxSwift.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 22 | 9D0505161CC35590005C4339 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D0505151CC3558F005C4339 /* SystemConfiguration.framework */; }; 23 | 9D0505181CC35595005C4339 /* CoreTelephony.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D0505171CC35595005C4339 /* CoreTelephony.framework */; }; 24 | 9D05051A1CC3559B005C4339 /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D0505191CC3559B005C4339 /* CoreLocation.framework */; }; 25 | 9D05051C1CC355AB005C4339 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D05051B1CC355AB005C4339 /* MobileCoreServices.framework */; }; 26 | 9D05051F1CC35606005C4339 /* XGNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D05051E1CC35606005C4339 /* XGNavigationController.swift */; }; 27 | 9D0505211CC357B8005C4339 /* XGExplorerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D0505201CC357B8005C4339 /* XGExplorerViewController.swift */; }; 28 | 9D0505241CC35892005C4339 /* UIImage+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D0505231CC35892005C4339 /* UIImage+Helpers.swift */; }; 29 | 9D0505271CC35AD2005C4339 /* XGEntryTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D0505261CC35AD2005C4339 /* XGEntryTableViewController.swift */; }; 30 | 9D0505291CC35B12005C4339 /* XGTagViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D0505281CC35B12005C4339 /* XGTagViewController.swift */; }; 31 | 9D05052C1CC35ED0005C4339 /* XGEntry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D05052B1CC35ED0005C4339 /* XGEntry.swift */; }; 32 | 9D05052F1CC36026005C4339 /* XGEntryAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D05052E1CC36026005C4339 /* XGEntryAPI.swift */; }; 33 | 9D0505321CC36046005C4339 /* XGConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D0505311CC36046005C4339 /* XGConfig.swift */; }; 34 | 9D0505361CC363A3005C4339 /* XGEntryCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D0505341CC363A3005C4339 /* XGEntryCell.swift */; }; 35 | 9D0505371CC363A3005C4339 /* XGEntryCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9D0505351CC363A3005C4339 /* XGEntryCell.xib */; }; 36 | 9D0505391CC36FD0005C4339 /* NSDate+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D0505381CC36FD0005C4339 /* NSDate+Helpers.swift */; }; 37 | 9D4B93581CC3C71F0098FB5A /* SMNetworkActivityController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D4B93571CC3C71F0098FB5A /* SMNetworkActivityController.swift */; }; 38 | 9D4B935A1CC3C8520098FB5A /* XGFilterViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D4B93591CC3C8520098FB5A /* XGFilterViewController.swift */; }; 39 | 9D4B935D1CC3CDDB0098FB5A /* XGFilterCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D4B935B1CC3CDDB0098FB5A /* XGFilterCell.swift */; }; 40 | 9D4B935E1CC3CDDB0098FB5A /* XGFilterCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9D4B935C1CC3CDDB0098FB5A /* XGFilterCell.xib */; }; 41 | 9D4B93611CC3CEB40098FB5A /* XGGroupTitleReusableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D4B935F1CC3CEB40098FB5A /* XGGroupTitleReusableView.swift */; }; 42 | 9D4B93621CC3CEB40098FB5A /* XGGroupTitleReusableView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9D4B93601CC3CEB40098FB5A /* XGGroupTitleReusableView.xib */; }; 43 | 9DA89D181CC7654600506D48 /* XGLoadableImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DA89D171CC7654600506D48 /* XGLoadableImageView.swift */; }; 44 | 9DA89D1A1CC7697700506D48 /* XGImageCacheController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DA89D191CC7697700506D48 /* XGImageCacheController.swift */; }; 45 | 9DA89D1C1CC77B4600506D48 /* XGTag.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DA89D1B1CC77B4600506D48 /* XGTag.swift */; }; 46 | 9DA89D1E1CC77BCF00506D48 /* XGTagAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DA89D1D1CC77BCF00506D48 /* XGTagAPI.swift */; }; 47 | 9DA89D211CC77D9000506D48 /* XGTagCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DA89D1F1CC77D9000506D48 /* XGTagCell.swift */; }; 48 | 9DA89D221CC77D9000506D48 /* XGTagCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9DA89D201CC77D9000506D48 /* XGTagCell.xib */; }; 49 | 9DA89D241CC77F6500506D48 /* UIViewController+Alert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DA89D231CC77F6500506D48 /* UIViewController+Alert.swift */; }; 50 | /* End PBXBuildFile section */ 51 | 52 | /* Begin PBXCopyFilesBuildPhase section */ 53 | 9D0505081CC35573005C4339 /* Embed Frameworks */ = { 54 | isa = PBXCopyFilesBuildPhase; 55 | buildActionMask = 2147483647; 56 | dstPath = ""; 57 | dstSubfolderSpec = 10; 58 | files = ( 59 | 9D0505141CC35588005C4339 /* RxSwift.framework in Embed Frameworks */, 60 | 9D0505121CC35588005C4339 /* RxCocoa.framework in Embed Frameworks */, 61 | 9D0505071CC35573005C4339 /* AVOSCloud.framework in Embed Frameworks */, 62 | 9D0505101CC35588005C4339 /* RxBlocking.framework in Embed Frameworks */, 63 | ); 64 | name = "Embed Frameworks"; 65 | runOnlyForDeploymentPostprocessing = 0; 66 | }; 67 | /* End PBXCopyFilesBuildPhase section */ 68 | 69 | /* Begin PBXFileReference section */ 70 | 9D0504D51CC34E39005C4339 /* XituGold.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = XituGold.app; sourceTree = BUILT_PRODUCTS_DIR; }; 71 | 9D0504D81CC34E39005C4339 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 72 | 9D0504DF1CC34E39005C4339 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 73 | 9D0504E21CC34E39005C4339 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 74 | 9D0504E41CC34E39005C4339 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 75 | 9D0504ED1CC3528C005C4339 /* XGTabBarController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XGTabBarController.swift; sourceTree = ""; }; 76 | 9D0505041CC35533005C4339 /* AVOSCloud.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = AVOSCloud.framework; sourceTree = ""; }; 77 | 9D0505091CC35580005C4339 /* RxBlocking.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = RxBlocking.framework; sourceTree = ""; }; 78 | 9D05050A1CC35580005C4339 /* RxCocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = RxCocoa.framework; sourceTree = ""; }; 79 | 9D05050B1CC35580005C4339 /* RxSwift.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = RxSwift.framework; sourceTree = ""; }; 80 | 9D0505151CC3558F005C4339 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; 81 | 9D0505171CC35595005C4339 /* CoreTelephony.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreTelephony.framework; path = System/Library/Frameworks/CoreTelephony.framework; sourceTree = SDKROOT; }; 82 | 9D0505191CC3559B005C4339 /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = System/Library/Frameworks/CoreLocation.framework; sourceTree = SDKROOT; }; 83 | 9D05051B1CC355AB005C4339 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; }; 84 | 9D05051E1CC35606005C4339 /* XGNavigationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XGNavigationController.swift; sourceTree = ""; }; 85 | 9D0505201CC357B8005C4339 /* XGExplorerViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XGExplorerViewController.swift; sourceTree = ""; }; 86 | 9D0505231CC35892005C4339 /* UIImage+Helpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImage+Helpers.swift"; sourceTree = ""; }; 87 | 9D0505261CC35AD2005C4339 /* XGEntryTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XGEntryTableViewController.swift; sourceTree = ""; }; 88 | 9D0505281CC35B12005C4339 /* XGTagViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XGTagViewController.swift; sourceTree = ""; }; 89 | 9D05052B1CC35ED0005C4339 /* XGEntry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XGEntry.swift; sourceTree = ""; }; 90 | 9D05052E1CC36026005C4339 /* XGEntryAPI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XGEntryAPI.swift; sourceTree = ""; }; 91 | 9D0505311CC36046005C4339 /* XGConfig.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XGConfig.swift; sourceTree = ""; }; 92 | 9D0505341CC363A3005C4339 /* XGEntryCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XGEntryCell.swift; sourceTree = ""; }; 93 | 9D0505351CC363A3005C4339 /* XGEntryCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = XGEntryCell.xib; sourceTree = ""; }; 94 | 9D0505381CC36FD0005C4339 /* NSDate+Helpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSDate+Helpers.swift"; sourceTree = ""; }; 95 | 9D4B93571CC3C71F0098FB5A /* SMNetworkActivityController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SMNetworkActivityController.swift; sourceTree = ""; }; 96 | 9D4B93591CC3C8520098FB5A /* XGFilterViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XGFilterViewController.swift; sourceTree = ""; }; 97 | 9D4B935B1CC3CDDB0098FB5A /* XGFilterCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XGFilterCell.swift; sourceTree = ""; }; 98 | 9D4B935C1CC3CDDB0098FB5A /* XGFilterCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = XGFilterCell.xib; sourceTree = ""; }; 99 | 9D4B935F1CC3CEB40098FB5A /* XGGroupTitleReusableView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XGGroupTitleReusableView.swift; sourceTree = ""; }; 100 | 9D4B93601CC3CEB40098FB5A /* XGGroupTitleReusableView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = XGGroupTitleReusableView.xib; sourceTree = ""; }; 101 | 9DA89D171CC7654600506D48 /* XGLoadableImageView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XGLoadableImageView.swift; sourceTree = ""; }; 102 | 9DA89D191CC7697700506D48 /* XGImageCacheController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XGImageCacheController.swift; sourceTree = ""; }; 103 | 9DA89D1B1CC77B4600506D48 /* XGTag.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XGTag.swift; sourceTree = ""; }; 104 | 9DA89D1D1CC77BCF00506D48 /* XGTagAPI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XGTagAPI.swift; sourceTree = ""; }; 105 | 9DA89D1F1CC77D9000506D48 /* XGTagCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XGTagCell.swift; sourceTree = ""; }; 106 | 9DA89D201CC77D9000506D48 /* XGTagCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = XGTagCell.xib; sourceTree = ""; }; 107 | 9DA89D231CC77F6500506D48 /* UIViewController+Alert.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIViewController+Alert.swift"; sourceTree = ""; }; 108 | /* End PBXFileReference section */ 109 | 110 | /* Begin PBXFrameworksBuildPhase section */ 111 | 9D0504D21CC34E39005C4339 /* Frameworks */ = { 112 | isa = PBXFrameworksBuildPhase; 113 | buildActionMask = 2147483647; 114 | files = ( 115 | 9D05051C1CC355AB005C4339 /* MobileCoreServices.framework in Frameworks */, 116 | 9D05051A1CC3559B005C4339 /* CoreLocation.framework in Frameworks */, 117 | 9D0505181CC35595005C4339 /* CoreTelephony.framework in Frameworks */, 118 | 9D0505161CC35590005C4339 /* SystemConfiguration.framework in Frameworks */, 119 | 9D05050E1CC35580005C4339 /* RxSwift.framework in Frameworks */, 120 | 9D0505111CC35588005C4339 /* RxCocoa.framework in Frameworks */, 121 | 9D0505061CC35573005C4339 /* AVOSCloud.framework in Frameworks */, 122 | 9D05050C1CC35580005C4339 /* RxBlocking.framework in Frameworks */, 123 | ); 124 | runOnlyForDeploymentPostprocessing = 0; 125 | }; 126 | /* End PBXFrameworksBuildPhase section */ 127 | 128 | /* Begin PBXGroup section */ 129 | 9D0504CC1CC34E39005C4339 = { 130 | isa = PBXGroup; 131 | children = ( 132 | 9D0504D71CC34E39005C4339 /* XituGold */, 133 | 9D0504EB1CC34E64005C4339 /* Frameworks */, 134 | 9D0504D61CC34E39005C4339 /* Products */, 135 | ); 136 | sourceTree = ""; 137 | }; 138 | 9D0504D61CC34E39005C4339 /* Products */ = { 139 | isa = PBXGroup; 140 | children = ( 141 | 9D0504D51CC34E39005C4339 /* XituGold.app */, 142 | ); 143 | name = Products; 144 | sourceTree = ""; 145 | }; 146 | 9D0504D71CC34E39005C4339 /* XituGold */ = { 147 | isa = PBXGroup; 148 | children = ( 149 | 9D0505301CC3603C005C4339 /* Config */, 150 | 9D0505221CC35870005C4339 /* Extension */, 151 | 9D05052D1CC36015005C4339 /* API */, 152 | 9D05052A1CC35EB0005C4339 /* Model */, 153 | 9D0505331CC36380005C4339 /* View */, 154 | 9D4B93561CC3C6FE0098FB5A /* Controller */, 155 | 9D0504EC1CC35226005C4339 /* View Controller */, 156 | 9D0504EA1CC34E51005C4339 /* Supporting Files */, 157 | ); 158 | path = XituGold; 159 | sourceTree = ""; 160 | }; 161 | 9D0504EA1CC34E51005C4339 /* Supporting Files */ = { 162 | isa = PBXGroup; 163 | children = ( 164 | 9D0504D81CC34E39005C4339 /* AppDelegate.swift */, 165 | 9D0504DF1CC34E39005C4339 /* Assets.xcassets */, 166 | 9D0504E11CC34E39005C4339 /* LaunchScreen.storyboard */, 167 | 9D0504E41CC34E39005C4339 /* Info.plist */, 168 | ); 169 | name = "Supporting Files"; 170 | sourceTree = ""; 171 | }; 172 | 9D0504EB1CC34E64005C4339 /* Frameworks */ = { 173 | isa = PBXGroup; 174 | children = ( 175 | 9D05051B1CC355AB005C4339 /* MobileCoreServices.framework */, 176 | 9D0505191CC3559B005C4339 /* CoreLocation.framework */, 177 | 9D0505171CC35595005C4339 /* CoreTelephony.framework */, 178 | 9D0505151CC3558F005C4339 /* SystemConfiguration.framework */, 179 | 9D0505091CC35580005C4339 /* RxBlocking.framework */, 180 | 9D05050A1CC35580005C4339 /* RxCocoa.framework */, 181 | 9D05050B1CC35580005C4339 /* RxSwift.framework */, 182 | 9D0505041CC35533005C4339 /* AVOSCloud.framework */, 183 | ); 184 | name = Frameworks; 185 | path = XituGold; 186 | sourceTree = ""; 187 | }; 188 | 9D0504EC1CC35226005C4339 /* View Controller */ = { 189 | isa = PBXGroup; 190 | children = ( 191 | 9D0505251CC35AAD005C4339 /* Reusable */, 192 | 9D05051D1CC355EE005C4339 /* Base */, 193 | 9D0504ED1CC3528C005C4339 /* XGTabBarController.swift */, 194 | 9D0505201CC357B8005C4339 /* XGExplorerViewController.swift */, 195 | 9D0505281CC35B12005C4339 /* XGTagViewController.swift */, 196 | 9D4B93591CC3C8520098FB5A /* XGFilterViewController.swift */, 197 | ); 198 | name = "View Controller"; 199 | sourceTree = ""; 200 | }; 201 | 9D05051D1CC355EE005C4339 /* Base */ = { 202 | isa = PBXGroup; 203 | children = ( 204 | 9D05051E1CC35606005C4339 /* XGNavigationController.swift */, 205 | ); 206 | name = Base; 207 | sourceTree = ""; 208 | }; 209 | 9D0505221CC35870005C4339 /* Extension */ = { 210 | isa = PBXGroup; 211 | children = ( 212 | 9D0505231CC35892005C4339 /* UIImage+Helpers.swift */, 213 | 9D0505381CC36FD0005C4339 /* NSDate+Helpers.swift */, 214 | 9DA89D231CC77F6500506D48 /* UIViewController+Alert.swift */, 215 | ); 216 | name = Extension; 217 | sourceTree = ""; 218 | }; 219 | 9D0505251CC35AAD005C4339 /* Reusable */ = { 220 | isa = PBXGroup; 221 | children = ( 222 | 9D0505261CC35AD2005C4339 /* XGEntryTableViewController.swift */, 223 | ); 224 | name = Reusable; 225 | sourceTree = ""; 226 | }; 227 | 9D05052A1CC35EB0005C4339 /* Model */ = { 228 | isa = PBXGroup; 229 | children = ( 230 | 9D05052B1CC35ED0005C4339 /* XGEntry.swift */, 231 | 9DA89D1B1CC77B4600506D48 /* XGTag.swift */, 232 | ); 233 | name = Model; 234 | sourceTree = ""; 235 | }; 236 | 9D05052D1CC36015005C4339 /* API */ = { 237 | isa = PBXGroup; 238 | children = ( 239 | 9D05052E1CC36026005C4339 /* XGEntryAPI.swift */, 240 | 9DA89D1D1CC77BCF00506D48 /* XGTagAPI.swift */, 241 | ); 242 | name = API; 243 | sourceTree = ""; 244 | }; 245 | 9D0505301CC3603C005C4339 /* Config */ = { 246 | isa = PBXGroup; 247 | children = ( 248 | 9D0505311CC36046005C4339 /* XGConfig.swift */, 249 | ); 250 | name = Config; 251 | sourceTree = ""; 252 | }; 253 | 9D0505331CC36380005C4339 /* View */ = { 254 | isa = PBXGroup; 255 | children = ( 256 | 9DA89D171CC7654600506D48 /* XGLoadableImageView.swift */, 257 | 9DA89D151CC7651B00506D48 /* Cell */, 258 | ); 259 | name = View; 260 | sourceTree = ""; 261 | }; 262 | 9D4B93561CC3C6FE0098FB5A /* Controller */ = { 263 | isa = PBXGroup; 264 | children = ( 265 | 9D4B93571CC3C71F0098FB5A /* SMNetworkActivityController.swift */, 266 | 9DA89D191CC7697700506D48 /* XGImageCacheController.swift */, 267 | ); 268 | name = Controller; 269 | sourceTree = ""; 270 | }; 271 | 9DA89D151CC7651B00506D48 /* Cell */ = { 272 | isa = PBXGroup; 273 | children = ( 274 | 9D0505341CC363A3005C4339 /* XGEntryCell.swift */, 275 | 9D0505351CC363A3005C4339 /* XGEntryCell.xib */, 276 | 9D4B935B1CC3CDDB0098FB5A /* XGFilterCell.swift */, 277 | 9D4B935C1CC3CDDB0098FB5A /* XGFilterCell.xib */, 278 | 9D4B935F1CC3CEB40098FB5A /* XGGroupTitleReusableView.swift */, 279 | 9D4B93601CC3CEB40098FB5A /* XGGroupTitleReusableView.xib */, 280 | 9DA89D1F1CC77D9000506D48 /* XGTagCell.swift */, 281 | 9DA89D201CC77D9000506D48 /* XGTagCell.xib */, 282 | ); 283 | name = Cell; 284 | sourceTree = ""; 285 | }; 286 | /* End PBXGroup section */ 287 | 288 | /* Begin PBXNativeTarget section */ 289 | 9D0504D41CC34E39005C4339 /* XituGold */ = { 290 | isa = PBXNativeTarget; 291 | buildConfigurationList = 9D0504E71CC34E39005C4339 /* Build configuration list for PBXNativeTarget "XituGold" */; 292 | buildPhases = ( 293 | 9D0504D11CC34E39005C4339 /* Sources */, 294 | 9D0504D21CC34E39005C4339 /* Frameworks */, 295 | 9D0504D31CC34E39005C4339 /* Resources */, 296 | 9D0505081CC35573005C4339 /* Embed Frameworks */, 297 | ); 298 | buildRules = ( 299 | ); 300 | dependencies = ( 301 | ); 302 | name = XituGold; 303 | productName = XituGold; 304 | productReference = 9D0504D51CC34E39005C4339 /* XituGold.app */; 305 | productType = "com.apple.product-type.application"; 306 | }; 307 | /* End PBXNativeTarget section */ 308 | 309 | /* Begin PBXProject section */ 310 | 9D0504CD1CC34E39005C4339 /* Project object */ = { 311 | isa = PBXProject; 312 | attributes = { 313 | LastSwiftUpdateCheck = 0730; 314 | LastUpgradeCheck = 0730; 315 | ORGANIZATIONNAME = Cyandev; 316 | TargetAttributes = { 317 | 9D0504D41CC34E39005C4339 = { 318 | CreatedOnToolsVersion = 7.3; 319 | DevelopmentTeam = S8ZP685HLU; 320 | }; 321 | }; 322 | }; 323 | buildConfigurationList = 9D0504D01CC34E39005C4339 /* Build configuration list for PBXProject "XituGold" */; 324 | compatibilityVersion = "Xcode 3.2"; 325 | developmentRegion = English; 326 | hasScannedForEncodings = 0; 327 | knownRegions = ( 328 | en, 329 | Base, 330 | ); 331 | mainGroup = 9D0504CC1CC34E39005C4339; 332 | productRefGroup = 9D0504D61CC34E39005C4339 /* Products */; 333 | projectDirPath = ""; 334 | projectRoot = ""; 335 | targets = ( 336 | 9D0504D41CC34E39005C4339 /* XituGold */, 337 | ); 338 | }; 339 | /* End PBXProject section */ 340 | 341 | /* Begin PBXResourcesBuildPhase section */ 342 | 9D0504D31CC34E39005C4339 /* Resources */ = { 343 | isa = PBXResourcesBuildPhase; 344 | buildActionMask = 2147483647; 345 | files = ( 346 | 9D4B93621CC3CEB40098FB5A /* XGGroupTitleReusableView.xib in Resources */, 347 | 9DA89D221CC77D9000506D48 /* XGTagCell.xib in Resources */, 348 | 9D0504E31CC34E39005C4339 /* LaunchScreen.storyboard in Resources */, 349 | 9D0504E01CC34E39005C4339 /* Assets.xcassets in Resources */, 350 | 9D4B935E1CC3CDDB0098FB5A /* XGFilterCell.xib in Resources */, 351 | 9D0505371CC363A3005C4339 /* XGEntryCell.xib in Resources */, 352 | ); 353 | runOnlyForDeploymentPostprocessing = 0; 354 | }; 355 | /* End PBXResourcesBuildPhase section */ 356 | 357 | /* Begin PBXSourcesBuildPhase section */ 358 | 9D0504D11CC34E39005C4339 /* Sources */ = { 359 | isa = PBXSourcesBuildPhase; 360 | buildActionMask = 2147483647; 361 | files = ( 362 | 9D0505271CC35AD2005C4339 /* XGEntryTableViewController.swift in Sources */, 363 | 9D05052C1CC35ED0005C4339 /* XGEntry.swift in Sources */, 364 | 9DA89D1E1CC77BCF00506D48 /* XGTagAPI.swift in Sources */, 365 | 9D0505211CC357B8005C4339 /* XGExplorerViewController.swift in Sources */, 366 | 9D4B93581CC3C71F0098FB5A /* SMNetworkActivityController.swift in Sources */, 367 | 9DA89D181CC7654600506D48 /* XGLoadableImageView.swift in Sources */, 368 | 9DA89D1A1CC7697700506D48 /* XGImageCacheController.swift in Sources */, 369 | 9D0504EE1CC3528C005C4339 /* XGTabBarController.swift in Sources */, 370 | 9D4B93611CC3CEB40098FB5A /* XGGroupTitleReusableView.swift in Sources */, 371 | 9DA89D1C1CC77B4600506D48 /* XGTag.swift in Sources */, 372 | 9D05051F1CC35606005C4339 /* XGNavigationController.swift in Sources */, 373 | 9D0505361CC363A3005C4339 /* XGEntryCell.swift in Sources */, 374 | 9D0505241CC35892005C4339 /* UIImage+Helpers.swift in Sources */, 375 | 9D0505321CC36046005C4339 /* XGConfig.swift in Sources */, 376 | 9D0504D91CC34E39005C4339 /* AppDelegate.swift in Sources */, 377 | 9DA89D241CC77F6500506D48 /* UIViewController+Alert.swift in Sources */, 378 | 9D0505291CC35B12005C4339 /* XGTagViewController.swift in Sources */, 379 | 9D05052F1CC36026005C4339 /* XGEntryAPI.swift in Sources */, 380 | 9D0505391CC36FD0005C4339 /* NSDate+Helpers.swift in Sources */, 381 | 9D4B935A1CC3C8520098FB5A /* XGFilterViewController.swift in Sources */, 382 | 9DA89D211CC77D9000506D48 /* XGTagCell.swift in Sources */, 383 | 9D4B935D1CC3CDDB0098FB5A /* XGFilterCell.swift in Sources */, 384 | ); 385 | runOnlyForDeploymentPostprocessing = 0; 386 | }; 387 | /* End PBXSourcesBuildPhase section */ 388 | 389 | /* Begin PBXVariantGroup section */ 390 | 9D0504E11CC34E39005C4339 /* LaunchScreen.storyboard */ = { 391 | isa = PBXVariantGroup; 392 | children = ( 393 | 9D0504E21CC34E39005C4339 /* Base */, 394 | ); 395 | name = LaunchScreen.storyboard; 396 | sourceTree = ""; 397 | }; 398 | /* End PBXVariantGroup section */ 399 | 400 | /* Begin XCBuildConfiguration section */ 401 | 9D0504E51CC34E39005C4339 /* Debug */ = { 402 | isa = XCBuildConfiguration; 403 | buildSettings = { 404 | ALWAYS_SEARCH_USER_PATHS = NO; 405 | CLANG_ANALYZER_NONNULL = YES; 406 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 407 | CLANG_CXX_LIBRARY = "libc++"; 408 | CLANG_ENABLE_MODULES = YES; 409 | CLANG_ENABLE_OBJC_ARC = YES; 410 | CLANG_WARN_BOOL_CONVERSION = YES; 411 | CLANG_WARN_CONSTANT_CONVERSION = YES; 412 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 413 | CLANG_WARN_EMPTY_BODY = YES; 414 | CLANG_WARN_ENUM_CONVERSION = YES; 415 | CLANG_WARN_INT_CONVERSION = YES; 416 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 417 | CLANG_WARN_UNREACHABLE_CODE = YES; 418 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 419 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 420 | COPY_PHASE_STRIP = NO; 421 | DEBUG_INFORMATION_FORMAT = dwarf; 422 | ENABLE_STRICT_OBJC_MSGSEND = YES; 423 | ENABLE_TESTABILITY = YES; 424 | GCC_C_LANGUAGE_STANDARD = gnu99; 425 | GCC_DYNAMIC_NO_PIC = NO; 426 | GCC_NO_COMMON_BLOCKS = YES; 427 | GCC_OPTIMIZATION_LEVEL = 0; 428 | GCC_PREPROCESSOR_DEFINITIONS = ( 429 | "DEBUG=1", 430 | "$(inherited)", 431 | ); 432 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 433 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 434 | GCC_WARN_UNDECLARED_SELECTOR = YES; 435 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 436 | GCC_WARN_UNUSED_FUNCTION = YES; 437 | GCC_WARN_UNUSED_VARIABLE = YES; 438 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 439 | MTL_ENABLE_DEBUG_INFO = YES; 440 | ONLY_ACTIVE_ARCH = YES; 441 | SDKROOT = iphoneos; 442 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 443 | }; 444 | name = Debug; 445 | }; 446 | 9D0504E61CC34E39005C4339 /* Release */ = { 447 | isa = XCBuildConfiguration; 448 | buildSettings = { 449 | ALWAYS_SEARCH_USER_PATHS = NO; 450 | CLANG_ANALYZER_NONNULL = YES; 451 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 452 | CLANG_CXX_LIBRARY = "libc++"; 453 | CLANG_ENABLE_MODULES = YES; 454 | CLANG_ENABLE_OBJC_ARC = YES; 455 | CLANG_WARN_BOOL_CONVERSION = YES; 456 | CLANG_WARN_CONSTANT_CONVERSION = YES; 457 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 458 | CLANG_WARN_EMPTY_BODY = YES; 459 | CLANG_WARN_ENUM_CONVERSION = YES; 460 | CLANG_WARN_INT_CONVERSION = YES; 461 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 462 | CLANG_WARN_UNREACHABLE_CODE = YES; 463 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 464 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 465 | COPY_PHASE_STRIP = NO; 466 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 467 | ENABLE_NS_ASSERTIONS = NO; 468 | ENABLE_STRICT_OBJC_MSGSEND = YES; 469 | GCC_C_LANGUAGE_STANDARD = gnu99; 470 | GCC_NO_COMMON_BLOCKS = YES; 471 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 472 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 473 | GCC_WARN_UNDECLARED_SELECTOR = YES; 474 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 475 | GCC_WARN_UNUSED_FUNCTION = YES; 476 | GCC_WARN_UNUSED_VARIABLE = YES; 477 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 478 | MTL_ENABLE_DEBUG_INFO = NO; 479 | SDKROOT = iphoneos; 480 | VALIDATE_PRODUCT = YES; 481 | }; 482 | name = Release; 483 | }; 484 | 9D0504E81CC34E39005C4339 /* Debug */ = { 485 | isa = XCBuildConfiguration; 486 | buildSettings = { 487 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 488 | EMBEDDED_CONTENT_CONTAINS_SWIFT = YES; 489 | FRAMEWORK_SEARCH_PATHS = ( 490 | "$(inherited)", 491 | "$(PROJECT_DIR)/XituGold", 492 | ); 493 | INFOPLIST_FILE = XituGold/Info.plist; 494 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 495 | OTHER_LDFLAGS = ( 496 | "-licucore", 497 | "-lz", 498 | "-ObjC", 499 | "-lsqlite3", 500 | "-lc++", 501 | ); 502 | PRODUCT_BUNDLE_IDENTIFIER = com.cyandev.XituGold; 503 | PRODUCT_NAME = "$(TARGET_NAME)"; 504 | }; 505 | name = Debug; 506 | }; 507 | 9D0504E91CC34E39005C4339 /* Release */ = { 508 | isa = XCBuildConfiguration; 509 | buildSettings = { 510 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 511 | EMBEDDED_CONTENT_CONTAINS_SWIFT = YES; 512 | FRAMEWORK_SEARCH_PATHS = ( 513 | "$(inherited)", 514 | "$(PROJECT_DIR)/XituGold", 515 | ); 516 | INFOPLIST_FILE = XituGold/Info.plist; 517 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 518 | OTHER_LDFLAGS = ( 519 | "-licucore", 520 | "-lz", 521 | "-ObjC", 522 | "-lsqlite3", 523 | "-lc++", 524 | ); 525 | PRODUCT_BUNDLE_IDENTIFIER = com.cyandev.XituGold; 526 | PRODUCT_NAME = "$(TARGET_NAME)"; 527 | }; 528 | name = Release; 529 | }; 530 | /* End XCBuildConfiguration section */ 531 | 532 | /* Begin XCConfigurationList section */ 533 | 9D0504D01CC34E39005C4339 /* Build configuration list for PBXProject "XituGold" */ = { 534 | isa = XCConfigurationList; 535 | buildConfigurations = ( 536 | 9D0504E51CC34E39005C4339 /* Debug */, 537 | 9D0504E61CC34E39005C4339 /* Release */, 538 | ); 539 | defaultConfigurationIsVisible = 0; 540 | defaultConfigurationName = Release; 541 | }; 542 | 9D0504E71CC34E39005C4339 /* Build configuration list for PBXNativeTarget "XituGold" */ = { 543 | isa = XCConfigurationList; 544 | buildConfigurations = ( 545 | 9D0504E81CC34E39005C4339 /* Debug */, 546 | 9D0504E91CC34E39005C4339 /* Release */, 547 | ); 548 | defaultConfigurationIsVisible = 0; 549 | defaultConfigurationName = Release; 550 | }; 551 | /* End XCConfigurationList section */ 552 | }; 553 | rootObject = 9D0504CD1CC34E39005C4339 /* Project object */; 554 | } 555 | -------------------------------------------------------------------------------- /XituGold.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /XituGold.xcodeproj/project.xcworkspace/xcuserdata/unixzii.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unixzii/XituGold-iOS/a326d427fff2bb509bb73b88a9b64f347f0f6b9b/XituGold.xcodeproj/project.xcworkspace/xcuserdata/unixzii.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /XituGold.xcodeproj/xcuserdata/unixzii.xcuserdatad/xcschemes/XituGold.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /XituGold.xcodeproj/xcuserdata/unixzii.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | XituGold.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 9D0504D41CC34E39005C4339 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /XituGold.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /XituGold.xcworkspace/xcuserdata/unixzii.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unixzii/XituGold-iOS/a326d427fff2bb509bb73b88a9b64f347f0f6b9b/XituGold.xcworkspace/xcuserdata/unixzii.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /XituGold.xcworkspace/xcuserdata/unixzii.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /XituGold/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // XituGold 4 | // 5 | // Created by 杨弘宇 on 16/4/17. 6 | // Copyright © 2016年 Cyandev. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import AVOSCloud 11 | 12 | @UIApplicationMain 13 | class AppDelegate: UIResponder, UIApplicationDelegate { 14 | 15 | var window: UIWindow? 16 | 17 | 18 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 19 | // Override point for customization after application launch. 20 | 21 | self.window = UIWindow(frame: UIScreen.mainScreen().bounds) 22 | self.window?.rootViewController = XGNavigationController(rootViewController: XGTabBarController()) 23 | 24 | self.customizeAppearance() 25 | 26 | self.window?.makeKeyAndVisible() 27 | 28 | AVOSCloud.setApplicationId(XGAppId, clientKey: XGAppKey) 29 | 30 | return true 31 | } 32 | 33 | func applicationWillResignActive(application: UIApplication) { 34 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 35 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 36 | } 37 | 38 | func applicationDidEnterBackground(application: UIApplication) { 39 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 40 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 41 | } 42 | 43 | func applicationWillEnterForeground(application: UIApplication) { 44 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 45 | } 46 | 47 | func applicationDidBecomeActive(application: UIApplication) { 48 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 49 | } 50 | 51 | func applicationWillTerminate(application: UIApplication) { 52 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 53 | } 54 | 55 | func applicationDidReceiveMemoryWarning(application: UIApplication) { 56 | XGImageCacheController.sharedController.clearCache() 57 | } 58 | 59 | func customizeAppearance() { 60 | let navigationBar = UINavigationBar.appearance() 61 | navigationBar.backgroundColor = UIColor.whiteColor() 62 | navigationBar.barTintColor = XGGlobalTintColor 63 | navigationBar.shadowImage = UIImage.imageFilledWithColor(UIColor.clearColor()) 64 | navigationBar.tintColor = UIColor.lightTextColor() 65 | navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.whiteColor()] 66 | 67 | let tabBar = UITabBar.appearance() 68 | tabBar.tintColor = XGGlobalTintColor 69 | } 70 | 71 | } 72 | 73 | -------------------------------------------------------------------------------- /XituGold/Assets.xcassets/AppIcon.appiconset/AppIcon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unixzii/XituGold-iOS/a326d427fff2bb509bb73b88a9b64f347f0f6b9b/XituGold/Assets.xcassets/AppIcon.appiconset/AppIcon@2x.png -------------------------------------------------------------------------------- /XituGold/Assets.xcassets/AppIcon.appiconset/AppIcon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unixzii/XituGold-iOS/a326d427fff2bb509bb73b88a9b64f347f0f6b9b/XituGold/Assets.xcassets/AppIcon.appiconset/AppIcon@3x.png -------------------------------------------------------------------------------- /XituGold/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "size" : "60x60", 25 | "idiom" : "iphone", 26 | "filename" : "AppIcon@2x.png", 27 | "scale" : "2x" 28 | }, 29 | { 30 | "size" : "60x60", 31 | "idiom" : "iphone", 32 | "filename" : "AppIcon@3x.png", 33 | "scale" : "3x" 34 | } 35 | ], 36 | "info" : { 37 | "version" : 1, 38 | "author" : "xcode" 39 | } 40 | } -------------------------------------------------------------------------------- /XituGold/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /XituGold/Assets.xcassets/Image-Failed.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Image-Failed.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Image-Failed@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Image-Failed@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /XituGold/Assets.xcassets/Image-Failed.imageset/Image-Failed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unixzii/XituGold-iOS/a326d427fff2bb509bb73b88a9b64f347f0f6b9b/XituGold/Assets.xcassets/Image-Failed.imageset/Image-Failed.png -------------------------------------------------------------------------------- /XituGold/Assets.xcassets/Image-Failed.imageset/Image-Failed@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unixzii/XituGold-iOS/a326d427fff2bb509bb73b88a9b64f347f0f6b9b/XituGold/Assets.xcassets/Image-Failed.imageset/Image-Failed@2x.png -------------------------------------------------------------------------------- /XituGold/Assets.xcassets/Image-Failed.imageset/Image-Failed@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unixzii/XituGold-iOS/a326d427fff2bb509bb73b88a9b64f347f0f6b9b/XituGold/Assets.xcassets/Image-Failed.imageset/Image-Failed@3x.png -------------------------------------------------------------------------------- /XituGold/Assets.xcassets/Image-Placeholder.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Image-Placeholder.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Image-Placeholder@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Image-Placeholder@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /XituGold/Assets.xcassets/Image-Placeholder.imageset/Image-Placeholder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unixzii/XituGold-iOS/a326d427fff2bb509bb73b88a9b64f347f0f6b9b/XituGold/Assets.xcassets/Image-Placeholder.imageset/Image-Placeholder.png -------------------------------------------------------------------------------- /XituGold/Assets.xcassets/Image-Placeholder.imageset/Image-Placeholder@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unixzii/XituGold-iOS/a326d427fff2bb509bb73b88a9b64f347f0f6b9b/XituGold/Assets.xcassets/Image-Placeholder.imageset/Image-Placeholder@2x.png -------------------------------------------------------------------------------- /XituGold/Assets.xcassets/Image-Placeholder.imageset/Image-Placeholder@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unixzii/XituGold-iOS/a326d427fff2bb509bb73b88a9b64f347f0f6b9b/XituGold/Assets.xcassets/Image-Placeholder.imageset/Image-Placeholder@3x.png -------------------------------------------------------------------------------- /XituGold/Assets.xcassets/Logo-Text.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Logo-Text.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Logo-Text@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Logo-Text@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /XituGold/Assets.xcassets/Logo-Text.imageset/Logo-Text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unixzii/XituGold-iOS/a326d427fff2bb509bb73b88a9b64f347f0f6b9b/XituGold/Assets.xcassets/Logo-Text.imageset/Logo-Text.png -------------------------------------------------------------------------------- /XituGold/Assets.xcassets/Logo-Text.imageset/Logo-Text@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unixzii/XituGold-iOS/a326d427fff2bb509bb73b88a9b64f347f0f6b9b/XituGold/Assets.xcassets/Logo-Text.imageset/Logo-Text@2x.png -------------------------------------------------------------------------------- /XituGold/Assets.xcassets/Logo-Text.imageset/Logo-Text@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unixzii/XituGold-iOS/a326d427fff2bb509bb73b88a9b64f347f0f6b9b/XituGold/Assets.xcassets/Logo-Text.imageset/Logo-Text@3x.png -------------------------------------------------------------------------------- /XituGold/Assets.xcassets/Logo.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Logo.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Logo@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Logo@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /XituGold/Assets.xcassets/Logo.imageset/Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unixzii/XituGold-iOS/a326d427fff2bb509bb73b88a9b64f347f0f6b9b/XituGold/Assets.xcassets/Logo.imageset/Logo.png -------------------------------------------------------------------------------- /XituGold/Assets.xcassets/Logo.imageset/Logo@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unixzii/XituGold-iOS/a326d427fff2bb509bb73b88a9b64f347f0f6b9b/XituGold/Assets.xcassets/Logo.imageset/Logo@2x.png -------------------------------------------------------------------------------- /XituGold/Assets.xcassets/Logo.imageset/Logo@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unixzii/XituGold-iOS/a326d427fff2bb509bb73b88a9b64f347f0f6b9b/XituGold/Assets.xcassets/Logo.imageset/Logo@3x.png -------------------------------------------------------------------------------- /XituGold/Assets.xcassets/Up.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Up.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "Up@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "Up@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /XituGold/Assets.xcassets/Up.imageset/Up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unixzii/XituGold-iOS/a326d427fff2bb509bb73b88a9b64f347f0f6b9b/XituGold/Assets.xcassets/Up.imageset/Up.png -------------------------------------------------------------------------------- /XituGold/Assets.xcassets/Up.imageset/Up@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unixzii/XituGold-iOS/a326d427fff2bb509bb73b88a9b64f347f0f6b9b/XituGold/Assets.xcassets/Up.imageset/Up@2x.png -------------------------------------------------------------------------------- /XituGold/Assets.xcassets/Up.imageset/Up@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unixzii/XituGold-iOS/a326d427fff2bb509bb73b88a9b64f347f0f6b9b/XituGold/Assets.xcassets/Up.imageset/Up@3x.png -------------------------------------------------------------------------------- /XituGold/Assets.xcassets/icon_explore.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_explore.pdf", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /XituGold/Assets.xcassets/icon_explore.imageset/icon_explore.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unixzii/XituGold-iOS/a326d427fff2bb509bb73b88a9b64f347f0f6b9b/XituGold/Assets.xcassets/icon_explore.imageset/icon_explore.pdf -------------------------------------------------------------------------------- /XituGold/Assets.xcassets/icon_explore_active.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_explore_active.pdf", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /XituGold/Assets.xcassets/icon_explore_active.imageset/icon_explore_active.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unixzii/XituGold-iOS/a326d427fff2bb509bb73b88a9b64f347f0f6b9b/XituGold/Assets.xcassets/icon_explore_active.imageset/icon_explore_active.pdf -------------------------------------------------------------------------------- /XituGold/Assets.xcassets/icon_tags.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_feeds.pdf", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /XituGold/Assets.xcassets/icon_tags.imageset/icon_feeds.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unixzii/XituGold-iOS/a326d427fff2bb509bb73b88a9b64f347f0f6b9b/XituGold/Assets.xcassets/icon_tags.imageset/icon_feeds.pdf -------------------------------------------------------------------------------- /XituGold/Assets.xcassets/icon_tags_active.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icon_feeds_active.pdf", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /XituGold/Assets.xcassets/icon_tags_active.imageset/icon_feeds_active.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unixzii/XituGold-iOS/a326d427fff2bb509bb73b88a9b64f347f0f6b9b/XituGold/Assets.xcassets/icon_tags_active.imageset/icon_feeds_active.pdf -------------------------------------------------------------------------------- /XituGold/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 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /XituGold/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDisplayName 6 | 稀土掘金 7 | UIStatusBarHidden 8 | 9 | CFBundleDevelopmentRegion 10 | zh_CN 11 | CFBundleExecutable 12 | $(EXECUTABLE_NAME) 13 | CFBundleIdentifier 14 | $(PRODUCT_BUNDLE_IDENTIFIER) 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleName 18 | $(PRODUCT_NAME) 19 | CFBundlePackageType 20 | APPL 21 | CFBundleShortVersionString 22 | 1.0 23 | CFBundleSignature 24 | ???? 25 | CFBundleVersion 26 | 1 27 | LSRequiresIPhoneOS 28 | 29 | UILaunchStoryboardName 30 | LaunchScreen 31 | UIMainStoryboardFile 32 | LaunchScreen 33 | UIRequiredDeviceCapabilities 34 | 35 | armv7 36 | 37 | LSApplicationCategoryType 38 | public.app-category.developer-tools 39 | NSAppTransportSecurity 40 | 41 | NSAllowsArbitraryLoads 42 | 43 | 44 | UISupportedInterfaceOrientations 45 | 46 | UIInterfaceOrientationPortrait 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /XituGold/NSDate+Helpers.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NSDate+Helpers.swift 3 | // XituGold 4 | // 5 | // Created by 杨弘宇 on 16/4/17. 6 | // Copyright © 2016年 Cyandev. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | extension NSDate { 12 | 13 | func formattedStringFromThenToNow() -> String { 14 | var timeInterval = NSDate(timeIntervalSinceNow: 0).timeIntervalSinceDate(self) 15 | 16 | if timeInterval < 60 { 17 | return "\(Int(timeInterval))秒" 18 | } 19 | 20 | timeInterval /= 60 21 | if timeInterval < 60 { 22 | return "\(Int(timeInterval))分钟" 23 | } 24 | 25 | timeInterval /= 60 26 | if timeInterval < 24 { 27 | return "\(Int(timeInterval))小时" 28 | } 29 | 30 | timeInterval /= 24 31 | if timeInterval < 30 { 32 | return "\(Int(timeInterval))天" 33 | } 34 | 35 | timeInterval /= 30 36 | if timeInterval < 12 { 37 | return "\(Int(timeInterval))月" 38 | } 39 | 40 | timeInterval /= 12 41 | return "\(Int(timeInterval))年" 42 | } 43 | 44 | } -------------------------------------------------------------------------------- /XituGold/SMNetworkActivityController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SMNetworkActivityController.swift 3 | // XituGold 4 | // 5 | // Created by 杨弘宇 on 16/4/17. 6 | // Copyright © 2016年 Cyandev. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class SMNetworkActivityController { 12 | 13 | static let sharedController = SMNetworkActivityController() 14 | 15 | private enum SMState { 16 | case Invisible 17 | case WillShow 18 | case Visible 19 | case WillHide 20 | } 21 | 22 | private let lock = NSLock() 23 | 24 | private var activityCount = 0 25 | 26 | private var state: SMState = .Invisible { 27 | didSet { 28 | currentCancelable?() 29 | 30 | switch state { 31 | case .Invisible: 32 | UIApplication.sharedApplication().networkActivityIndicatorVisible = false 33 | break 34 | case .WillShow: 35 | currentCancelable = delay(forMilliseconds: 100) { 36 | if self.state == .WillShow { 37 | UIApplication.sharedApplication().networkActivityIndicatorVisible = true 38 | self.state = .Visible 39 | } 40 | } 41 | break 42 | case .Visible: 43 | UIApplication.sharedApplication().networkActivityIndicatorVisible = true 44 | break 45 | case .WillHide: 46 | currentCancelable = delay(forMilliseconds: 300) { 47 | if self.state == .WillHide { 48 | UIApplication.sharedApplication().networkActivityIndicatorVisible = false 49 | self.state = .Invisible 50 | } 51 | } 52 | break 53 | } 54 | } 55 | } 56 | 57 | private var currentCancelable: (Void -> Void)? 58 | 59 | func startActivity() { 60 | performInCriticalZone { 61 | self.activityCount += 1 62 | 63 | return nil 64 | } 65 | 66 | switch state { 67 | case .Invisible: 68 | state = .WillShow 69 | break 70 | case .WillHide: 71 | state = .Visible 72 | break 73 | default: 74 | break 75 | } 76 | } 77 | 78 | func endActivity() { 79 | let count = performInCriticalZone { 80 | self.activityCount -= 1 81 | 82 | if self.activityCount < 0 { 83 | self.activityCount = 0 84 | } 85 | 86 | return self.activityCount 87 | }! as! Int 88 | 89 | if count > 0 { 90 | return 91 | } 92 | 93 | switch state { 94 | case .Visible: 95 | state = .WillHide 96 | break 97 | case .WillShow: 98 | state = .Invisible 99 | break 100 | default: 101 | break 102 | } 103 | 104 | } 105 | 106 | private func delay(forMilliseconds ms: UInt64, action: Void -> Void) -> (Void -> Void) { 107 | var cancelled = false 108 | 109 | let time = dispatch_time(DISPATCH_TIME_NOW, Int64(NSEC_PER_MSEC * ms)) 110 | dispatch_after(time, dispatch_get_main_queue()) { 111 | if !cancelled { 112 | action() 113 | } 114 | } 115 | 116 | return { 117 | cancelled = true 118 | } 119 | } 120 | 121 | private func performInCriticalZone(action: Void -> AnyObject?) -> AnyObject? { 122 | lock.lock() 123 | 124 | defer { 125 | lock.unlock() 126 | } 127 | 128 | return action() 129 | } 130 | 131 | } 132 | -------------------------------------------------------------------------------- /XituGold/UIImage+Helpers.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+Helpers.swift 3 | // XituGold 4 | // 5 | // Created by 杨弘宇 on 16/4/17. 6 | // Copyright © 2016年 Cyandev. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UIImage { 12 | 13 | class func imageFilledWithColor(color: UIColor) -> UIImage { 14 | let size = CGSize(width: 1, height: 1) 15 | 16 | UIGraphicsBeginImageContextWithOptions(size, false, 0) 17 | defer { 18 | UIGraphicsEndImageContext() 19 | } 20 | color.setFill() 21 | CGContextFillRect(UIGraphicsGetCurrentContext(), CGRect(origin: CGPointZero, size: size)) 22 | return UIGraphicsGetImageFromCurrentImageContext() 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /XituGold/UIViewController+Alert.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+Alert.swift 3 | // XituGold 4 | // 5 | // Created by 杨弘宇 on 16/4/20. 6 | // Copyright © 2016年 Cyandev. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UIViewController { 12 | 13 | func showAlertWithTitle(title: String?, message: String?) { 14 | let alert = UIAlertController(title: title, message: message, preferredStyle: .Alert) 15 | alert.addAction(UIAlertAction(title: "好的", style: .Default, handler: nil)) 16 | 17 | self.presentViewController(alert, animated: true, completion: nil) 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /XituGold/XGConfig.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XGConfig.swift 3 | // XituGold 4 | // 5 | // Created by 杨弘宇 on 16/4/17. 6 | // Copyright © 2016年 Cyandev. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | let XGAppId = "YOUR_APP_ID" 12 | let XGAppKey = "YOUR_APP_KEY" 13 | 14 | let XGGlobalTintColor = UIColor(red:0.1, green:0.52, blue:0.91, alpha:1) 15 | 16 | let XGTagNames = ["全部", "Android", "设计", "前端", "iOS", "后端", "产品", "工具资源", "阅读"] 17 | let XGTags = ["", "android", "design", "frontend", "ios", "backend", "product", "freebie", "article"] 18 | -------------------------------------------------------------------------------- /XituGold/XGEntry.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XGEntry.swift 3 | // XituGold 4 | // 5 | // Created by 杨弘宇 on 16/4/17. 6 | // Copyright © 2016年 Cyandev. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class XGEntry: NSObject { 12 | 13 | var title: String? 14 | var category: String? 15 | var content: String? 16 | var createdAt: NSDate? 17 | var hotIndex = -1 18 | var URL: NSURL? 19 | var screenshot: NSURL? 20 | var tags = [String]() 21 | var commentsCount = 0 22 | var collectionCount = 0 23 | var viewsCount = 0 24 | 25 | } 26 | -------------------------------------------------------------------------------- /XituGold/XGEntryAPI.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XGEntryAPI.swift 3 | // XituGold 4 | // 5 | // Created by 杨弘宇 on 16/4/17. 6 | // Copyright © 2016年 Cyandev. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import RxSwift 11 | import AVOSCloud 12 | 13 | let XGOrderTypeOptionName = "XGOrderTypeOptionName" 14 | let XGTagOptionName = "XGTagOptionName" 15 | let XGDTagOptionName = "XGDTagOptionName" 16 | let XGObjectsOptionName = "XGObjectIdsOptionName" 17 | 18 | 19 | class XGEntryAPI: NSObject { 20 | 21 | class func searchWithKeyword(keyword: String) -> Observable<[XGEntry]> { 22 | return Observable<[AnyObject]>.create { observer in 23 | let query = AVSearchQuery.searchWithQueryString(keyword) 24 | query.className = "Entry" 25 | query.cachePolicy = .CacheElseNetwork 26 | query.maxCacheAge = 60 27 | 28 | SMNetworkActivityController.sharedController.endActivity() 29 | 30 | query.findInBackground { (objects, error) in 31 | SMNetworkActivityController.sharedController.endActivity() 32 | 33 | if error != nil { 34 | observer.onError(error) 35 | return 36 | } 37 | 38 | observer.onNext(objects) 39 | observer.onCompleted() 40 | } 41 | 42 | return NopDisposable.instance 43 | }.flatMap { objects -> Observable<[XGEntry]> in 44 | return XGEntryAPI.fetchEntries(withOptions: [XGObjectsOptionName: objects]) 45 | } 46 | } 47 | 48 | class func fetchEntries(skipCount: Int = 0, withOptions options: [String:AnyObject?]) -> Observable<[XGEntry]> { 49 | return Observable<[AnyObject]>.create { observer -> Disposable in 50 | let query = AVQuery(className: "Entry") 51 | query.limit = 10 52 | query.skip = skipCount 53 | 54 | if options[XGOrderTypeOptionName] as? Int == 1 { 55 | query.orderByDescending("createdAt") 56 | } else { 57 | query.orderByDescending("rankIndex") 58 | } 59 | 60 | if let tag = options[XGTagOptionName] as? String where !tag.isEmpty { 61 | query.whereKey("category", equalTo: tag) 62 | } 63 | 64 | if let dtag = options[XGDTagOptionName] { 65 | query.whereKey("tags", equalTo: dtag) 66 | } 67 | 68 | if let objects = options[XGObjectsOptionName] as? [AVObject] { 69 | query.whereKey("objectId", containedIn: objects.map { $0.objectId }) 70 | } 71 | 72 | SMNetworkActivityController.sharedController.startActivity() 73 | 74 | query.findObjectsInBackgroundWithBlock { (objects, error) in 75 | SMNetworkActivityController.sharedController.endActivity() 76 | 77 | if (error != nil) { 78 | observer.onError(error) 79 | return 80 | } 81 | 82 | observer.onNext(objects) 83 | observer.onCompleted() 84 | } 85 | 86 | return NopDisposable.instance 87 | } 88 | .map { (objects) -> [XGEntry] in 89 | objects.map { 90 | let avo = $0 as! AVObject 91 | let transformed = XGEntry() 92 | transformed.title = avo.objectForKey("title") as? String 93 | transformed.category = avo.objectForKey("category") as? String 94 | transformed.content = avo.objectForKey("content") as? String 95 | transformed.createdAt = avo.createdAt 96 | transformed.hotIndex = avo.objectForKey("hotIndex") as? Int ?? -1 97 | transformed.URL = NSURL(string: avo.objectForKey("url") as? String ?? "") 98 | transformed.tags.appendContentsOf(avo.objectForKey("tagsTitleArray") as? [String] ?? []) 99 | transformed.commentsCount = avo.objectForKey("commentsCount") as? Int ?? 0 100 | transformed.collectionCount = avo.objectForKey("collectionCount") as? Int ?? 0 101 | transformed.viewsCount = avo.objectForKey("viewsCount") as? Int ?? 0 102 | 103 | // Check out whether there is a screenshot 104 | if let screenshot = avo.objectForKey("screenshot") as? AVFile { 105 | transformed.screenshot = NSURL(string: screenshot.url) 106 | } 107 | 108 | return transformed 109 | } 110 | } 111 | .retry(3) 112 | } 113 | 114 | } 115 | -------------------------------------------------------------------------------- /XituGold/XGEntryCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XGEntryCell.swift 3 | // XituGold 4 | // 5 | // Created by 杨弘宇 on 16/4/17. 6 | // Copyright © 2016年 Cyandev. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import RxSwift 11 | 12 | class XGEntryCell: UITableViewCell { 13 | 14 | @IBOutlet weak var titleLabel: UILabel! 15 | @IBOutlet weak var readsLabel: UILabel! 16 | @IBOutlet weak var commentsLabel: UILabel! 17 | @IBOutlet weak var createdAtLabel: UILabel! 18 | @IBOutlet weak var collectionLabel: UILabel! 19 | @IBOutlet weak var screenShotImageView: XGLoadableImageView! 20 | @IBOutlet weak var screenShotImageViewWidthConstraint: NSLayoutConstraint! 21 | @IBOutlet weak var screenShotImageViewRatioConstraint: NSLayoutConstraint! 22 | 23 | func collapseImageView(collapse: Bool) { 24 | if collapse { 25 | self.screenShotImageViewRatioConstraint.active = false 26 | self.screenShotImageViewWidthConstraint.active = true 27 | } else { 28 | self.screenShotImageViewWidthConstraint.active = false 29 | self.screenShotImageViewRatioConstraint.active = true 30 | } 31 | 32 | self.setNeedsLayout() 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /XituGold/XGEntryCell.xib: -------------------------------------------------------------------------------- 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 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 72 | 78 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /XituGold/XGEntryTableViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XGEntryTableViewController.swift 3 | // XituGold 4 | // 5 | // Created by 杨弘宇 on 16/4/17. 6 | // Copyright © 2016年 Cyandev. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import SafariServices 11 | import RxSwift 12 | import RxCocoa 13 | 14 | class XGEntryTableViewController: UITableViewController { 15 | 16 | var entries = [XGEntry]() 17 | 18 | var searchController: UISearchController! 19 | 20 | var selectedOrderType = 0 21 | var selectedTag = 0 22 | var selectedDTag: AnyObject? = nil // Shit, I miscalled that "Category" at the very beginning!!! 23 | 24 | private var loading = false 25 | 26 | let loadMoreTrigger = PublishSubject() 27 | let cancelLoadingTrigger = PublishSubject() 28 | 29 | private let disposeBag = DisposeBag() 30 | 31 | override func viewDidLoad() { 32 | super.viewDidLoad() 33 | 34 | self.searchController = UISearchController(searchResultsController: nil) 35 | self.searchController.dimsBackgroundDuringPresentation = false 36 | self.searchController.searchResultsUpdater = self 37 | self.tableView.tableHeaderView = self.searchController.searchBar 38 | 39 | self.tableView.rowHeight = 90 40 | self.tableView.registerNib(UINib(nibName: "XGEntryCell", bundle: nil), forCellReuseIdentifier: "EntryCell") 41 | 42 | self.refreshControl = UIRefreshControl() 43 | self.refreshControl?.addTarget(self, action: #selector(reload), forControlEvents: .ValueChanged) 44 | 45 | self.loadMoreTrigger 46 | .throttle(0.2, scheduler: MainScheduler.instance) 47 | .subscribeNext { [unowned self] in 48 | self.fetchEntriesSkipped(self.entries.count) 49 | } 50 | .addDisposableTo(self.disposeBag) 51 | 52 | self.registerForPreviewingWithDelegate(self, sourceView: self.view) 53 | } 54 | 55 | override func preferredStatusBarStyle() -> UIStatusBarStyle { 56 | return .LightContent 57 | } 58 | 59 | // MARK: - Convenience Methods 60 | 61 | func reloadData() { 62 | self.tableView.reloadData() 63 | } 64 | 65 | func deselectSelectedRowAnimated(animated: Bool) { 66 | if let indexPath = self.tableView.indexPathForSelectedRow { 67 | self.tableView.deselectRowAtIndexPath(indexPath, animated: animated) 68 | } 69 | } 70 | 71 | func makeSafariViewControllerWithEntry(entry: XGEntry) -> SFSafariViewController { 72 | let vc = SFSafariViewController(URL: entry.URL ?? NSURL()) 73 | vc.view.tintColor = XGGlobalTintColor 74 | 75 | return vc 76 | } 77 | 78 | // MARK: - 79 | 80 | func reload() { 81 | self.cancelLoadingTrigger.onNext() 82 | self.refreshControl?.beginRefreshing() 83 | self.entries.removeAll() 84 | self.reloadData() 85 | self.fetchEntriesSkipped(0) 86 | } 87 | 88 | func fetchEntriesSkipped(skipCount: Int) { 89 | self.loading = true 90 | 91 | var observable: Observable<[XGEntry]>! 92 | 93 | if let searchText = self.searchController.searchBar.text where !searchText.isEmpty { 94 | observable = XGEntryAPI.searchWithKeyword(searchText) 95 | .takeUntil(self.cancelLoadingTrigger) 96 | } else { 97 | var options: [String:AnyObject?] = [ 98 | XGOrderTypeOptionName: self.selectedOrderType, 99 | XGTagOptionName: self.selectedTag == 0 ? "" : XGTags[self.selectedTag] 100 | ] 101 | 102 | if self.selectedDTag != nil { 103 | options[XGDTagOptionName] = self.selectedDTag! 104 | } 105 | 106 | observable = XGEntryAPI.fetchEntries(skipCount, withOptions: options) 107 | .takeUntil(self.cancelLoadingTrigger) 108 | } 109 | 110 | observable.observeOn(MainScheduler.instance) 111 | .subscribe { [unowned self] event in 112 | self.loading = false 113 | self.refreshControl?.endRefreshing() 114 | 115 | if event.element != nil { 116 | self.entries.appendContentsOf(event.element!) 117 | self.reloadData() 118 | } 119 | 120 | if event.error != nil { 121 | self.searchController.dismissViewControllerAnimated(true, completion: nil) 122 | self.showAlertWithTitle("网络问题", message: "无法连接到服务器,请检查网络设置。") 123 | } 124 | } 125 | .addDisposableTo(self.disposeBag) 126 | } 127 | 128 | // MARK: - Data Source 129 | 130 | override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 131 | return self.entries.count 132 | } 133 | 134 | override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 135 | let cell = tableView.dequeueReusableCellWithIdentifier("EntryCell", forIndexPath: indexPath) as! XGEntryCell 136 | let entry = self.entries[indexPath.row] 137 | 138 | cell.titleLabel.text = entry.title 139 | cell.readsLabel.text = "\(entry.viewsCount)次浏览" 140 | cell.commentsLabel.text = "\(entry.commentsCount)条评论" 141 | cell.createdAtLabel.text = entry.createdAt?.formattedStringFromThenToNow().stringByAppendingString("之前") 142 | cell.collectionLabel.text = String(entry.collectionCount) 143 | 144 | if entry.screenshot == nil { 145 | cell.collapseImageView(true) 146 | } else { 147 | cell.screenShotImageView.imageURL.onNext(entry.screenshot!) 148 | cell.collapseImageView(false) 149 | } 150 | 151 | return cell 152 | } 153 | 154 | // MARK: - Delegate 155 | 156 | override func scrollViewDidScroll(scrollView: UIScrollView) { 157 | let offsetY = scrollView.contentOffset.y 158 | if offsetY + scrollView.frame.height + scrollView.contentInset.bottom + 20 > scrollView.contentSize.height { 159 | self.loadMoreTrigger.onNext() 160 | } 161 | } 162 | 163 | override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { 164 | self.deselectSelectedRowAnimated(true) 165 | 166 | let vc = self.makeSafariViewControllerWithEntry(self.entries[indexPath.row]) 167 | self.presentViewController(vc, animated: true, completion: nil) 168 | } 169 | 170 | } 171 | 172 | 173 | extension XGEntryTableViewController: UISearchResultsUpdating { 174 | 175 | func updateSearchResultsForSearchController(searchController: UISearchController) { 176 | self.reload() 177 | } 178 | 179 | } 180 | 181 | 182 | extension XGEntryTableViewController: UIViewControllerPreviewingDelegate { 183 | 184 | func previewingContext(previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? { 185 | if let indexPath = self.tableView.indexPathForRowAtPoint(location) { 186 | let vc = self.makeSafariViewControllerWithEntry(self.entries[indexPath.row]) 187 | 188 | previewingContext.sourceRect = self.tableView.cellForRowAtIndexPath(indexPath)?.frame ?? CGRectZero 189 | 190 | return vc 191 | } 192 | 193 | return nil 194 | } 195 | 196 | func previewingContext(previewingContext: UIViewControllerPreviewing, commitViewController viewControllerToCommit: UIViewController) { 197 | self.presentViewController(viewControllerToCommit, animated: true, completion: nil) 198 | } 199 | 200 | } 201 | -------------------------------------------------------------------------------- /XituGold/XGExplorerViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XGExplorerViewController.swift 3 | // XituGold 4 | // 5 | // Created by 杨弘宇 on 16/4/17. 6 | // Copyright © 2016年 Cyandev. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import RxSwift 11 | import RxCocoa 12 | 13 | class XGExplorerViewController: UIViewController { 14 | 15 | var tableViewController: XGEntryTableViewController { 16 | return self._tableViewController 17 | } 18 | 19 | private var _tableViewController = XGEntryTableViewController() 20 | 21 | private var useDefaultStatusBarStyle = false 22 | private var needToReload = true 23 | 24 | private let disposeBag = DisposeBag() 25 | 26 | override func viewDidLoad() { 27 | super.viewDidLoad() 28 | 29 | let filterButtonItem = UIBarButtonItem(title: "筛选", style: .Plain, target: nil, action: nil) 30 | filterButtonItem.rx_tap 31 | .subscribeNext { [unowned self] in 32 | self.showFilterView() 33 | }.addDisposableTo(self.disposeBag) 34 | 35 | let actionButtonItem = UIBarButtonItem(barButtonSystemItem: .Action, target: nil, action: nil) 36 | actionButtonItem.rx_tap 37 | .subscribeNext { [unowned self] in 38 | self.showActionSheet() 39 | }.addDisposableTo(self.disposeBag) 40 | 41 | self.navigationItem.title = "发现" 42 | self.navigationItem.leftBarButtonItems = [filterButtonItem] 43 | self.navigationItem.rightBarButtonItems = [actionButtonItem] 44 | 45 | self.view.backgroundColor = UIColor.whiteColor() 46 | 47 | self.tableViewController.willMoveToParentViewController(self) 48 | self.addChildViewController(self.tableViewController) 49 | self.tableViewController.view.frame = self.view.bounds 50 | self.tableViewController.tableView.contentInset.bottom = 64 51 | self.view.addSubview(self.tableViewController.view) 52 | self.tableViewController.didMoveToParentViewController(self) 53 | } 54 | 55 | override func preferredStatusBarStyle() -> UIStatusBarStyle { 56 | return self.useDefaultStatusBarStyle ? .Default : .LightContent 57 | } 58 | 59 | override func viewDidAppear(animated: Bool) { 60 | super.viewDidAppear(animated) 61 | 62 | if self.needToReload { 63 | self.tableViewController.reload() 64 | self.needToReload = false 65 | } 66 | } 67 | 68 | override func didReceiveMemoryWarning() { 69 | super.didReceiveMemoryWarning() 70 | // Dispose of any resources that can be recreated. 71 | } 72 | 73 | // MARK: - 74 | 75 | func showActionSheet() { 76 | let actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: .ActionSheet) 77 | actionSheet.addAction(UIAlertAction(title: "重新载入", style: .Default) { _ in 78 | self.tableViewController.reload() 79 | }) 80 | actionSheet.addAction(UIAlertAction(title: "设置", style: .Default) { _ in 81 | let shakeAnimation = CAKeyframeAnimation(keyPath: "transform.translation.x") 82 | shakeAnimation.values = [0, -20, 15, -10, 10, -9, 9, -6, 6, -1, 0] 83 | shakeAnimation.duration = 1.0 84 | 85 | UIApplication.sharedApplication().keyWindow?.layer.addAnimation(shakeAnimation, forKey: "") 86 | }) 87 | actionSheet.addAction(UIAlertAction(title: "取消", style: .Cancel, handler: nil)) 88 | 89 | self.presentViewController(actionSheet, animated: true, completion: nil) 90 | } 91 | 92 | func showFilterView() { 93 | let filterVC = XGFilterViewController() 94 | filterVC.selectedOrderType = self.tableViewController.selectedOrderType 95 | filterVC.selectedTag = self.tableViewController.selectedTag 96 | filterVC.delegate = self 97 | filterVC.rx_deallocated 98 | .subscribeNext { 99 | self.useDefaultStatusBarStyle = false 100 | self.setNeedsStatusBarAppearanceUpdate() 101 | } 102 | .addDisposableTo(self.disposeBag) 103 | 104 | let wrappedNC = XGNavigationController(rootViewController: filterVC) 105 | wrappedNC.navigationBar.backgroundColor = nil 106 | wrappedNC.navigationBar.barTintColor = nil 107 | wrappedNC.navigationBar.tintColor = nil 108 | wrappedNC.navigationBar.titleTextAttributes = nil 109 | wrappedNC.modalPresentationStyle = .OverFullScreen 110 | 111 | self.presentViewController(wrappedNC, animated: true) { 112 | self.useDefaultStatusBarStyle = true 113 | self.setNeedsStatusBarAppearanceUpdate() 114 | } 115 | } 116 | 117 | } 118 | 119 | 120 | extension XGExplorerViewController: XGFilterViewControllerDelegate { 121 | 122 | func filterViewControllerDidChangeValue(vc: XGFilterViewController) { 123 | self.tableViewController.selectedOrderType = vc.selectedOrderType 124 | self.tableViewController.selectedTag = vc.selectedTag 125 | 126 | self.tableViewController.reload() 127 | } 128 | 129 | } -------------------------------------------------------------------------------- /XituGold/XGFilterCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XGFilterCell.swift 3 | // XituGold 4 | // 5 | // Created by 杨弘宇 on 16/4/17. 6 | // Copyright © 2016年 Cyandev. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class XGFilterCell: UICollectionViewCell { 12 | 13 | @IBOutlet weak var label: UILabel! 14 | @IBOutlet weak var selectedView: UIView! 15 | 16 | override var selected: Bool { 17 | didSet { 18 | if self.selected { 19 | self.label.textColor = UIColor.whiteColor() 20 | self.selectedView.hidden = false 21 | } else { 22 | self.label.textColor = UIColor.blackColor() 23 | self.selectedView.hidden = true 24 | } 25 | } 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /XituGold/XGFilterCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 28 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /XituGold/XGFilterViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XGFilterViewController.swift 3 | // XituGold 4 | // 5 | // Created by 杨弘宇 on 16/4/17. 6 | // Copyright © 2016年 Cyandev. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import RxSwift 11 | import RxCocoa 12 | 13 | protocol XGFilterViewControllerDelegate: NSObjectProtocol { 14 | 15 | func filterViewControllerDidChangeValue(vc: XGFilterViewController) 16 | 17 | } 18 | 19 | 20 | class XGFilterViewController: UIViewController { 21 | 22 | var collectionView: UICollectionView! 23 | 24 | var selectedOrderType = 0 25 | var selectedTag = 0 26 | 27 | weak var delegate: XGFilterViewControllerDelegate? 28 | 29 | private let disposeBag = DisposeBag() 30 | 31 | override func viewDidLoad() { 32 | super.viewDidLoad() 33 | 34 | let doneButtonItem = UIBarButtonItem(barButtonSystemItem: .Done, target: nil, action: nil) 35 | doneButtonItem.rx_tap 36 | .subscribeNext { [unowned self] in 37 | self.dismissViewControllerAnimated(true, completion: nil) 38 | } 39 | .addDisposableTo(self.disposeBag) 40 | 41 | self.navigationItem.title = "筛选" 42 | self.navigationItem.rightBarButtonItems = [doneButtonItem] 43 | 44 | self.view.backgroundColor = UIColor.clearColor() 45 | 46 | let backgroundView = UIVisualEffectView(effect: UIBlurEffect(style: .ExtraLight)) 47 | backgroundView.frame = self.view.bounds 48 | self.view.addSubview(backgroundView) 49 | 50 | let flowLayout = UICollectionViewFlowLayout() 51 | flowLayout.itemSize = CGSize(width: 70, height: 40) 52 | flowLayout.headerReferenceSize = CGSize(width: self.view.frame.width, height: 30) 53 | 54 | self.collectionView = UICollectionView(frame: self.view.bounds, collectionViewLayout: flowLayout) 55 | self.collectionView.backgroundColor = UIColor.clearColor() 56 | self.collectionView.contentInset = UIEdgeInsets(top: 80, left: 30, bottom: 0, right: 30) 57 | self.collectionView.allowsMultipleSelection = true 58 | self.collectionView.dataSource = self 59 | self.collectionView.delegate = self 60 | self.view.addSubview(self.collectionView) 61 | 62 | self.collectionView.registerNib(UINib(nibName: "XGFilterCell", bundle: nil), forCellWithReuseIdentifier: "Cell") 63 | self.collectionView.registerNib(UINib(nibName: "XGGroupTitleReusableView", bundle: nil), forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "HeaderView") 64 | } 65 | 66 | override func viewWillAppear(animated: Bool) { 67 | super.viewWillAppear(animated) 68 | 69 | self.collectionView.selectItemAtIndexPath(NSIndexPath(forItem: self.selectedOrderType, inSection: 0), animated: true, scrollPosition: .None) 70 | self.collectionView.selectItemAtIndexPath(NSIndexPath(forItem: self.selectedTag, inSection: 1), animated: true, scrollPosition: .None) 71 | } 72 | 73 | } 74 | 75 | 76 | extension XGFilterViewController: UICollectionViewDataSource { 77 | 78 | func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int { 79 | return 2 80 | } 81 | 82 | func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 83 | return section == 0 ? 2 : XGTagNames.count 84 | } 85 | 86 | func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell { 87 | let cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath) as! XGFilterCell 88 | 89 | if indexPath.section == 0 { 90 | cell.label.text = indexPath.item == 0 ? "热门" : "最新" 91 | } else { 92 | cell.label.text = XGTagNames[indexPath.item] 93 | } 94 | 95 | return cell 96 | } 97 | 98 | func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView { 99 | let view = collectionView.dequeueReusableSupplementaryViewOfKind(UICollectionElementKindSectionHeader, withReuseIdentifier: "HeaderView", forIndexPath: indexPath) as! XGGroupTitleReusableView 100 | 101 | view.label.text = indexPath.section == 0 ? "排序方式" : "标签" 102 | 103 | return view 104 | } 105 | 106 | } 107 | 108 | 109 | extension XGFilterViewController: UICollectionViewDelegate { 110 | 111 | func collectionView(collectionView: UICollectionView, shouldSelectItemAtIndexPath indexPath: NSIndexPath) -> Bool { 112 | if let indexPaths = collectionView.indexPathsForSelectedItems() { 113 | if let indexPath = indexPaths.filter({ $0.section == indexPath.section && $0.item != indexPath.item }).first { 114 | collectionView.deselectItemAtIndexPath(indexPath, animated: true) 115 | } 116 | } 117 | 118 | return true 119 | } 120 | 121 | func collectionView(collectionView: UICollectionView, shouldDeselectItemAtIndexPath indexPath: NSIndexPath) -> Bool { 122 | return false 123 | } 124 | 125 | func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) { 126 | if indexPath.section == 0 { 127 | self.selectedOrderType = indexPath.item 128 | } else { 129 | self.selectedTag = indexPath.item 130 | } 131 | 132 | self.delegate?.filterViewControllerDidChangeValue(self) 133 | } 134 | 135 | } 136 | -------------------------------------------------------------------------------- /XituGold/XGGroupTitleReusableView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XGGroupTitleReusableView.swift 3 | // XituGold 4 | // 5 | // Created by 杨弘宇 on 16/4/17. 6 | // Copyright © 2016年 Cyandev. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class XGGroupTitleReusableView: UICollectionReusableView { 12 | 13 | @IBOutlet weak var label: UILabel! 14 | 15 | } 16 | -------------------------------------------------------------------------------- /XituGold/XGGroupTitleReusableView.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /XituGold/XGImageCacheController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XGImageCacheController.swift 3 | // XituGold 4 | // 5 | // Created by 杨弘宇 on 16/4/20. 6 | // Copyright © 2016年 Cyandev. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class XGImageCacheController: NSObject { 12 | 13 | static let sharedController = XGImageCacheController() 14 | 15 | private var cachedImages = [NSURL:UIImage]() 16 | private let lock = NSLock() 17 | 18 | func putImage(image: UIImage, forKey key: NSURL) { 19 | performInCriticalZone { 20 | self.cachedImages[key] = image 21 | return nil 22 | } 23 | } 24 | 25 | func imageForKey(key: NSURL) -> UIImage? { 26 | return performInCriticalZone { 27 | return self.cachedImages[key] 28 | } as? UIImage 29 | } 30 | 31 | func clearCache() { 32 | self.cachedImages.removeAll() 33 | } 34 | 35 | func performInCriticalZone(action: () -> AnyObject?) -> AnyObject? { 36 | self.lock.lock() 37 | defer { 38 | self.lock.unlock() 39 | } 40 | 41 | return action() 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /XituGold/XGLoadableImageView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XGLoadableImageView.swift 3 | // XituGold 4 | // 5 | // Created by 杨弘宇 on 16/4/20. 6 | // Copyright © 2016年 Cyandev. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import RxSwift 11 | import RxCocoa 12 | 13 | class XGLoadableImageView: UIImageView { 14 | 15 | var imageURL = PublishSubject() 16 | var placeholderImage: UIImage? 17 | var errorImage: UIImage? 18 | 19 | private let disposeBag = DisposeBag() 20 | 21 | override init(frame: CGRect) { 22 | super.init(frame: frame) 23 | self.commonInit() 24 | } 25 | 26 | required init?(coder aDecoder: NSCoder) { 27 | super.init(coder: aDecoder) 28 | self.commonInit() 29 | } 30 | 31 | func commonInit() { 32 | self.imageURL.subscribeNext { [unowned self] in 33 | self.fetchAndSetImageWithURL($0) 34 | }.addDisposableTo(self.disposeBag) 35 | } 36 | 37 | func fetchAndSetImageWithURL(URL: NSURL) { 38 | if let cachedImage = XGImageCacheController.sharedController.imageForKey(URL) { 39 | self.image = cachedImage 40 | return 41 | } 42 | 43 | SMNetworkActivityController.sharedController.startActivity() 44 | 45 | NSURLSession.sharedSession().rx_data(NSURLRequest(URL: URL)) 46 | .takeUntil(self.imageURL) 47 | .retry(2) 48 | .map { UIImage(data: $0) } 49 | .catchErrorJustReturn(self.errorImage) 50 | .startWith(self.placeholderImage) 51 | .observeOn(MainScheduler.instance) 52 | .subscribeNext { [weak self] in 53 | SMNetworkActivityController.sharedController.endActivity() 54 | if $0 != nil { 55 | XGImageCacheController.sharedController.putImage($0!, forKey: URL) 56 | } 57 | self?.image = $0 58 | } 59 | .addDisposableTo(self.disposeBag) 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /XituGold/XGNavigationController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XGNavigationController.swift 3 | // XituGold 4 | // 5 | // Created by 杨弘宇 on 16/4/17. 6 | // Copyright © 2016年 Cyandev. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class XGNavigationController: UINavigationController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | 16 | self.delegate = self 17 | } 18 | 19 | override func preferredStatusBarStyle() -> UIStatusBarStyle { 20 | return self.topViewController?.preferredStatusBarStyle() ?? super.preferredStatusBarStyle() 21 | } 22 | 23 | } 24 | 25 | 26 | extension XGNavigationController: UINavigationControllerDelegate { 27 | 28 | func navigationController(navigationController: UINavigationController, willShowViewController viewController: UIViewController, animated: Bool) { 29 | self.setNeedsStatusBarAppearanceUpdate() 30 | } 31 | 32 | } -------------------------------------------------------------------------------- /XituGold/XGTabBarController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XGTabBarController.swift 3 | // XituGold 4 | // 5 | // Created by 杨弘宇 on 16/4/17. 6 | // Copyright © 2016年 Cyandev. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class XGTabBarController: UITabBarController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | 16 | self.delegate = self 17 | 18 | let explorerVC = XGExplorerViewController() 19 | explorerVC.tabBarItem.image = UIImage(named: "icon_explore") 20 | explorerVC.tabBarItem.selectedImage = UIImage(named: "icon_explore_active") 21 | explorerVC.tabBarItem.title = "发现" 22 | 23 | let tagVC = XGTagViewController() 24 | tagVC.tabBarItem.image = UIImage(named: "icon_tags") 25 | tagVC.tabBarItem.selectedImage = UIImage(named: "icon_tags_active") 26 | tagVC.tabBarItem.title = "标签" 27 | 28 | self.viewControllers = [explorerVC, tagVC] 29 | self.tabBarController(self, didSelectViewController: explorerVC) 30 | } 31 | 32 | override func preferredStatusBarStyle() -> UIStatusBarStyle { 33 | return self.selectedViewController?.preferredStatusBarStyle() ?? .LightContent 34 | } 35 | 36 | } 37 | 38 | 39 | extension XGTabBarController: UITabBarControllerDelegate { 40 | 41 | func tabBarController(tabBarController: UITabBarController, didSelectViewController viewController: UIViewController) { 42 | self.navigationItem.title = viewController.navigationItem.title 43 | self.navigationItem.rightBarButtonItems = viewController.navigationItem.rightBarButtonItems 44 | self.navigationItem.leftBarButtonItems = viewController.navigationItem.leftBarButtonItems 45 | 46 | self.setNeedsStatusBarAppearanceUpdate() 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /XituGold/XGTag.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XGTag.swift 3 | // XituGold 4 | // 5 | // Created by 杨弘宇 on 16/4/20. 6 | // Copyright © 2016年 Cyandev. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class XGTag: NSObject { 12 | 13 | var title: String? 14 | var color: String? 15 | var icon: NSURL? 16 | var entriesCount = 0 17 | var subscribersCount = 0 18 | var objectRef: AnyObject! 19 | 20 | } 21 | -------------------------------------------------------------------------------- /XituGold/XGTagAPI.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XGTagAPI.swift 3 | // XituGold 4 | // 5 | // Created by 杨弘宇 on 16/4/20. 6 | // Copyright © 2016年 Cyandev. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import RxSwift 11 | import AVOSCloud 12 | 13 | class XGTagAPI: NSObject { 14 | 15 | class func fetchTags() -> Observable<[XGTag]> { 16 | return Observable<[AnyObject]>.create { observer in 17 | let query = AVQuery(className: "Tag") 18 | query.addDescendingOrder("subscribersCount") 19 | 20 | SMNetworkActivityController.sharedController.startActivity() 21 | 22 | query.findObjectsInBackgroundWithBlock { (objects, error) in 23 | SMNetworkActivityController.sharedController.endActivity() 24 | 25 | if (error != nil) { 26 | observer.onError(error) 27 | return 28 | } 29 | 30 | observer.onNext(objects) 31 | observer.onCompleted() 32 | } 33 | 34 | return NopDisposable.instance 35 | } 36 | .map { (objects) -> [XGTag] in 37 | objects.map { 38 | let avo = $0 as! AVObject 39 | let transformed = XGTag() 40 | transformed.title = avo.objectForKey("title") as? String 41 | transformed.color = avo.objectForKey("color") as? String 42 | transformed.entriesCount = avo.objectForKey("entriesCount") as? Int ?? 0 43 | transformed.subscribersCount = avo.objectForKey("subscribersCount") as? Int ?? 0 44 | transformed.objectRef = avo 45 | 46 | if let icon = avo.objectForKey("icon") as? AVFile { 47 | transformed.icon = NSURL(string: icon.url) 48 | } 49 | 50 | return transformed 51 | } 52 | } 53 | .retry(3) 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /XituGold/XGTagCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XGTagCell.swift 3 | // XituGold 4 | // 5 | // Created by 杨弘宇 on 16/4/20. 6 | // Copyright © 2016年 Cyandev. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class XGTagCell: UICollectionViewCell { 12 | 13 | @IBOutlet weak var iconImageView: XGLoadableImageView! 14 | @IBOutlet weak var titleLabel: UILabel! 15 | @IBOutlet weak var subcLabel: UILabel! 16 | @IBOutlet weak var entLabel: UILabel! 17 | 18 | } 19 | -------------------------------------------------------------------------------- /XituGold/XGTagCell.xib: -------------------------------------------------------------------------------- 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 | 34 | 35 | 44 | 45 | 46 | 47 | 53 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /XituGold/XGTagViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // XGTagViewController.swift 3 | // XituGold 4 | // 5 | // Created by 杨弘宇 on 16/4/17. 6 | // Copyright © 2016年 Cyandev. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import RxSwift 11 | 12 | class XGTagViewController: UIViewController { 13 | 14 | var tags = [XGTag]() 15 | 16 | var collectionView: UICollectionView! 17 | 18 | private let disposeBag = DisposeBag() 19 | 20 | override func viewDidLoad() { 21 | super.viewDidLoad() 22 | 23 | self.navigationItem.title = "标签" 24 | 25 | self.view.backgroundColor = UIColor.whiteColor() 26 | 27 | let flowLayout = UICollectionViewFlowLayout() 28 | flowLayout.itemSize = CGSize(width: self.view.bounds.width / 2.0, height: 150) 29 | flowLayout.minimumInteritemSpacing = 0 30 | flowLayout.minimumLineSpacing = 0 31 | 32 | self.collectionView = UICollectionView(frame: self.view.bounds, collectionViewLayout: flowLayout) 33 | self.collectionView.backgroundColor = UIColor(white: 0.95, alpha: 1) 34 | self.collectionView.dataSource = self 35 | self.collectionView.delegate = self 36 | self.view.addSubview(self.collectionView) 37 | 38 | self.collectionView.registerNib(UINib(nibName: "XGTagCell", bundle: nil), forCellWithReuseIdentifier: "Cell") 39 | 40 | reload() 41 | } 42 | 43 | override func preferredStatusBarStyle() -> UIStatusBarStyle { 44 | return .LightContent 45 | } 46 | 47 | override func didReceiveMemoryWarning() { 48 | super.didReceiveMemoryWarning() 49 | // Dispose of any resources that can be recreated. 50 | } 51 | 52 | func reload() { 53 | self.tags.removeAll() 54 | 55 | XGTagAPI.fetchTags() 56 | .subscribe { [unowned self] event in 57 | if event.element != nil { 58 | self.tags.appendContentsOf(event.element!) 59 | self.collectionView.reloadData() 60 | } 61 | 62 | if event.error != nil { 63 | self.showAlertWithTitle("网络问题", message: "无法连接到服务器,请检查网络设置。") 64 | } 65 | } 66 | .addDisposableTo(self.disposeBag) 67 | } 68 | 69 | } 70 | 71 | 72 | extension XGTagViewController: UICollectionViewDataSource { 73 | 74 | func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 75 | return self.tags.count 76 | } 77 | 78 | func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell { 79 | let cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath) as! XGTagCell 80 | 81 | let tag = self.tags[indexPath.item] 82 | 83 | cell.titleLabel.text = tag.title 84 | cell.iconImageView.imageURL.onNext(tag.icon ?? NSURL()) 85 | cell.subcLabel.text = "\(tag.subscribersCount) 关注" 86 | cell.entLabel.text = "\(tag.entriesCount) 文章" 87 | 88 | return cell 89 | } 90 | 91 | } 92 | 93 | 94 | extension XGTagViewController: UICollectionViewDelegate { 95 | 96 | func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) { 97 | let vc = XGEntryTableViewController() 98 | vc.navigationItem.title = self.tags[indexPath.item].title 99 | vc.selectedDTag = self.tags[indexPath.item].objectRef 100 | 101 | self.navigationController?.pushViewController(vc, animated: true) 102 | 103 | dispatch_async(dispatch_get_main_queue()) { 104 | vc.reload() 105 | } 106 | } 107 | 108 | } 109 | --------------------------------------------------------------------------------