├── .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 |
--------------------------------------------------------------------------------
/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 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
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 |
--------------------------------------------------------------------------------