├── .gitattributes
├── .gitignore
├── .travis.yml
├── Cartfile.resolved
├── Gemfile
├── Gemfile.lock
├── LICENSE
├── Podfile
├── Podfile.lock
├── README.md
├── Swift-ZHI.xcodeproj
├── project.pbxproj
├── project.xcworkspace
│ └── contents.xcworkspacedata
└── xcshareddata
│ └── xcschemes
│ └── Swift-ZHI.xcscheme
├── Swift-ZHI.xcworkspace
└── contents.xcworkspacedata
├── SwiftDaily-ZhiHu
├── .gitkeep
├── Controllers
│ ├── .gitkeep
│ ├── AppDelegate.swift
│ ├── DailyTableViewController.swift
│ ├── HideNavBarViewController.swift
│ ├── HidesHairLineUnderNavBarViewController.swift
│ ├── NewsViewController.swift
│ ├── RealmCommentViewController.swift
│ ├── RealmDailyTableViewController.swift
│ └── RealmNewsViewController.swift
├── Extensions
│ └── .gitkeep
├── Helpers
│ ├── .gitkeep
│ ├── CommentContentFormatter.swift
│ ├── DailyDates.swift
│ ├── Delay.swift
│ └── RealmHelpers.swift
├── Models
│ ├── .gitkeep
│ ├── DailyRealmStore.swift
│ ├── RealmModels.swift
│ └── UserPreferences.swift
├── Protocols
│ └── .gitkeep
├── Resources
│ ├── .gitkeep
│ ├── Base.lproj
│ │ └── Localizable.strings
│ ├── Images.xcassets
│ │ └── AppIcon.appiconset
│ │ │ ├── Contents.json
│ │ │ ├── Icon-29.png
│ │ │ ├── Icon-29@2x-1.png
│ │ │ ├── Icon-29@2x.png
│ │ │ ├── Icon-29@3x.png
│ │ │ ├── Icon-40.png
│ │ │ ├── Icon-40@2x-1.png
│ │ │ ├── Icon-40@2x.png
│ │ │ ├── Icon-40@3x.png
│ │ │ ├── Icon-60@2x.png
│ │ │ ├── Icon-60@3x.png
│ │ │ ├── Icon-76.png
│ │ │ └── Icon-76@2x.png
│ ├── Info.plist
│ ├── Localizations
│ │ └── Swift-ZHI
│ │ │ ├── zh-Hans.xliff
│ │ │ └── zh-Hant.xliff
│ ├── Nibs
│ │ ├── .gitkeep
│ │ ├── Base.lproj
│ │ │ └── CommentSectionHeaderView.xib
│ │ ├── DailySectionHeaderView.xib
│ │ ├── LaunchScreen.xib
│ │ ├── zh-Hans.lproj
│ │ │ └── CommentSectionHeaderView.strings
│ │ └── zh-Hant.lproj
│ │ │ └── CommentSectionHeaderView.strings
│ ├── Settings.bundle
│ │ ├── Root.plist
│ │ └── en.lproj
│ │ │ └── Root.strings
│ ├── Storyboards
│ │ ├── .gitkeep
│ │ ├── Base.lproj
│ │ │ └── Main.storyboard
│ │ ├── zh-Hans.lproj
│ │ │ └── Main.strings
│ │ └── zh-Hant.lproj
│ │ │ └── Main.strings
│ ├── zh-Hans.lproj
│ │ ├── InfoPlist.strings
│ │ └── Localizable.strings
│ └── zh-Hant.lproj
│ │ ├── InfoPlist.strings
│ │ └── Localizable.strings
├── ViewModels
│ └── .gitkeep
└── Views
│ ├── .gitkeep
│ ├── CommentSectionHeaderView.swift
│ ├── DailySectionHeaderView.swift
│ └── LoadingCell.swift
├── SwiftDaily-ZhiHuTests
├── Info.plist
├── SwiftDaily_ZhiHuTests.swift
├── zh-Hans.lproj
│ └── InfoPlist.strings
└── zh-Hant.lproj
│ └── InfoPlist.strings
├── SwiftDaily-ZhiHuUITests
├── Info.plist
├── SwiftDaily_ZhiHuUITests.swift
├── zh-Hans.lproj
│ └── InfoPlist.strings
└── zh-Hant.lproj
│ └── InfoPlist.strings
├── Tests
├── .gitkeep
├── Helpers
│ └── .gitkeep
├── Resources
│ ├── .gitkeep
│ └── Tests-Info.plist
└── Tests
│ └── .gitkeep
└── bin
├── bump
├── merge
├── new_branch
└── test
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.pbxproj merge=union
2 | *.strings text diff
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # OS X Finder
2 | .DS_Store
3 |
4 | # Xcode per-user config
5 | *.mode1
6 | *.mode1v3
7 | *.mode2v3
8 | *.perspective
9 | *.perspectivev3
10 | *.pbxuser
11 | xcuserdata
12 | *.xccheckout
13 | *.xcscmblueprint
14 |
15 | # Build products
16 | build/
17 | *.o
18 | *.LinkFileList
19 | *.hmap
20 |
21 | # Automatic backup files
22 | *~.nib/
23 | *.swp
24 | *~
25 | *.dat
26 | *.dep
27 |
28 | # Cocoapods
29 | Pods
30 |
31 | # Carthage
32 | Carthage/Checkouts
33 | Carthage/Build
34 |
35 | # AppCode specific files
36 | .idea/
37 | *.iml
38 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: objective-c
2 | osx_image: xcode7.2
3 | env:
4 | global:
5 | - LC_CTYPE=en_US.UTF-8
6 | - LANG=en_US.UTF-8
7 | script:
8 | - set -o pipefail
9 | - xcodebuild -version
10 | - xcodebuild -showsdks
11 |
12 | - xcodebuild -workspace Swift-ZHI.xcworkspace -scheme "Swift-ZHI" -destination "OS=9.2,name=iPhone 6s Plus" build | xcpretty -c
13 |
--------------------------------------------------------------------------------
/Cartfile.resolved:
--------------------------------------------------------------------------------
1 | github "andreamazz/AMScrollingNavbar" "1.5.1"
2 | github "Alamofire/Alamofire" "1.3.1"
3 | github "robrix/Box" "1.2.2"
4 | github "thoughtbot/Runes" "v2.0.0"
5 | github "rs/SDWebImage" "3.7.3"
6 | github "realm/realm-cocoa" "v0.93.2"
7 | github "thoughtbot/Argo" "v1.0.4"
8 | github "NicholasTD07/SwiftDailyAPI" "9ce09b5061d4aa22188541de202f9427c16b6ec4"
9 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | gem 'xcpretty'
4 |
--------------------------------------------------------------------------------
/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: https://rubygems.org/
3 | specs:
4 | xcpretty (0.1.10)
5 |
6 | PLATFORMS
7 | ruby
8 |
9 | DEPENDENCIES
10 | xcpretty
11 |
12 | BUNDLED WITH
13 | 1.10.0
14 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Nicholas T.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Podfile:
--------------------------------------------------------------------------------
1 | platform :ios, '8.0'
2 | use_frameworks!
3 |
4 | pod 'SwiftDailyAPI', '~> 2.0'
5 | pod 'RealmSwift', '~> 0.97'
6 | pod 'SDWebImage', '~> 3.7.3'
7 | pod 'AMScrollingNavbar', '~> 1.5'
8 |
--------------------------------------------------------------------------------
/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - Alamofire (3.1.4)
3 | - AMScrollingNavbar (1.5.1)
4 | - Argo (2.2.0)
5 | - Realm (0.97.0):
6 | - Realm/Headers (= 0.97.0)
7 | - Realm/Headers (0.97.0)
8 | - RealmSwift (0.97.0):
9 | - Realm (= 0.97.0)
10 | - SDWebImage (3.7.4):
11 | - SDWebImage/Core (= 3.7.4)
12 | - SDWebImage/Core (3.7.4)
13 | - SwiftDailyAPI (2.0.1):
14 | - Alamofire (~> 3.0)
15 | - Argo (~> 2.2.0)
16 |
17 | DEPENDENCIES:
18 | - AMScrollingNavbar (~> 1.5)
19 | - RealmSwift (~> 0.97)
20 | - SDWebImage (~> 3.7.3)
21 | - SwiftDailyAPI (~> 2.0)
22 |
23 | SPEC CHECKSUMS:
24 | Alamofire: fbc829692f351fa1d8a31dd75fd7f7f56fea31fb
25 | AMScrollingNavbar: 767ed2db60d927a809bddff5d01b739b7020b12b
26 | Argo: 4f52a32b4cd913c204e5a45f420b3fccad3e3f24
27 | Realm: b498a6fb9d288b171ff98d0e2d4384c295be8990
28 | RealmSwift: d014810dec75c9a3f1a33926d2dabfed855c582c
29 | SDWebImage: 247edd7dd80dd6124197b0d6a17846fe9d1df968
30 | SwiftDailyAPI: 0ea377af335824d17564dc5972331c045095de86
31 |
32 | COCOAPODS: 0.39.0
33 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SwiftDaily-ZhiHu
2 |
3 | [](https://travis-ci.org/NicholasTD07/Swift-ZHI)
4 |
5 | iOS ZhiHuDaily client, implemented in Swift.
6 |
7 | No need to wait for the loading screen of any News you'd like to read. You can
8 | save it first before you read it. It will be there for you.
9 |
10 | If you are reading ZhiHuDaily outside of China, the loading time for the content
11 | of a News is about 3-5 seconds. And on average a user reads 7-10 news a day.
12 |
13 | See [here](#user-content-there-is-already-an-official-zhihudaily-app-why-another) for detailed reason why I create this App.
14 |
15 |
16 |
17 | ## Features
18 |
19 | ### Basics
20 |
21 | Basic functionality that the official App offers.
22 |
23 | * Show a list of latest daily news from Zhihu's API - DailyView
24 | * Infinite scrolling
25 | * Show news content in a detail view - NewsView
26 |
27 | ### Features I added
28 |
29 | * Offline storage/cache by using [Realm]
30 | * News list items - [`NewsMetaObject`](./SwiftDaily-ZhiHu/Models/RealmModels.swift)
31 | * News content - [`NewsObject`](./SwiftDaily-ZhiHu/Models/RealmModels.swift)
32 |
33 | ## Setup
34 |
35 | ```sh
36 | gem install cocoapods
37 | pod install
38 | ```
39 |
40 | ### Minimum Requirement for Build Environment
41 |
42 | * Xcode 7.2
43 | * Swift 2.1
44 |
45 | ## Frameworks
46 |
47 | * [Realm] - Offline storage
48 |
49 | ### [SwiftDailyAPI]
50 |
51 | Framework I write to help myself building this App and possibly an Mac version
52 | of this App, also to help people who may want to build one themselves.
53 |
54 | #### Using
55 |
56 | * [Alamofire] - Elegant HTTP networking
57 | * [Argo] - Functional JSON parsing
58 | * [Quick] - Testing
59 | * [Nimble] - Matcher
60 |
61 | ## Documentation
62 |
63 | * [Use Protocol as Function Parameter in Swift](http://dev.nicktd.com/tldr/2015/06/08/use-protocol-in-swift-as-function-parameter.html)
64 |
65 | ### Planned
66 |
67 | * ZhiHuDaily's API
68 | * How to use mitmproxy to reverse engineer an App's API
69 | * Using Core Data with Swift and Protocol
70 |
71 | ## Q&A
72 |
73 | ### About the branch model for `git`
74 |
75 | * master - stable release
76 | * develop - mainly developing on this branch
77 | * experiment/ - testing things I am not sure whether it will work out or not
78 | * feature/ - building features
79 |
80 | ### There is already an official ZhihuDaily App. Why another?
81 |
82 | The official App can do lots of things, e.g. load the latest news, show detail news content, likes and comments, etc.
83 |
84 | However, it is missing some features that I would like to have.
85 |
86 | For example, as I mentioned at the top, because of network latency it takes
87 | about 3-5 seconds to load the content of a News, if you are using the official
88 | App outside of China. And I hate waiting. It's a waste of my time and my life. I
89 | want to be able to save multiple News' contents before I read it so that I don't
90 | have to wait for the loading screen. This is the main reason why I made this
91 | App, to save time and life, mine and also others'.
92 |
93 | Another thing is that the official App also tracks user behaviour and gives this
94 | information to a third party company in China. I just don't like it.
95 |
96 | ## APPENDIX
97 |
98 | ### ZhiHu
99 |
100 | From Wikipedia:
101 | "Zhihu" is a Chinese question-and-answer website. It has a similar product model as Quora.
102 |
103 | [link to wiki page](http://en.wikipedia.org/wiki/Zhihu)
104 |
105 | ### ZhihuDaily
106 |
107 | Daily highly-rated answers in ZhiHu, which are picked by editors.
108 |
109 | ### Previous Version
110 |
111 | [DailyNews](https://github.com/NicholasTD07/ios-playgrounds/tree/all-merged/ios8-restkit-zhihu)
112 |
113 | Screeshot:
114 |
115 | 
116 |
117 | [Alamofire]: https://github.com/Alamofire/Alamofire
118 | [Argo]: https://github.com/thoughtbot/Argo
119 | [Quick]: https://github.com/Quick/Quick
120 | [Nimble]: https://github.com/Quick/Nimble
121 | [SwiftDailyAPI]: https://github.com/NicholasTD07/SwiftDailyAPI
122 | [Realm]: https://realm.io
123 |
--------------------------------------------------------------------------------
/Swift-ZHI.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 2D96E2C2697856C72E2AD083 /* Pods.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4879E42D2BF192538AA36F94 /* Pods.framework */; };
11 | 751788E91B3D47E700526889 /* DailyDates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 751788E81B3D47E700526889 /* DailyDates.swift */; };
12 | 7529FA421B3E5EF5007D54A8 /* NewsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7529FA411B3E5EF5007D54A8 /* NewsViewController.swift */; };
13 | 7529FA441B3E6B68007D54A8 /* RealmNewsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7529FA431B3E6B68007D54A8 /* RealmNewsViewController.swift */; };
14 | 7530F3FD1B3D53D10035AD7A /* DailyTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7530F3FC1B3D53D10035AD7A /* DailyTableViewController.swift */; };
15 | 7571839E1B4418ED00E345B3 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 757183A01B4418ED00E345B3 /* Main.storyboard */; };
16 | 757183A51B441CDA00E345B3 /* HideNavBarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 757183A41B441CDA00E345B3 /* HideNavBarViewController.swift */; };
17 | 757FEB891B3ACF5600B4F327 /* SwiftDaily_ZhiHuTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 757FEB881B3ACF5600B4F327 /* SwiftDaily_ZhiHuTests.swift */; };
18 | 757FEBC91B3ACFE200B4F327 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 757FEBA51B3ACFE100B4F327 /* AppDelegate.swift */; };
19 | 757FEBCB1B3ACFE200B4F327 /* HidesHairLineUnderNavBarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 757FEBA71B3ACFE100B4F327 /* HidesHairLineUnderNavBarViewController.swift */; };
20 | 757FEBCD1B3ACFE200B4F327 /* RealmDailyTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 757FEBA91B3ACFE100B4F327 /* RealmDailyTableViewController.swift */; };
21 | 757FEBD11B3ACFE200B4F327 /* RealmModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 757FEBB01B3ACFE100B4F327 /* RealmModels.swift */; };
22 | 757FEBD41B3ACFE200B4F327 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 757FEBB51B3ACFE100B4F327 /* Images.xcassets */; };
23 | 757FEBD71B3ACFE200B4F327 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 757FEBB91B3ACFE200B4F327 /* LaunchScreen.xib */; };
24 | 757FEBDA1B3ACFE200B4F327 /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 757FEBBD1B3ACFE200B4F327 /* Settings.bundle */; };
25 | 757FEBDF1B3ACFE200B4F327 /* DailySectionHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 757FEBC51B3ACFE200B4F327 /* DailySectionHeaderView.swift */; };
26 | 757FEBE01B3ACFE200B4F327 /* LoadingCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 757FEBC61B3ACFE200B4F327 /* LoadingCell.swift */; };
27 | 758872E91B6A12FC006ECF61 /* CommentSectionHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 758872E81B6A12FC006ECF61 /* CommentSectionHeaderView.swift */; };
28 | 758872EE1B6B1026006ECF61 /* CommentContentFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 758872ED1B6B1026006ECF61 /* CommentContentFormatter.swift */; };
29 | 758872FD1B70AE8B006ECF61 /* DailySectionHeaderView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 757FEBB81B3ACFE200B4F327 /* DailySectionHeaderView.xib */; };
30 | 758872FE1B70AE94006ECF61 /* CommentSectionHeaderView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 758872F41B70ACF5006ECF61 /* CommentSectionHeaderView.xib */; };
31 | 75AE08F21B65B12000462941 /* RealmCommentViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75AE08F11B65B12000462941 /* RealmCommentViewController.swift */; };
32 | 75B5F5FC1B44BA18001E1461 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 75D98CA81B44B93B001B4F9C /* InfoPlist.strings */; };
33 | 75B5F60A1B44BF2C001E1461 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 75B5F6081B44BF2C001E1461 /* Localizable.strings */; };
34 | 75CDD20C1B3BBB4A00343CAA /* DailyRealmStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75CDD20B1B3BBB4A00343CAA /* DailyRealmStore.swift */; };
35 | 75CDD20E1B3BBD3900343CAA /* RealmHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75CDD20D1B3BBD3900343CAA /* RealmHelpers.swift */; };
36 | 75D98CAB1B44B93C001B4F9C /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 75D98CAD1B44B93C001B4F9C /* InfoPlist.strings */; };
37 | 75EDD0C91B55340300C3DC41 /* UserPreferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75EDD0C81B55340300C3DC41 /* UserPreferences.swift */; };
38 | 75EF90F61B50E2D4006D008B /* Delay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 75EF90F51B50E2D4006D008B /* Delay.swift */; };
39 | /* End PBXBuildFile section */
40 |
41 | /* Begin PBXContainerItemProxy section */
42 | 757FEB851B3ACF5600B4F327 /* PBXContainerItemProxy */ = {
43 | isa = PBXContainerItemProxy;
44 | containerPortal = 757FEB681B3ACF5600B4F327 /* Project object */;
45 | proxyType = 1;
46 | remoteGlobalIDString = 757FEB6F1B3ACF5600B4F327;
47 | remoteInfo = "SwiftDaily-ZhiHu";
48 | };
49 | /* End PBXContainerItemProxy section */
50 |
51 | /* Begin PBXFileReference section */
52 | 4879E42D2BF192538AA36F94 /* Pods.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods.framework; sourceTree = BUILT_PRODUCTS_DIR; };
53 | 6115B445073C89C047AB9EBB /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = ""; };
54 | 751788E81B3D47E700526889 /* DailyDates.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DailyDates.swift; sourceTree = ""; };
55 | 7529FA411B3E5EF5007D54A8 /* NewsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NewsViewController.swift; sourceTree = ""; };
56 | 7529FA431B3E6B68007D54A8 /* RealmNewsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RealmNewsViewController.swift; sourceTree = ""; };
57 | 7530F3FC1B3D53D10035AD7A /* DailyTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DailyTableViewController.swift; sourceTree = ""; };
58 | 75656D011B46549E007D11EA /* Realm.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Realm.framework; path = "Carthage/Checkouts/realm-cocoa/build/ios/swift/Realm.framework"; sourceTree = ""; };
59 | 75656D021B46549E007D11EA /* RealmSwift.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RealmSwift.framework; path = "Carthage/Checkouts/realm-cocoa/build/ios/swift/RealmSwift.framework"; sourceTree = ""; };
60 | 75656D091B4659B4007D11EA /* Box.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Box.framework; path = Carthage/Build/iOS/Box.framework; sourceTree = ""; };
61 | 757183A11B4418F300E345B3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
62 | 757183A41B441CDA00E345B3 /* HideNavBarViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HideNavBarViewController.swift; sourceTree = ""; };
63 | 757FEB701B3ACF5600B4F327 /* Swift-ZHI.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Swift-ZHI.app"; sourceTree = BUILT_PRODUCTS_DIR; };
64 | 757FEB841B3ACF5600B4F327 /* Swift-ZHITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Swift-ZHITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
65 | 757FEB881B3ACF5600B4F327 /* SwiftDaily_ZhiHuTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftDaily_ZhiHuTests.swift; sourceTree = ""; };
66 | 757FEB8A1B3ACF5600B4F327 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
67 | 757FEB931B3ACF5600B4F327 /* SwiftDaily_ZhiHuUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftDaily_ZhiHuUITests.swift; sourceTree = ""; };
68 | 757FEB951B3ACF5600B4F327 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
69 | 757FEBA51B3ACFE100B4F327 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
70 | 757FEBA71B3ACFE100B4F327 /* HidesHairLineUnderNavBarViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HidesHairLineUnderNavBarViewController.swift; sourceTree = ""; };
71 | 757FEBA91B3ACFE100B4F327 /* RealmDailyTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RealmDailyTableViewController.swift; sourceTree = ""; };
72 | 757FEBB01B3ACFE100B4F327 /* RealmModels.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RealmModels.swift; sourceTree = ""; };
73 | 757FEBB51B3ACFE100B4F327 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
74 | 757FEBB81B3ACFE200B4F327 /* DailySectionHeaderView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = DailySectionHeaderView.xib; sourceTree = ""; };
75 | 757FEBB91B3ACFE200B4F327 /* LaunchScreen.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = LaunchScreen.xib; sourceTree = ""; };
76 | 757FEBBD1B3ACFE200B4F327 /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = ""; };
77 | 757FEBC51B3ACFE200B4F327 /* DailySectionHeaderView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DailySectionHeaderView.swift; sourceTree = ""; };
78 | 757FEBC61B3ACFE200B4F327 /* LoadingCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoadingCell.swift; sourceTree = ""; };
79 | 757FEBE11B3AD0C800B4F327 /* Alamofire.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Alamofire.framework; path = Carthage/Build/iOS/Alamofire.framework; sourceTree = ""; };
80 | 757FEBE21B3AD0C800B4F327 /* AMScrollingNavbar.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AMScrollingNavbar.framework; path = Carthage/Build/iOS/AMScrollingNavbar.framework; sourceTree = ""; };
81 | 757FEBE31B3AD0C800B4F327 /* Argo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Argo.framework; path = Carthage/Build/iOS/Argo.framework; sourceTree = ""; };
82 | 757FEBE41B3AD0C800B4F327 /* Runes.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Runes.framework; path = Carthage/Build/iOS/Runes.framework; sourceTree = ""; };
83 | 757FEBE51B3AD0C800B4F327 /* SwiftDailyAPI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftDailyAPI.framework; path = Carthage/Build/iOS/SwiftDailyAPI.framework; sourceTree = ""; };
84 | 758872E81B6A12FC006ECF61 /* CommentSectionHeaderView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommentSectionHeaderView.swift; sourceTree = ""; };
85 | 758872ED1B6B1026006ECF61 /* CommentContentFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommentContentFormatter.swift; sourceTree = ""; };
86 | 758872F31B70ACF5006ECF61 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/CommentSectionHeaderView.xib; sourceTree = ""; };
87 | 758872F61B70AD04006ECF61 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/CommentSectionHeaderView.strings"; sourceTree = ""; };
88 | 758872F81B70AD05006ECF61 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/CommentSectionHeaderView.strings"; sourceTree = ""; };
89 | 758872FA1B70AD6A006ECF61 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Main.strings"; sourceTree = ""; };
90 | 758872FC1B70AD71006ECF61 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/Main.strings"; sourceTree = ""; };
91 | 758F0B921B9888C8006B6842 /* WebImage.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebImage.framework; path = Carthage/Build/iOS/WebImage.framework; sourceTree = ""; };
92 | 75AE08F11B65B12000462941 /* RealmCommentViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RealmCommentViewController.swift; sourceTree = ""; };
93 | 75B5F5F71B44B97D001E1461 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/InfoPlist.strings"; sourceTree = ""; };
94 | 75B5F5F81B44B97D001E1461 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/InfoPlist.strings"; sourceTree = ""; };
95 | 75B5F5F91B44B97E001E1461 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/InfoPlist.strings"; sourceTree = ""; };
96 | 75B5F6091B44BF2C001E1461 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = "SwiftDaily-ZhiHu/Resources/Base.lproj/Localizable.strings"; sourceTree = SOURCE_ROOT; };
97 | 75B5F60B1B44BF37001E1461 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "SwiftDaily-ZhiHu/Resources/zh-Hans.lproj/Localizable.strings"; sourceTree = SOURCE_ROOT; };
98 | 75B5F60C1B44BF3E001E1461 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "SwiftDaily-ZhiHu/Resources/zh-Hant.lproj/Localizable.strings"; sourceTree = SOURCE_ROOT; };
99 | 75CDD20B1B3BBB4A00343CAA /* DailyRealmStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DailyRealmStore.swift; sourceTree = ""; };
100 | 75CDD20D1B3BBD3900343CAA /* RealmHelpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RealmHelpers.swift; sourceTree = ""; };
101 | 75D98C9D1B44B704001B4F9C /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
102 | 75D98CA71B44B93B001B4F9C /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/InfoPlist.strings"; sourceTree = ""; };
103 | 75D98CAC1B44B93C001B4F9C /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/InfoPlist.strings"; sourceTree = ""; };
104 | 75D98CB11B44B93C001B4F9C /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/InfoPlist.strings"; sourceTree = ""; };
105 | 75E2E5AE1B46B24200E26DD0 /* zh-Hans.xliff */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = "zh-Hans.xliff"; sourceTree = ""; };
106 | 75E2E5AF1B46B24200E26DD0 /* zh-Hant.xliff */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = "zh-Hant.xliff"; sourceTree = ""; };
107 | 75EDD0C81B55340300C3DC41 /* UserPreferences.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserPreferences.swift; sourceTree = ""; };
108 | 75EF90F51B50E2D4006D008B /* Delay.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Delay.swift; sourceTree = ""; };
109 | 83EB994A3DBD56F213E19F2B /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = ""; };
110 | /* End PBXFileReference section */
111 |
112 | /* Begin PBXFrameworksBuildPhase section */
113 | 757FEB6D1B3ACF5600B4F327 /* Frameworks */ = {
114 | isa = PBXFrameworksBuildPhase;
115 | buildActionMask = 2147483647;
116 | files = (
117 | 2D96E2C2697856C72E2AD083 /* Pods.framework in Frameworks */,
118 | );
119 | runOnlyForDeploymentPostprocessing = 0;
120 | };
121 | 757FEB811B3ACF5600B4F327 /* Frameworks */ = {
122 | isa = PBXFrameworksBuildPhase;
123 | buildActionMask = 2147483647;
124 | files = (
125 | );
126 | runOnlyForDeploymentPostprocessing = 0;
127 | };
128 | /* End PBXFrameworksBuildPhase section */
129 |
130 | /* Begin PBXGroup section */
131 | 757FEB671B3ACF5600B4F327 = {
132 | isa = PBXGroup;
133 | children = (
134 | 757FEBA11B3ACFE100B4F327 /* SwiftDaily-ZhiHu */,
135 | 757FEB871B3ACF5600B4F327 /* SwiftDaily-ZhiHuTests */,
136 | 757FEB921B3ACF5600B4F327 /* SwiftDaily-ZhiHuUITests */,
137 | 757FEBEB1B3AD0D300B4F327 /* Frameworks */,
138 | 757FEB711B3ACF5600B4F327 /* Products */,
139 | CC2923247F366A7C2E322078 /* Pods */,
140 | );
141 | sourceTree = "";
142 | };
143 | 757FEB711B3ACF5600B4F327 /* Products */ = {
144 | isa = PBXGroup;
145 | children = (
146 | 757FEB701B3ACF5600B4F327 /* Swift-ZHI.app */,
147 | 757FEB841B3ACF5600B4F327 /* Swift-ZHITests.xctest */,
148 | );
149 | name = Products;
150 | sourceTree = "";
151 | };
152 | 757FEB871B3ACF5600B4F327 /* SwiftDaily-ZhiHuTests */ = {
153 | isa = PBXGroup;
154 | children = (
155 | 75D98CAD1B44B93C001B4F9C /* InfoPlist.strings */,
156 | 757FEB881B3ACF5600B4F327 /* SwiftDaily_ZhiHuTests.swift */,
157 | 757FEB8A1B3ACF5600B4F327 /* Info.plist */,
158 | );
159 | path = "SwiftDaily-ZhiHuTests";
160 | sourceTree = "";
161 | };
162 | 757FEB921B3ACF5600B4F327 /* SwiftDaily-ZhiHuUITests */ = {
163 | isa = PBXGroup;
164 | children = (
165 | 75D98CB21B44B93C001B4F9C /* InfoPlist.strings */,
166 | 757FEB931B3ACF5600B4F327 /* SwiftDaily_ZhiHuUITests.swift */,
167 | 757FEB951B3ACF5600B4F327 /* Info.plist */,
168 | );
169 | path = "SwiftDaily-ZhiHuUITests";
170 | sourceTree = "";
171 | };
172 | 757FEBA11B3ACFE100B4F327 /* SwiftDaily-ZhiHu */ = {
173 | isa = PBXGroup;
174 | children = (
175 | 757FEBA31B3ACFE100B4F327 /* Controllers */,
176 | 757FEBAA1B3ACFE100B4F327 /* Extensions */,
177 | 757FEBAC1B3ACFE100B4F327 /* Helpers */,
178 | 757FEBAE1B3ACFE100B4F327 /* Models */,
179 | 757FEBB11B3ACFE100B4F327 /* Protocols */,
180 | 757FEBB31B3ACFE100B4F327 /* Resources */,
181 | 757FEBC11B3ACFE200B4F327 /* ViewModels */,
182 | 757FEBC31B3ACFE200B4F327 /* Views */,
183 | );
184 | path = "SwiftDaily-ZhiHu";
185 | sourceTree = "";
186 | };
187 | 757FEBA31B3ACFE100B4F327 /* Controllers */ = {
188 | isa = PBXGroup;
189 | children = (
190 | 757FEBA51B3ACFE100B4F327 /* AppDelegate.swift */,
191 | 7530F3FC1B3D53D10035AD7A /* DailyTableViewController.swift */,
192 | 757183A41B441CDA00E345B3 /* HideNavBarViewController.swift */,
193 | 757FEBA71B3ACFE100B4F327 /* HidesHairLineUnderNavBarViewController.swift */,
194 | 7529FA411B3E5EF5007D54A8 /* NewsViewController.swift */,
195 | 757FEBA91B3ACFE100B4F327 /* RealmDailyTableViewController.swift */,
196 | 7529FA431B3E6B68007D54A8 /* RealmNewsViewController.swift */,
197 | 75AE08F11B65B12000462941 /* RealmCommentViewController.swift */,
198 | );
199 | path = Controllers;
200 | sourceTree = "";
201 | };
202 | 757FEBAA1B3ACFE100B4F327 /* Extensions */ = {
203 | isa = PBXGroup;
204 | children = (
205 | );
206 | path = Extensions;
207 | sourceTree = "";
208 | };
209 | 757FEBAC1B3ACFE100B4F327 /* Helpers */ = {
210 | isa = PBXGroup;
211 | children = (
212 | 751788E81B3D47E700526889 /* DailyDates.swift */,
213 | 75CDD20D1B3BBD3900343CAA /* RealmHelpers.swift */,
214 | 75EF90F51B50E2D4006D008B /* Delay.swift */,
215 | 758872ED1B6B1026006ECF61 /* CommentContentFormatter.swift */,
216 | );
217 | path = Helpers;
218 | sourceTree = "";
219 | };
220 | 757FEBAE1B3ACFE100B4F327 /* Models */ = {
221 | isa = PBXGroup;
222 | children = (
223 | 757FEBB01B3ACFE100B4F327 /* RealmModels.swift */,
224 | 75CDD20B1B3BBB4A00343CAA /* DailyRealmStore.swift */,
225 | 75EDD0C81B55340300C3DC41 /* UserPreferences.swift */,
226 | );
227 | path = Models;
228 | sourceTree = "";
229 | };
230 | 757FEBB11B3ACFE100B4F327 /* Protocols */ = {
231 | isa = PBXGroup;
232 | children = (
233 | );
234 | path = Protocols;
235 | sourceTree = "";
236 | };
237 | 757FEBB31B3ACFE100B4F327 /* Resources */ = {
238 | isa = PBXGroup;
239 | children = (
240 | 75D98C9D1B44B704001B4F9C /* Info.plist */,
241 | 757FEBB51B3ACFE100B4F327 /* Images.xcassets */,
242 | 75D98C9F1B44B920001B4F9C /* Localizations */,
243 | 757FEBB61B3ACFE100B4F327 /* Nibs */,
244 | 757FEBBD1B3ACFE200B4F327 /* Settings.bundle */,
245 | 757FEBBE1B3ACFE200B4F327 /* Storyboards */,
246 | );
247 | path = Resources;
248 | sourceTree = "";
249 | };
250 | 757FEBB61B3ACFE100B4F327 /* Nibs */ = {
251 | isa = PBXGroup;
252 | children = (
253 | 757FEBB81B3ACFE200B4F327 /* DailySectionHeaderView.xib */,
254 | 757FEBB91B3ACFE200B4F327 /* LaunchScreen.xib */,
255 | 758872F41B70ACF5006ECF61 /* CommentSectionHeaderView.xib */,
256 | );
257 | path = Nibs;
258 | sourceTree = "";
259 | };
260 | 757FEBBE1B3ACFE200B4F327 /* Storyboards */ = {
261 | isa = PBXGroup;
262 | children = (
263 | 757183A01B4418ED00E345B3 /* Main.storyboard */,
264 | );
265 | path = Storyboards;
266 | sourceTree = "";
267 | };
268 | 757FEBC11B3ACFE200B4F327 /* ViewModels */ = {
269 | isa = PBXGroup;
270 | children = (
271 | );
272 | path = ViewModels;
273 | sourceTree = "";
274 | };
275 | 757FEBC31B3ACFE200B4F327 /* Views */ = {
276 | isa = PBXGroup;
277 | children = (
278 | 757FEBC51B3ACFE200B4F327 /* DailySectionHeaderView.swift */,
279 | 757FEBC61B3ACFE200B4F327 /* LoadingCell.swift */,
280 | 758872E81B6A12FC006ECF61 /* CommentSectionHeaderView.swift */,
281 | );
282 | path = Views;
283 | sourceTree = "";
284 | };
285 | 757FEBEB1B3AD0D300B4F327 /* Frameworks */ = {
286 | isa = PBXGroup;
287 | children = (
288 | 758F0B921B9888C8006B6842 /* WebImage.framework */,
289 | 757FEBE31B3AD0C800B4F327 /* Argo.framework */,
290 | 75656D091B4659B4007D11EA /* Box.framework */,
291 | 75656D011B46549E007D11EA /* Realm.framework */,
292 | 75656D021B46549E007D11EA /* RealmSwift.framework */,
293 | 757FEBE11B3AD0C800B4F327 /* Alamofire.framework */,
294 | 757FEBE21B3AD0C800B4F327 /* AMScrollingNavbar.framework */,
295 | 757FEBE41B3AD0C800B4F327 /* Runes.framework */,
296 | 757FEBE51B3AD0C800B4F327 /* SwiftDailyAPI.framework */,
297 | 4879E42D2BF192538AA36F94 /* Pods.framework */,
298 | );
299 | name = Frameworks;
300 | sourceTree = "";
301 | };
302 | 75D98C9F1B44B920001B4F9C /* Localizations */ = {
303 | isa = PBXGroup;
304 | children = (
305 | 75D98CA81B44B93B001B4F9C /* InfoPlist.strings */,
306 | 75B5F6081B44BF2C001E1461 /* Localizable.strings */,
307 | 75E2E5AD1B46B24200E26DD0 /* Swift-ZHI */,
308 | );
309 | path = Localizations;
310 | sourceTree = "";
311 | };
312 | 75E2E5AD1B46B24200E26DD0 /* Swift-ZHI */ = {
313 | isa = PBXGroup;
314 | children = (
315 | 75E2E5AE1B46B24200E26DD0 /* zh-Hans.xliff */,
316 | 75E2E5AF1B46B24200E26DD0 /* zh-Hant.xliff */,
317 | );
318 | path = "Swift-ZHI";
319 | sourceTree = "";
320 | };
321 | CC2923247F366A7C2E322078 /* Pods */ = {
322 | isa = PBXGroup;
323 | children = (
324 | 83EB994A3DBD56F213E19F2B /* Pods.debug.xcconfig */,
325 | 6115B445073C89C047AB9EBB /* Pods.release.xcconfig */,
326 | );
327 | name = Pods;
328 | sourceTree = "";
329 | };
330 | /* End PBXGroup section */
331 |
332 | /* Begin PBXNativeTarget section */
333 | 757FEB6F1B3ACF5600B4F327 /* Swift-ZHI */ = {
334 | isa = PBXNativeTarget;
335 | buildConfigurationList = 757FEB981B3ACF5600B4F327 /* Build configuration list for PBXNativeTarget "Swift-ZHI" */;
336 | buildPhases = (
337 | DBD108EAE0BDD61F51EDD061 /* Check Pods Manifest.lock */,
338 | 757FEB6C1B3ACF5600B4F327 /* Sources */,
339 | 757FEB6D1B3ACF5600B4F327 /* Frameworks */,
340 | 757FEB6E1B3ACF5600B4F327 /* Resources */,
341 | 75B5F60D1B44BF70001E1461 /* genstrings */,
342 | D95A75E2DF6A4894F1E2968D /* Embed Pods Frameworks */,
343 | 8CA5F546ECEC4BDE500DFC3E /* Copy Pods Resources */,
344 | );
345 | buildRules = (
346 | );
347 | dependencies = (
348 | );
349 | name = "Swift-ZHI";
350 | productName = "SwiftDaily-ZhiHu";
351 | productReference = 757FEB701B3ACF5600B4F327 /* Swift-ZHI.app */;
352 | productType = "com.apple.product-type.application";
353 | };
354 | 757FEB831B3ACF5600B4F327 /* Swift-ZHITests */ = {
355 | isa = PBXNativeTarget;
356 | buildConfigurationList = 757FEB9B1B3ACF5600B4F327 /* Build configuration list for PBXNativeTarget "Swift-ZHITests" */;
357 | buildPhases = (
358 | 757FEB801B3ACF5600B4F327 /* Sources */,
359 | 757FEB811B3ACF5600B4F327 /* Frameworks */,
360 | 757FEB821B3ACF5600B4F327 /* Resources */,
361 | );
362 | buildRules = (
363 | );
364 | dependencies = (
365 | 757FEB861B3ACF5600B4F327 /* PBXTargetDependency */,
366 | );
367 | name = "Swift-ZHITests";
368 | productName = "SwiftDaily-ZhiHuTests";
369 | productReference = 757FEB841B3ACF5600B4F327 /* Swift-ZHITests.xctest */;
370 | productType = "com.apple.product-type.bundle.unit-test";
371 | };
372 | /* End PBXNativeTarget section */
373 |
374 | /* Begin PBXProject section */
375 | 757FEB681B3ACF5600B4F327 /* Project object */ = {
376 | isa = PBXProject;
377 | attributes = {
378 | LastSwiftMigration = 0730;
379 | LastSwiftUpdateCheck = 0700;
380 | LastUpgradeCheck = 0700;
381 | ORGANIZATIONNAME = nickTD;
382 | TargetAttributes = {
383 | 757FEB6F1B3ACF5600B4F327 = {
384 | CreatedOnToolsVersion = 7.0;
385 | };
386 | 757FEB831B3ACF5600B4F327 = {
387 | CreatedOnToolsVersion = 7.0;
388 | TestTargetID = 757FEB6F1B3ACF5600B4F327;
389 | };
390 | };
391 | };
392 | buildConfigurationList = 757FEB6B1B3ACF5600B4F327 /* Build configuration list for PBXProject "Swift-ZHI" */;
393 | compatibilityVersion = "Xcode 3.2";
394 | developmentRegion = English;
395 | hasScannedForEncodings = 0;
396 | knownRegions = (
397 | en,
398 | Base,
399 | "zh-Hans",
400 | "zh-Hant",
401 | );
402 | mainGroup = 757FEB671B3ACF5600B4F327;
403 | productRefGroup = 757FEB711B3ACF5600B4F327 /* Products */;
404 | projectDirPath = "";
405 | projectRoot = "";
406 | targets = (
407 | 757FEB6F1B3ACF5600B4F327 /* Swift-ZHI */,
408 | 757FEB831B3ACF5600B4F327 /* Swift-ZHITests */,
409 | );
410 | };
411 | /* End PBXProject section */
412 |
413 | /* Begin PBXResourcesBuildPhase section */
414 | 757FEB6E1B3ACF5600B4F327 /* Resources */ = {
415 | isa = PBXResourcesBuildPhase;
416 | buildActionMask = 2147483647;
417 | files = (
418 | 758872FE1B70AE94006ECF61 /* CommentSectionHeaderView.xib in Resources */,
419 | 758872FD1B70AE8B006ECF61 /* DailySectionHeaderView.xib in Resources */,
420 | 75B5F5FC1B44BA18001E1461 /* InfoPlist.strings in Resources */,
421 | 757FEBD41B3ACFE200B4F327 /* Images.xcassets in Resources */,
422 | 75B5F60A1B44BF2C001E1461 /* Localizable.strings in Resources */,
423 | 757FEBDA1B3ACFE200B4F327 /* Settings.bundle in Resources */,
424 | 7571839E1B4418ED00E345B3 /* Main.storyboard in Resources */,
425 | 757FEBD71B3ACFE200B4F327 /* LaunchScreen.xib in Resources */,
426 | );
427 | runOnlyForDeploymentPostprocessing = 0;
428 | };
429 | 757FEB821B3ACF5600B4F327 /* Resources */ = {
430 | isa = PBXResourcesBuildPhase;
431 | buildActionMask = 2147483647;
432 | files = (
433 | 75D98CAB1B44B93C001B4F9C /* InfoPlist.strings in Resources */,
434 | );
435 | runOnlyForDeploymentPostprocessing = 0;
436 | };
437 | /* End PBXResourcesBuildPhase section */
438 |
439 | /* Begin PBXShellScriptBuildPhase section */
440 | 75B5F60D1B44BF70001E1461 /* genstrings */ = {
441 | isa = PBXShellScriptBuildPhase;
442 | buildActionMask = 2147483647;
443 | files = (
444 | );
445 | inputPaths = (
446 | );
447 | name = genstrings;
448 | outputPaths = (
449 | );
450 | runOnlyForDeploymentPostprocessing = 0;
451 | shellPath = /bin/sh;
452 | shellScript = "cd $PROJECT_DIR && find ./SwiftDaily-Zhihu -name \\*.swift | xargs genstrings -o SwiftDaily-ZhiHu/Resources/Base.lproj/";
453 | };
454 | 8CA5F546ECEC4BDE500DFC3E /* Copy Pods Resources */ = {
455 | isa = PBXShellScriptBuildPhase;
456 | buildActionMask = 2147483647;
457 | files = (
458 | );
459 | inputPaths = (
460 | );
461 | name = "Copy Pods Resources";
462 | outputPaths = (
463 | );
464 | runOnlyForDeploymentPostprocessing = 0;
465 | shellPath = /bin/sh;
466 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n";
467 | showEnvVarsInLog = 0;
468 | };
469 | D95A75E2DF6A4894F1E2968D /* Embed Pods Frameworks */ = {
470 | isa = PBXShellScriptBuildPhase;
471 | buildActionMask = 2147483647;
472 | files = (
473 | );
474 | inputPaths = (
475 | );
476 | name = "Embed Pods Frameworks";
477 | outputPaths = (
478 | );
479 | runOnlyForDeploymentPostprocessing = 0;
480 | shellPath = /bin/sh;
481 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-frameworks.sh\"\n";
482 | showEnvVarsInLog = 0;
483 | };
484 | DBD108EAE0BDD61F51EDD061 /* Check Pods Manifest.lock */ = {
485 | isa = PBXShellScriptBuildPhase;
486 | buildActionMask = 2147483647;
487 | files = (
488 | );
489 | inputPaths = (
490 | );
491 | name = "Check Pods Manifest.lock";
492 | outputPaths = (
493 | );
494 | runOnlyForDeploymentPostprocessing = 0;
495 | shellPath = /bin/sh;
496 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
497 | showEnvVarsInLog = 0;
498 | };
499 | /* End PBXShellScriptBuildPhase section */
500 |
501 | /* Begin PBXSourcesBuildPhase section */
502 | 757FEB6C1B3ACF5600B4F327 /* Sources */ = {
503 | isa = PBXSourcesBuildPhase;
504 | buildActionMask = 2147483647;
505 | files = (
506 | 751788E91B3D47E700526889 /* DailyDates.swift in Sources */,
507 | 7529FA441B3E6B68007D54A8 /* RealmNewsViewController.swift in Sources */,
508 | 757FEBCD1B3ACFE200B4F327 /* RealmDailyTableViewController.swift in Sources */,
509 | 757FEBCB1B3ACFE200B4F327 /* HidesHairLineUnderNavBarViewController.swift in Sources */,
510 | 757FEBE01B3ACFE200B4F327 /* LoadingCell.swift in Sources */,
511 | 75CDD20C1B3BBB4A00343CAA /* DailyRealmStore.swift in Sources */,
512 | 757FEBC91B3ACFE200B4F327 /* AppDelegate.swift in Sources */,
513 | 7529FA421B3E5EF5007D54A8 /* NewsViewController.swift in Sources */,
514 | 758872E91B6A12FC006ECF61 /* CommentSectionHeaderView.swift in Sources */,
515 | 75CDD20E1B3BBD3900343CAA /* RealmHelpers.swift in Sources */,
516 | 757FEBD11B3ACFE200B4F327 /* RealmModels.swift in Sources */,
517 | 75EDD0C91B55340300C3DC41 /* UserPreferences.swift in Sources */,
518 | 758872EE1B6B1026006ECF61 /* CommentContentFormatter.swift in Sources */,
519 | 757FEBDF1B3ACFE200B4F327 /* DailySectionHeaderView.swift in Sources */,
520 | 75AE08F21B65B12000462941 /* RealmCommentViewController.swift in Sources */,
521 | 75EF90F61B50E2D4006D008B /* Delay.swift in Sources */,
522 | 757183A51B441CDA00E345B3 /* HideNavBarViewController.swift in Sources */,
523 | 7530F3FD1B3D53D10035AD7A /* DailyTableViewController.swift in Sources */,
524 | );
525 | runOnlyForDeploymentPostprocessing = 0;
526 | };
527 | 757FEB801B3ACF5600B4F327 /* Sources */ = {
528 | isa = PBXSourcesBuildPhase;
529 | buildActionMask = 2147483647;
530 | files = (
531 | 757FEB891B3ACF5600B4F327 /* SwiftDaily_ZhiHuTests.swift in Sources */,
532 | );
533 | runOnlyForDeploymentPostprocessing = 0;
534 | };
535 | /* End PBXSourcesBuildPhase section */
536 |
537 | /* Begin PBXTargetDependency section */
538 | 757FEB861B3ACF5600B4F327 /* PBXTargetDependency */ = {
539 | isa = PBXTargetDependency;
540 | target = 757FEB6F1B3ACF5600B4F327 /* Swift-ZHI */;
541 | targetProxy = 757FEB851B3ACF5600B4F327 /* PBXContainerItemProxy */;
542 | };
543 | /* End PBXTargetDependency section */
544 |
545 | /* Begin PBXVariantGroup section */
546 | 757183A01B4418ED00E345B3 /* Main.storyboard */ = {
547 | isa = PBXVariantGroup;
548 | children = (
549 | 757183A11B4418F300E345B3 /* Base */,
550 | 758872FA1B70AD6A006ECF61 /* zh-Hans */,
551 | 758872FC1B70AD71006ECF61 /* zh-Hant */,
552 | );
553 | name = Main.storyboard;
554 | sourceTree = "";
555 | };
556 | 758872F41B70ACF5006ECF61 /* CommentSectionHeaderView.xib */ = {
557 | isa = PBXVariantGroup;
558 | children = (
559 | 758872F31B70ACF5006ECF61 /* Base */,
560 | 758872F61B70AD04006ECF61 /* zh-Hans */,
561 | 758872F81B70AD05006ECF61 /* zh-Hant */,
562 | );
563 | name = CommentSectionHeaderView.xib;
564 | sourceTree = "";
565 | };
566 | 75B5F6081B44BF2C001E1461 /* Localizable.strings */ = {
567 | isa = PBXVariantGroup;
568 | children = (
569 | 75B5F6091B44BF2C001E1461 /* Base */,
570 | 75B5F60B1B44BF37001E1461 /* zh-Hans */,
571 | 75B5F60C1B44BF3E001E1461 /* zh-Hant */,
572 | );
573 | name = Localizable.strings;
574 | sourceTree = "";
575 | };
576 | 75D98CA81B44B93B001B4F9C /* InfoPlist.strings */ = {
577 | isa = PBXVariantGroup;
578 | children = (
579 | 75D98CA71B44B93B001B4F9C /* zh-Hans */,
580 | 75B5F5F71B44B97D001E1461 /* zh-Hant */,
581 | );
582 | name = InfoPlist.strings;
583 | path = ..;
584 | sourceTree = "";
585 | };
586 | 75D98CAD1B44B93C001B4F9C /* InfoPlist.strings */ = {
587 | isa = PBXVariantGroup;
588 | children = (
589 | 75D98CAC1B44B93C001B4F9C /* zh-Hans */,
590 | 75B5F5F81B44B97D001E1461 /* zh-Hant */,
591 | );
592 | name = InfoPlist.strings;
593 | sourceTree = "";
594 | };
595 | 75D98CB21B44B93C001B4F9C /* InfoPlist.strings */ = {
596 | isa = PBXVariantGroup;
597 | children = (
598 | 75D98CB11B44B93C001B4F9C /* zh-Hans */,
599 | 75B5F5F91B44B97E001E1461 /* zh-Hant */,
600 | );
601 | name = InfoPlist.strings;
602 | sourceTree = "";
603 | };
604 | /* End PBXVariantGroup section */
605 |
606 | /* Begin XCBuildConfiguration section */
607 | 757FEB961B3ACF5600B4F327 /* Debug */ = {
608 | isa = XCBuildConfiguration;
609 | buildSettings = {
610 | ALWAYS_SEARCH_USER_PATHS = NO;
611 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
612 | CLANG_CXX_LIBRARY = "libc++";
613 | CLANG_ENABLE_MODULES = YES;
614 | CLANG_ENABLE_OBJC_ARC = YES;
615 | CLANG_WARN_BOOL_CONVERSION = YES;
616 | CLANG_WARN_CONSTANT_CONVERSION = YES;
617 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
618 | CLANG_WARN_EMPTY_BODY = YES;
619 | CLANG_WARN_ENUM_CONVERSION = YES;
620 | CLANG_WARN_INT_CONVERSION = YES;
621 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
622 | CLANG_WARN_UNREACHABLE_CODE = YES;
623 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
624 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
625 | COPY_PHASE_STRIP = NO;
626 | DEBUG_INFORMATION_FORMAT = dwarf;
627 | ENABLE_STRICT_OBJC_MSGSEND = YES;
628 | ENABLE_TESTABILITY = YES;
629 | FRAMEWORK_SEARCH_PATHS = "";
630 | GCC_C_LANGUAGE_STANDARD = gnu99;
631 | GCC_DYNAMIC_NO_PIC = NO;
632 | GCC_NO_COMMON_BLOCKS = YES;
633 | GCC_OPTIMIZATION_LEVEL = 0;
634 | GCC_PREPROCESSOR_DEFINITIONS = (
635 | "DEBUG=1",
636 | "$(inherited)",
637 | );
638 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
639 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
640 | GCC_WARN_UNDECLARED_SELECTOR = YES;
641 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
642 | GCC_WARN_UNUSED_FUNCTION = YES;
643 | GCC_WARN_UNUSED_VARIABLE = YES;
644 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
645 | MTL_ENABLE_DEBUG_INFO = YES;
646 | ONLY_ACTIVE_ARCH = YES;
647 | SDKROOT = iphoneos;
648 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
649 | };
650 | name = Debug;
651 | };
652 | 757FEB971B3ACF5600B4F327 /* Release */ = {
653 | isa = XCBuildConfiguration;
654 | buildSettings = {
655 | ALWAYS_SEARCH_USER_PATHS = NO;
656 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
657 | CLANG_CXX_LIBRARY = "libc++";
658 | CLANG_ENABLE_MODULES = YES;
659 | CLANG_ENABLE_OBJC_ARC = YES;
660 | CLANG_WARN_BOOL_CONVERSION = YES;
661 | CLANG_WARN_CONSTANT_CONVERSION = YES;
662 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
663 | CLANG_WARN_EMPTY_BODY = YES;
664 | CLANG_WARN_ENUM_CONVERSION = YES;
665 | CLANG_WARN_INT_CONVERSION = YES;
666 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
667 | CLANG_WARN_UNREACHABLE_CODE = YES;
668 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
669 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
670 | COPY_PHASE_STRIP = NO;
671 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
672 | ENABLE_NS_ASSERTIONS = NO;
673 | ENABLE_STRICT_OBJC_MSGSEND = YES;
674 | FRAMEWORK_SEARCH_PATHS = "";
675 | GCC_C_LANGUAGE_STANDARD = gnu99;
676 | GCC_NO_COMMON_BLOCKS = YES;
677 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
678 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
679 | GCC_WARN_UNDECLARED_SELECTOR = YES;
680 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
681 | GCC_WARN_UNUSED_FUNCTION = YES;
682 | GCC_WARN_UNUSED_VARIABLE = YES;
683 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
684 | MTL_ENABLE_DEBUG_INFO = NO;
685 | SDKROOT = iphoneos;
686 | VALIDATE_PRODUCT = YES;
687 | };
688 | name = Release;
689 | };
690 | 757FEB991B3ACF5600B4F327 /* Debug */ = {
691 | isa = XCBuildConfiguration;
692 | baseConfigurationReference = 83EB994A3DBD56F213E19F2B /* Pods.debug.xcconfig */;
693 | buildSettings = {
694 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
695 | ENABLE_BITCODE = NO;
696 | FRAMEWORK_SEARCH_PATHS = "";
697 | INFOPLIST_FILE = "$(SRCROOT)/SwiftDaily-ZhiHu/Resources/Info.plist";
698 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
699 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
700 | PRODUCT_BUNDLE_IDENTIFIER = "com.nickTD.Swift-ZHI";
701 | PRODUCT_NAME = "Swift-ZHI";
702 | TARGETED_DEVICE_FAMILY = "1,2";
703 | };
704 | name = Debug;
705 | };
706 | 757FEB9A1B3ACF5600B4F327 /* Release */ = {
707 | isa = XCBuildConfiguration;
708 | baseConfigurationReference = 6115B445073C89C047AB9EBB /* Pods.release.xcconfig */;
709 | buildSettings = {
710 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
711 | ENABLE_BITCODE = NO;
712 | FRAMEWORK_SEARCH_PATHS = "";
713 | INFOPLIST_FILE = "$(SRCROOT)/SwiftDaily-ZhiHu/Resources/Info.plist";
714 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
715 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
716 | PRODUCT_BUNDLE_IDENTIFIER = "com.nickTD.Swift-ZHI";
717 | PRODUCT_NAME = "Swift-ZHI";
718 | TARGETED_DEVICE_FAMILY = "1,2";
719 | };
720 | name = Release;
721 | };
722 | 757FEB9C1B3ACF5600B4F327 /* Debug */ = {
723 | isa = XCBuildConfiguration;
724 | buildSettings = {
725 | BUNDLE_LOADER = "$(TEST_HOST)";
726 | INFOPLIST_FILE = "SwiftDaily-ZhiHuTests/Info.plist";
727 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
728 | PRODUCT_BUNDLE_IDENTIFIER = "com.nickTD.SwiftDaily-ZhiHuTests";
729 | PRODUCT_NAME = "Swift-ZHITests";
730 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Swift-ZHI.app/Swift-ZHI";
731 | };
732 | name = Debug;
733 | };
734 | 757FEB9D1B3ACF5600B4F327 /* Release */ = {
735 | isa = XCBuildConfiguration;
736 | buildSettings = {
737 | BUNDLE_LOADER = "$(TEST_HOST)";
738 | INFOPLIST_FILE = "SwiftDaily-ZhiHuTests/Info.plist";
739 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
740 | PRODUCT_BUNDLE_IDENTIFIER = "com.nickTD.SwiftDaily-ZhiHuTests";
741 | PRODUCT_NAME = "Swift-ZHITests";
742 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Swift-ZHI.app/Swift-ZHI";
743 | };
744 | name = Release;
745 | };
746 | /* End XCBuildConfiguration section */
747 |
748 | /* Begin XCConfigurationList section */
749 | 757FEB6B1B3ACF5600B4F327 /* Build configuration list for PBXProject "Swift-ZHI" */ = {
750 | isa = XCConfigurationList;
751 | buildConfigurations = (
752 | 757FEB961B3ACF5600B4F327 /* Debug */,
753 | 757FEB971B3ACF5600B4F327 /* Release */,
754 | );
755 | defaultConfigurationIsVisible = 0;
756 | defaultConfigurationName = Release;
757 | };
758 | 757FEB981B3ACF5600B4F327 /* Build configuration list for PBXNativeTarget "Swift-ZHI" */ = {
759 | isa = XCConfigurationList;
760 | buildConfigurations = (
761 | 757FEB991B3ACF5600B4F327 /* Debug */,
762 | 757FEB9A1B3ACF5600B4F327 /* Release */,
763 | );
764 | defaultConfigurationIsVisible = 0;
765 | defaultConfigurationName = Release;
766 | };
767 | 757FEB9B1B3ACF5600B4F327 /* Build configuration list for PBXNativeTarget "Swift-ZHITests" */ = {
768 | isa = XCConfigurationList;
769 | buildConfigurations = (
770 | 757FEB9C1B3ACF5600B4F327 /* Debug */,
771 | 757FEB9D1B3ACF5600B4F327 /* Release */,
772 | );
773 | defaultConfigurationIsVisible = 0;
774 | defaultConfigurationName = Release;
775 | };
776 | /* End XCConfigurationList section */
777 | };
778 | rootObject = 757FEB681B3ACF5600B4F327 /* Project object */;
779 | }
780 |
--------------------------------------------------------------------------------
/Swift-ZHI.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Swift-ZHI.xcodeproj/xcshareddata/xcschemes/Swift-ZHI.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
16 |
22 |
23 |
24 |
25 |
26 |
31 |
32 |
34 |
40 |
41 |
42 |
43 |
44 |
50 |
51 |
52 |
53 |
54 |
55 |
65 |
67 |
73 |
74 |
75 |
76 |
77 |
78 |
84 |
86 |
92 |
93 |
94 |
95 |
97 |
98 |
101 |
102 |
103 |
--------------------------------------------------------------------------------
/Swift-ZHI.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NicholasTD07/Swift-ZHI/2a380d7855f2b55d1973ee59fbf2e5ca4c4b001f/SwiftDaily-ZhiHu/.gitkeep
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Controllers/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NicholasTD07/Swift-ZHI/2a380d7855f2b55d1973ee59fbf2e5ca4c4b001f/SwiftDaily-ZhiHu/Controllers/.gitkeep
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Controllers/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // SwiftDaily-ZhiHu
4 | //
5 | // Created by Nicholas Tian on 5/29/15
6 | // Copyright (c) 2015 nickTD. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 | var window: UIWindow?
14 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
15 | if let splitViewController = window!.rootViewController as? UISplitViewController {
16 | setUpSplitViewController(splitViewController)
17 | }
18 |
19 | UserPreferences.registerDefaults()
20 |
21 | return true
22 | }
23 | }
24 |
25 | extension AppDelegate {
26 | private func setUpSplitViewController(svc: UISplitViewController) {
27 | // TODO: Check whether next two lines is needed.
28 | let navigationController = svc.viewControllers[svc.viewControllers.count-1] as! UINavigationController
29 | navigationController.topViewController!.navigationItem.leftBarButtonItem = svc.displayModeButtonItem()
30 |
31 | svc.preferredDisplayMode = .AllVisible
32 | svc.delegate = self
33 | }
34 | }
35 |
36 | // MARK: - Split View Delegate
37 | extension AppDelegate: UISplitViewControllerDelegate {
38 | func splitViewController(splitViewController: UISplitViewController, collapseSecondaryViewController secondaryViewController:UIViewController, ontoPrimaryViewController primaryViewController:UIViewController) -> Bool {
39 | if let secondaryAsNavController = secondaryViewController as? UINavigationController {
40 | if let topAsDetailController = secondaryAsNavController.topViewController as? RealmNewsViewController {
41 | if topAsDetailController.newsId == nil {
42 | // Without this, RealmNewsViewController is first shown when on iPhone.
43 | return true
44 | }
45 | }
46 | }
47 |
48 | return false
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Controllers/DailyTableViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DailyTableViewController.swift
3 | // SwiftDaily-ZhiHu
4 | //
5 | // Created by Nicholas Tian on 26/06/2015.
6 | // Copyright © 2015 nickTD. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import AMScrollingNavbar
11 |
12 | class DailyTableViewController: HideNavBarViewController {
13 | // MARK: UI
14 | @IBOutlet weak var tableView: UITableView!
15 | let refreshControl: UIRefreshControl = UIRefreshControl()
16 |
17 | var firstAppeared = false
18 | let dateFormatter: NSDateFormatter = {
19 | let dateFormatter = NSDateFormatter()
20 | dateFormatter.dateStyle = NSDateFormatterStyle.MediumStyle
21 | return dateFormatter
22 | }()
23 | }
24 |
25 | // MARK: Abstract methods
26 | extension DailyTableViewController {
27 | func hasDailyAtIndexPath(indexPath: NSIndexPath) -> Bool {
28 | fatalError()
29 | }
30 |
31 | func hasNewsMetaAtIndexPath(indexPath: NSIndexPath) -> Bool {
32 | fatalError()
33 | }
34 |
35 | func hasNewsAtIndexPath(indexPath: NSIndexPath) -> Bool {
36 | return false
37 | }
38 |
39 | func dateStringAtSection(section: Int) -> String {
40 | fatalError()
41 | }
42 |
43 | func loadLatestDaily() {
44 | }
45 |
46 | func loadDailyAtIndexPath(indexPath: NSIndexPath) {
47 | }
48 |
49 | func loadNewsAtIndexPath(indexPath: NSIndexPath) {
50 | }
51 |
52 | func deleteNewsAtIndexPath(indexPath: NSIndexPath) {
53 | }
54 |
55 | // Will only be called if `hasNewsMetaAtIndexPath` returns `true`
56 | func cellAtIndexPath(indexPath: NSIndexPath) -> UITableViewCell {
57 | fatalError()
58 | }
59 | }
60 |
61 | // MARK: UI methods
62 | extension DailyTableViewController {
63 | override func viewDidLoad() {
64 | super.viewDidLoad()
65 |
66 | setupUi()
67 | }
68 |
69 | func setupUi() {
70 | refreshControl.addTarget(self, action: "refreshLatestDaily", forControlEvents: UIControlEvents.ValueChanged)
71 |
72 | tableView.addSubview(refreshControl)
73 | tableView.registerNib(UINib(nibName: "DailySectionHeaderView", bundle: nil), forHeaderFooterViewReuseIdentifier: "DailySectionHeaderView")
74 | }
75 |
76 |
77 | @IBAction func refreshLatestDaily() {
78 | loadLatestDaily()
79 | }
80 |
81 | override func viewWillAppear(animated: Bool) {
82 | super.viewWillAppear(animated)
83 |
84 | if !firstAppeared {
85 | beginRefreshing()
86 | firstAppeared = true
87 | loadLatestDaily()
88 | }
89 |
90 | if let indexPath = tableView.indexPathForSelectedRow {
91 | tableView.deselectRowAtIndexPath(indexPath, animated: true)
92 | }
93 | }
94 |
95 | func beginRefreshing() {
96 | tableView.setContentOffset(CGPoint(x: 0, y: -refreshControl.frame.size.height), animated: true)
97 | refreshControl.beginRefreshing()
98 | }
99 | }
100 |
101 | // MARK: Data Source
102 | extension DailyTableViewController {
103 | func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
104 | if hasNewsMetaAtIndexPath(indexPath) {
105 | return cellAtIndexPath(indexPath)
106 | } else {
107 | let loadingCell = tableView.dequeueReusableCellWithIdentifier("LoadingCell", forIndexPath: indexPath) as! LoadingCell
108 | loadingCell.activityIndicator.startAnimating()
109 | return loadingCell
110 | }
111 | }
112 |
113 | func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
114 | return true
115 | }
116 |
117 | func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
118 | }
119 | }
120 |
121 | // MARK: Delegate
122 | extension DailyTableViewController {
123 | func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
124 | if let header = tableView.dequeueReusableHeaderFooterViewWithIdentifier("DailySectionHeaderView") as? DailySectionHeaderView {
125 | header.backgroundView = {
126 | let view = UIView(frame: header.bounds)
127 | // HACK: To put color in Storyboard, not in code
128 | view.backgroundColor = header.titleLabel.highlightedTextColor
129 | return view
130 | }()
131 |
132 | header.titleLabel.text = self.dateStringAtSection(section)
133 |
134 | return header
135 | } else {
136 | return nil
137 | }
138 | }
139 |
140 | func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
141 | if let _ = cell as? LoadingCell where !hasDailyAtIndexPath(indexPath) {
142 | loadDailyAtIndexPath(indexPath)
143 | }
144 | }
145 |
146 | func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? {
147 | if hasNewsAtIndexPath(indexPath) {
148 | return [deleteNewsAction()]
149 | } else {
150 | return [downloadAndSaveNewsAction()]
151 | }
152 | }
153 |
154 | private func downloadAndSaveNewsAction() -> UITableViewRowAction {
155 | let download = NSLocalizedString("Download & Save",
156 | comment: "Download button in DailyView")
157 | let save = UITableViewRowAction(style: .Default, title: download)
158 | { (_, indexPath) in
159 | self.tableView.setEditing(false, animated: true)
160 | self.loadNewsAtIndexPath(indexPath)
161 | }
162 | save.backgroundColor = UIColor(hue: 0.353, saturation: 0.635, brightness: 0.765, alpha: 1)
163 |
164 | return save
165 | }
166 |
167 | private func deleteNewsAction() -> UITableViewRowAction {
168 | let deleteString = NSLocalizedString("Delete", comment: "Delete News button in DailyView")
169 | let deleteAction = UITableViewRowAction(style: .Default, title: deleteString)
170 | { (_, indexPath) in
171 | self.tableView.setEditing(false, animated: true)
172 |
173 | // HACK: To let the animation finish
174 | // before table view gets refreshed
175 | delay(0.3) {
176 | self.deleteNewsAtIndexPath(indexPath)
177 | }
178 | }
179 |
180 | return deleteAction
181 | }
182 | }
183 |
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Controllers/HideNavBarViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // HideNavBarViewController.swift
3 | // SwiftDaily-ZhiHu
4 | //
5 | // Created by Nicholas Tian on 1/07/2015.
6 | // Copyright © 2015 nickTD. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import AMScrollingNavbar
11 |
12 |
13 | class HideNavBarViewController: HidesHairLineUnderNavBarViewController {
14 | @IBOutlet weak var scrollableView: UIView!
15 | @IBOutlet weak var scrollableViewTopConstraint: NSLayoutConstraint!
16 |
17 | deinit {
18 | stopFollowingScrollView()
19 | }
20 | }
21 |
22 | // MARK: UI methods
23 | extension HideNavBarViewController {
24 | override func viewDidLoad() {
25 | super.viewDidLoad()
26 |
27 | followScrollView(scrollableView, usingTopConstraint: scrollableViewTopConstraint)
28 | }
29 |
30 | override func viewWillDisappear(animated: Bool) {
31 | showNavBarAnimated(false)
32 |
33 | super.viewWillDisappear(animated)
34 | }
35 | }
36 |
37 | extension HideNavBarViewController: UIScrollViewDelegate {
38 | func scrollViewShouldScrollToTop(scrollView: UIScrollView) -> Bool {
39 | // NOTE: Must set self to scrollView's delegate
40 | showNavbar()
41 |
42 | return true
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Controllers/HidesHairLineUnderNavBarViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // HidesHairLineUnderNavBarViewController.swift
3 | // SwiftDaily-ZhiHu
4 | //
5 | // Created by Nicholas Tian on 22/06/2015.
6 | // Copyright © 2015 nickTD. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class HidesHairLineUnderNavBarViewController: UIViewController {
12 |
13 | override func viewDidLoad() {
14 | super.viewDidLoad()
15 |
16 | // source: http://stackoverflow.com/questions/19226965/how-to-hide-ios7-uinavigationbar-1px-bottom-line
17 |
18 | if let bar = navigationController?.navigationBar {
19 | findHairLineImageViewUnder(bar)?.hidden = true
20 | }
21 |
22 | }
23 |
24 | private func findHairLineImageViewUnder(view: UIView) -> UIImageView? {
25 | if view.isKindOfClass(UIImageView.self) && view.bounds.size.height <= 1.0 {
26 | return view as? UIImageView
27 | }
28 |
29 | for subView in view.subviews {
30 | if let imageView = findHairLineImageViewUnder(subView ) {
31 | return imageView
32 | } else { continue }
33 | }
34 | return nil
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Controllers/NewsViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NewsViewController.swift
3 | // SwiftDaily-ZhiHu
4 | //
5 | // Created by Nicholas Tian on 27/06/2015.
6 | // Copyright © 2015 nickTD. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import AMScrollingNavbar
11 |
12 | class NewsViewController: HideNavBarViewController {
13 | // MARK: UI
14 | @IBOutlet weak var activityIndicator: UIActivityIndicatorView!
15 | @IBOutlet weak var webView: UIWebView!
16 | }
17 |
18 | // MARK: Abstract methods
19 | extension NewsViewController {
20 | func loadNews() {
21 | }
22 | }
23 |
24 | // MARK: UI methods
25 | extension NewsViewController {
26 | override func viewDidLoad() {
27 | super.viewDidLoad()
28 |
29 | webView.scrollView.delegate = self
30 | navigationItem.leftBarButtonItem = splitViewController?.displayModeButtonItem()
31 | }
32 |
33 | override func viewWillAppear(animated: Bool) {
34 | super.viewWillAppear(animated)
35 |
36 | loadNews()
37 | }
38 |
39 | override func viewWillDisappear(animated: Bool) {
40 | saveReadingProgress()
41 |
42 | super.viewWillDisappear(animated)
43 | }
44 |
45 | func saveReadingProgress() {
46 | let offset = webView.scrollView.contentOffset.y
47 | let height = webView.scrollView.contentSize.height
48 | let percentage = Double(offset/height)
49 | print("height: \(height), offset: \(offset), \(percentage*100)% read")
50 |
51 | // TODO: Actually save the percentage
52 | }
53 |
54 | func stopIndicator() {
55 | activityIndicator.stopAnimating()
56 | activityIndicator.hidden = true
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Controllers/RealmCommentViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RealmCommentViewController.swift
3 | // Swift-ZHI
4 | //
5 | // Created by Nicholas Tian on 27/07/2015.
6 | // Copyright (c) 2015 nickTD. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import SwiftDailyAPI
11 | import SDWebImage
12 | import RealmSwift
13 |
14 | class RealmCommentViewController: UIViewController {
15 | var newsId: Int!
16 |
17 | @IBOutlet weak var tableView: UITableView!
18 | let refreshControl = UIRefreshControl()
19 |
20 | private var store = DailyRealmStore()
21 | private var token: NotificationToken?
22 |
23 | private var commentsSortDescriptors = [
24 | SortDescriptor(property: "isShortComment", ascending: true),
25 | SortDescriptor(property: "repliedAt", ascending: false)
26 | ]
27 | private var comments: Results {
28 | get {
29 | return store.commentsForNewsId(newsId).sorted(self.commentsSortDescriptors)
30 | }
31 | }
32 |
33 | private var dateFormatter: NSDateFormatter = {
34 | let formatter = NSDateFormatter()
35 | formatter.timeStyle = .ShortStyle
36 | formatter.dateStyle = .ShortStyle
37 | return formatter
38 | }()
39 | }
40 |
41 | // MARK:
42 | extension RealmCommentViewController {
43 | func loadNewsComments() {
44 | if let newsId = newsId { // TODO: Swift 2.0, guard
45 | beginRefreshing()
46 | store.shortComments(forNewsId: newsId)
47 | store.longComments(forNewsId: newsId)
48 | }
49 | }
50 |
51 | func commentInSection(section: Int) -> CommentObject {
52 | return comments[section]
53 | }
54 | }
55 |
56 | // MARK: DidScrollToEnd
57 | extension RealmCommentViewController: UIScrollViewDelegate {
58 | func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
59 | let didComeToTheEnd = scrollView.contentOffset.y + scrollView.frame.size.height >= scrollView.contentSize.height
60 | if let lastShortComment = store.shortCommentsForNewsId(newsId).sorted("commentId", ascending: true).first where didComeToTheEnd {
61 | // TODO: There could be a test for whether this is the correct way to get the last comment or not
62 | store.shortComments(forNewsId: newsId, beforeCommentId: lastShortComment.commentId)
63 | }
64 | }
65 | }
66 |
67 | // MARK: UI methods
68 | extension RealmCommentViewController {
69 | override func viewDidLoad() {
70 | super.viewDidLoad()
71 |
72 | setupUi()
73 | setupRealm()
74 | }
75 |
76 | private func setupRealm() {
77 | token = defaultRealm().addNotificationBlock { (_, _) in
78 | self.tableView.reloadData()
79 | self.refreshControl.endRefreshing()
80 | }
81 | }
82 |
83 | private func setupUi() {
84 | tableView.rowHeight = UITableViewAutomaticDimension
85 | tableView.estimatedRowHeight = 44
86 |
87 | refreshControl.addTarget(self, action: "loadNewsComments", forControlEvents: .ValueChanged)
88 | tableView.addSubview(refreshControl)
89 |
90 | tableView.registerNib(UINib(nibName: "CommentSectionHeaderView", bundle: nil),
91 | forHeaderFooterViewReuseIdentifier: "CommentSectionHeaderView")
92 | }
93 |
94 | func beginRefreshing() {
95 | tableView.setContentOffset(CGPoint(x: 0, y: -refreshControl.frame.size.height), animated: true)
96 | refreshControl.beginRefreshing()
97 | }
98 |
99 | override func viewWillAppear(animated: Bool) {
100 | super.viewWillAppear(animated)
101 |
102 | loadNewsComments()
103 | }
104 | }
105 |
106 | // MARK: Data Source
107 | extension RealmCommentViewController: UITableViewDataSource {
108 | func numberOfSectionsInTableView(tableView: UITableView) -> Int {
109 | return comments.count
110 | }
111 |
112 | func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
113 | return 1
114 | }
115 |
116 | func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
117 | let cell = tableView.dequeueReusableCellWithIdentifier("CommentCell/TextOnly")!
118 |
119 | let comment = commentInSection(indexPath.section)
120 |
121 | cell.textLabel?.attributedText = CommentContentFormatter(comment: comment).attributedContent
122 | cell.textLabel?.sizeToFit()
123 | cell.sizeToFit()
124 |
125 | return cell
126 | }
127 | }
128 |
129 | extension RealmCommentViewController: UITableViewDelegate {
130 | func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
131 | if let header = tableView.dequeueReusableHeaderFooterViewWithIdentifier("CommentSectionHeaderView") as? CommentSectionHeaderView {
132 | // FIX/HACK: cant create a header view with `contentView` like the one in the xib for UITableViewCell
133 | header.backgroundView = {
134 | let view = UIView(frame: header.bounds)
135 | view.backgroundColor = tableView.backgroundColor
136 | view.alpha = 0.96
137 | return view
138 | }()
139 |
140 | let comment = commentInSection(section)
141 |
142 | header.usernameLabel.text = comment.authorName
143 | header.repliedAtLabel.text = dateFormatter.stringFromDate(comment.repliedAt)
144 |
145 | header.longCommentIndicator.hidden = comment.isShortComment
146 |
147 | header.avatarImageView.sd_setImageWithURL(comment.avatarURL)
148 |
149 | return header
150 | } else {
151 | return nil
152 | }
153 | }
154 | }
155 |
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Controllers/RealmDailyTableViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RealmDailyTableViewController.swift
3 | // SwiftDaily-ZhiHu
4 | //
5 | // Created by Nicholas Tian on 24/06/2015.
6 | // Copyright © 2015 nickTD. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import RealmSwift
11 | import SwiftDailyAPI
12 |
13 | class RealmDailyTableViewController: DailyTableViewController {
14 | private let store = DailyRealmStore()
15 | private let dailyDates = DailyDates()
16 |
17 | private var token: NotificationToken?
18 |
19 | private func dailyAtDate(date: NSDate) -> DailyObject? {
20 | return store.dailyAtDate(date)
21 | }
22 |
23 | private func newsMetaAtIndexPath(indexPath: NSIndexPath) -> NewsMetaObject? {
24 | let date = dailyDates.dateAtIndex(indexPath.section)
25 | if let daily = dailyAtDate(date) {
26 | return daily.news[indexPath.row]
27 | } else {
28 | return nil
29 | }
30 | }
31 |
32 | private func hasNewsWithId(newsId: Int) -> Bool {
33 | let news = store.newsWithId(newsId)
34 | return news != nil
35 | }
36 | }
37 |
38 | // MARK: Concrete methods
39 | extension RealmDailyTableViewController {
40 | override func hasDailyAtIndexPath(indexPath: NSIndexPath) -> Bool {
41 | let date = dailyDates.dateAtIndex(indexPath.section)
42 | return store.dailyAtDate(date) != nil
43 | }
44 |
45 | override func hasNewsMetaAtIndexPath(indexPath: NSIndexPath) -> Bool {
46 | return newsMetaAtIndexPath(indexPath) != nil
47 | }
48 |
49 | override func hasNewsAtIndexPath(indexPath: NSIndexPath) -> Bool {
50 | if let newsMeta = newsMetaAtIndexPath(indexPath) {
51 | return store.newsWithId(newsMeta.newsId) != nil
52 | } else {
53 | return false
54 | }
55 | }
56 |
57 | override func dateStringAtSection(section: Int) -> String {
58 | let date = dailyDates.dateAtIndex(section)
59 | return dateFormatter.stringFromDate(date)
60 | }
61 |
62 | override func loadDailyAtIndexPath(indexPath: NSIndexPath) {
63 | store.daily(forDate: dailyDates.dateAtIndex(indexPath.section))
64 | }
65 |
66 | override func loadLatestDaily() {
67 | store.updateLatestDaily()
68 | }
69 |
70 | override func loadNewsAtIndexPath(indexPath: NSIndexPath) {
71 | if let newsMeta = self.newsMetaAtIndexPath(indexPath) {
72 | self.store.news(newsMeta.newsId)
73 | } else {
74 | return
75 | }
76 | }
77 |
78 | override func deleteNewsAtIndexPath(indexPath: NSIndexPath) {
79 | if let newsMeta = newsMetaAtIndexPath(indexPath) {
80 | store.deleteNewsWithId(newsMeta.newsId)
81 | }
82 | }
83 |
84 | override func cellAtIndexPath(indexPath: NSIndexPath) -> UITableViewCell {
85 | let cell = tableView.dequeueReusableCellWithIdentifier("NewsMetaCell", forIndexPath: indexPath)
86 | let newsMeta = newsMetaAtIndexPath(indexPath)!
87 |
88 | cell.textLabel!.text = newsMeta.title
89 |
90 | if hasNewsWithId(newsMeta.newsId) {
91 | cell.accessoryType = .Checkmark
92 | } else {
93 | cell.accessoryType = .None
94 | }
95 |
96 | return cell
97 | }
98 | }
99 |
100 | // MARK: UI methods
101 | extension RealmDailyTableViewController {
102 | override func viewDidLoad() {
103 | super.viewDidLoad()
104 |
105 | token = defaultRealm().addNotificationBlock { (_, _) in
106 | self.dailyDates.endDate = self.store.latestDate
107 | self.reloadTableViewWhenNotEditing()
108 | }
109 | }
110 |
111 | func reloadTableViewWhenNotEditing() {
112 | if tableView.editing {
113 | delay(0.1) { self.reloadTableViewWhenNotEditing() }
114 | } else {
115 | // HACK: To let the animation for ending editing finish
116 | // before table view gets refreshed
117 | delay(0.3) { self.reloadTableView() }
118 | }
119 | }
120 |
121 | func reloadTableView() {
122 | tableView.reloadData()
123 | refreshControl.endRefreshing()
124 | }
125 |
126 | override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
127 | if segue.identifier == "showNews/Realm" {
128 | if let indexPath = tableView.indexPathForSelectedRow,
129 | let newsMeta = newsMetaAtIndexPath(indexPath),
130 | let nvc = segue.destinationViewController as? UINavigationController,
131 | let vc = nvc.topViewController as? RealmNewsViewController {
132 | vc.newsId = newsMeta.newsId
133 | vc.navigationItem.leftBarButtonItem = splitViewController?.displayModeButtonItem()
134 | vc.navigationItem.leftItemsSupplementBackButton = true
135 | }
136 | }
137 | }
138 | }
139 |
140 | // MARK: Data Source
141 | extension RealmDailyTableViewController: UITableViewDataSource {
142 | func numberOfSectionsInTableView(tableView: UITableView) -> Int {
143 | return dailyDates.days()
144 | }
145 |
146 | func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
147 | let date = dailyDates.dateAtIndex(section)
148 | if let daily = dailyAtDate(date) {
149 | return daily.news.count
150 | } else {
151 | return 1
152 | }
153 | }
154 |
155 | }
156 |
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Controllers/RealmNewsViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RealmNewsViewController.swift
3 | // SwiftDaily-ZhiHu
4 | //
5 | // Created by Nicholas Tian on 27/06/2015.
6 | // Copyright © 2015 nickTD. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import RealmSwift
11 |
12 | class RealmNewsViewController: NewsViewController {
13 | var newsId: Int?
14 |
15 | private let store = DailyRealmStore()
16 | private let preferences = UserPreferences()
17 | private var loadedNewsId: Int?
18 |
19 | private var token: NotificationToken?
20 | }
21 |
22 | // MARK: UI methods
23 | extension RealmNewsViewController {
24 | override func viewDidLoad() {
25 | super.viewDidLoad()
26 |
27 | token = defaultRealm().addNotificationBlock { (_, _) in
28 | if let newsId = self.newsId,
29 | let news = self.store.newsWithId(newsId) where newsId != self.loadedNewsId {
30 | self.loadNews(news)
31 | self.stopIndicator()
32 | }
33 | }
34 | }
35 |
36 | override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
37 | if segue.identifier == "showComments/Realm" {
38 | if let commentsVC = segue.destinationViewController as? RealmCommentViewController {
39 | commentsVC.newsId = newsId ?? preferences.lastReadNewsId
40 | }
41 | }
42 | }
43 | }
44 |
45 | // Concrete methods
46 | extension RealmNewsViewController {
47 | override func loadNews() {
48 | let newsId = self.newsId ?? preferences.lastReadNewsId
49 |
50 | if let news = store.newsWithId(newsId) {
51 | loadNews(news)
52 | didLoadNewsInWebViewWithNewsId(newsId)
53 | } else {
54 | activityIndicator.startAnimating()
55 | store.news(newsId)
56 | }
57 | }
58 |
59 | private func didLoadNewsInWebViewWithNewsId(newsId: Int) {
60 | loadedNewsId = newsId
61 | preferences.lastReadNewsId = newsId
62 | }
63 |
64 | // TODO: Use protocol
65 | private func loadNews(news: NewsObject) {
66 | let css = news.cssURLStrings.map { "" }
67 | var newsBody = css.reduce(news.body) { $0 + $1 }
68 | // hide 200px #div.img-place-holder in css
69 | newsBody += ""
70 |
71 | webView.loadHTMLString(newsBody, baseURL: nil)
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Extensions/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NicholasTD07/Swift-ZHI/2a380d7855f2b55d1973ee59fbf2e5ca4c4b001f/SwiftDaily-ZhiHu/Extensions/.gitkeep
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Helpers/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NicholasTD07/Swift-ZHI/2a380d7855f2b55d1973ee59fbf2e5ca4c4b001f/SwiftDaily-ZhiHu/Helpers/.gitkeep
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Helpers/CommentContentFormatter.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CommentContentFormatter.swift
3 | // Swift-ZHI
4 | //
5 | // Created by Nicholas Tian on 31/07/2015.
6 | // Copyright (c) 2015 nickTD. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import SwiftDailyAPI
11 |
12 | struct CommentContentFormatter {
13 | let comment: CommentObject
14 | let replyToComment: ReplyToCommentObject?
15 | static let replyString = NSLocalizedString("Reply", comment: "Reply string in CommentView")
16 | static let newlinesBetweenCommentAndReply = "\n\n"
17 |
18 | init(comment: CommentObject) {
19 | self.comment = comment
20 | self.replyToComment = comment.replyToComment
21 | }
22 |
23 | var attributedContent: NSAttributedString {
24 | get {
25 | let attributedContent = NSMutableAttributedString(string: content)
26 | let systemFontSize = UIFont.systemFontSize()
27 |
28 | attributedContent.addAttributes(
29 | [
30 | NSForegroundColorAttributeName: UIColor.grayColor(),
31 | NSFontAttributeName: UIFont.systemFontOfSize(systemFontSize - 1)
32 | ],
33 | range: rangeOfReplyContentWithNewlines
34 | )
35 | attributedContent.addAttributes(
36 | [NSFontAttributeName: UIFont.boldSystemFontOfSize(systemFontSize)],
37 | range: rangeOfReplyAuthor
38 | )
39 |
40 | return attributedContent
41 | }
42 | }
43 |
44 | var rangeOfReplyAuthor: NSRange {
45 | get { return (content as NSString).rangeOfString(replyAuthorString) }
46 | }
47 |
48 | var rangeOfReplyContentWithNewlines: NSRange {
49 | get { return (content as NSString).rangeOfString(replyContentString) }
50 | }
51 |
52 | var content: String {
53 | get {
54 | return replyContentStringWithNewlines + commentContentString
55 | }
56 | }
57 |
58 | var commentContentString: String { get { return comment.content } }
59 |
60 | var replyContentStringWithNewlines: String {
61 | get {
62 | if replyToComment == nil {
63 | return ""
64 | }
65 |
66 | return CommentContentFormatter.replyString + " " + replyContentString + CommentContentFormatter.newlinesBetweenCommentAndReply
67 | }
68 | }
69 |
70 | var replyContentString: String { get { return replyAuthorString + "\n\n" + replyCommentString} }
71 |
72 | var replyCommentString: String { get { return replyToComment?.content ?? "" } }
73 |
74 | var replyAuthorString: String { get { return replyToComment?.authorName ?? "" } }
75 | }
76 |
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Helpers/DailyDates.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DailyDates.swift
3 | // SwiftDaily-ZhiHu
4 | //
5 | // Created by Nicholas Tian on 26/06/2015.
6 | // Copyright © 2015 nickTD. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | class DailyDates {
12 | let startDate = NSDate.dateAt(year: 2013, month: 05, day: 19)!
13 | var endDate: NSDate
14 |
15 | private var calendar = NSCalendar.currentCalendar()
16 |
17 | init(endDate: NSDate = NSDate()) {
18 | self.endDate = endDate
19 | }
20 |
21 | func dateAtIndex(index: Int) -> NSDate {
22 | return calendar.dateByAddingUnit(.Day, value: -index, toDate: endDate, options: [])!
23 | }
24 |
25 | func days() -> Int {
26 | return calendar.components(.Day, fromDate: startDate, toDate: endDate, options: []).day + 1
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Helpers/Delay.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Delay.swift
3 | // Swift-ZHI
4 | //
5 | // Created by Nicholas Tian on 11/07/2015.
6 | // Copyright © 2015 nickTD. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | func delay(seconds: Double, queue: dispatch_queue_t = dispatch_get_main_queue(), closure: () -> Void) {
12 | let delay = dispatch_time(DISPATCH_TIME_NOW, Int64(seconds * Double(NSEC_PER_SEC)))
13 | dispatch_after(delay, queue, closure)
14 | }
15 |
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Helpers/RealmHelpers.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RealmHelpers.swift
3 | // SwiftDaily-ZhiHu
4 | //
5 | // Created by Nicholas Tian on 25/06/2015.
6 | // Copyright © 2015 nickTD. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import RealmSwift
11 |
12 | func defaultRealm() -> Realm {
13 | // TODO: Until next release, use in memroy realm
14 | // NOTE: So there's no need to migrate XD until a stable model
15 |
16 | return try! Realm()
17 | // return Realm(inMemoryIdentifier: "DailyTestGround")
18 | }
19 |
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Models/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NicholasTD07/Swift-ZHI/2a380d7855f2b55d1973ee59fbf2e5ca4c4b001f/SwiftDaily-ZhiHu/Models/.gitkeep
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Models/DailyRealmStore.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DailyRealmStore.swift
3 | // SwiftDaily-ZhiHu
4 | //
5 | // Created by Nicholas Tian on 25/06/2015.
6 | // Copyright © 2015 nickTD. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import RealmSwift
11 | import SwiftDailyAPI
12 |
13 | public class DailyRealmStore {
14 | public var latestDaily: LatestDaily?
15 | public var latestDate: NSDate {
16 | return latestDaily?.date ?? NSDate()
17 | }
18 |
19 | let dailyAPI: DailyAPI
20 | let realm = defaultRealm()
21 |
22 | public init(completionQueue: dispatch_queue_t? = nil)
23 | {
24 | dailyAPI = DailyAPI(completionQueue: completionQueue)
25 | }
26 | }
27 |
28 | extension DailyRealmStore {
29 | // MARK: Insertion by calling to `DailyAPI`
30 | public func updateLatestDaily() {
31 | dailyAPI.latestDaily { latestDaily in
32 | self.latestDaily = latestDaily
33 | self.addDaily(Daily(latestDaily))
34 | }
35 | }
36 |
37 | public func daily(forDate date: NSDate) {
38 | dailyAPI.daily(forDate: date) { self.addDaily($0) }
39 | }
40 |
41 | public func news(newsId: Int) {
42 | dailyAPI.news(newsId) { self.addObject(NewsObject.from($0)) }
43 | }
44 |
45 | public func longComments(forNewsId newsId: Int) {
46 | dailyAPI.longComments(newsId) {
47 | $0.comments.forEach {
48 | self.addObject(CommentObject.from($0, forNewsId: newsId, isShortComment: false))
49 | }
50 | }
51 | }
52 |
53 | public func shortComments(forNewsId newsId: Int) {
54 | dailyAPI.shortComments(newsId) {
55 | self.addShortComments(fromComments: $0, forNewsId: newsId)
56 | }
57 | }
58 |
59 | public func shortComments(forNewsId newsId: Int, beforeCommentId commentId: Int) {
60 | dailyAPI.shortComments(newsId, beforeCommentId: commentId) {
61 | self.addShortComments(fromComments: $0, forNewsId: newsId)
62 | }
63 | }
64 |
65 | // MARK: Deletion
66 | public func deleteNewsWithId(newsId: Int, inRealm realm: Realm = defaultRealm()) {
67 | if let news = newsWithId(newsId) {
68 | try! realm.write { realm.delete(news) }
69 | }
70 | }
71 | }
72 |
73 | // MARK: Getters
74 | extension DailyRealmStore {
75 | public func dailyAtDate(date: NSDate) -> DailyObject? {
76 | let results = realm.objects(DailyObject).filter("dateHash == \(date.hash)")
77 | return results.first
78 | }
79 |
80 | public func newsWithId(newsId: Int) -> NewsObject? {
81 | let results = realm.objects(NewsObject).filter("newsId == \(newsId)")
82 | return results.first
83 | }
84 |
85 | public func commentsForNewsId(newsId: Int) -> Results {
86 | let results = realm.objects(CommentObject).filter("newsId == \(newsId)")
87 | return results
88 | }
89 |
90 | public func shortCommentsForNewsId(newsId: Int) -> Results {
91 | let results = realm.objects(CommentObject).filter("newsId == \(newsId) AND isShortComment == TRUE")
92 | return results
93 | }
94 | }
95 |
96 | // MARK: Private methods
97 | extension DailyRealmStore {
98 | private func addShortComments(fromComments comments: Comments, forNewsId newsId: Int) {
99 | comments.comments.forEach {
100 | self.addObject(CommentObject.from($0, forNewsId: newsId, isShortComment: true))
101 | }
102 | }
103 |
104 | private func addDaily(daily: Daily) {
105 | addObject(DailyObject.from(daily))
106 | }
107 |
108 | private func addObject(object: Object, toRealm realm: Realm = defaultRealm()) {
109 | try! realm.write { realm.add(object, update: true) }
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Models/RealmModels.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RealmModels.swift
3 | // SwiftDaily-ZhiHu
4 | //
5 | // Created by Nicholas Tian on 24/06/2015.
6 | // Copyright © 2015 nickTD. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import RealmSwift
11 | import SwiftDailyAPI
12 |
13 | public class NewsMetaObject: Object {
14 | dynamic public var newsId: Int = 0
15 | dynamic public var title: String = ""
16 |
17 | override static public func primaryKey() -> String? {
18 | return "newsId"
19 | }
20 |
21 | convenience public init(newsId: Int, title: String) {
22 | self.init()
23 | self.newsId = newsId
24 | self.title = title
25 | }
26 |
27 | static public func from(newsMeta: NewsMeta) -> NewsMetaObject {
28 | return NewsMetaObject(newsId: newsMeta.newsId, title: newsMeta.title)
29 | }
30 | }
31 |
32 | public class DailyObject: Object {
33 | dynamic public var dateHash: Int = 0
34 | dynamic public var date: NSDate = NSDate()
35 | public var news = List()
36 |
37 | override public static func primaryKey() -> String? {
38 | return "dateHash"
39 | }
40 |
41 | override public static func indexedProperties() -> [String] {
42 | return ["dateHash"]
43 | }
44 |
45 | convenience public init(date: NSDate, news: [NewsMeta]) {
46 | self.init()
47 | self.date = date
48 | self.dateHash = date.hash
49 | self.news.appendContentsOf(news.map { NewsMetaObject.from($0) })
50 | }
51 |
52 | static public func from(daily: Daily) -> DailyObject {
53 | // Note: Why not use `convenience init(daily: Daily)`
54 | // Because it will cause "abort trap 6".
55 |
56 | // TODO: Wait for response from bug report: 21559246
57 | return DailyObject(date: daily.date, news: daily.news)
58 | }
59 | }
60 |
61 | public class StringObject: Object {
62 | dynamic public var value: String = ""
63 |
64 | convenience public init(stringValue: String) {
65 | self.init()
66 | self.value = stringValue
67 | }
68 | }
69 |
70 | public class NewsObject: Object {
71 | dynamic public var newsId: Int = 0
72 | dynamic public var title: String = ""
73 | dynamic public var body: String = ""
74 | public var cssURLStrings = List()
75 |
76 | override static public func primaryKey() -> String? {
77 | return "newsId"
78 | }
79 |
80 | convenience public init(newsId: Int, title: String, body: String, cssURLStrings: [String]) {
81 | self.init()
82 | self.newsId = newsId
83 | self.title = title
84 | self.body = body
85 | self.cssURLStrings.appendContentsOf(cssURLStrings.map { StringObject(stringValue: $0) })
86 | }
87 |
88 | static public func from(news: News) -> NewsObject {
89 | return NewsObject(newsId: news.newsId, title: news.title, body: news.body, cssURLStrings: news.cssURLs.map {$0.absoluteString})
90 | }
91 | }
92 |
93 | public class ReplyToCommentObject: Object {
94 | dynamic public var authorName: String = ""
95 | dynamic public var content: String = ""
96 | dynamic public var _primaryKey: Int = 0
97 |
98 |
99 | override static public func primaryKey() -> String? {
100 | return "_primaryKey"
101 | }
102 |
103 | public func setAuthorName(authorName: String, content: String) {
104 | self.authorName = authorName
105 | self.content = content
106 |
107 | _primaryKey = "\(authorName)\(content)".hash
108 | }
109 |
110 | static public func from(replyToComment: ReplyToComment?) -> Self? {
111 | // TODO: guard
112 | if let replyToComment = replyToComment {
113 | let object = self.init()
114 | object.setAuthorName(replyToComment.authorName, content: replyToComment.content)
115 | return object
116 | } else {
117 | return nil
118 | }
119 | }
120 | }
121 |
122 | public class CommentObject: Object {
123 | // MARK: vars exist only in Realm
124 | dynamic public var newsId: Int = 0
125 | dynamic public var isShortComment: Bool = true
126 | // MARK: vars in JSON
127 | dynamic public var commentId: Int = 0
128 | dynamic public var authorName: String = ""
129 | dynamic public var content: String = ""
130 | dynamic public var likes: Int = 0
131 | dynamic public var repliedAt: NSDate = NSDate()
132 | dynamic public var avatarURLString: String = ""
133 | dynamic public var replyToComment: ReplyToCommentObject?
134 |
135 | public var avatarURL: NSURL {
136 | get { return NSURL(string: avatarURLString)! }
137 | }
138 |
139 | override static public func primaryKey() -> String? {
140 | return "commentId"
141 | }
142 |
143 | public func setCommentId(commentId: Int , authorName: String , content: String , likes: Int , repliedAt: NSDate , avatarURL: NSURL , replyToComment: ReplyToComment?, newsId: Int, isShortComment: Bool) {
144 | self.newsId = newsId
145 | self.isShortComment = isShortComment
146 |
147 | self.commentId = commentId
148 | self.authorName = authorName
149 | self.content = content
150 | self.likes = likes
151 | self.repliedAt = repliedAt
152 | self.avatarURLString = avatarURL.absoluteString
153 | self.replyToComment = ReplyToCommentObject.from(replyToComment)
154 | }
155 |
156 | // Default to short comment.
157 | static public func from(comment: Comment, forNewsId newsId: Int, isShortComment: Bool) -> Self {
158 | let object = self.init()
159 |
160 | object.setCommentId(comment.commentId, authorName: comment.authorName , content: comment.content , likes: comment.likes , repliedAt: comment.repliedAt, avatarURL: comment.avatarURL, replyToComment: comment.replyToComment, newsId: newsId, isShortComment: isShortComment)
161 |
162 | return object
163 | }
164 | }
165 |
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Models/UserPreferences.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UserPreferences.swift
3 | // Swift-ZHI
4 | //
5 | // Created by Nicholas Tian on 14/07/2015.
6 | // Copyright © 2015 nickTD. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | class UserPreferences {
12 | let userDefaults: NSUserDefaults
13 |
14 | static let userDefaultsDictionary = [
15 | PreferenceKeys.LastReadNewsId.rawValue: 4862871
16 | // Title: 高大上的苹果店,装修究竟好在哪儿?
17 | // Web page URL: http://daily.zhihu.com/story/4862871
18 | ]
19 |
20 | init(userDefaults: NSUserDefaults = NSUserDefaults()) {
21 | self.userDefaults = userDefaults
22 | }
23 |
24 | class func registerDefaults() {
25 | NSUserDefaults().registerDefaults(userDefaultsDictionary)
26 | }
27 |
28 | enum PreferenceKeys: String {
29 | case LastReadNewsId = "lastReadNewsId"
30 | }
31 |
32 | var lastReadNewsId: Int {
33 | get {
34 | return userDefaults.integerForKey(PreferenceKeys.LastReadNewsId.rawValue)
35 | }
36 |
37 | set {
38 | userDefaults.setInteger(newValue, forKey: PreferenceKeys.LastReadNewsId.rawValue)
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Protocols/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NicholasTD07/Swift-ZHI/2a380d7855f2b55d1973ee59fbf2e5ca4c4b001f/SwiftDaily-ZhiHu/Protocols/.gitkeep
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Resources/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NicholasTD07/Swift-ZHI/2a380d7855f2b55d1973ee59fbf2e5ca4c4b001f/SwiftDaily-ZhiHu/Resources/.gitkeep
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Resources/Base.lproj/Localizable.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NicholasTD07/Swift-ZHI/2a380d7855f2b55d1973ee59fbf2e5ca4c4b001f/SwiftDaily-ZhiHu/Resources/Base.lproj/Localizable.strings
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Resources/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "29x29",
5 | "idiom" : "iphone",
6 | "filename" : "Icon-29@2x.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "29x29",
11 | "idiom" : "iphone",
12 | "filename" : "Icon-29@3x.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "40x40",
17 | "idiom" : "iphone",
18 | "filename" : "Icon-40@2x.png",
19 | "scale" : "2x"
20 | },
21 | {
22 | "size" : "40x40",
23 | "idiom" : "iphone",
24 | "filename" : "Icon-40@3x.png",
25 | "scale" : "3x"
26 | },
27 | {
28 | "size" : "60x60",
29 | "idiom" : "iphone",
30 | "filename" : "Icon-60@2x.png",
31 | "scale" : "2x"
32 | },
33 | {
34 | "size" : "60x60",
35 | "idiom" : "iphone",
36 | "filename" : "Icon-60@3x.png",
37 | "scale" : "3x"
38 | },
39 | {
40 | "size" : "29x29",
41 | "idiom" : "ipad",
42 | "filename" : "Icon-29.png",
43 | "scale" : "1x"
44 | },
45 | {
46 | "size" : "29x29",
47 | "idiom" : "ipad",
48 | "filename" : "Icon-29@2x-1.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "40x40",
53 | "idiom" : "ipad",
54 | "filename" : "Icon-40.png",
55 | "scale" : "1x"
56 | },
57 | {
58 | "size" : "40x40",
59 | "idiom" : "ipad",
60 | "filename" : "Icon-40@2x-1.png",
61 | "scale" : "2x"
62 | },
63 | {
64 | "size" : "76x76",
65 | "idiom" : "ipad",
66 | "filename" : "Icon-76.png",
67 | "scale" : "1x"
68 | },
69 | {
70 | "size" : "76x76",
71 | "idiom" : "ipad",
72 | "filename" : "Icon-76@2x.png",
73 | "scale" : "2x"
74 | }
75 | ],
76 | "info" : {
77 | "version" : 1,
78 | "author" : "xcode"
79 | }
80 | }
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Resources/Images.xcassets/AppIcon.appiconset/Icon-29.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NicholasTD07/Swift-ZHI/2a380d7855f2b55d1973ee59fbf2e5ca4c4b001f/SwiftDaily-ZhiHu/Resources/Images.xcassets/AppIcon.appiconset/Icon-29.png
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Resources/Images.xcassets/AppIcon.appiconset/Icon-29@2x-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NicholasTD07/Swift-ZHI/2a380d7855f2b55d1973ee59fbf2e5ca4c4b001f/SwiftDaily-ZhiHu/Resources/Images.xcassets/AppIcon.appiconset/Icon-29@2x-1.png
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Resources/Images.xcassets/AppIcon.appiconset/Icon-29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NicholasTD07/Swift-ZHI/2a380d7855f2b55d1973ee59fbf2e5ca4c4b001f/SwiftDaily-ZhiHu/Resources/Images.xcassets/AppIcon.appiconset/Icon-29@2x.png
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Resources/Images.xcassets/AppIcon.appiconset/Icon-29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NicholasTD07/Swift-ZHI/2a380d7855f2b55d1973ee59fbf2e5ca4c4b001f/SwiftDaily-ZhiHu/Resources/Images.xcassets/AppIcon.appiconset/Icon-29@3x.png
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Resources/Images.xcassets/AppIcon.appiconset/Icon-40.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NicholasTD07/Swift-ZHI/2a380d7855f2b55d1973ee59fbf2e5ca4c4b001f/SwiftDaily-ZhiHu/Resources/Images.xcassets/AppIcon.appiconset/Icon-40.png
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Resources/Images.xcassets/AppIcon.appiconset/Icon-40@2x-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NicholasTD07/Swift-ZHI/2a380d7855f2b55d1973ee59fbf2e5ca4c4b001f/SwiftDaily-ZhiHu/Resources/Images.xcassets/AppIcon.appiconset/Icon-40@2x-1.png
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Resources/Images.xcassets/AppIcon.appiconset/Icon-40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NicholasTD07/Swift-ZHI/2a380d7855f2b55d1973ee59fbf2e5ca4c4b001f/SwiftDaily-ZhiHu/Resources/Images.xcassets/AppIcon.appiconset/Icon-40@2x.png
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Resources/Images.xcassets/AppIcon.appiconset/Icon-40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NicholasTD07/Swift-ZHI/2a380d7855f2b55d1973ee59fbf2e5ca4c4b001f/SwiftDaily-ZhiHu/Resources/Images.xcassets/AppIcon.appiconset/Icon-40@3x.png
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Resources/Images.xcassets/AppIcon.appiconset/Icon-60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NicholasTD07/Swift-ZHI/2a380d7855f2b55d1973ee59fbf2e5ca4c4b001f/SwiftDaily-ZhiHu/Resources/Images.xcassets/AppIcon.appiconset/Icon-60@2x.png
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Resources/Images.xcassets/AppIcon.appiconset/Icon-60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NicholasTD07/Swift-ZHI/2a380d7855f2b55d1973ee59fbf2e5ca4c4b001f/SwiftDaily-ZhiHu/Resources/Images.xcassets/AppIcon.appiconset/Icon-60@3x.png
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Resources/Images.xcassets/AppIcon.appiconset/Icon-76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NicholasTD07/Swift-ZHI/2a380d7855f2b55d1973ee59fbf2e5ca4c4b001f/SwiftDaily-ZhiHu/Resources/Images.xcassets/AppIcon.appiconset/Icon-76.png
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Resources/Images.xcassets/AppIcon.appiconset/Icon-76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NicholasTD07/Swift-ZHI/2a380d7855f2b55d1973ee59fbf2e5ca4c4b001f/SwiftDaily-ZhiHu/Resources/Images.xcassets/AppIcon.appiconset/Icon-76@2x.png
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Resources/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en_US
7 | CFBundleDisplayName
8 | ${PRODUCT_NAME}
9 | CFBundleExecutable
10 | ${EXECUTABLE_NAME}
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | ${PRODUCT_NAME}
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.4.8
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1.8.10
25 | LSHasLocalizedDisplayName
26 |
27 | LSRequiresIPhoneOS
28 |
29 | NSAppTransportSecurity
30 |
31 | NSExceptionDomains
32 |
33 | zhihu.com
34 |
35 | NSIncludesSubdomains
36 |
37 | NSTemporaryExceptionAllowsInsecureHTTPLoads
38 |
39 |
40 | zhimg.com
41 |
42 | NSIncludesSubdomains
43 |
44 | NSTemporaryExceptionAllowsInsecureHTTPLoads
45 |
46 |
47 |
48 |
49 | UILaunchStoryboardName
50 | LaunchScreen
51 | UIMainStoryboardFile
52 | Main
53 | UIRequiredDeviceCapabilities
54 |
55 | armv7
56 |
57 | UIStatusBarStyle
58 | UIStatusBarStyleLightContent
59 | UISupportedInterfaceOrientations
60 |
61 | UIInterfaceOrientationPortrait
62 | UIInterfaceOrientationLandscapeLeft
63 | UIInterfaceOrientationLandscapeRight
64 |
65 | UIViewControllerBasedStatusBarAppearance
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Resources/Localizations/Swift-ZHI/zh-Hans.xliff:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 | ${PRODUCT_NAME}
10 | 速知
11 |
12 |
13 | ${PRODUCT_NAME}
14 | 速知
15 |
16 |
17 | 1.3.5
18 |
19 |
20 |
21 |
22 |
25 |
26 |
27 | Delete
28 | 删除
29 | Delete News button in DailyView
30 |
31 |
32 | Download & Save
33 | 下载并保存
34 | Download button in DailyView
35 |
36 |
37 | Reply
38 | 回复
39 | Reply string in CommentView
40 |
41 |
42 |
43 |
44 |
47 |
48 |
49 | Title
50 | Class = "UILabel"; text = "Title"; ObjectID = "Gt5-Zn-vsE";
51 |
52 |
53 | Swift ZHI
54 | 速知
55 | Class = "UIBarButtonItem"; title = "Swift ZHI"; ObjectID = "Sz8-Ml-p5c";
56 |
57 |
58 | Title
59 | Class = "UILabel"; text = "Title"; ObjectID = "loV-SC-E0Y";
60 |
61 |
62 | Comments
63 | 评论
64 | Class = "UIBarButtonItem"; title = "Comments"; ObjectID = "qMw-ph-xNh";
65 |
66 |
67 | Swift ZHI
68 | 速知
69 | Class = "UINavigationItem"; title = "Swift ZHI"; ObjectID = "u84-IW-9ED";
70 |
71 |
72 |
73 |
74 |
77 |
78 |
79 | $(PRODUCT_NAME)
80 | 速知
81 |
82 |
83 | 1.0
84 | 1.0
85 |
86 |
87 |
88 |
89 |
92 |
93 |
94 | $(PRODUCT_NAME)
95 | 速知
96 |
97 |
98 | 1.0
99 | 1.0
100 |
101 |
102 |
103 |
104 |
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Resources/Localizations/Swift-ZHI/zh-Hant.xliff:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 | ${PRODUCT_NAME}
10 | 速知
11 |
12 |
13 | ${PRODUCT_NAME}
14 | 速知
15 |
16 |
17 | 1.3.5
18 |
19 |
20 |
21 |
22 |
25 |
26 |
27 | Delete
28 | 刪除
29 | Delete News button in DailyView
30 |
31 |
32 | Download & Save
33 | 下載並保存
34 | Download button in DailyView
35 |
36 |
37 | Reply
38 | 回復
39 | Reply string in CommentView
40 |
41 |
42 |
43 |
44 |
47 |
48 |
49 | Title
50 | Class = "UILabel"; text = "Title"; ObjectID = "Gt5-Zn-vsE";
51 |
52 |
53 | Swift ZHI
54 | 速知
55 | Class = "UIBarButtonItem"; title = "Swift ZHI"; ObjectID = "Sz8-Ml-p5c";
56 |
57 |
58 | Title
59 | Class = "UILabel"; text = "Title"; ObjectID = "loV-SC-E0Y";
60 |
61 |
62 | Comments
63 | 評論
64 | Class = "UIBarButtonItem"; title = "Comments"; ObjectID = "qMw-ph-xNh";
65 |
66 |
67 | Swift ZHI
68 | 速知
69 | Class = "UINavigationItem"; title = "Swift ZHI"; ObjectID = "u84-IW-9ED";
70 |
71 |
72 |
73 |
74 |
77 |
78 |
79 | $(PRODUCT_NAME)
80 | 速知
81 |
82 |
83 | 1.0
84 | 1.0
85 |
86 |
87 |
88 |
89 |
92 |
93 |
94 | $(PRODUCT_NAME)
95 | 速知
96 |
97 |
98 | 1.0
99 | 1.0
100 |
101 |
102 |
103 |
104 |
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Resources/Nibs/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NicholasTD07/Swift-ZHI/2a380d7855f2b55d1973ee59fbf2e5ca4c4b001f/SwiftDaily-ZhiHu/Resources/Nibs/.gitkeep
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Resources/Nibs/Base.lproj/CommentSectionHeaderView.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 |
34 |
41 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Resources/Nibs/DailySectionHeaderView.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Resources/Nibs/LaunchScreen.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Resources/Nibs/zh-Hans.lproj/CommentSectionHeaderView.strings:
--------------------------------------------------------------------------------
1 |
2 | /* Class = "UILabel"; text = "Label"; ObjectID = "Lac-36-zzP"; */
3 | "Lac-36-zzP.text" = "Label";
4 |
5 | /* Class = "UILabel"; text = "Long comment"; ObjectID = "gXd-Hz-Wc1"; */
6 | "gXd-Hz-Wc1.text" = "长评论";
7 |
8 | /* Class = "UILabel"; text = "Label"; ObjectID = "qD9-Ly-Dbj"; */
9 | "qD9-Ly-Dbj.text" = "Label";
10 |
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Resources/Nibs/zh-Hant.lproj/CommentSectionHeaderView.strings:
--------------------------------------------------------------------------------
1 |
2 | /* Class = "UILabel"; text = "Label"; ObjectID = "Lac-36-zzP"; */
3 | "Lac-36-zzP.text" = "Label";
4 |
5 | /* Class = "UILabel"; text = "Long comment"; ObjectID = "gXd-Hz-Wc1"; */
6 | "gXd-Hz-Wc1.text" = "長評論";
7 |
8 | /* Class = "UILabel"; text = "Label"; ObjectID = "qD9-Ly-Dbj"; */
9 | "qD9-Ly-Dbj.text" = "Label";
10 |
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Resources/Settings.bundle/Root.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreferenceSpecifiers
6 |
7 |
8 |
9 | StringsTable
10 | Root
11 |
12 |
13 |
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Resources/Settings.bundle/en.lproj/Root.strings:
--------------------------------------------------------------------------------
1 | /* A single strings file, whose title is specified in your preferences schema. The strings files provide the localized content to display to the user for each of your preferences. */
2 |
3 | "Acknowledgements" = "Acknowledgements";
4 |
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Resources/Storyboards/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NicholasTD07/Swift-ZHI/2a380d7855f2b55d1973ee59fbf2e5ca4c4b001f/SwiftDaily-ZhiHu/Resources/Storyboards/.gitkeep
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Resources/Storyboards/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
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 |
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 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Resources/Storyboards/zh-Hans.lproj/Main.strings:
--------------------------------------------------------------------------------
1 | /* Class = "UIBarButtonItem"; title = "Swift ZHI"; ObjectID = "Sz8-Ml-p5c"; */
2 | "Sz8-Ml-p5c.title" = "速知";
3 |
4 | /* Class = "UIBarButtonItem"; title = "Comments"; ObjectID = "qMw-ph-xNh"; */
5 | "qMw-ph-xNh.title" = "评论";
6 |
7 | /* Class = "UINavigationItem"; title = "Swift ZHI"; ObjectID = "u84-IW-9ED"; */
8 | "u84-IW-9ED.title" = "速知";
9 |
10 |
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Resources/Storyboards/zh-Hant.lproj/Main.strings:
--------------------------------------------------------------------------------
1 | /* Class = "UIBarButtonItem"; title = "Swift ZHI"; ObjectID = "Sz8-Ml-p5c"; */
2 | "Sz8-Ml-p5c.title" = "速知";
3 |
4 | /* Class = "UIBarButtonItem"; title = "Comments"; ObjectID = "qMw-ph-xNh"; */
5 | "qMw-ph-xNh.title" = "評論";
6 |
7 | /* Class = "UINavigationItem"; title = "Swift ZHI"; ObjectID = "u84-IW-9ED"; */
8 | "u84-IW-9ED.title" = "速知";
9 |
10 |
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Resources/zh-Hans.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* (No Commment) */
2 | "CFBundleDisplayName" = "速知";
3 |
4 | /* (No Commment) */
5 | "CFBundleName" = "速知";
6 |
7 |
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Resources/zh-Hans.lproj/Localizable.strings:
--------------------------------------------------------------------------------
1 | /* Delete News button in DailyView */
2 | "Delete" = "删除";
3 |
4 | /* Download button in DailyView */
5 | "Download & Save" = "下载并保存";
6 |
7 | /* Reply string in CommentView */
8 | "Reply" = "回复";
9 |
10 |
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Resources/zh-Hant.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* (No Commment) */
2 | "CFBundleDisplayName" = "速知";
3 |
4 | /* (No Commment) */
5 | "CFBundleName" = "速知";
6 |
7 |
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Resources/zh-Hant.lproj/Localizable.strings:
--------------------------------------------------------------------------------
1 | /* Delete News button in DailyView */
2 | "Delete" = "刪除";
3 |
4 | /* Download button in DailyView */
5 | "Download & Save" = "下載並保存";
6 |
7 | /* Reply string in CommentView */
8 | "Reply" = "回復";
9 |
10 |
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/ViewModels/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NicholasTD07/Swift-ZHI/2a380d7855f2b55d1973ee59fbf2e5ca4c4b001f/SwiftDaily-ZhiHu/ViewModels/.gitkeep
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Views/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NicholasTD07/Swift-ZHI/2a380d7855f2b55d1973ee59fbf2e5ca4c4b001f/SwiftDaily-ZhiHu/Views/.gitkeep
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Views/CommentSectionHeaderView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CommentSectionHeaderView.swift
3 | // Swift-ZHI
4 | //
5 | // Created by Nicholas Tian on 30/07/2015.
6 | // Copyright (c) 2015 nickTD. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class CommentSectionHeaderView: UITableViewHeaderFooterView {
12 | @IBOutlet weak var avatarImageView: UIImageView!
13 | @IBOutlet weak var usernameLabel: UILabel!
14 | @IBOutlet weak var repliedAtLabel: UILabel!
15 | @IBOutlet weak var longCommentIndicator: UILabel!
16 |
17 | var avatarURL: NSURL?
18 | }
19 |
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Views/DailySectionHeaderView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DailySectionHeaderView.swift
3 | // SwiftDaily-ZhiHu
4 | //
5 | // Created by Nicholas Tian on 22/06/2015.
6 | // Copyright © 2015 nickTD. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class DailySectionHeaderView: UITableViewHeaderFooterView {
12 | @IBOutlet weak var titleLabel: UILabel!
13 | }
14 |
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHu/Views/LoadingCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LoadingCell.swift
3 | // SwiftDaily-ZhiHu
4 | //
5 | // Created by Nicholas Tian on 17/06/2015.
6 | // Copyright © 2015 nickTD. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class LoadingCell: UITableViewCell {
12 | @IBOutlet weak var activityIndicator: UIActivityIndicatorView!
13 | }
14 |
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHuTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHuTests/SwiftDaily_ZhiHuTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SwiftDaily_ZhiHuTests.swift
3 | // SwiftDaily-ZhiHuTests
4 | //
5 | // Created by Nicholas Tian on 24/06/2015.
6 | // Copyright © 2015 nickTD. All rights reserved.
7 | //
8 |
9 | import XCTest
10 |
11 | class SwiftDaily_ZhiHuTests: XCTestCase {
12 |
13 | override func setUp() {
14 | super.setUp()
15 | // Put setup code here. This method is called before the invocation of each test method in the class.
16 | }
17 |
18 | override func tearDown() {
19 | // Put teardown code here. This method is called after the invocation of each test method in the class.
20 | super.tearDown()
21 | }
22 |
23 | func testExample() {
24 | // This is an example of a functional test case.
25 | // Use XCTAssert and related functions to verify your tests produce the correct results.
26 | }
27 |
28 | func testPerformanceExample() {
29 | // This is an example of a performance test case.
30 | self.measureBlock() {
31 | // Put the code you want to measure the time of here.
32 | }
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHuTests/zh-Hans.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* (No Commment) */
2 | "CFBundleName" = "速知";
3 |
4 | /* (No Commment) */
5 | "CFBundleShortVersionString" = "1.0";
6 |
7 |
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHuTests/zh-Hant.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* (No Commment) */
2 | "CFBundleName" = "速知";
3 |
4 | /* (No Commment) */
5 | "CFBundleShortVersionString" = "1.0";
6 |
7 |
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHuUITests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHuUITests/SwiftDaily_ZhiHuUITests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SwiftDaily_ZhiHuUITests.swift
3 | // SwiftDaily-ZhiHuUITests
4 | //
5 | // Created by Nicholas Tian on 24/06/2015.
6 | // Copyright © 2015 nickTD. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import XCTest
11 |
12 | @available(iOS 9.0, *)
13 | class SwiftDaily_ZhiHuUITests: XCTestCase {
14 | override func setUp() {
15 | super.setUp()
16 |
17 | // Put setup code here. This method is called before the invocation of each test method in the class.
18 |
19 | // In UI tests it is usually best to stop immediately when a failure occurs.
20 | continueAfterFailure = false
21 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
22 | XCUIApplication().launch()
23 | }
24 |
25 | override func tearDown() {
26 | // Put teardown code here. This method is called after the invocation of each test method in the class.
27 | super.tearDown()
28 | }
29 |
30 | func testExample() {
31 | // Use recording to get started writing UI tests.
32 | // Use XCTAssert and related functions to verify your tests produce the correct results.
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHuUITests/zh-Hans.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* (No Commment) */
2 | "CFBundleName" = "速知";
3 |
4 | /* (No Commment) */
5 | "CFBundleShortVersionString" = "1.0";
6 |
7 |
--------------------------------------------------------------------------------
/SwiftDaily-ZhiHuUITests/zh-Hant.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* (No Commment) */
2 | "CFBundleName" = "速知";
3 |
4 | /* (No Commment) */
5 | "CFBundleShortVersionString" = "1.0";
6 |
7 |
--------------------------------------------------------------------------------
/Tests/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NicholasTD07/Swift-ZHI/2a380d7855f2b55d1973ee59fbf2e5ca4c4b001f/Tests/.gitkeep
--------------------------------------------------------------------------------
/Tests/Helpers/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NicholasTD07/Swift-ZHI/2a380d7855f2b55d1973ee59fbf2e5ca4c4b001f/Tests/Helpers/.gitkeep
--------------------------------------------------------------------------------
/Tests/Resources/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NicholasTD07/Swift-ZHI/2a380d7855f2b55d1973ee59fbf2e5ca4c4b001f/Tests/Resources/.gitkeep
--------------------------------------------------------------------------------
/Tests/Resources/Tests-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | com.nickTD.${PRODUCT_NAME:rfc1034identifier}
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundlePackageType
14 | BNDL
15 | CFBundleShortVersionString
16 | 1.0
17 | CFBundleSignature
18 | ????
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Tests/Tests/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NicholasTD07/Swift-ZHI/2a380d7855f2b55d1973ee59fbf2e5ca4c4b001f/Tests/Tests/.gitkeep
--------------------------------------------------------------------------------
/bin/bump:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | SHORT_VERSION=`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" ./SwiftDaily-ZhiHu/Resources/Info.plist`
4 | VERSION=`/usr/libexec/PlistBuddy -c "Print CFBundleVersion" ./SwiftDaily-ZhiHu/Resources/Info.plist`
5 |
6 | git commit -v -e -m "Bump version number $SHORT_VERSION/$VERSION"
7 |
--------------------------------------------------------------------------------
/bin/merge:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | # Merge but keep files in Carthage/Checkouts/* as is in this branch
3 |
4 | git merge --no-commit $*
5 | git checkout ./Carthage/Checkouts/*
6 | echo "Remember to commit the changes. :]"
7 |
--------------------------------------------------------------------------------
/bin/new_branch:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | # Create branches whose base if the merge base of develop and release branch.
3 | # To minimize changes to git's commit graph, when merge new changes into both branch.
4 |
5 | git fetch --all
6 | git checkout -b $* `git merge-base remotes/origin/develop remotes/origin/release/Xcode-6.3.2-Swift-1.2`
7 |
--------------------------------------------------------------------------------
/bin/test:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -o pipefail
4 |
5 | xcodebuild test -workspace SwiftDaily-ZhiHu.xcworkspace -scheme SwiftDaily-ZhiHu -sdk iphonesimulator BUILD_ACTIVE_ARCH=NO | xcpretty -t -c
6 |
--------------------------------------------------------------------------------