├── .gitignore
├── LICENSE
├── README.md
├── TWSReleaseNotesView Docs
├── html
│ ├── Classes
│ │ ├── TWSReleaseNotesDownloadOperation.html
│ │ └── TWSReleaseNotesView.html
│ ├── css
│ │ ├── styles.css
│ │ └── stylesPrint.css
│ ├── hierarchy.html
│ ├── img
│ │ ├── button_bar_background.png
│ │ ├── disclosure.png
│ │ ├── disclosure_open.png
│ │ ├── library_background.png
│ │ └── title_background.png
│ └── index.html
└── it.matteolallone.TWSReleaseNotesView.docset
│ └── Contents
│ ├── Info.plist
│ └── Resources
│ ├── Documents
│ ├── Classes
│ │ ├── TWSReleaseNotesDownloadOperation.html
│ │ └── TWSReleaseNotesView.html
│ ├── css
│ │ ├── styles.css
│ │ └── stylesPrint.css
│ ├── hierarchy.html
│ ├── img
│ │ ├── button_bar_background.png
│ │ ├── disclosure.png
│ │ ├── disclosure_open.png
│ │ ├── library_background.png
│ │ └── title_background.png
│ └── index.html
│ ├── docSet.dsidx
│ ├── docSet.mom
│ ├── docSet.skidx
│ └── docSet.toc
├── TWSReleaseNotesView
├── TWSReleaseNotesDownloadOperation.h
├── TWSReleaseNotesDownloadOperation.m
├── TWSReleaseNotesView.h
├── TWSReleaseNotesView.m
├── UIImage+ImageEffects.h
└── UIImage+ImageEffects.m
├── TWSReleaseNotesViewSample
├── TWSReleaseNotesViewSample.xcodeproj
│ └── project.pbxproj
└── TWSReleaseNotesViewSample
│ ├── AppDelegate.h
│ ├── AppDelegate.m
│ ├── Default-568h@2x.png
│ ├── Default.png
│ ├── Default@2x.png
│ ├── RootViewController.h
│ ├── RootViewController.m
│ ├── RootViewController.xib
│ ├── TWSReleaseNotesViewSample-Info.plist
│ ├── TWSReleaseNotesViewSample-Prefix.pch
│ ├── background.png
│ ├── background@2x.png
│ ├── btn_bg.png
│ ├── btn_bg@2x.png
│ ├── btn_bg_hl.png
│ ├── btn_bg_hl@2x.png
│ ├── en.lproj
│ └── InfoPlist.strings
│ ├── icon.png
│ ├── icon@2x.png
│ ├── icon_7@2x.png
│ └── main.m
└── TutorialImages
├── sampleProject01.png
└── sampleProject02.png
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | .DS_Store
3 | build/
4 | *.pbxuser
5 | !default.pbxuser
6 | *.mode1v3
7 | !default.mode1v3
8 | *.mode2v3
9 | !default.mode2v3
10 | *.perspectivev3
11 | !default.perspectivev3
12 | *.xcworkspace
13 | !default.xcworkspace
14 | xcuserdata
15 | profile
16 | *.moved-aside
17 | DerivedData
18 | .idea/
19 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2013 Matteo Lallone
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | 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, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | TWSReleaseNotesView
2 | ===================
3 |
4 | Among other crazy features, iOS 7 enables users to have automatic updates for their apps, wiping away the infamous App Store badge. This is really convenient both for users and developers, but it comes with a couple of downsides:
5 |
6 | * users are not aware about the changes introduced in the latest update, unless they explicitly open the App Store page to check the release notes;
7 | * developers who spend their time working on well-written release notes lose their chance to inform and communicate with their users.
8 |
9 | ## So what?
10 | TWSReleaseNotesView is a simple way to address those issues. It comes with a straightforward API which enables developers to show in-app release notes with a fully customizable popup view.
11 |
12 |
13 | ## How to get started
14 | ### CocoaPods
15 | 1. Just add the following line to your Podfile: `pod 'TWSReleaseNotesView', '~> 1.2.0'`
16 | 2. You're good to go!
17 |
18 | ### Manual installation
19 | 1. Download the TWSReleaseNotesView folder and add it to your project.
20 | 2. In addition to the default `UIKit`, `CoreGraphics` and `Foundation`, there's a dependency from the `Accelerate` and the `Quartzcore` frameworks. If any of them is missing in your Frameworks list, follow these steps in order to add them:
21 | * Go to the "Build Phases" tab for your project target.
22 | * Click the `+` button in the collapsible "Link Binary With Libraries" section.
23 | * Add the missing frameworks.
24 | 3. That's it!
25 |
26 | # Example usage
27 |
28 | ## Version check and local release notes view setup
29 | ```objective-c
30 | // Check for first app launch and app update
31 | if (![TWSReleaseNotesView isAppOnFirstLaunch] && [TWSReleaseNotesView isAppVersionUpdated])
32 | {
33 | // Create the release notes view
34 | NSString *currentAppVersion = [[NSBundle mainBundle] infoDictionary][@"CFBundleVersion"];
35 | TWSReleaseNotesView *releaseNotesView = [TWSReleaseNotesView viewWithReleaseNotesTitle:[NSString stringWithFormat:@"What's new in version %@:", currentAppVersion] text:@"• Great new feature\n• Annoying bug wiped away\n• Optimizations and other great stuff!\n• Additional performance and stability improvements" closeButtonTitle:@"Close"];
36 |
37 | // Show the release notes view
38 | [releaseNotesView showInView:self.view];
39 | }
40 | ```
41 |
42 | ## Version check and remote release notes view setup
43 | ```objective-c
44 | // Check for app update
45 | if ([TWSReleaseNotesView isAppVersionUpdated])
46 | {
47 | // Setup a remote release notes view
48 | NSString *currentAppVersion = [[NSBundle mainBundle] infoDictionary][@"CFBundleVersion"];
49 | [TWSReleaseNotesView setupViewWithAppIdentifier:@"XXXXXXXXX" releaseNotesTitle:[NSString stringWithFormat:@"What's new in version %@:", currentAppVersion] closeButtonTitle:@"Close" completionBlock:^(TWSReleaseNotesView *releaseNotesView, NSString *releaseNotesText, NSError *error){
50 | if (error)
51 | {
52 | // Handle errors
53 | NSLog(@"An error occurred: %@", [error localizedDescription]);
54 | }
55 | else
56 | {
57 | // Create and show release notes view
58 | [releaseNotesView showInView:self.view];
59 | }
60 | }];
61 | }
62 | ```
63 |
64 | ## Sample project
65 | The **TWSReleaseNotesViewSample** sample project shows how to deal with the two use cases described above.
66 |
67 |  
68 |
69 | ## Features
70 | * First app launch check.
71 | * Version check in order to choose whether showing the release notes view or not.
72 | * Local release notes view with custom appearance and text information.
73 | * Remote release notes view using the application's Apple ID, in order to retrieve the last release notes directly from App Store, using the iTunes Search API.
74 |
75 | ## Documentation
76 | The code is fully commented using a [Javadoc](http://en.wikipedia.org/wiki/Javadoc)-like syntax, in order to use [appledoc](https://github.com/tomaz/appledoc) for the documentation generation. Check the **TWReleaseNotesView Docs** folder for the complete documentation, in both html and .docset format. The .docset file can be copied in the `~/Library/Developer/Shared/Documentation/DocSets` folder, in order to be able to read the documentation in Xcode. If you decide to do so, please, remember to close Xcode before copying the .docset file in the proper folder, then re-open it.
77 |
78 | ## Credits
79 | TWSReleaseNotesView was developed by **Tapwings**: Matteo Lallone (iOS developer - [@iGriever](https://twitter.com/iGriever)) and Gianluca Divisi (UI/UX designer - [@gianlucadivisi](https://twitter.com/gianlucadivisi)). Follow us on Twitter ([@tapwings](https://twitter.com/tapwings)) to receive updates on our work.
80 |
81 | ## License
82 | The MIT License (MIT)
83 |
84 | Copyright (c) 2013 Matteo Lallone
85 |
86 | Permission is hereby granted, free of charge, to any person obtaining a copy of
87 | this software and associated documentation files (the "Software"), to deal in
88 | the Software without restriction, including without limitation the rights to
89 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
90 | the Software, and to permit persons to whom the Software is furnished to do so,
91 | subject to the following conditions:
92 |
93 | The above copyright notice and this permission notice shall be included in all
94 | copies or substantial portions of the Software.
95 |
96 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
97 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
98 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
99 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
100 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
101 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
102 |
--------------------------------------------------------------------------------
/TWSReleaseNotesView Docs/html/Classes/TWSReleaseNotesDownloadOperation.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | TWSReleaseNotesDownloadOperation Class Reference
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
62 |
63 |
102 |
103 |
104 |
105 |
106 |
112 |
117 |
118 |
119 |
120 |
121 | Inherits from
122 | NSOperation
123 |
124 | Declared in
125 | TWSReleaseNotesDownloadOperation.h TWSReleaseNotesDownloadOperation.m
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
Overview
135 |
Use the TWSReleaseNotesDownloadOperation class to create an operation with the purpose of downloading the release notes text for a specified app, using the iTunes Search API.
136 |
137 |
The result of the operation is accessible in the completionBlock, using the releaseNotesText and the error properties.
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
Tasks
147 |
148 |
149 |
150 |
Getting main properties
151 |
152 |
153 |
154 |
155 | releaseNotesText
156 | The downloaded release notes text.
157 |
158 | property
159 |
160 |
161 |
162 | error
163 | An error object associated to the failed operation.
164 |
165 | property
166 |
167 |
168 |
169 |
170 |
171 |
172 |
Creating the operation
173 |
174 |
175 |
176 |
177 | – initWithAppIdentifier:
178 | Creates and operation with custom parameters.
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
Properties
194 |
195 |
196 |
197 |
error
198 |
199 |
200 |
201 |
202 |
An error object associated to the failed operation.
203 |
204 |
205 |
206 |
207 |
@property (readonly, strong, nonatomic) NSError *error
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
Declared In
225 | TWSReleaseNotesDownloadOperation.h
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
releaseNotesText
234 |
235 |
236 |
237 |
238 |
The downloaded release notes text.
239 |
240 |
241 |
242 |
243 |
@property (readonly, copy, nonatomic) NSString *releaseNotesText
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
Declared In
261 | TWSReleaseNotesDownloadOperation.h
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
Instance Methods
276 |
277 |
278 |
279 |
initWithAppIdentifier:
280 |
281 |
282 |
283 |
284 |
Creates and operation with custom parameters.
285 |
286 |
287 |
288 |
289 |
- (id)initWithAppIdentifier:(NSString *)appIdentifier
290 |
291 |
292 |
293 |
294 |
Parameters
295 |
296 |
297 | appIdentifier
298 | The App Store app identifier for remote release notes retrieval.
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
Return Value
307 |
The initialized operation.
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
Declared In
322 | TWSReleaseNotesDownloadOperation.h
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
338 |
347 |
348 |
349 |
440 |
441 |
--------------------------------------------------------------------------------
/TWSReleaseNotesView Docs/html/css/styles.css:
--------------------------------------------------------------------------------
1 | body {
2 | font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif;
3 | font-size: 13px;
4 | }
5 |
6 | code {
7 | font-family: Courier, Consolas, monospace;
8 | font-size: 13px;
9 | color: #666;
10 | }
11 |
12 | pre {
13 | font-family: Courier, Consolas, monospace;
14 | font-size: 13px;
15 | line-height: 18px;
16 | tab-interval: 0.5em;
17 | border: 1px solid #C7CFD5;
18 | background-color: #F1F5F9;
19 | color: #666;
20 | padding: 0.3em 1em;
21 | }
22 |
23 | ul {
24 | list-style-type: square;
25 | }
26 |
27 | li {
28 | margin-bottom: 10px;
29 | }
30 |
31 | a, a code {
32 | text-decoration: none;
33 | color: #36C;
34 | }
35 |
36 | a:hover, a:hover code {
37 | text-decoration: underline;
38 | color: #36C;
39 | }
40 |
41 | h2 {
42 | border-bottom: 1px solid #8391A8;
43 | color: #3C4C6C;
44 | font-size: 187%;
45 | font-weight: normal;
46 | margin-top: 1.75em;
47 | padding-bottom: 2px;
48 | }
49 |
50 | table {
51 | margin-bottom: 4em;
52 | border-collapse:collapse;
53 | vertical-align: middle;
54 | }
55 |
56 | td {
57 | border: 1px solid #9BB3CD;
58 | padding: .667em;
59 | font-size: 100%;
60 | }
61 |
62 | th {
63 | border: 1px solid #9BB3CD;
64 | padding: .3em .667em .3em .667em;
65 | background: #93A5BB;
66 | font-size: 103%;
67 | font-weight: bold;
68 | color: white;
69 | text-align: left;
70 | }
71 |
72 | /* @group Common page elements */
73 |
74 | #top_header {
75 | height: 91px;
76 | left: 0;
77 | min-width: 598px;
78 | position: absolute;
79 | right: 0;
80 | top: 0;
81 | z-index: 900;
82 | }
83 |
84 | #footer {
85 | clear: both;
86 | padding-top: 20px;
87 | text-align: center;
88 | }
89 |
90 | #contents, #overview_contents {
91 | -webkit-overflow-scrolling: touch;
92 | border-top: 1px solid #2B334F;
93 | position: absolute;
94 | top: 91px;
95 | left: 0;
96 | right: 0;
97 | bottom: 0;
98 | overflow-x: hidden;
99 | overflow-y: auto;
100 | padding-left: 2em;
101 | padding-right: 2em;
102 | padding-top: 1em;
103 | min-width: 550px;
104 | }
105 |
106 | #contents.isShowingTOC {
107 | left: 230px;
108 | min-width: 320px;
109 | }
110 |
111 | .copyright {
112 | font-size: 12px;
113 | }
114 |
115 | .generator {
116 | font-size: 11px;
117 | }
118 |
119 | .main-navigation ul li {
120 | display: inline;
121 | margin-left: 15px;
122 | list-style: none;
123 | }
124 |
125 | .navigation-top {
126 | clear: both;
127 | float: right;
128 | }
129 |
130 | .navigation-bottom {
131 | clear: both;
132 | float: right;
133 | margin-top: 20px;
134 | margin-bottom: -10px;
135 | }
136 |
137 | .open > .disclosure {
138 | background-image: url("../img/disclosure_open.png");
139 | }
140 |
141 | .disclosure {
142 | background: url("../img/disclosure.png") no-repeat scroll 0 0;
143 | }
144 |
145 | .disclosure, .nodisclosure {
146 | display: inline-block;
147 | height: 8px;
148 | margin-right: 5px;
149 | position: relative;
150 | width: 9px;
151 | }
152 |
153 | /* @end */
154 |
155 | /* @group Header */
156 |
157 | #top_header #library {
158 | background: url("../img/library_background.png") repeat-x 0 0 #485E78;
159 | background-color: #ccc;
160 | height: 35px;
161 | font-size: 115%;
162 | }
163 |
164 | #top_header #library #libraryTitle {
165 | color: #FFFFFF;
166 | margin-left: 15px;
167 | text-shadow: 0 -1px 0 #485E78;
168 | top: 8px;
169 | position: absolute;
170 | }
171 |
172 | #top_header #library #developerHome {
173 | color: #92979E;
174 | right: 15px;
175 | top: 8px;
176 | position: absolute;
177 | }
178 |
179 | #top_header #library a:hover {
180 | text-decoration: none;
181 | }
182 |
183 | #top_header #title {
184 | background: url("../img/title_background.png") repeat-x 0 0 #8A98A9;
185 | border-bottom: 1px solid #B6B6B6;
186 | height: 25px;
187 | overflow: hidden;
188 | }
189 |
190 | #top_header h1 {
191 | font-size: 115%;
192 | font-weight: normal;
193 | margin: 0;
194 | padding: 3px 0 2px;
195 | text-align: center;
196 | text-shadow: 0 1px 0 #D5D5D5;
197 | white-space: nowrap;
198 | }
199 |
200 | #headerButtons {
201 | background-color: #D8D8D8;
202 | background-image: url("../img/button_bar_background.png");
203 | border-bottom: 1px solid #EDEDED;
204 | border-top: 1px solid #2B334F;
205 | font-size: 8pt;
206 | height: 28px;
207 | left: 0;
208 | list-style: none outside none;
209 | margin: 0;
210 | overflow: hidden;
211 | padding: 0;
212 | position: absolute;
213 | right: 0;
214 | top: 61px;
215 | }
216 |
217 | #headerButtons li {
218 | background-repeat: no-repeat;
219 | display: inline;
220 | margin-top: 0;
221 | margin-bottom: 0;
222 | padding: 0;
223 | }
224 |
225 | #toc_button button {
226 | border-color: #ACACAC;
227 | border-style: none solid none none;
228 | border-width: 0 1px 0 0;
229 | height: 28px;
230 | margin: 0;
231 | padding-left: 30px;
232 | text-align: left;
233 | width: 230px;
234 | }
235 |
236 | li#jumpto_button {
237 | left: 230px;
238 | margin-left: 0;
239 | position: absolute;
240 | }
241 |
242 | li#jumpto_button select {
243 | height: 22px;
244 | margin: 5px 2px 0 10px;
245 | max-width: 300px;
246 | }
247 |
248 | /* @end */
249 |
250 | /* @group Table of contents */
251 |
252 | #tocContainer.isShowingTOC {
253 | border-right: 1px solid #ACACAC;
254 | display: block;
255 | overflow-x: hidden;
256 | overflow-y: auto;
257 | padding: 0;
258 | }
259 |
260 | #tocContainer {
261 | background-color: #E4EBF7;
262 | border-top: 1px solid #2B334F;
263 | bottom: 0;
264 | display: none;
265 | left: 0;
266 | overflow: hidden;
267 | position: absolute;
268 | top: 91px;
269 | width: 229px;
270 | }
271 |
272 | #tocContainer > ul#toc {
273 | font-size: 11px;
274 | margin: 0;
275 | padding: 12px 0 18px;
276 | width: 209px;
277 | -moz-user-select: none;
278 | -webkit-user-select: none;
279 | user-select: none;
280 | }
281 |
282 | #tocContainer > ul#toc > li {
283 | margin: 0;
284 | padding: 0 0 7px 30px;
285 | text-indent: -15px;
286 | }
287 |
288 | #tocContainer > ul#toc > li > .sectionName a {
289 | color: #000000;
290 | font-weight: bold;
291 | }
292 |
293 | #tocContainer > ul#toc > li > .sectionName a:hover {
294 | text-decoration: none;
295 | }
296 |
297 | #tocContainer > ul#toc li.children > ul {
298 | display: none;
299 | height: 0;
300 | }
301 |
302 | #tocContainer > ul#toc > li > ul {
303 | margin: 0;
304 | padding: 0;
305 | }
306 |
307 | #tocContainer > ul#toc > li > ul, ul#toc > li > ul > li {
308 | margin-left: 0;
309 | margin-bottom: 0;
310 | padding-left: 15px;
311 | }
312 |
313 | #tocContainer > ul#toc > li ul {
314 | list-style: none;
315 | margin-right: 0;
316 | padding-right: 0;
317 | }
318 |
319 | #tocContainer > ul#toc li.children.open > ul {
320 | display: block;
321 | height: auto;
322 | margin-left: -15px;
323 | padding-left: 0;
324 | }
325 |
326 | #tocContainer > ul#toc > li > ul, ul#toc > li > ul > li {
327 | margin-left: 0;
328 | padding-left: 15px;
329 | }
330 |
331 | #tocContainer li ul li {
332 | margin-top: 0.583em;
333 | overflow: hidden;
334 | text-overflow: ellipsis;
335 | white-space: nowrap;
336 | }
337 |
338 | #tocContainer li ul li span.sectionName {
339 | white-space: normal;
340 | }
341 |
342 | #tocContainer > ul#toc > li > ul > li > .sectionName a {
343 | font-weight: bold;
344 | }
345 |
346 | #tocContainer > ul#toc > li > ul a {
347 | color: #4F4F4F;
348 | }
349 |
350 | /* @end */
351 |
352 | /* @group Index formatting */
353 |
354 | .index-title {
355 | font-size: 13px;
356 | font-weight: normal;
357 | }
358 |
359 | .index-column {
360 | float: left;
361 | width: 30%;
362 | min-width: 200px;
363 | font-size: 11px;
364 | }
365 |
366 | .index-column ul {
367 | margin: 8px 0 0 0;
368 | padding: 0;
369 | list-style: none;
370 | }
371 |
372 | .index-column ul li {
373 | margin: 0 0 3px 0;
374 | padding: 0;
375 | }
376 |
377 | .hierarchy-column {
378 | min-width: 400px;
379 | }
380 |
381 | .hierarchy-column ul {
382 | margin: 3px 0 0 15px;
383 | }
384 |
385 | .hierarchy-column ul li {
386 | list-style-type: square;
387 | }
388 |
389 | /* @end */
390 |
391 | /* @group Common formatting elements */
392 |
393 | .title {
394 | font-weight: normal;
395 | font-size: 215%;
396 | margin-top:0;
397 | }
398 |
399 | .subtitle {
400 | font-weight: normal;
401 | font-size: 180%;
402 | color: #3C4C6C;
403 | border-bottom: 1px solid #5088C5;
404 | }
405 |
406 | .subsubtitle {
407 | font-weight: normal;
408 | font-size: 145%;
409 | height: 0.7em;
410 | }
411 |
412 | .note {
413 | border: 1px solid #5088C5;
414 | background-color: white;
415 | margin: 1.667em 0 1.75em 0;
416 | padding: 0 .667em .083em .750em;
417 | }
418 |
419 | .warning {
420 | border: 1px solid #5088C5;
421 | background-color: #F0F3F7;
422 | margin-bottom: 0.5em;
423 | padding: 0.3em 0.8em;
424 | }
425 |
426 | .bug {
427 | border: 1px solid #000;
428 | background-color: #ffffcc;
429 | margin-bottom: 0.5em;
430 | padding: 0.3em 0.8em;
431 | }
432 |
433 | .deprecated {
434 | color: #F60425;
435 | }
436 |
437 | /* @end */
438 |
439 | /* @group Common layout */
440 |
441 | .section {
442 | margin-top: 3em;
443 | }
444 |
445 | /* @end */
446 |
447 | /* @group Object specification section */
448 |
449 | .section-specification {
450 | margin-left: 2.5em;
451 | margin-right: 2.5em;
452 | font-size: 12px;
453 | }
454 |
455 | .section-specification table {
456 | margin-bottom: 0em;
457 | border-top: 1px solid #d6e0e5;
458 | }
459 |
460 | .section-specification td {
461 | vertical-align: top;
462 | border-bottom: 1px solid #d6e0e5;
463 | border-left-width: 0px;
464 | border-right-width: 0px;
465 | border-top-width: 0px;
466 | padding: .6em;
467 | }
468 |
469 | .section-specification .specification-title {
470 | font-weight: bold;
471 | }
472 |
473 | /* @end */
474 |
475 | /* @group Tasks section */
476 |
477 | .task-list {
478 | list-style-type: none;
479 | padding-left: 0px;
480 | }
481 |
482 | .task-list li {
483 | margin-bottom: 3px;
484 | }
485 |
486 | .task-item-suffix {
487 | color: #996;
488 | font-size: 12px;
489 | font-style: italic;
490 | margin-left: 0.5em;
491 | }
492 |
493 | span.tooltip span.tooltip {
494 | font-size: 1.0em;
495 | display: none;
496 | padding: 0.3em;
497 | border: 1px solid #aaa;
498 | background-color: #fdfec8;
499 | color: #000;
500 | text-align: left;
501 | }
502 |
503 | span.tooltip:hover span.tooltip {
504 | display: block;
505 | position: absolute;
506 | margin-left: 2em;
507 | }
508 |
509 | /* @end */
510 |
511 | /* @group Method section */
512 |
513 | .section-method {
514 | margin-top: 2.3em;
515 | }
516 |
517 | .method-title {
518 | margin-bottom: 1.5em;
519 | }
520 |
521 | .method-subtitle {
522 | margin-top: 0.7em;
523 | margin-bottom: 0.2em;
524 | }
525 |
526 | .method-subsection p {
527 | margin-top: 0.4em;
528 | margin-bottom: 0.8em;
529 | }
530 |
531 | .method-declaration {
532 | margin-top:1.182em;
533 | margin-bottom:.909em;
534 | }
535 |
536 | .method-declaration code {
537 | font:14px Courier, Consolas, monospace;
538 | color:#000;
539 | }
540 |
541 | .declaration {
542 | color: #000;
543 | }
544 |
545 | .argument-def {
546 | margin-top: 0.3em;
547 | margin-bottom: 0.3em;
548 | }
549 |
550 | .argument-def dd {
551 | margin-left: 1.25em;
552 | }
553 |
554 | .see-also-section ul {
555 | list-style-type: none;
556 | padding-left: 0px;
557 | margin-top: 0;
558 | }
559 |
560 | .see-also-section li {
561 | margin-bottom: 3px;
562 | }
563 |
564 | .declared-in-ref {
565 | color: #666;
566 | }
567 |
568 | #tocContainer.hideInXcode {
569 | display: none;
570 | border: 0px solid black;
571 | }
572 |
573 | #top_header.hideInXcode {
574 | display: none;
575 | }
576 |
577 | #contents.hideInXcode {
578 | border: 0px solid black;
579 | top: 0px;
580 | left: 0px;
581 | }
582 |
583 | /* @end */
584 |
585 |
--------------------------------------------------------------------------------
/TWSReleaseNotesView Docs/html/css/stylesPrint.css:
--------------------------------------------------------------------------------
1 |
2 | header {
3 | display: none;
4 | }
5 |
6 | div.main-navigation, div.navigation-top {
7 | display: none;
8 | }
9 |
10 | div#overview_contents, div#contents.isShowingTOC, div#contents {
11 | overflow: visible;
12 | position: relative;
13 | top: 0px;
14 | border: none;
15 | left: 0;
16 | }
17 | #tocContainer.isShowingTOC {
18 | display: none;
19 | }
20 | nav {
21 | display: none;
22 | }
--------------------------------------------------------------------------------
/TWSReleaseNotesView Docs/html/hierarchy.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | TWSReleaseNotesView Hierarchy
6 |
7 |
8 |
9 |
10 |
11 |
22 |
23 |
24 |
27 |
32 |
33 |
34 |
35 |
Class Hierarchy
36 |
37 |
38 |
39 | NSOperation
40 |
45 |
46 |
47 | UIView
48 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
65 |
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/TWSReleaseNotesView Docs/html/img/button_bar_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iGriever/TWSReleaseNotesView/HEAD/TWSReleaseNotesView Docs/html/img/button_bar_background.png
--------------------------------------------------------------------------------
/TWSReleaseNotesView Docs/html/img/disclosure.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iGriever/TWSReleaseNotesView/HEAD/TWSReleaseNotesView Docs/html/img/disclosure.png
--------------------------------------------------------------------------------
/TWSReleaseNotesView Docs/html/img/disclosure_open.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iGriever/TWSReleaseNotesView/HEAD/TWSReleaseNotesView Docs/html/img/disclosure_open.png
--------------------------------------------------------------------------------
/TWSReleaseNotesView Docs/html/img/library_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iGriever/TWSReleaseNotesView/HEAD/TWSReleaseNotesView Docs/html/img/library_background.png
--------------------------------------------------------------------------------
/TWSReleaseNotesView Docs/html/img/title_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iGriever/TWSReleaseNotesView/HEAD/TWSReleaseNotesView Docs/html/img/title_background.png
--------------------------------------------------------------------------------
/TWSReleaseNotesView Docs/html/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | TWSReleaseNotesView Reference
6 |
7 |
8 |
9 |
10 |
11 |
22 |
23 |
24 |
27 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
Class References
40 |
47 |
48 |
49 |
50 |
51 |
52 |
55 |
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/TWSReleaseNotesView Docs/it.matteolallone.TWSReleaseNotesView.docset/Contents/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleIdentifier
8 | it.matteolallone.TWSReleaseNotesView
9 | CFBundleName
10 | TWSReleaseNotesView Documentation
11 | CFBundleShortVersionString
12 | 1.0
13 | CFBundleVersion
14 | 1.0
15 |
16 |
17 |
18 |
19 | DocSetFeedName
20 | TWSReleaseNotesView Documentation
21 |
22 | DocSetMinimumXcodeVersion
23 | 3.0
24 |
25 | DocSetPublisherIdentifier
26 | it.matteolallone.documentation
27 | DocSetPublisherName
28 | Matteo Lallone
29 | NSHumanReadableCopyright
30 | Copyright © 2013 Matteo Lallone. All rights reserved.
31 |
32 |
33 |
--------------------------------------------------------------------------------
/TWSReleaseNotesView Docs/it.matteolallone.TWSReleaseNotesView.docset/Contents/Resources/Documents/Classes/TWSReleaseNotesDownloadOperation.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | TWSReleaseNotesDownloadOperation Class Reference
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
62 |
63 |
102 |
103 |
104 |
105 |
106 |
112 |
117 |
118 |
119 |
120 |
121 | Inherits from
122 | NSOperation
123 |
124 | Declared in
125 | TWSReleaseNotesDownloadOperation.h TWSReleaseNotesDownloadOperation.m
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
Overview
135 |
Use the TWSReleaseNotesDownloadOperation class to create an operation with the purpose of downloading the release notes text for a specified app, using the iTunes Search API.
136 |
137 |
The result of the operation is accessible in the completionBlock, using the releaseNotesText and the error properties.
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
Tasks
147 |
148 |
149 |
150 |
Getting main properties
151 |
152 |
153 |
154 |
155 | releaseNotesText
156 | The downloaded release notes text.
157 |
158 | property
159 |
160 |
161 |
162 | error
163 | An error object associated to the failed operation.
164 |
165 | property
166 |
167 |
168 |
169 |
170 |
171 |
172 |
Creating the operation
173 |
174 |
175 |
176 |
177 | – initWithAppIdentifier:
178 | Creates and operation with custom parameters.
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
Properties
194 |
195 |
196 |
197 |
error
198 |
199 |
200 |
201 |
202 |
An error object associated to the failed operation.
203 |
204 |
205 |
206 |
207 |
@property (readonly, strong, nonatomic) NSError *error
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
Declared In
225 | TWSReleaseNotesDownloadOperation.h
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
releaseNotesText
234 |
235 |
236 |
237 |
238 |
The downloaded release notes text.
239 |
240 |
241 |
242 |
243 |
@property (readonly, copy, nonatomic) NSString *releaseNotesText
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
Declared In
261 | TWSReleaseNotesDownloadOperation.h
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
Instance Methods
276 |
277 |
278 |
279 |
initWithAppIdentifier:
280 |
281 |
282 |
283 |
284 |
Creates and operation with custom parameters.
285 |
286 |
287 |
288 |
289 |
- (id)initWithAppIdentifier:(NSString *)appIdentifier
290 |
291 |
292 |
293 |
294 |
Parameters
295 |
296 |
297 | appIdentifier
298 | The App Store app identifier for remote release notes retrieval.
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
Return Value
307 |
The initialized operation.
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
Declared In
322 | TWSReleaseNotesDownloadOperation.h
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
338 |
347 |
348 |
349 |
440 |
441 |
--------------------------------------------------------------------------------
/TWSReleaseNotesView Docs/it.matteolallone.TWSReleaseNotesView.docset/Contents/Resources/Documents/css/styles.css:
--------------------------------------------------------------------------------
1 | body {
2 | font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif;
3 | font-size: 13px;
4 | }
5 |
6 | code {
7 | font-family: Courier, Consolas, monospace;
8 | font-size: 13px;
9 | color: #666;
10 | }
11 |
12 | pre {
13 | font-family: Courier, Consolas, monospace;
14 | font-size: 13px;
15 | line-height: 18px;
16 | tab-interval: 0.5em;
17 | border: 1px solid #C7CFD5;
18 | background-color: #F1F5F9;
19 | color: #666;
20 | padding: 0.3em 1em;
21 | }
22 |
23 | ul {
24 | list-style-type: square;
25 | }
26 |
27 | li {
28 | margin-bottom: 10px;
29 | }
30 |
31 | a, a code {
32 | text-decoration: none;
33 | color: #36C;
34 | }
35 |
36 | a:hover, a:hover code {
37 | text-decoration: underline;
38 | color: #36C;
39 | }
40 |
41 | h2 {
42 | border-bottom: 1px solid #8391A8;
43 | color: #3C4C6C;
44 | font-size: 187%;
45 | font-weight: normal;
46 | margin-top: 1.75em;
47 | padding-bottom: 2px;
48 | }
49 |
50 | table {
51 | margin-bottom: 4em;
52 | border-collapse:collapse;
53 | vertical-align: middle;
54 | }
55 |
56 | td {
57 | border: 1px solid #9BB3CD;
58 | padding: .667em;
59 | font-size: 100%;
60 | }
61 |
62 | th {
63 | border: 1px solid #9BB3CD;
64 | padding: .3em .667em .3em .667em;
65 | background: #93A5BB;
66 | font-size: 103%;
67 | font-weight: bold;
68 | color: white;
69 | text-align: left;
70 | }
71 |
72 | /* @group Common page elements */
73 |
74 | #top_header {
75 | height: 91px;
76 | left: 0;
77 | min-width: 598px;
78 | position: absolute;
79 | right: 0;
80 | top: 0;
81 | z-index: 900;
82 | }
83 |
84 | #footer {
85 | clear: both;
86 | padding-top: 20px;
87 | text-align: center;
88 | }
89 |
90 | #contents, #overview_contents {
91 | -webkit-overflow-scrolling: touch;
92 | border-top: 1px solid #2B334F;
93 | position: absolute;
94 | top: 91px;
95 | left: 0;
96 | right: 0;
97 | bottom: 0;
98 | overflow-x: hidden;
99 | overflow-y: auto;
100 | padding-left: 2em;
101 | padding-right: 2em;
102 | padding-top: 1em;
103 | min-width: 550px;
104 | }
105 |
106 | #contents.isShowingTOC {
107 | left: 230px;
108 | min-width: 320px;
109 | }
110 |
111 | .copyright {
112 | font-size: 12px;
113 | }
114 |
115 | .generator {
116 | font-size: 11px;
117 | }
118 |
119 | .main-navigation ul li {
120 | display: inline;
121 | margin-left: 15px;
122 | list-style: none;
123 | }
124 |
125 | .navigation-top {
126 | clear: both;
127 | float: right;
128 | }
129 |
130 | .navigation-bottom {
131 | clear: both;
132 | float: right;
133 | margin-top: 20px;
134 | margin-bottom: -10px;
135 | }
136 |
137 | .open > .disclosure {
138 | background-image: url("../img/disclosure_open.png");
139 | }
140 |
141 | .disclosure {
142 | background: url("../img/disclosure.png") no-repeat scroll 0 0;
143 | }
144 |
145 | .disclosure, .nodisclosure {
146 | display: inline-block;
147 | height: 8px;
148 | margin-right: 5px;
149 | position: relative;
150 | width: 9px;
151 | }
152 |
153 | /* @end */
154 |
155 | /* @group Header */
156 |
157 | #top_header #library {
158 | background: url("../img/library_background.png") repeat-x 0 0 #485E78;
159 | background-color: #ccc;
160 | height: 35px;
161 | font-size: 115%;
162 | }
163 |
164 | #top_header #library #libraryTitle {
165 | color: #FFFFFF;
166 | margin-left: 15px;
167 | text-shadow: 0 -1px 0 #485E78;
168 | top: 8px;
169 | position: absolute;
170 | }
171 |
172 | #top_header #library #developerHome {
173 | color: #92979E;
174 | right: 15px;
175 | top: 8px;
176 | position: absolute;
177 | }
178 |
179 | #top_header #library a:hover {
180 | text-decoration: none;
181 | }
182 |
183 | #top_header #title {
184 | background: url("../img/title_background.png") repeat-x 0 0 #8A98A9;
185 | border-bottom: 1px solid #B6B6B6;
186 | height: 25px;
187 | overflow: hidden;
188 | }
189 |
190 | #top_header h1 {
191 | font-size: 115%;
192 | font-weight: normal;
193 | margin: 0;
194 | padding: 3px 0 2px;
195 | text-align: center;
196 | text-shadow: 0 1px 0 #D5D5D5;
197 | white-space: nowrap;
198 | }
199 |
200 | #headerButtons {
201 | background-color: #D8D8D8;
202 | background-image: url("../img/button_bar_background.png");
203 | border-bottom: 1px solid #EDEDED;
204 | border-top: 1px solid #2B334F;
205 | font-size: 8pt;
206 | height: 28px;
207 | left: 0;
208 | list-style: none outside none;
209 | margin: 0;
210 | overflow: hidden;
211 | padding: 0;
212 | position: absolute;
213 | right: 0;
214 | top: 61px;
215 | }
216 |
217 | #headerButtons li {
218 | background-repeat: no-repeat;
219 | display: inline;
220 | margin-top: 0;
221 | margin-bottom: 0;
222 | padding: 0;
223 | }
224 |
225 | #toc_button button {
226 | border-color: #ACACAC;
227 | border-style: none solid none none;
228 | border-width: 0 1px 0 0;
229 | height: 28px;
230 | margin: 0;
231 | padding-left: 30px;
232 | text-align: left;
233 | width: 230px;
234 | }
235 |
236 | li#jumpto_button {
237 | left: 230px;
238 | margin-left: 0;
239 | position: absolute;
240 | }
241 |
242 | li#jumpto_button select {
243 | height: 22px;
244 | margin: 5px 2px 0 10px;
245 | max-width: 300px;
246 | }
247 |
248 | /* @end */
249 |
250 | /* @group Table of contents */
251 |
252 | #tocContainer.isShowingTOC {
253 | border-right: 1px solid #ACACAC;
254 | display: block;
255 | overflow-x: hidden;
256 | overflow-y: auto;
257 | padding: 0;
258 | }
259 |
260 | #tocContainer {
261 | background-color: #E4EBF7;
262 | border-top: 1px solid #2B334F;
263 | bottom: 0;
264 | display: none;
265 | left: 0;
266 | overflow: hidden;
267 | position: absolute;
268 | top: 91px;
269 | width: 229px;
270 | }
271 |
272 | #tocContainer > ul#toc {
273 | font-size: 11px;
274 | margin: 0;
275 | padding: 12px 0 18px;
276 | width: 209px;
277 | -moz-user-select: none;
278 | -webkit-user-select: none;
279 | user-select: none;
280 | }
281 |
282 | #tocContainer > ul#toc > li {
283 | margin: 0;
284 | padding: 0 0 7px 30px;
285 | text-indent: -15px;
286 | }
287 |
288 | #tocContainer > ul#toc > li > .sectionName a {
289 | color: #000000;
290 | font-weight: bold;
291 | }
292 |
293 | #tocContainer > ul#toc > li > .sectionName a:hover {
294 | text-decoration: none;
295 | }
296 |
297 | #tocContainer > ul#toc li.children > ul {
298 | display: none;
299 | height: 0;
300 | }
301 |
302 | #tocContainer > ul#toc > li > ul {
303 | margin: 0;
304 | padding: 0;
305 | }
306 |
307 | #tocContainer > ul#toc > li > ul, ul#toc > li > ul > li {
308 | margin-left: 0;
309 | margin-bottom: 0;
310 | padding-left: 15px;
311 | }
312 |
313 | #tocContainer > ul#toc > li ul {
314 | list-style: none;
315 | margin-right: 0;
316 | padding-right: 0;
317 | }
318 |
319 | #tocContainer > ul#toc li.children.open > ul {
320 | display: block;
321 | height: auto;
322 | margin-left: -15px;
323 | padding-left: 0;
324 | }
325 |
326 | #tocContainer > ul#toc > li > ul, ul#toc > li > ul > li {
327 | margin-left: 0;
328 | padding-left: 15px;
329 | }
330 |
331 | #tocContainer li ul li {
332 | margin-top: 0.583em;
333 | overflow: hidden;
334 | text-overflow: ellipsis;
335 | white-space: nowrap;
336 | }
337 |
338 | #tocContainer li ul li span.sectionName {
339 | white-space: normal;
340 | }
341 |
342 | #tocContainer > ul#toc > li > ul > li > .sectionName a {
343 | font-weight: bold;
344 | }
345 |
346 | #tocContainer > ul#toc > li > ul a {
347 | color: #4F4F4F;
348 | }
349 |
350 | /* @end */
351 |
352 | /* @group Index formatting */
353 |
354 | .index-title {
355 | font-size: 13px;
356 | font-weight: normal;
357 | }
358 |
359 | .index-column {
360 | float: left;
361 | width: 30%;
362 | min-width: 200px;
363 | font-size: 11px;
364 | }
365 |
366 | .index-column ul {
367 | margin: 8px 0 0 0;
368 | padding: 0;
369 | list-style: none;
370 | }
371 |
372 | .index-column ul li {
373 | margin: 0 0 3px 0;
374 | padding: 0;
375 | }
376 |
377 | .hierarchy-column {
378 | min-width: 400px;
379 | }
380 |
381 | .hierarchy-column ul {
382 | margin: 3px 0 0 15px;
383 | }
384 |
385 | .hierarchy-column ul li {
386 | list-style-type: square;
387 | }
388 |
389 | /* @end */
390 |
391 | /* @group Common formatting elements */
392 |
393 | .title {
394 | font-weight: normal;
395 | font-size: 215%;
396 | margin-top:0;
397 | }
398 |
399 | .subtitle {
400 | font-weight: normal;
401 | font-size: 180%;
402 | color: #3C4C6C;
403 | border-bottom: 1px solid #5088C5;
404 | }
405 |
406 | .subsubtitle {
407 | font-weight: normal;
408 | font-size: 145%;
409 | height: 0.7em;
410 | }
411 |
412 | .note {
413 | border: 1px solid #5088C5;
414 | background-color: white;
415 | margin: 1.667em 0 1.75em 0;
416 | padding: 0 .667em .083em .750em;
417 | }
418 |
419 | .warning {
420 | border: 1px solid #5088C5;
421 | background-color: #F0F3F7;
422 | margin-bottom: 0.5em;
423 | padding: 0.3em 0.8em;
424 | }
425 |
426 | .bug {
427 | border: 1px solid #000;
428 | background-color: #ffffcc;
429 | margin-bottom: 0.5em;
430 | padding: 0.3em 0.8em;
431 | }
432 |
433 | .deprecated {
434 | color: #F60425;
435 | }
436 |
437 | /* @end */
438 |
439 | /* @group Common layout */
440 |
441 | .section {
442 | margin-top: 3em;
443 | }
444 |
445 | /* @end */
446 |
447 | /* @group Object specification section */
448 |
449 | .section-specification {
450 | margin-left: 2.5em;
451 | margin-right: 2.5em;
452 | font-size: 12px;
453 | }
454 |
455 | .section-specification table {
456 | margin-bottom: 0em;
457 | border-top: 1px solid #d6e0e5;
458 | }
459 |
460 | .section-specification td {
461 | vertical-align: top;
462 | border-bottom: 1px solid #d6e0e5;
463 | border-left-width: 0px;
464 | border-right-width: 0px;
465 | border-top-width: 0px;
466 | padding: .6em;
467 | }
468 |
469 | .section-specification .specification-title {
470 | font-weight: bold;
471 | }
472 |
473 | /* @end */
474 |
475 | /* @group Tasks section */
476 |
477 | .task-list {
478 | list-style-type: none;
479 | padding-left: 0px;
480 | }
481 |
482 | .task-list li {
483 | margin-bottom: 3px;
484 | }
485 |
486 | .task-item-suffix {
487 | color: #996;
488 | font-size: 12px;
489 | font-style: italic;
490 | margin-left: 0.5em;
491 | }
492 |
493 | span.tooltip span.tooltip {
494 | font-size: 1.0em;
495 | display: none;
496 | padding: 0.3em;
497 | border: 1px solid #aaa;
498 | background-color: #fdfec8;
499 | color: #000;
500 | text-align: left;
501 | }
502 |
503 | span.tooltip:hover span.tooltip {
504 | display: block;
505 | position: absolute;
506 | margin-left: 2em;
507 | }
508 |
509 | /* @end */
510 |
511 | /* @group Method section */
512 |
513 | .section-method {
514 | margin-top: 2.3em;
515 | }
516 |
517 | .method-title {
518 | margin-bottom: 1.5em;
519 | }
520 |
521 | .method-subtitle {
522 | margin-top: 0.7em;
523 | margin-bottom: 0.2em;
524 | }
525 |
526 | .method-subsection p {
527 | margin-top: 0.4em;
528 | margin-bottom: 0.8em;
529 | }
530 |
531 | .method-declaration {
532 | margin-top:1.182em;
533 | margin-bottom:.909em;
534 | }
535 |
536 | .method-declaration code {
537 | font:14px Courier, Consolas, monospace;
538 | color:#000;
539 | }
540 |
541 | .declaration {
542 | color: #000;
543 | }
544 |
545 | .argument-def {
546 | margin-top: 0.3em;
547 | margin-bottom: 0.3em;
548 | }
549 |
550 | .argument-def dd {
551 | margin-left: 1.25em;
552 | }
553 |
554 | .see-also-section ul {
555 | list-style-type: none;
556 | padding-left: 0px;
557 | margin-top: 0;
558 | }
559 |
560 | .see-also-section li {
561 | margin-bottom: 3px;
562 | }
563 |
564 | .declared-in-ref {
565 | color: #666;
566 | }
567 |
568 | #tocContainer.hideInXcode {
569 | display: none;
570 | border: 0px solid black;
571 | }
572 |
573 | #top_header.hideInXcode {
574 | display: none;
575 | }
576 |
577 | #contents.hideInXcode {
578 | border: 0px solid black;
579 | top: 0px;
580 | left: 0px;
581 | }
582 |
583 | /* @end */
584 |
585 |
--------------------------------------------------------------------------------
/TWSReleaseNotesView Docs/it.matteolallone.TWSReleaseNotesView.docset/Contents/Resources/Documents/css/stylesPrint.css:
--------------------------------------------------------------------------------
1 |
2 | header {
3 | display: none;
4 | }
5 |
6 | div.main-navigation, div.navigation-top {
7 | display: none;
8 | }
9 |
10 | div#overview_contents, div#contents.isShowingTOC, div#contents {
11 | overflow: visible;
12 | position: relative;
13 | top: 0px;
14 | border: none;
15 | left: 0;
16 | }
17 | #tocContainer.isShowingTOC {
18 | display: none;
19 | }
20 | nav {
21 | display: none;
22 | }
--------------------------------------------------------------------------------
/TWSReleaseNotesView Docs/it.matteolallone.TWSReleaseNotesView.docset/Contents/Resources/Documents/hierarchy.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | TWSReleaseNotesView Hierarchy
6 |
7 |
8 |
9 |
10 |
11 |
22 |
23 |
24 |
27 |
32 |
33 |
34 |
35 |
Class Hierarchy
36 |
37 |
38 |
39 | NSOperation
40 |
45 |
46 |
47 | UIView
48 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
65 |
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/TWSReleaseNotesView Docs/it.matteolallone.TWSReleaseNotesView.docset/Contents/Resources/Documents/img/button_bar_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iGriever/TWSReleaseNotesView/HEAD/TWSReleaseNotesView Docs/it.matteolallone.TWSReleaseNotesView.docset/Contents/Resources/Documents/img/button_bar_background.png
--------------------------------------------------------------------------------
/TWSReleaseNotesView Docs/it.matteolallone.TWSReleaseNotesView.docset/Contents/Resources/Documents/img/disclosure.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iGriever/TWSReleaseNotesView/HEAD/TWSReleaseNotesView Docs/it.matteolallone.TWSReleaseNotesView.docset/Contents/Resources/Documents/img/disclosure.png
--------------------------------------------------------------------------------
/TWSReleaseNotesView Docs/it.matteolallone.TWSReleaseNotesView.docset/Contents/Resources/Documents/img/disclosure_open.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iGriever/TWSReleaseNotesView/HEAD/TWSReleaseNotesView Docs/it.matteolallone.TWSReleaseNotesView.docset/Contents/Resources/Documents/img/disclosure_open.png
--------------------------------------------------------------------------------
/TWSReleaseNotesView Docs/it.matteolallone.TWSReleaseNotesView.docset/Contents/Resources/Documents/img/library_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iGriever/TWSReleaseNotesView/HEAD/TWSReleaseNotesView Docs/it.matteolallone.TWSReleaseNotesView.docset/Contents/Resources/Documents/img/library_background.png
--------------------------------------------------------------------------------
/TWSReleaseNotesView Docs/it.matteolallone.TWSReleaseNotesView.docset/Contents/Resources/Documents/img/title_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iGriever/TWSReleaseNotesView/HEAD/TWSReleaseNotesView Docs/it.matteolallone.TWSReleaseNotesView.docset/Contents/Resources/Documents/img/title_background.png
--------------------------------------------------------------------------------
/TWSReleaseNotesView Docs/it.matteolallone.TWSReleaseNotesView.docset/Contents/Resources/Documents/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | TWSReleaseNotesView Reference
6 |
7 |
8 |
9 |
10 |
11 |
22 |
23 |
24 |
27 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
Class References
40 |
47 |
48 |
49 |
50 |
51 |
52 |
55 |
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/TWSReleaseNotesView Docs/it.matteolallone.TWSReleaseNotesView.docset/Contents/Resources/docSet.dsidx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iGriever/TWSReleaseNotesView/HEAD/TWSReleaseNotesView Docs/it.matteolallone.TWSReleaseNotesView.docset/Contents/Resources/docSet.dsidx
--------------------------------------------------------------------------------
/TWSReleaseNotesView Docs/it.matteolallone.TWSReleaseNotesView.docset/Contents/Resources/docSet.mom:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iGriever/TWSReleaseNotesView/HEAD/TWSReleaseNotesView Docs/it.matteolallone.TWSReleaseNotesView.docset/Contents/Resources/docSet.mom
--------------------------------------------------------------------------------
/TWSReleaseNotesView Docs/it.matteolallone.TWSReleaseNotesView.docset/Contents/Resources/docSet.skidx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iGriever/TWSReleaseNotesView/HEAD/TWSReleaseNotesView Docs/it.matteolallone.TWSReleaseNotesView.docset/Contents/Resources/docSet.skidx
--------------------------------------------------------------------------------
/TWSReleaseNotesView Docs/it.matteolallone.TWSReleaseNotesView.docset/Contents/Resources/docSet.toc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iGriever/TWSReleaseNotesView/HEAD/TWSReleaseNotesView Docs/it.matteolallone.TWSReleaseNotesView.docset/Contents/Resources/docSet.toc
--------------------------------------------------------------------------------
/TWSReleaseNotesView/TWSReleaseNotesDownloadOperation.h:
--------------------------------------------------------------------------------
1 | //
2 | // TWSReleaseNotesDownloadOperation.h
3 | // TWSReleaseNotesViewSample
4 | //
5 | // Created by Matteo Lallone on 03/08/13.
6 | // Copyright (c) 2013 Tapwings. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | /**
12 | Use the `TWSReleaseNotesDownloadOperation` class to create an operation with the purpose of downloading the release notes text for a specified app, using the iTunes Search API.
13 |
14 | The result of the operation is accessible in the `completionBlock`, using the and the properties.
15 |
16 | */
17 | @interface TWSReleaseNotesDownloadOperation : NSOperation
18 |
19 |
20 | /** @name Getting main properties */
21 |
22 | /// The downloaded release notes text.
23 | @property (readonly, copy, nonatomic) NSString *releaseNotesText;
24 |
25 | /// An error object associated to the failed operation.
26 | @property (readonly, strong, nonatomic) NSError *error;
27 |
28 |
29 | /** @name Creating the operation */
30 |
31 | /**
32 | Creates and operation with custom parameters.
33 | @param appIdentifier The App Store app identifier for remote release notes retrieval.
34 | @return The initialized operation.
35 | */
36 | - (id)initWithAppIdentifier:(NSString *)appIdentifier;
37 |
38 | @end
39 |
--------------------------------------------------------------------------------
/TWSReleaseNotesView/TWSReleaseNotesDownloadOperation.m:
--------------------------------------------------------------------------------
1 | //
2 | // TWSReleaseNotesDownloadOperation.m
3 | // TWSReleaseNotesViewSample
4 | //
5 | // Created by Matteo Lallone on 03/08/13.
6 | // Copyright (c) 2013 Tapwings. All rights reserved.
7 | //
8 |
9 | #import "TWSReleaseNotesDownloadOperation.h"
10 | #import
11 |
12 | static NSString *const kTWSReleaseNotesDownloadOperationSearchURL = @"http://itunes.apple.com/lookup";
13 | static NSString *const kTWSReleaseNotesDownloadOperationResultsArrayKey = @"results";
14 | static NSString *const kTWSReleaseNotesDownloadOperationReleaseNotesKey = @"releaseNotes";
15 | static NSString *const kTWSReleaseNotesDownloadOperationErrorDomain = @"com.tapwings.open.error.releaseNotes";
16 | static const NSInteger kTWSReleaseNotesDownloadOperationDecodeErrorCode = 0;
17 |
18 | @interface TWSReleaseNotesDownloadOperation ()
19 |
20 | @property (strong, nonatomic) NSURL *requestURL;
21 | @property (strong, nonatomic) NSURLConnection *urlConnection;
22 | @property (readwrite, strong, nonatomic) NSError *error;
23 | @property (readwrite, copy, nonatomic) NSString *releaseNotesText;
24 | @property (strong, nonatomic) NSMutableData *bufferData;
25 | @property (strong, nonatomic) NSData *appMetadata;
26 | @property (assign, nonatomic) BOOL isExecuting;
27 | @property (assign, nonatomic) BOOL isConcurrent;
28 | @property (assign, nonatomic) BOOL isFinished;
29 |
30 | - (void)extractReleaseNotes;
31 |
32 | @end
33 |
34 | @implementation TWSReleaseNotesDownloadOperation
35 |
36 | #pragma mark - Init - dealloc Methods
37 |
38 | - (id)initWithAppIdentifier:(NSString *)appIdentifier
39 | {
40 | self = [super init];
41 |
42 | if (self)
43 | {
44 | // Setup request URL
45 | NSLocale *locale = [NSLocale currentLocale];
46 | NSString *countryCode = [locale objectForKey:NSLocaleCountryCode];
47 | _requestURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@?id=%@&country=%@", kTWSReleaseNotesDownloadOperationSearchURL, appIdentifier, countryCode]];
48 | }
49 |
50 | return self;
51 | }
52 |
53 | #pragma mark - Instance Methods
54 |
55 | - (void)start
56 | {
57 | // Setup URL request
58 | NSURLRequest *request = [NSURLRequest requestWithURL:self.requestURL];
59 | self.isExecuting = YES;
60 | self.isConcurrent = YES;
61 | self.isFinished = NO;
62 |
63 | // Setup URL connection
64 | [[NSOperationQueue mainQueue] addOperationWithBlock:^{
65 | self.urlConnection = [NSURLConnection connectionWithRequest:request delegate:self];
66 | }];
67 | }
68 |
69 | - (void)setIsExecuting:(BOOL)isExecuting
70 | {
71 | [self willChangeValueForKey:@"isExecuting"];
72 | _isExecuting = isExecuting;
73 | [self didChangeValueForKey:@"isExecuting"];
74 |
75 | // Toggle network activity indicator
76 | [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:isExecuting];
77 | }
78 |
79 | - (void)setIsFinished:(BOOL)isFinished
80 | {
81 | [self willChangeValueForKey:@"isFinished"];
82 | _isFinished = isFinished;
83 | [self didChangeValueForKey:@"isFinished"];
84 | }
85 |
86 | - (void)cancel
87 | {
88 | [super cancel];
89 |
90 | // Cancel URL connection
91 | [self.urlConnection cancel];
92 | self.isFinished = YES;
93 | self.isExecuting = NO;
94 | }
95 |
96 | #pragma mark - Private Methods
97 |
98 | - (void)extractReleaseNotes
99 | {
100 | // Decode data
101 | NSError *decodeError;
102 | id rootObject = [NSJSONSerialization JSONObjectWithData:self.appMetadata options:NSJSONReadingAllowFragments error:&decodeError];
103 |
104 | if (!decodeError && [rootObject isKindOfClass:[NSDictionary class]])
105 | {
106 | NSDictionary *rootDictionary = (NSDictionary *)rootObject;
107 | id resultsObject = rootDictionary[kTWSReleaseNotesDownloadOperationResultsArrayKey];
108 |
109 | if ([resultsObject isKindOfClass:[NSArray class]])
110 | {
111 | NSArray *resultsArray = (NSArray *)resultsObject;
112 | if ([resultsArray count])
113 | {
114 | id metadataObject = resultsArray[0];
115 |
116 | if ([metadataObject isKindOfClass:[NSDictionary class]])
117 | {
118 | NSDictionary *metadataDictionary = (NSDictionary *)metadataObject;
119 | id releaseNotesObject = metadataDictionary[kTWSReleaseNotesDownloadOperationReleaseNotesKey];
120 |
121 | if ([releaseNotesObject isKindOfClass:[NSString class]])
122 | {
123 | // Set release note text
124 | self.releaseNotesText = releaseNotesObject;
125 |
126 | self.isExecuting = NO;
127 | self.isFinished = YES;
128 |
129 | return;
130 | }
131 | }
132 | }
133 | }
134 | }
135 |
136 | decodeError = [NSError errorWithDomain:kTWSReleaseNotesDownloadOperationErrorDomain code:kTWSReleaseNotesDownloadOperationDecodeErrorCode userInfo:nil];
137 | self.error = decodeError;
138 | self.isExecuting = NO;
139 | self.isFinished = YES;
140 | }
141 |
142 | #pragma mark - NSURLConnectionDelegate Methods
143 |
144 | - (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)response
145 | {
146 | return request;
147 | }
148 |
149 | - (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse
150 | {
151 | return cachedResponse;
152 | }
153 |
154 | - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
155 | {
156 | // Setup buffer
157 | self.bufferData = [NSMutableData data];
158 | }
159 |
160 | - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
161 | {
162 | // Append data to buffer
163 | [self.bufferData appendData:data];
164 | }
165 |
166 | - (void)connectionDidFinishLoading:(NSURLConnection *)connection
167 | {
168 | // Set release notes data
169 | self.appMetadata = self.bufferData;
170 | self.bufferData = nil;
171 |
172 | // Extract release notes text
173 | [self extractReleaseNotes];
174 | }
175 |
176 | - (void)connection:(NSURLConnection*)connection didFailWithError:(NSError*)error
177 | {
178 | // Set error
179 | self.error = error;
180 |
181 | self.isExecuting = NO;
182 | self.isFinished = YES;
183 | }
184 |
185 | @end
186 |
--------------------------------------------------------------------------------
/TWSReleaseNotesView/TWSReleaseNotesView.h:
--------------------------------------------------------------------------------
1 | //
2 | // TWSReleaseNotesView.h
3 | // TWSReleaseNotesViewSample
4 | //
5 | // Created by Matteo Lallone on 02/08/13.
6 | // Copyright (c) 2013 Tapwings. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | /**
12 | Use the `TWSReleaseNotesView` class to display a custom release notes view, to be shown when the app is opened for the first time after an update.
13 |
14 | If you want to check if the app is on its first launch, you can use the method. This method will check a previously stored app version string. If a stored app version string does not exist, it will return `YES`, storing the current version string.
15 |
16 | In order to check if the app was updated, the method can be used. This method will check a previously stored app version string. If a stored app version string is present but it does not match the current version string, it will return `YES`, storing the current version string.
17 |
18 | The release notes view can be initialized using the class method, if the release notes text is set directly when calling the method. If the release notes must be retrieved from the App Store, you must use the class method.
19 |
20 | The appearance of the view can be customized using its alpha, color and font properties, to be set before showing the release notes view with the instance method.
21 | */
22 | @interface TWSReleaseNotesView : UIView
23 |
24 |
25 | /** @name Setting main properties */
26 |
27 | /// The alpha value for the overlay to be applied to the container view. Default is `0.5f`.
28 | @property (assign, nonatomic) CGFloat overlayAlpha;
29 |
30 | /// The alpha value for the background color to be applied to the text container view. Default is `0.8f`.
31 | @property (assign, nonatomic) CGFloat textViewAlpha;
32 |
33 | /// The background color to be applied to the text container view. Default is `[UIColor blackColor]`.
34 | @property (strong, nonatomic) UIColor *textViewBackgroundColor;
35 |
36 | /// The dark separator color. Default is `[UIColor colorWithRed:16.0f/255.0f green:16.0f/255.0f blue:16.0f/255.0f alpha:1.0]`.
37 | @property (strong, nonatomic) UIColor *darkSeparatorColor;
38 |
39 | /// The light separator color. Default is `[UIColor colorWithRed:58.0f/255.0f green:58.0f/255.0f blue:65.0f/255.0f alpha:1.0]`.
40 | @property (strong, nonatomic) UIColor *lightSeparatorColor;
41 |
42 | /// The shadow color for the release notes view. Default is `[UIColor blackColor]`.
43 | @property (strong, nonatomic) UIColor *viewShadowColor;
44 |
45 | /// The shadow offset for the release notes view. Default is `(0.0f, 3.0f)`.
46 | @property (assign, nonatomic) CGSize viewShadowOffset;
47 |
48 | /// The shadow radius for the release notes view. Default is `3.0f`.
49 | @property (assign, nonatomic) CGFloat viewShadowRadius;
50 |
51 | /// The shadow opacity for the release notes view. Default is `1.0f`.
52 | @property (assign, nonatomic) CGFloat viewShadowOpacity;
53 |
54 | /// The font for the title label. Default is `[UIFont systemFontOfSize:16.0f]`.
55 | @property (strong, nonatomic) UIFont *titleFont;
56 |
57 | /// The color for the title label. Default is `[UIColor whiteColor]`.
58 | @property (strong, nonatomic) UIColor *titleColor;
59 |
60 | /// The shadow color for the title label. Default is `[UIColor blackColor]`.
61 | @property (strong, nonatomic) UIColor *titleShadowColor;
62 |
63 | /// The shadow offset for the title label. Default is `(0.0f, -1.0f)`.
64 | @property (assign, nonatomic) CGSize titleShadowOffset;
65 |
66 | /// The font for the release notes text view. Default is `[UIFont systemFontOfSize:14.0f]`.
67 | @property (strong, nonatomic) UIFont *releaseNotesFont;
68 |
69 | /// The color for the release notes text view. Default is `[UIColor whiteColor]`.
70 | @property (strong, nonatomic) UIColor *releaseNotesColor;
71 |
72 | /// The shadow color for the release notes text view. Default is `[UIColor blackColor]`.
73 | @property (strong, nonatomic) UIColor *releaseNotesShadowColor;
74 |
75 | /// The shadow offset for the release notes text view. Default is `(0.0f, -1.0f)`.
76 | @property (assign, nonatomic) CGSize releaseNotesShadowOffset;
77 |
78 | /// The font for the close button. Default is `[UIFont systemFontOfSize:16.0f]`.
79 | @property (strong, nonatomic) UIFont *closeButtonFont;
80 |
81 | /// The color for the close button. Default is `[UIColor whiteColor]`.
82 | @property (strong, nonatomic) UIColor *closeButtonColor;
83 |
84 | /// The shadow color for the close button. Default is `[UIColor blackColor]`.
85 | @property (strong, nonatomic) UIColor *closeButtonShadowColor;
86 |
87 | /// The shadow offset for the close button. Default is `(0.0f, -1.0f)`.
88 | @property (assign, nonatomic) CGSize closeButtonShadowOffset;
89 |
90 |
91 | /** @name Creating the release notes view */
92 |
93 | /**
94 | Returns a release notes view initialized with custom parameters.
95 | @param releaseNotesTitle The title for the release notes view.
96 | @param releaseNotesText The release notes text.
97 | @param closeButtonTitle The title for the close button.
98 | @return The initialized release notes view.
99 | */
100 | + (TWSReleaseNotesView *)viewWithReleaseNotesTitle:(NSString *)releaseNotesTitle text:(NSString *)releaseNotesText closeButtonTitle:(NSString *)closeButtonTitle;
101 |
102 | /**
103 | Creates a release notes view initialized with custom parameters and returns it in the completion block.
104 | @param appIdentifier The App Store app identifier for remote release notes retrieval.
105 | @param releaseNotesTitle The title for the release notes view.
106 | @param closeButtonTitle The title for the close button.
107 | @param completionBlock The block to be used as a completion handler. If the release notes retrieval is successful, a reference to the initialized release notes view is passed to the block. A `NSError` object is passed to the block otherwise.
108 | */
109 | + (void)setupViewWithAppIdentifier:(NSString *)appIdentifier releaseNotesTitle:(NSString *)releaseNotesTitle closeButtonTitle:(NSString *)closeButtonTitle completionBlock:(void (^)(TWSReleaseNotesView *releaseView, NSString *releaseNoteText, NSError *error))completionBlock;
110 |
111 |
112 | /** @name Checking the app version */
113 |
114 | /**
115 | Checks for app update state, using the `CFBundleVersion` key in the application `Info.plist`.
116 | @return Returns `YES` if a previous app version string was stored and if it does not match the current version string, `NO` otherwise.
117 | */
118 | + (BOOL)isAppVersionUpdated;
119 |
120 | /**
121 | Checks if the app version key is currently stored or not.
122 | @return Returns `YES` if no previous app version string was stored, `NO` otherwise.
123 | */
124 | + (BOOL)isAppOnFirstLaunch;
125 |
126 |
127 | /** @name Showing the release notes view */
128 |
129 | /**
130 | Shows the release notes view in the specified container view.
131 | @param containerView The container view in which the release notes view must be shown.
132 | */
133 | - (void)showInView:(UIView *)containerView;
134 |
135 | @end
136 |
--------------------------------------------------------------------------------
/TWSReleaseNotesView/TWSReleaseNotesView.m:
--------------------------------------------------------------------------------
1 | //
2 | // TWSReleaseNotesView.m
3 | // TWSReleaseNotesViewSample
4 | //
5 | // Created by Matteo Lallone on 02/08/13.
6 | // Copyright (c) 2013 Tapwings. All rights reserved.
7 | //
8 |
9 | #import "TWSReleaseNotesView.h"
10 | #import
11 | #import "UIImage+ImageEffects.h"
12 | #import "TWSReleaseNotesDownloadOperation.h"
13 |
14 | @interface TWSUnselectableTextView : UITextView
15 |
16 | - (BOOL)canBecomeFirstResponder;
17 |
18 | @end
19 |
20 | @implementation TWSUnselectableTextView
21 |
22 | - (BOOL)canBecomeFirstResponder
23 | {
24 | return NO;
25 | }
26 |
27 | @end
28 |
29 | static NSString *const kTWSReleaseNotesViewVersionKey = @"com.tapwings.open.kTWSReleaseNotesViewControllerVersionKey";
30 | static const CGFloat kTWSReleaseNotesViewDefaultOverlayAlpha = 0.5f;
31 | static const CGFloat kTWSReleaseNotesViewDefaultTextViewBackgroundAlpha = 0.8f;
32 | static const CGFloat kTWSReleaseNotesViewContainerViewCornerRadius = 3.0f;
33 | static const CGFloat kTWSReleaseNotesViewContainerViewWidth = 280.0f;
34 | static const CGFloat kTWSReleaseNotesViewContainerViewMinVerticalPadding = 60.0f;
35 | static const CGFloat kTWSReleaseNotesViewInnerContainerSidePadding = 6.0f;
36 | static const CGFloat kTWSReleaseNotesViewBlurredImageViewCornerRadius = 5.0f;
37 | static const CGFloat kTWSReleaseNotesViewTitleSidePadding = 6.0f;
38 | static const CGFloat kTWSReleaseNotesViewTitleLabelHeight = 44.0f;
39 | static const CGFloat kTWSReleaseNotesViewTextViewInsetHeight = 9.0f;
40 | static const CGFloat kTWSReleaseNotesViewButtonBoxHeight = 44.0f;
41 | static const CGFloat kTWSReleaseNotesViewSeparatorHeight = 1.0f;
42 | static const CGFloat kTWSReleaseNotesViewAnimationSpringScaleFactor = 0.05f;
43 | static const NSTimeInterval kTWSReleaseNotesViewTransitionDuration = 0.2f;
44 |
45 | @interface TWSReleaseNotesView ()
46 |
47 | @property (copy, nonatomic) NSString *releaseNotesTitle;
48 | @property (copy, nonatomic) NSString *releaseNotesText;
49 | @property (copy, nonatomic) NSString *closeButtonTitle;
50 | @property (strong, nonatomic) UIView *popupView;
51 | @property (strong, nonatomic) UIImageView *backgroundBlurredImageView;
52 | @property (strong, nonatomic) UIView *backgroundOverlayView;
53 | @property (strong, nonatomic) UIView *textContainerView;
54 | @property (strong, nonatomic) UILabel *titleLabel;
55 | @property (strong, nonatomic) TWSUnselectableTextView *textView;
56 | @property (strong, nonatomic) UIButton *closeButton;
57 |
58 | - (id)initWithReleaseNotesTitle:(NSString *)releaseNotesTitle text:(NSString *)releaseNotesText closeButtonTitle:(NSString *)closeButtonTitle;
59 | - (void)setupSubviews;
60 | - (void)updateSubviewsLayoutInContainerView:(UIView *)containerView;
61 | - (void)prepareToShowInView:(UIView *)containerView;
62 | - (void)applyBlurredImageBackgroundFromView:(UIView *)view;
63 | - (UIView *)separatorInView:(UIView *)containerView belowView:(UIView *)topView;
64 | - (CGFloat)expectedReleaseNotesTextHeightWithWidth:(CGFloat)width;
65 | - (void)closeButtonTouchedDown:(id)sender;
66 | - (void)closeButtonTouchedUp:(id)sender;
67 | - (void)closeButtonDragExit:(id)sender;
68 | - (void)closeButtonDragEnter:(id)sender;
69 | - (void)dismiss;
70 | + (void)storeCurrentAppVersionString;
71 |
72 | @end
73 |
74 | @implementation TWSReleaseNotesView
75 |
76 | #pragma mark - Init - dealloc Methods
77 |
78 | - (id)initWithReleaseNotesTitle:(NSString *)releaseNotesTitle text:(NSString *)releaseNotesText closeButtonTitle:(NSString *)closeButtonTitle
79 | {
80 | self = [super init];
81 |
82 | if (self)
83 | {
84 | // Setup user-defined properties
85 | _releaseNotesTitle = [releaseNotesTitle copy];
86 | _releaseNotesText = [releaseNotesText copy];
87 | _closeButtonTitle = [closeButtonTitle copy];
88 |
89 | // Setup default properties
90 | _overlayAlpha = kTWSReleaseNotesViewDefaultOverlayAlpha;
91 | _textViewAlpha = kTWSReleaseNotesViewDefaultTextViewBackgroundAlpha;
92 | _textViewBackgroundColor = [UIColor blackColor];
93 | _darkSeparatorColor = [UIColor colorWithRed:16.0f/255.0f green:16.0f/255.0f blue:16.0f/255.0f alpha:1.0];
94 | _lightSeparatorColor = [UIColor colorWithRed:58.0f/255.0f green:58.0f/255.0f blue:65.0f/255.0f alpha:1.0];
95 | _viewShadowColor = [UIColor blackColor];
96 | _viewShadowOffset = CGSizeMake(0.0f, 3.0f);
97 | _viewShadowRadius = 3.0f;
98 | _viewShadowOpacity = 1.0f;
99 | _titleFont = [UIFont systemFontOfSize:16.0f];
100 | _titleColor = [UIColor whiteColor];
101 | _titleShadowColor = [UIColor blackColor];
102 | _titleShadowOffset = CGSizeMake(0.0f, -1.0f);
103 | _releaseNotesFont = [UIFont systemFontOfSize:14.0f];
104 | _releaseNotesColor = [UIColor whiteColor];
105 | _releaseNotesShadowColor = [UIColor blackColor];
106 | _releaseNotesShadowOffset = CGSizeMake(0.0f, -1.0f);
107 | _closeButtonFont = [UIFont systemFontOfSize:16.0f];
108 | _closeButtonColor = [UIColor whiteColor];
109 | _closeButtonShadowColor = [UIColor blackColor];
110 | _closeButtonShadowOffset = CGSizeMake(0.0f, -1.0f);
111 |
112 | // Orientation change notification
113 | __weak TWSReleaseNotesView *weakSelf = self;
114 | [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidChangeStatusBarOrientationNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note){
115 | double delayInSeconds = 0.01f;
116 | dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
117 | dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
118 | // Refresh blurred image background
119 | TWSReleaseNotesView *strongSelf = weakSelf;
120 | UIView *containerView = [strongSelf superview];
121 | [strongSelf removeFromSuperview];
122 | [strongSelf applyBlurredImageBackgroundFromView:containerView];
123 | [strongSelf updateSubviewsLayoutInContainerView:containerView];
124 | [containerView addSubview:strongSelf];
125 | });
126 | }];
127 |
128 | // Setup subview hierarchy
129 | [self setupSubviews];
130 | }
131 |
132 | return self;
133 | }
134 |
135 | - (void)dealloc
136 | {
137 | // Remove orientation change notification
138 | [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];
139 | }
140 |
141 | #pragma mark - Class Methods
142 |
143 | + (TWSReleaseNotesView *)viewWithReleaseNotesTitle:(NSString *)releaseNotesTitle text:(NSString *)releaseNotesText closeButtonTitle:(NSString *)closeButtonTitle
144 | {
145 | // Setup release controller
146 | TWSReleaseNotesView *releaseNotesView = [[TWSReleaseNotesView alloc] initWithReleaseNotesTitle:releaseNotesTitle text:releaseNotesText closeButtonTitle:closeButtonTitle];
147 | return releaseNotesView;
148 | }
149 |
150 | + (void)setupViewWithAppIdentifier:(NSString *)appIdentifier releaseNotesTitle:(NSString *)releaseNotesTitle closeButtonTitle:(NSString *)closeButtonTitle completionBlock:(void (^)(TWSReleaseNotesView *, NSString *, NSError *))completionBlock
151 | {
152 | // Setup operation queue
153 | NSOperationQueue *operationQueue = [[NSOperationQueue alloc] init];
154 | operationQueue.maxConcurrentOperationCount = 1;
155 | TWSReleaseNotesDownloadOperation *operation = [[TWSReleaseNotesDownloadOperation alloc] initWithAppIdentifier:appIdentifier];
156 |
157 | __weak TWSReleaseNotesDownloadOperation *weakOperation = operation;
158 | [operation setCompletionBlock:^{
159 | TWSReleaseNotesDownloadOperation *strongOperation = weakOperation;
160 | if (completionBlock)
161 | {
162 | if (strongOperation.error)
163 | {
164 | NSError *error = strongOperation.error;
165 |
166 | [[NSOperationQueue mainQueue] addOperationWithBlock:^{
167 | // Perform completion block with error
168 | completionBlock(nil, nil, error);
169 | }];
170 | }
171 | else
172 | {
173 | // Get release note text
174 | NSString *releaseNotesText = strongOperation.releaseNotesText;
175 |
176 | [[NSOperationQueue mainQueue] addOperationWithBlock:^{
177 | // Create and show release notes view
178 | TWSReleaseNotesView *releaseNotesView = [TWSReleaseNotesView viewWithReleaseNotesTitle:releaseNotesTitle text:releaseNotesText closeButtonTitle:closeButtonTitle];
179 |
180 | // Perform completion block
181 | completionBlock(releaseNotesView, releaseNotesText, nil);
182 | }];
183 | }
184 | }
185 | }];
186 |
187 | // Add operation
188 | [operationQueue addOperation:operation];
189 | }
190 |
191 | + (BOOL)isAppVersionUpdated
192 | {
193 | // Read stored version string and current version string
194 | NSString *previousAppVersion = [[NSUserDefaults standardUserDefaults] stringForKey:kTWSReleaseNotesViewVersionKey];
195 | NSString *currentAppVersion = [[NSBundle mainBundle] infoDictionary][@"CFBundleVersion"];
196 |
197 | // Flag app as updated if a previous version string is found and it does not match with the current version string
198 | BOOL isUpdated = (previousAppVersion && ![previousAppVersion isEqualToString:currentAppVersion]) ? YES : NO;
199 |
200 | if (isUpdated || !previousAppVersion)
201 | {
202 | // Store current app version if needed
203 | [self storeCurrentAppVersionString];
204 | }
205 |
206 | return isUpdated;
207 | }
208 |
209 | + (BOOL)isAppOnFirstLaunch
210 | {
211 | // Read stored version string
212 | NSString *previousAppVersion = [[NSUserDefaults standardUserDefaults] stringForKey:kTWSReleaseNotesViewVersionKey];
213 |
214 | // Flag app as on first launch if no previous app string is found
215 | BOOL isFirstLaunch = (!previousAppVersion) ? YES : NO;
216 |
217 | if (isFirstLaunch)
218 | {
219 | // Store current app version if needed
220 | [self storeCurrentAppVersionString];
221 | }
222 |
223 | return isFirstLaunch;
224 | }
225 |
226 | #pragma mark - Private Methods
227 |
228 | - (void)setupSubviews
229 | {
230 | // Main properties
231 | [self setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
232 |
233 | // Main text container view
234 | _popupView = [[UIView alloc] initWithFrame:CGRectZero];
235 | [_popupView setBackgroundColor:[UIColor clearColor]];
236 | [_popupView setClipsToBounds:NO];
237 | [_popupView.layer setCornerRadius:kTWSReleaseNotesViewContainerViewCornerRadius];
238 | [_popupView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
239 | [self addSubview:_popupView];
240 |
241 | // Blurred background view
242 | _backgroundBlurredImageView = [[UIImageView alloc] initWithFrame:CGRectZero];
243 | [_backgroundBlurredImageView setContentMode:UIViewContentModeCenter];
244 | [_backgroundBlurredImageView setClipsToBounds:YES];
245 | [_backgroundBlurredImageView.layer setCornerRadius:kTWSReleaseNotesViewBlurredImageViewCornerRadius];
246 | [_backgroundBlurredImageView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
247 | [_popupView addSubview:_backgroundBlurredImageView];
248 |
249 | // Background overlay view
250 | _backgroundOverlayView = [[UIView alloc] initWithFrame:CGRectZero];
251 | [_backgroundOverlayView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
252 | [_backgroundOverlayView setClipsToBounds:YES];
253 | [_backgroundOverlayView.layer setCornerRadius:kTWSReleaseNotesViewContainerViewCornerRadius];
254 | [_backgroundBlurredImageView addSubview:_backgroundOverlayView];
255 |
256 | // Main text container view
257 | _textContainerView = [[UIView alloc] initWithFrame:CGRectZero];
258 | [_textContainerView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
259 | [_textContainerView.layer setBorderWidth:1.0f];
260 | [_textContainerView.layer setShadowOffset:CGSizeMake(0.0f, 1.0f)];
261 | [_textContainerView.layer setShadowRadius:0.0f];
262 | [_textContainerView.layer setShadowOpacity:1.0f];
263 | [_popupView addSubview:_textContainerView];
264 |
265 | // Title label
266 | _titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
267 | [_titleLabel setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin];
268 | [_titleLabel setBackgroundColor:[UIColor clearColor]];
269 | [_titleLabel setNumberOfLines:2];
270 | [_titleLabel.layer setShadowRadius:0.0f];
271 | [_titleLabel.layer setShadowOpacity:1.0f];
272 | [_titleLabel setTextAlignment:NSTextAlignmentCenter];
273 | [_titleLabel setText:_releaseNotesTitle];
274 | [_popupView addSubview:_titleLabel];
275 |
276 | // Release notes text view
277 | _textView = [[TWSUnselectableTextView alloc] initWithFrame:CGRectZero];
278 | [_textView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
279 | [_textView setBackgroundColor:[UIColor clearColor]];
280 | [_textView.layer setShadowRadius:0.0f];
281 | [_textView.layer setShadowOpacity:1.0f];
282 | [_textView setEditable:NO];
283 | [_textView setText:_releaseNotesText];
284 | [_popupView addSubview:_textView];
285 |
286 | // Close button
287 | _closeButton = [UIButton buttonWithType:UIButtonTypeCustom];
288 | [_closeButton setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin];
289 | [_closeButton setTitle:_closeButtonTitle forState:UIControlStateNormal];
290 | [_closeButton addTarget:self action:@selector(closeButtonTouchedUp:) forControlEvents:UIControlEventTouchUpInside];
291 | [_closeButton addTarget:self action:@selector(closeButtonTouchedDown:) forControlEvents:UIControlEventTouchDown];
292 | [_closeButton addTarget:self action:@selector(closeButtonDragExit:) forControlEvents:UIControlEventTouchDragExit];
293 | [_closeButton addTarget:self action:@selector(closeButtonDragEnter:) forControlEvents:UIControlEventTouchDragEnter];
294 | [_popupView addSubview:_closeButton];
295 | }
296 |
297 | - (void)updateSubviewsLayoutInContainerView:(UIView *)containerView
298 | {
299 | // Update main properties
300 | CGRect containerBounds = [containerView bounds];
301 | [self setFrame:containerBounds];
302 |
303 | // Calculate text view height
304 | CGFloat textViewWidth = kTWSReleaseNotesViewContainerViewWidth - 2*kTWSReleaseNotesViewInnerContainerSidePadding;
305 | CGFloat textViewContentHeight = [self expectedReleaseNotesTextHeightWithWidth:textViewWidth];
306 |
307 | // Calculate popup view vertical padding
308 | CGFloat popupViewExpectedHeight = kTWSReleaseNotesViewTitleLabelHeight + textViewContentHeight + kTWSReleaseNotesViewButtonBoxHeight + 2*kTWSReleaseNotesViewSeparatorHeight + 2*kTWSReleaseNotesViewInnerContainerSidePadding;
309 | CGFloat popupViewExpectedVerticalPadding = floorf((containerBounds.size.height - popupViewExpectedHeight) / 2.0f);
310 | CGFloat popupViewVerticalPadding = MAX(popupViewExpectedVerticalPadding, kTWSReleaseNotesViewContainerViewMinVerticalPadding);
311 |
312 | // Popup view
313 | [self.popupView setFrame:CGRectInset(containerBounds, floorf((containerBounds.size.width - kTWSReleaseNotesViewContainerViewWidth)/2.0f), popupViewVerticalPadding)];
314 | [self.popupView.layer setShadowPath:[[UIBezierPath bezierPathWithRect:self.popupView.bounds] CGPath]];
315 |
316 | // Background blurred image view
317 | [self.backgroundBlurredImageView setFrame:self.popupView.bounds];
318 |
319 | // Background overlay view
320 | [self.backgroundOverlayView setFrame:self.popupView.bounds];
321 |
322 | // Text container view
323 | [self.textContainerView setFrame:CGRectInset(self.popupView.bounds, kTWSReleaseNotesViewInnerContainerSidePadding, kTWSReleaseNotesViewInnerContainerSidePadding)];
324 |
325 | // Title label frame
326 | CGRect titleLabelFrame = CGRectInset(self.textContainerView.frame, kTWSReleaseNotesViewTitleSidePadding, 0.0f);
327 | titleLabelFrame.size.height = kTWSReleaseNotesViewTitleLabelHeight;
328 | [self.titleLabel setFrame:titleLabelFrame];
329 |
330 | // Top separator
331 | UIView *topSeparatorView = [self separatorInView:self.textContainerView belowView:self.titleLabel];
332 | [topSeparatorView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin];
333 | [self.textContainerView addSubview:topSeparatorView];
334 |
335 | // Text view frame
336 | CGRect textViewFrame = self.textContainerView.frame;
337 | textViewFrame.origin.y = CGRectGetMinY(textViewFrame) + kTWSReleaseNotesViewTitleLabelHeight + 2*kTWSReleaseNotesViewSeparatorHeight;
338 | textViewFrame.size.height = self.textContainerView.frame.size.height - kTWSReleaseNotesViewTitleLabelHeight - 3*kTWSReleaseNotesViewSeparatorHeight - kTWSReleaseNotesViewButtonBoxHeight;
339 | [self.textView setFrame:textViewFrame];
340 |
341 | // Bottom separator
342 | UIView *bottomSeparatorView = [self separatorInView:self.textContainerView belowView:self.textView];
343 | [bottomSeparatorView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin];
344 | [self.textContainerView addSubview:bottomSeparatorView];
345 |
346 | // Close button
347 | CGRect closeButtonFrame = self.textContainerView.frame;
348 | closeButtonFrame.origin.y = CGRectGetMaxY(closeButtonFrame) - kTWSReleaseNotesViewButtonBoxHeight;
349 | closeButtonFrame.size.height = kTWSReleaseNotesViewButtonBoxHeight;
350 | [self.closeButton setFrame:closeButtonFrame];
351 | }
352 |
353 | - (void)prepareToShowInView:(UIView *)containerView
354 | {
355 | // Update subviews layout
356 | [self updateSubviewsLayoutInContainerView:containerView];
357 |
358 | // Initial properties for show animation
359 | [self setBackgroundColor:[UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.0f]];
360 |
361 | [self.popupView setAlpha:0.0f];
362 | [self.popupView setTransform:CGAffineTransformScale(CGAffineTransformIdentity, 0.0f, 0.0f)];
363 | [self.popupView.layer setShadowColor:[self.viewShadowColor CGColor]];
364 | [self.popupView.layer setShadowOffset:self.viewShadowOffset];
365 | [self.popupView.layer setShadowRadius:self.viewShadowRadius];
366 | [self.popupView.layer setShadowOpacity:self.viewShadowOpacity];
367 |
368 | [self.backgroundOverlayView setBackgroundColor:[self.textViewBackgroundColor colorWithAlphaComponent:self.textViewAlpha]];
369 |
370 | [self.textContainerView.layer setBorderColor:[self.darkSeparatorColor CGColor]];
371 | [self.textContainerView.layer setShadowColor:[self.lightSeparatorColor CGColor]];
372 |
373 | [self.titleLabel setFont:self.titleFont];
374 | [self.titleLabel setTextColor:self.titleColor];
375 | [self.titleLabel.layer setShadowColor:[self.titleShadowColor CGColor]];
376 | [self.titleLabel.layer setShadowOffset:self.titleShadowOffset];
377 |
378 | [self.textView setFont:self.releaseNotesFont];
379 | [self.textView setTextColor:self.releaseNotesColor];
380 | [self.textView.layer setShadowColor:[self.releaseNotesShadowColor CGColor]];
381 | [self.textView.layer setShadowOffset:self.releaseNotesShadowOffset];
382 |
383 | [self.closeButton.titleLabel setFont:self.closeButtonFont];
384 | [self.closeButton setTitleColor:self.closeButtonColor forState:UIControlStateNormal];
385 | [self.closeButton setTitleShadowColor:self.closeButtonShadowColor forState:UIControlStateNormal];
386 | [self.closeButton.titleLabel setShadowOffset:self.closeButtonShadowOffset];
387 |
388 | [self applyBlurredImageBackgroundFromView:containerView];
389 |
390 | // Add to container view
391 | [containerView addSubview:self];
392 | }
393 |
394 | - (void)applyBlurredImageBackgroundFromView:(UIView *)view
395 | {
396 | // Clone background image
397 | UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, 0.0f);
398 | [view.layer renderInContext:UIGraphicsGetCurrentContext()];
399 | UIImage *cloneImage = UIGraphicsGetImageFromCurrentImageContext();
400 | UIGraphicsEndImageContext();
401 |
402 | // Apply blur effect
403 | UIImage *blurredImage = [cloneImage applySubtleEffect];
404 | self.backgroundBlurredImageView.image = blurredImage;
405 | [self.backgroundBlurredImageView setNeedsDisplay];
406 | }
407 |
408 | - (UIView *)separatorInView:(UIView *)containerView belowView:(UIView *)topView
409 | {
410 | // Setup separator view
411 | CGRect topViewFrame = [containerView convertRect:topView.frame fromView:[topView superview]];
412 | CGRect separatorFrame = CGRectMake(containerView.bounds.origin.x, CGRectGetMaxY(topViewFrame), containerView.bounds.size.width, kTWSReleaseNotesViewSeparatorHeight);
413 | UIView *separatorView = [[UIView alloc] initWithFrame:separatorFrame];
414 | [separatorView setBackgroundColor:self.darkSeparatorColor];
415 |
416 | return separatorView;
417 | }
418 |
419 | - (CGFloat)expectedReleaseNotesTextHeightWithWidth:(CGFloat)width;
420 | {
421 | CGSize maximumLabelSize = CGSizeMake(width, MAXFLOAT);
422 | CGSize expectedLabelSize = [self.releaseNotesText sizeWithFont:self.releaseNotesFont constrainedToSize:maximumLabelSize lineBreakMode:NSLineBreakByWordWrapping];
423 | return expectedLabelSize.height + 2*kTWSReleaseNotesViewTextViewInsetHeight;
424 | }
425 |
426 | - (void)closeButtonTouchedUp:(id)sender
427 | {
428 | // Un-highlight button on touch up
429 | [self.closeButton setBackgroundColor:[UIColor clearColor]];
430 |
431 | // Dismiss release notes view
432 | [self dismiss];
433 | }
434 |
435 | - (void)closeButtonTouchedDown:(id)sender
436 | {
437 | // Highlight button on touch down
438 | [self.closeButton setBackgroundColor:[UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.5f]];
439 | }
440 |
441 | - (void)closeButtonDragExit:(id)sender
442 | {
443 | // Un-highlight button on exit
444 | [self.closeButton setBackgroundColor:[UIColor clearColor]];
445 | }
446 |
447 | - (void)closeButtonDragEnter:(id)sender
448 | {
449 | // Highlight button on enter
450 | [self.closeButton setBackgroundColor:[UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.5f]];
451 | }
452 |
453 | - (void)dismiss
454 | {
455 | // Dismiss release notes view
456 | [UIView animateWithDuration:kTWSReleaseNotesViewTransitionDuration/2.0f animations:^{
457 | [self.popupView setTransform:CGAffineTransformScale(CGAffineTransformIdentity, 1.0f + kTWSReleaseNotesViewAnimationSpringScaleFactor, 1.0f + kTWSReleaseNotesViewAnimationSpringScaleFactor)];
458 | } completion:^(BOOL finished){
459 | if (finished)
460 | {
461 | [UIView animateWithDuration:kTWSReleaseNotesViewTransitionDuration animations:^{
462 | [self setBackgroundColor:[UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.0f]];
463 | [self.popupView setAlpha:0.0f];
464 | [self.popupView setTransform:CGAffineTransformScale(CGAffineTransformIdentity, 0.0f, 0.0f)];
465 | } completion:^(BOOL finished){
466 | if (finished)
467 | {
468 | [self removeFromSuperview];
469 | }
470 | }];
471 | }
472 | }];
473 | }
474 |
475 | + (void)storeCurrentAppVersionString
476 | {
477 | // Store current app version string in the user defaults
478 | NSString *currentAppVersion = [[NSBundle mainBundle] infoDictionary][@"CFBundleVersion"];
479 | [[NSUserDefaults standardUserDefaults] setObject:currentAppVersion forKey:kTWSReleaseNotesViewVersionKey];
480 | [[NSUserDefaults standardUserDefaults] synchronize];
481 | }
482 |
483 | #pragma mark - Instance Methods
484 |
485 | - (void)showInView:(UIView *)containerView
486 | {
487 | // Setup view before animation
488 | [self prepareToShowInView:containerView];
489 |
490 | // Show release notes view
491 | [UIView animateWithDuration:kTWSReleaseNotesViewTransitionDuration animations:^{
492 | [self setBackgroundColor:[UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:self.overlayAlpha]];
493 | [self.popupView setAlpha:1.0f];
494 | [self.popupView setTransform:CGAffineTransformScale(CGAffineTransformIdentity, 1.0f + kTWSReleaseNotesViewAnimationSpringScaleFactor, 1.0f + kTWSReleaseNotesViewAnimationSpringScaleFactor)];
495 | } completion:^(BOOL finished){
496 | if (finished)
497 | {
498 | [UIView animateWithDuration:kTWSReleaseNotesViewTransitionDuration/2.0f animations:^{
499 | [self.popupView setTransform:CGAffineTransformScale(CGAffineTransformIdentity, 1.0f - kTWSReleaseNotesViewAnimationSpringScaleFactor, 1.0f - kTWSReleaseNotesViewAnimationSpringScaleFactor)];
500 | } completion:^(BOOL finished){
501 | if (finished)
502 | {
503 | [UIView animateWithDuration:kTWSReleaseNotesViewTransitionDuration/2.0f animations:^{
504 | [self.popupView setTransform:CGAffineTransformIdentity];
505 | }];
506 | }
507 | }];
508 | }
509 | }];
510 | }
511 |
512 | @end
513 |
--------------------------------------------------------------------------------
/TWSReleaseNotesView/UIImage+ImageEffects.h:
--------------------------------------------------------------------------------
1 | /*
2 | File: UIImage+ImageEffects.h
3 | Abstract: This is a category of UIImage that adds methods to apply blur and tint effects to an image. This is the code you’ll want to look out to find out how to use vImage to efficiently calculate a blur.
4 | Version: 1.0
5 |
6 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
7 | Inc. ("Apple") in consideration of your agreement to the following
8 | terms, and your use, installation, modification or redistribution of
9 | this Apple software constitutes acceptance of these terms. If you do
10 | not agree with these terms, please do not use, install, modify or
11 | redistribute this Apple software.
12 |
13 | In consideration of your agreement to abide by the following terms, and
14 | subject to these terms, Apple grants you a personal, non-exclusive
15 | license, under Apple's copyrights in this original Apple software (the
16 | "Apple Software"), to use, reproduce, modify and redistribute the Apple
17 | Software, with or without modifications, in source and/or binary forms;
18 | provided that if you redistribute the Apple Software in its entirety and
19 | without modifications, you must retain this notice and the following
20 | text and disclaimers in all such redistributions of the Apple Software.
21 | Neither the name, trademarks, service marks or logos of Apple Inc. may
22 | be used to endorse or promote products derived from the Apple Software
23 | without specific prior written permission from Apple. Except as
24 | expressly stated in this notice, no other rights or licenses, express or
25 | implied, are granted by Apple herein, including but not limited to any
26 | patent rights that may be infringed by your derivative works or by other
27 | works in which the Apple Software may be incorporated.
28 |
29 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE
30 | MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
31 | THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
32 | FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
33 | OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
34 |
35 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
36 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
37 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
38 | INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
39 | MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
40 | AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
41 | STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
42 | POSSIBILITY OF SUCH DAMAGE.
43 |
44 | Copyright (C) 2013 Apple Inc. All Rights Reserved.
45 |
46 |
47 | Copyright © 2013 Apple Inc. All rights reserved.
48 | WWDC 2013 License
49 |
50 | NOTE: This Apple Software was supplied by Apple as part of a WWDC 2013
51 | Session. Please refer to the applicable WWDC 2013 Session for further
52 | information.
53 |
54 | IMPORTANT: This Apple software is supplied to you by Apple Inc.
55 | ("Apple") in consideration of your agreement to the following terms, and
56 | your use, installation, modification or redistribution of this Apple
57 | software constitutes acceptance of these terms. If you do not agree with
58 | these terms, please do not use, install, modify or redistribute this
59 | Apple software.
60 |
61 | In consideration of your agreement to abide by the following terms, and
62 | subject to these terms, Apple grants you a non-exclusive license, under
63 | Apple's copyrights in this original Apple software (the "Apple
64 | Software"), to use, reproduce, modify and redistribute the Apple
65 | Software, with or without modifications, in source and/or binary forms;
66 | provided that if you redistribute the Apple Software in its entirety and
67 | without modifications, you must retain this notice and the following
68 | text and disclaimers in all such redistributions of the Apple Software.
69 | Neither the name, trademarks, service marks or logos of Apple Inc. may
70 | be used to endorse or promote products derived from the Apple Software
71 | without specific prior written permission from Apple. Except as
72 | expressly stated in this notice, no other rights or licenses, express or
73 | implied, are granted by Apple herein, including but not limited to any
74 | patent rights that may be infringed by your derivative works or by other
75 | works in which the Apple Software may be incorporated.
76 |
77 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES
78 | NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE
79 | IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR
80 | A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
81 | OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
82 |
83 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
84 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
85 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
86 | INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
87 | MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
88 | AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
89 | STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
90 | POSSIBILITY OF SUCH DAMAGE.
91 |
92 | EA1002
93 | 5/3/2013
94 | */
95 |
96 | #import
97 | #import
98 |
99 | @interface UIImage (ImageEffects)
100 |
101 | - (UIImage *)applySubtleEffect;
102 | - (UIImage *)applyLightEffect;
103 | - (UIImage *)applyExtraLightEffect;
104 | - (UIImage *)applyDarkEffect;
105 | - (UIImage *)applyTintEffectWithColor:(UIColor *)tintColor;
106 |
107 | - (UIImage *)applyBlurWithRadius:(CGFloat)blurRadius tintColor:(UIColor *)tintColor saturationDeltaFactor:(CGFloat)saturationDeltaFactor maskImage:(UIImage *)maskImage;
108 |
109 | @end
110 |
--------------------------------------------------------------------------------
/TWSReleaseNotesView/UIImage+ImageEffects.m:
--------------------------------------------------------------------------------
1 | /*
2 | File: UIImage+ImageEffects.m
3 | Abstract: This is a category of UIImage that adds methods to apply blur and tint effects to an image. This is the code you’ll want to look out to find out how to use vImage to efficiently calculate a blur.
4 | Version: 1.0
5 |
6 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple
7 | Inc. ("Apple") in consideration of your agreement to the following
8 | terms, and your use, installation, modification or redistribution of
9 | this Apple software constitutes acceptance of these terms. If you do
10 | not agree with these terms, please do not use, install, modify or
11 | redistribute this Apple software.
12 |
13 | In consideration of your agreement to abide by the following terms, and
14 | subject to these terms, Apple grants you a personal, non-exclusive
15 | license, under Apple's copyrights in this original Apple software (the
16 | "Apple Software"), to use, reproduce, modify and redistribute the Apple
17 | Software, with or without modifications, in source and/or binary forms;
18 | provided that if you redistribute the Apple Software in its entirety and
19 | without modifications, you must retain this notice and the following
20 | text and disclaimers in all such redistributions of the Apple Software.
21 | Neither the name, trademarks, service marks or logos of Apple Inc. may
22 | be used to endorse or promote products derived from the Apple Software
23 | without specific prior written permission from Apple. Except as
24 | expressly stated in this notice, no other rights or licenses, express or
25 | implied, are granted by Apple herein, including but not limited to any
26 | patent rights that may be infringed by your derivative works or by other
27 | works in which the Apple Software may be incorporated.
28 |
29 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE
30 | MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
31 | THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
32 | FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
33 | OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
34 |
35 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
36 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
37 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
38 | INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
39 | MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
40 | AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
41 | STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
42 | POSSIBILITY OF SUCH DAMAGE.
43 |
44 | Copyright (C) 2013 Apple Inc. All Rights Reserved.
45 |
46 |
47 | Copyright © 2013 Apple Inc. All rights reserved.
48 | WWDC 2013 License
49 |
50 | NOTE: This Apple Software was supplied by Apple as part of a WWDC 2013
51 | Session. Please refer to the applicable WWDC 2013 Session for further
52 | information.
53 |
54 | IMPORTANT: This Apple software is supplied to you by Apple Inc.
55 | ("Apple") in consideration of your agreement to the following terms, and
56 | your use, installation, modification or redistribution of this Apple
57 | software constitutes acceptance of these terms. If you do not agree with
58 | these terms, please do not use, install, modify or redistribute this
59 | Apple software.
60 |
61 | In consideration of your agreement to abide by the following terms, and
62 | subject to these terms, Apple grants you a non-exclusive license, under
63 | Apple's copyrights in this original Apple software (the "Apple
64 | Software"), to use, reproduce, modify and redistribute the Apple
65 | Software, with or without modifications, in source and/or binary forms;
66 | provided that if you redistribute the Apple Software in its entirety and
67 | without modifications, you must retain this notice and the following
68 | text and disclaimers in all such redistributions of the Apple Software.
69 | Neither the name, trademarks, service marks or logos of Apple Inc. may
70 | be used to endorse or promote products derived from the Apple Software
71 | without specific prior written permission from Apple. Except as
72 | expressly stated in this notice, no other rights or licenses, express or
73 | implied, are granted by Apple herein, including but not limited to any
74 | patent rights that may be infringed by your derivative works or by other
75 | works in which the Apple Software may be incorporated.
76 |
77 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES
78 | NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE
79 | IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR
80 | A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
81 | OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
82 |
83 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
84 | OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
85 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
86 | INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
87 | MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
88 | AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
89 | STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
90 | POSSIBILITY OF SUCH DAMAGE.
91 |
92 | EA1002
93 | 5/3/2013
94 | */
95 |
96 | #import "UIImage+ImageEffects.h"
97 | #import
98 |
99 |
100 | @implementation UIImage (ImageEffects)
101 |
102 |
103 | - (UIImage *)applySubtleEffect
104 | {
105 | UIColor *tintColor = [UIColor colorWithWhite:1.0 alpha:0.3];
106 | return [self applyBlurWithRadius:5 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil];
107 | }
108 |
109 |
110 | - (UIImage *)applyLightEffect
111 | {
112 | UIColor *tintColor = [UIColor colorWithWhite:1.0 alpha:0.3];
113 | return [self applyBlurWithRadius:30 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil];
114 | }
115 |
116 |
117 | - (UIImage *)applyExtraLightEffect
118 | {
119 | UIColor *tintColor = [UIColor colorWithWhite:0.97 alpha:0.82];
120 | return [self applyBlurWithRadius:20 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil];
121 | }
122 |
123 |
124 | - (UIImage *)applyDarkEffect
125 | {
126 | UIColor *tintColor = [UIColor colorWithWhite:0.11 alpha:0.73];
127 | return [self applyBlurWithRadius:20 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil];
128 | }
129 |
130 |
131 | - (UIImage *)applyTintEffectWithColor:(UIColor *)tintColor
132 | {
133 | const CGFloat EffectColorAlpha = 0.6;
134 | UIColor *effectColor = tintColor;
135 | int componentCount = CGColorGetNumberOfComponents(tintColor.CGColor);
136 | if (componentCount == 2) {
137 | CGFloat b;
138 | if ([tintColor getWhite:&b alpha:NULL]) {
139 | effectColor = [UIColor colorWithWhite:b alpha:EffectColorAlpha];
140 | }
141 | }
142 | else {
143 | CGFloat r, g, b;
144 | if ([tintColor getRed:&r green:&g blue:&b alpha:NULL]) {
145 | effectColor = [UIColor colorWithRed:r green:g blue:b alpha:EffectColorAlpha];
146 | }
147 | }
148 | return [self applyBlurWithRadius:10 tintColor:effectColor saturationDeltaFactor:-1.0 maskImage:nil];
149 | }
150 |
151 |
152 | - (UIImage *)applyBlurWithRadius:(CGFloat)blurRadius tintColor:(UIColor *)tintColor saturationDeltaFactor:(CGFloat)saturationDeltaFactor maskImage:(UIImage *)maskImage
153 | {
154 | // Check pre-conditions.
155 | if (self.size.width < 1 || self.size.height < 1) {
156 | NSLog (@"*** error: invalid size: (%.2f x %.2f). Both dimensions must be >= 1: %@", self.size.width, self.size.height, self);
157 | return nil;
158 | }
159 | if (!self.CGImage) {
160 | NSLog (@"*** error: image must be backed by a CGImage: %@", self);
161 | return nil;
162 | }
163 | if (maskImage && !maskImage.CGImage) {
164 | NSLog (@"*** error: maskImage must be backed by a CGImage: %@", maskImage);
165 | return nil;
166 | }
167 |
168 | CGRect imageRect = { CGPointZero, self.size };
169 | UIImage *effectImage = self;
170 |
171 | BOOL hasBlur = blurRadius > __FLT_EPSILON__;
172 | BOOL hasSaturationChange = fabs(saturationDeltaFactor - 1.) > __FLT_EPSILON__;
173 | if (hasBlur || hasSaturationChange) {
174 | UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]);
175 | CGContextRef effectInContext = UIGraphicsGetCurrentContext();
176 | CGContextScaleCTM(effectInContext, 1.0, -1.0);
177 | CGContextTranslateCTM(effectInContext, 0, -self.size.height);
178 | CGContextDrawImage(effectInContext, imageRect, self.CGImage);
179 |
180 | vImage_Buffer effectInBuffer;
181 | effectInBuffer.data = CGBitmapContextGetData(effectInContext);
182 | effectInBuffer.width = CGBitmapContextGetWidth(effectInContext);
183 | effectInBuffer.height = CGBitmapContextGetHeight(effectInContext);
184 | effectInBuffer.rowBytes = CGBitmapContextGetBytesPerRow(effectInContext);
185 |
186 | UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]);
187 | CGContextRef effectOutContext = UIGraphicsGetCurrentContext();
188 | vImage_Buffer effectOutBuffer;
189 | effectOutBuffer.data = CGBitmapContextGetData(effectOutContext);
190 | effectOutBuffer.width = CGBitmapContextGetWidth(effectOutContext);
191 | effectOutBuffer.height = CGBitmapContextGetHeight(effectOutContext);
192 | effectOutBuffer.rowBytes = CGBitmapContextGetBytesPerRow(effectOutContext);
193 |
194 | if (hasBlur) {
195 | // A description of how to compute the box kernel width from the Gaussian
196 | // radius (aka standard deviation) appears in the SVG spec:
197 | // http://www.w3.org/TR/SVG/filters.html#feGaussianBlurElement
198 | //
199 | // For larger values of 's' (s >= 2.0), an approximation can be used: Three
200 | // successive box-blurs build a piece-wise quadratic convolution kernel, which
201 | // approximates the Gaussian kernel to within roughly 3%.
202 | //
203 | // let d = floor(s * 3*sqrt(2*pi)/4 + 0.5)
204 | //
205 | // ... if d is odd, use three box-blurs of size 'd', centered on the output pixel.
206 | //
207 | CGFloat inputRadius = blurRadius * [[UIScreen mainScreen] scale];
208 | NSUInteger radius = floor(inputRadius * 3. * sqrt(2 * M_PI) / 4 + 0.5);
209 | if (radius % 2 != 1) {
210 | radius += 1; // force radius to be odd so that the three box-blur methodology works.
211 | }
212 | vImageBoxConvolve_ARGB8888(&effectInBuffer, &effectOutBuffer, NULL, 0, 0, radius, radius, 0, kvImageEdgeExtend);
213 | vImageBoxConvolve_ARGB8888(&effectOutBuffer, &effectInBuffer, NULL, 0, 0, radius, radius, 0, kvImageEdgeExtend);
214 | vImageBoxConvolve_ARGB8888(&effectInBuffer, &effectOutBuffer, NULL, 0, 0, radius, radius, 0, kvImageEdgeExtend);
215 | }
216 | BOOL effectImageBuffersAreSwapped = NO;
217 | if (hasSaturationChange) {
218 | CGFloat s = saturationDeltaFactor;
219 | CGFloat floatingPointSaturationMatrix[] = {
220 | 0.0722 + 0.9278 * s, 0.0722 - 0.0722 * s, 0.0722 - 0.0722 * s, 0,
221 | 0.7152 - 0.7152 * s, 0.7152 + 0.2848 * s, 0.7152 - 0.7152 * s, 0,
222 | 0.2126 - 0.2126 * s, 0.2126 - 0.2126 * s, 0.2126 + 0.7873 * s, 0,
223 | 0, 0, 0, 1,
224 | };
225 | const int32_t divisor = 256;
226 | NSUInteger matrixSize = sizeof(floatingPointSaturationMatrix)/sizeof(floatingPointSaturationMatrix[0]);
227 | int16_t saturationMatrix[matrixSize];
228 | for (NSUInteger i = 0; i < matrixSize; ++i) {
229 | saturationMatrix[i] = (int16_t)roundf(floatingPointSaturationMatrix[i] * divisor);
230 | }
231 | if (hasBlur) {
232 | vImageMatrixMultiply_ARGB8888(&effectOutBuffer, &effectInBuffer, saturationMatrix, divisor, NULL, NULL, kvImageNoFlags);
233 | effectImageBuffersAreSwapped = YES;
234 | }
235 | else {
236 | vImageMatrixMultiply_ARGB8888(&effectInBuffer, &effectOutBuffer, saturationMatrix, divisor, NULL, NULL, kvImageNoFlags);
237 | }
238 | }
239 | if (!effectImageBuffersAreSwapped)
240 | effectImage = UIGraphicsGetImageFromCurrentImageContext();
241 | UIGraphicsEndImageContext();
242 |
243 | if (effectImageBuffersAreSwapped)
244 | effectImage = UIGraphicsGetImageFromCurrentImageContext();
245 | UIGraphicsEndImageContext();
246 | }
247 |
248 | // Set up output context.
249 | UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]);
250 | CGContextRef outputContext = UIGraphicsGetCurrentContext();
251 | CGContextScaleCTM(outputContext, 1.0, -1.0);
252 | CGContextTranslateCTM(outputContext, 0, -self.size.height);
253 |
254 | // Draw base image.
255 | CGContextDrawImage(outputContext, imageRect, self.CGImage);
256 |
257 | // Draw effect image.
258 | if (hasBlur) {
259 | CGContextSaveGState(outputContext);
260 | if (maskImage) {
261 | CGContextClipToMask(outputContext, imageRect, maskImage.CGImage);
262 | }
263 | CGContextDrawImage(outputContext, imageRect, effectImage.CGImage);
264 | CGContextRestoreGState(outputContext);
265 | }
266 |
267 | // Add in color tint.
268 | if (tintColor) {
269 | CGContextSaveGState(outputContext);
270 | CGContextSetFillColorWithColor(outputContext, tintColor.CGColor);
271 | CGContextFillRect(outputContext, imageRect);
272 | CGContextRestoreGState(outputContext);
273 | }
274 |
275 | // Output image is ready.
276 | UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();
277 | UIGraphicsEndImageContext();
278 |
279 | return outputImage;
280 | }
281 |
282 |
283 | @end
284 |
--------------------------------------------------------------------------------
/TWSReleaseNotesViewSample/TWSReleaseNotesViewSample.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | F819042C17AC0BE5006A0896 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F819042B17AC0BE5006A0896 /* UIKit.framework */; };
11 | F819042E17AC0BE5006A0896 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F819042D17AC0BE5006A0896 /* Foundation.framework */; };
12 | F819043017AC0BE5006A0896 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F819042F17AC0BE5006A0896 /* CoreGraphics.framework */; };
13 | F819043617AC0BE5006A0896 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = F819043417AC0BE5006A0896 /* InfoPlist.strings */; };
14 | F819043817AC0BE5006A0896 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = F819043717AC0BE5006A0896 /* main.m */; };
15 | F819043C17AC0BE5006A0896 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = F819043B17AC0BE5006A0896 /* AppDelegate.m */; };
16 | F819043E17AC0BE5006A0896 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = F819043D17AC0BE5006A0896 /* Default.png */; };
17 | F819044017AC0BE5006A0896 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F819043F17AC0BE5006A0896 /* Default@2x.png */; };
18 | F819044217AC0BE5006A0896 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F819044117AC0BE5006A0896 /* Default-568h@2x.png */; };
19 | F819044F17AC1520006A0896 /* RootViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F819044D17AC1520006A0896 /* RootViewController.m */; };
20 | F844C4D217BAEF3900021701 /* background@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F844C4CF17BAEF3900021701 /* background@2x.png */; };
21 | F844C4D317BAEF3900021701 /* btn_bg_hl@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F844C4D017BAEF3900021701 /* btn_bg_hl@2x.png */; };
22 | F844C4D417BAEF3900021701 /* btn_bg@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F844C4D117BAEF3900021701 /* btn_bg@2x.png */; };
23 | F844C4D817BAF48B00021701 /* icon_7@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F844C4D517BAF48B00021701 /* icon_7@2x.png */; };
24 | F844C4D917BAF48B00021701 /* icon.png in Resources */ = {isa = PBXBuildFile; fileRef = F844C4D617BAF48B00021701 /* icon.png */; };
25 | F844C4DA17BAF48B00021701 /* icon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F844C4D717BAF48B00021701 /* icon@2x.png */; };
26 | F893E7FA17AD69FF005DB2FC /* RootViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F893E7F917AD69FF005DB2FC /* RootViewController.xib */; };
27 | F8B6D83017BAE1F000C2ECB0 /* background.png in Resources */ = {isa = PBXBuildFile; fileRef = F8B6D82F17BAE1F000C2ECB0 /* background.png */; };
28 | F8B6D83317BAED4400C2ECB0 /* btn_bg_hl.png in Resources */ = {isa = PBXBuildFile; fileRef = F8B6D83117BAED4400C2ECB0 /* btn_bg_hl.png */; };
29 | F8B6D83417BAED4400C2ECB0 /* btn_bg.png in Resources */ = {isa = PBXBuildFile; fileRef = F8B6D83217BAED4400C2ECB0 /* btn_bg.png */; };
30 | F8C4A09717B1395E003CA095 /* TWSReleaseNotesDownloadOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = F8C4A09217B1395E003CA095 /* TWSReleaseNotesDownloadOperation.m */; };
31 | F8C4A09817B1395E003CA095 /* TWSReleaseNotesView.m in Sources */ = {isa = PBXBuildFile; fileRef = F8C4A09417B1395E003CA095 /* TWSReleaseNotesView.m */; };
32 | F8C4A09917B1395E003CA095 /* UIImage+ImageEffects.m in Sources */ = {isa = PBXBuildFile; fileRef = F8C4A09617B1395E003CA095 /* UIImage+ImageEffects.m */; };
33 | F8E345D217AC3B74005478D6 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8E345D117AC3B74005478D6 /* QuartzCore.framework */; };
34 | F8E345D417AC3B89005478D6 /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8E345D317AC3B89005478D6 /* Accelerate.framework */; };
35 | /* End PBXBuildFile section */
36 |
37 | /* Begin PBXFileReference section */
38 | F819042817AC0BE5006A0896 /* TWSReleaseNotesViewSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TWSReleaseNotesViewSample.app; sourceTree = BUILT_PRODUCTS_DIR; };
39 | F819042B17AC0BE5006A0896 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
40 | F819042D17AC0BE5006A0896 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
41 | F819042F17AC0BE5006A0896 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
42 | F819043317AC0BE5006A0896 /* TWSReleaseNotesViewSample-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "TWSReleaseNotesViewSample-Info.plist"; sourceTree = ""; };
43 | F819043517AC0BE5006A0896 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; };
44 | F819043717AC0BE5006A0896 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
45 | F819043917AC0BE5006A0896 /* TWSReleaseNotesViewSample-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "TWSReleaseNotesViewSample-Prefix.pch"; sourceTree = ""; };
46 | F819043A17AC0BE5006A0896 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
47 | F819043B17AC0BE5006A0896 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
48 | F819043D17AC0BE5006A0896 /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = ""; };
49 | F819043F17AC0BE5006A0896 /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default@2x.png"; sourceTree = ""; };
50 | F819044117AC0BE5006A0896 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; };
51 | F819044C17AC1520006A0896 /* RootViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RootViewController.h; sourceTree = ""; };
52 | F819044D17AC1520006A0896 /* RootViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RootViewController.m; sourceTree = ""; };
53 | F844C4CF17BAEF3900021701 /* background@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "background@2x.png"; sourceTree = ""; };
54 | F844C4D017BAEF3900021701 /* btn_bg_hl@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "btn_bg_hl@2x.png"; sourceTree = ""; };
55 | F844C4D117BAEF3900021701 /* btn_bg@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "btn_bg@2x.png"; sourceTree = ""; };
56 | F844C4D517BAF48B00021701 /* icon_7@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon_7@2x.png"; sourceTree = ""; };
57 | F844C4D617BAF48B00021701 /* icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = icon.png; sourceTree = ""; };
58 | F844C4D717BAF48B00021701 /* icon@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon@2x.png"; sourceTree = ""; };
59 | F893E7F917AD69FF005DB2FC /* RootViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = RootViewController.xib; sourceTree = ""; };
60 | F8B6D82F17BAE1F000C2ECB0 /* background.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = background.png; sourceTree = ""; };
61 | F8B6D83117BAED4400C2ECB0 /* btn_bg_hl.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = btn_bg_hl.png; sourceTree = ""; };
62 | F8B6D83217BAED4400C2ECB0 /* btn_bg.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = btn_bg.png; sourceTree = ""; };
63 | F8C4A09117B1395E003CA095 /* TWSReleaseNotesDownloadOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TWSReleaseNotesDownloadOperation.h; sourceTree = ""; };
64 | F8C4A09217B1395E003CA095 /* TWSReleaseNotesDownloadOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TWSReleaseNotesDownloadOperation.m; sourceTree = ""; };
65 | F8C4A09317B1395E003CA095 /* TWSReleaseNotesView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TWSReleaseNotesView.h; sourceTree = ""; };
66 | F8C4A09417B1395E003CA095 /* TWSReleaseNotesView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TWSReleaseNotesView.m; sourceTree = ""; };
67 | F8C4A09517B1395E003CA095 /* UIImage+ImageEffects.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+ImageEffects.h"; sourceTree = ""; };
68 | F8C4A09617B1395E003CA095 /* UIImage+ImageEffects.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+ImageEffects.m"; sourceTree = ""; };
69 | F8E345D117AC3B74005478D6 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
70 | F8E345D317AC3B89005478D6 /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; };
71 | /* End PBXFileReference section */
72 |
73 | /* Begin PBXFrameworksBuildPhase section */
74 | F819042517AC0BE5006A0896 /* Frameworks */ = {
75 | isa = PBXFrameworksBuildPhase;
76 | buildActionMask = 2147483647;
77 | files = (
78 | F8E345D417AC3B89005478D6 /* Accelerate.framework in Frameworks */,
79 | F8E345D217AC3B74005478D6 /* QuartzCore.framework in Frameworks */,
80 | F819042C17AC0BE5006A0896 /* UIKit.framework in Frameworks */,
81 | F819042E17AC0BE5006A0896 /* Foundation.framework in Frameworks */,
82 | F819043017AC0BE5006A0896 /* CoreGraphics.framework in Frameworks */,
83 | );
84 | runOnlyForDeploymentPostprocessing = 0;
85 | };
86 | /* End PBXFrameworksBuildPhase section */
87 |
88 | /* Begin PBXGroup section */
89 | F819041F17AC0BE5006A0896 = {
90 | isa = PBXGroup;
91 | children = (
92 | F819043117AC0BE5006A0896 /* TWSReleaseNotesViewControllerSample */,
93 | F819042A17AC0BE5006A0896 /* Frameworks */,
94 | F819042917AC0BE5006A0896 /* Products */,
95 | );
96 | sourceTree = "";
97 | };
98 | F819042917AC0BE5006A0896 /* Products */ = {
99 | isa = PBXGroup;
100 | children = (
101 | F819042817AC0BE5006A0896 /* TWSReleaseNotesViewSample.app */,
102 | );
103 | name = Products;
104 | sourceTree = "";
105 | };
106 | F819042A17AC0BE5006A0896 /* Frameworks */ = {
107 | isa = PBXGroup;
108 | children = (
109 | F8E345D317AC3B89005478D6 /* Accelerate.framework */,
110 | F819042F17AC0BE5006A0896 /* CoreGraphics.framework */,
111 | F819042D17AC0BE5006A0896 /* Foundation.framework */,
112 | F8E345D117AC3B74005478D6 /* QuartzCore.framework */,
113 | F819042B17AC0BE5006A0896 /* UIKit.framework */,
114 | );
115 | name = Frameworks;
116 | sourceTree = "";
117 | };
118 | F819043117AC0BE5006A0896 /* TWSReleaseNotesViewControllerSample */ = {
119 | isa = PBXGroup;
120 | children = (
121 | F8C4A09017B1395E003CA095 /* TWSReleaseNotesView */,
122 | F819043A17AC0BE5006A0896 /* AppDelegate.h */,
123 | F819043B17AC0BE5006A0896 /* AppDelegate.m */,
124 | F819044C17AC1520006A0896 /* RootViewController.h */,
125 | F819044D17AC1520006A0896 /* RootViewController.m */,
126 | F893E7F917AD69FF005DB2FC /* RootViewController.xib */,
127 | F8B6D83517BAED4B00C2ECB0 /* Resources */,
128 | F819043217AC0BE5006A0896 /* Supporting Files */,
129 | );
130 | name = TWSReleaseNotesViewControllerSample;
131 | path = TWSReleaseNotesViewSample;
132 | sourceTree = "";
133 | };
134 | F819043217AC0BE5006A0896 /* Supporting Files */ = {
135 | isa = PBXGroup;
136 | children = (
137 | F819043317AC0BE5006A0896 /* TWSReleaseNotesViewSample-Info.plist */,
138 | F819043417AC0BE5006A0896 /* InfoPlist.strings */,
139 | F819043717AC0BE5006A0896 /* main.m */,
140 | F819043917AC0BE5006A0896 /* TWSReleaseNotesViewSample-Prefix.pch */,
141 | F819043D17AC0BE5006A0896 /* Default.png */,
142 | F819043F17AC0BE5006A0896 /* Default@2x.png */,
143 | F819044117AC0BE5006A0896 /* Default-568h@2x.png */,
144 | );
145 | name = "Supporting Files";
146 | sourceTree = "";
147 | };
148 | F8B6D83517BAED4B00C2ECB0 /* Resources */ = {
149 | isa = PBXGroup;
150 | children = (
151 | F844C4D517BAF48B00021701 /* icon_7@2x.png */,
152 | F844C4D617BAF48B00021701 /* icon.png */,
153 | F844C4D717BAF48B00021701 /* icon@2x.png */,
154 | F844C4CF17BAEF3900021701 /* background@2x.png */,
155 | F844C4D017BAEF3900021701 /* btn_bg_hl@2x.png */,
156 | F844C4D117BAEF3900021701 /* btn_bg@2x.png */,
157 | F8B6D82F17BAE1F000C2ECB0 /* background.png */,
158 | F8B6D83117BAED4400C2ECB0 /* btn_bg_hl.png */,
159 | F8B6D83217BAED4400C2ECB0 /* btn_bg.png */,
160 | );
161 | name = Resources;
162 | sourceTree = "";
163 | };
164 | F8C4A09017B1395E003CA095 /* TWSReleaseNotesView */ = {
165 | isa = PBXGroup;
166 | children = (
167 | F8C4A09117B1395E003CA095 /* TWSReleaseNotesDownloadOperation.h */,
168 | F8C4A09217B1395E003CA095 /* TWSReleaseNotesDownloadOperation.m */,
169 | F8C4A09317B1395E003CA095 /* TWSReleaseNotesView.h */,
170 | F8C4A09417B1395E003CA095 /* TWSReleaseNotesView.m */,
171 | F8C4A09517B1395E003CA095 /* UIImage+ImageEffects.h */,
172 | F8C4A09617B1395E003CA095 /* UIImage+ImageEffects.m */,
173 | );
174 | name = TWSReleaseNotesView;
175 | path = ../../TWSReleaseNotesView;
176 | sourceTree = "";
177 | };
178 | /* End PBXGroup section */
179 |
180 | /* Begin PBXNativeTarget section */
181 | F819042717AC0BE5006A0896 /* TWSReleaseNotesViewSample */ = {
182 | isa = PBXNativeTarget;
183 | buildConfigurationList = F819044517AC0BE5006A0896 /* Build configuration list for PBXNativeTarget "TWSReleaseNotesViewSample" */;
184 | buildPhases = (
185 | F819042417AC0BE5006A0896 /* Sources */,
186 | F819042517AC0BE5006A0896 /* Frameworks */,
187 | F819042617AC0BE5006A0896 /* Resources */,
188 | );
189 | buildRules = (
190 | );
191 | dependencies = (
192 | );
193 | name = TWSReleaseNotesViewSample;
194 | productName = TWSReleaseNotesViewControllerSample;
195 | productReference = F819042817AC0BE5006A0896 /* TWSReleaseNotesViewSample.app */;
196 | productType = "com.apple.product-type.application";
197 | };
198 | /* End PBXNativeTarget section */
199 |
200 | /* Begin PBXProject section */
201 | F819042017AC0BE5006A0896 /* Project object */ = {
202 | isa = PBXProject;
203 | attributes = {
204 | LastUpgradeCheck = 0460;
205 | ORGANIZATIONNAME = Tapwings;
206 | };
207 | buildConfigurationList = F819042317AC0BE5006A0896 /* Build configuration list for PBXProject "TWSReleaseNotesViewSample" */;
208 | compatibilityVersion = "Xcode 3.2";
209 | developmentRegion = English;
210 | hasScannedForEncodings = 0;
211 | knownRegions = (
212 | en,
213 | );
214 | mainGroup = F819041F17AC0BE5006A0896;
215 | productRefGroup = F819042917AC0BE5006A0896 /* Products */;
216 | projectDirPath = "";
217 | projectRoot = "";
218 | targets = (
219 | F819042717AC0BE5006A0896 /* TWSReleaseNotesViewSample */,
220 | );
221 | };
222 | /* End PBXProject section */
223 |
224 | /* Begin PBXResourcesBuildPhase section */
225 | F819042617AC0BE5006A0896 /* Resources */ = {
226 | isa = PBXResourcesBuildPhase;
227 | buildActionMask = 2147483647;
228 | files = (
229 | F8B6D83317BAED4400C2ECB0 /* btn_bg_hl.png in Resources */,
230 | F8B6D83417BAED4400C2ECB0 /* btn_bg.png in Resources */,
231 | F819043617AC0BE5006A0896 /* InfoPlist.strings in Resources */,
232 | F819043E17AC0BE5006A0896 /* Default.png in Resources */,
233 | F8B6D83017BAE1F000C2ECB0 /* background.png in Resources */,
234 | F819044017AC0BE5006A0896 /* Default@2x.png in Resources */,
235 | F819044217AC0BE5006A0896 /* Default-568h@2x.png in Resources */,
236 | F893E7FA17AD69FF005DB2FC /* RootViewController.xib in Resources */,
237 | F844C4D217BAEF3900021701 /* background@2x.png in Resources */,
238 | F844C4D317BAEF3900021701 /* btn_bg_hl@2x.png in Resources */,
239 | F844C4D417BAEF3900021701 /* btn_bg@2x.png in Resources */,
240 | F844C4D817BAF48B00021701 /* icon_7@2x.png in Resources */,
241 | F844C4D917BAF48B00021701 /* icon.png in Resources */,
242 | F844C4DA17BAF48B00021701 /* icon@2x.png in Resources */,
243 | );
244 | runOnlyForDeploymentPostprocessing = 0;
245 | };
246 | /* End PBXResourcesBuildPhase section */
247 |
248 | /* Begin PBXSourcesBuildPhase section */
249 | F819042417AC0BE5006A0896 /* Sources */ = {
250 | isa = PBXSourcesBuildPhase;
251 | buildActionMask = 2147483647;
252 | files = (
253 | F819043817AC0BE5006A0896 /* main.m in Sources */,
254 | F819043C17AC0BE5006A0896 /* AppDelegate.m in Sources */,
255 | F8C4A09917B1395E003CA095 /* UIImage+ImageEffects.m in Sources */,
256 | F8C4A09717B1395E003CA095 /* TWSReleaseNotesDownloadOperation.m in Sources */,
257 | F819044F17AC1520006A0896 /* RootViewController.m in Sources */,
258 | F8C4A09817B1395E003CA095 /* TWSReleaseNotesView.m in Sources */,
259 | );
260 | runOnlyForDeploymentPostprocessing = 0;
261 | };
262 | /* End PBXSourcesBuildPhase section */
263 |
264 | /* Begin PBXVariantGroup section */
265 | F819043417AC0BE5006A0896 /* InfoPlist.strings */ = {
266 | isa = PBXVariantGroup;
267 | children = (
268 | F819043517AC0BE5006A0896 /* en */,
269 | );
270 | name = InfoPlist.strings;
271 | sourceTree = "";
272 | };
273 | /* End PBXVariantGroup section */
274 |
275 | /* Begin XCBuildConfiguration section */
276 | F819044317AC0BE5006A0896 /* Debug */ = {
277 | isa = XCBuildConfiguration;
278 | buildSettings = {
279 | ALWAYS_SEARCH_USER_PATHS = NO;
280 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
281 | CLANG_CXX_LIBRARY = "libc++";
282 | CLANG_ENABLE_OBJC_ARC = YES;
283 | CLANG_WARN_CONSTANT_CONVERSION = YES;
284 | CLANG_WARN_EMPTY_BODY = YES;
285 | CLANG_WARN_ENUM_CONVERSION = YES;
286 | CLANG_WARN_INT_CONVERSION = YES;
287 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
288 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
289 | COPY_PHASE_STRIP = NO;
290 | GCC_C_LANGUAGE_STANDARD = gnu99;
291 | GCC_DYNAMIC_NO_PIC = NO;
292 | GCC_OPTIMIZATION_LEVEL = 0;
293 | GCC_PREPROCESSOR_DEFINITIONS = (
294 | "DEBUG=1",
295 | "$(inherited)",
296 | );
297 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
298 | GCC_WARN_ABOUT_RETURN_TYPE = YES;
299 | GCC_WARN_UNINITIALIZED_AUTOS = YES;
300 | GCC_WARN_UNUSED_VARIABLE = YES;
301 | IPHONEOS_DEPLOYMENT_TARGET = 6.1;
302 | ONLY_ACTIVE_ARCH = YES;
303 | SDKROOT = iphoneos;
304 | };
305 | name = Debug;
306 | };
307 | F819044417AC0BE5006A0896 /* Release */ = {
308 | isa = XCBuildConfiguration;
309 | buildSettings = {
310 | ALWAYS_SEARCH_USER_PATHS = NO;
311 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
312 | CLANG_CXX_LIBRARY = "libc++";
313 | CLANG_ENABLE_OBJC_ARC = YES;
314 | CLANG_WARN_CONSTANT_CONVERSION = YES;
315 | CLANG_WARN_EMPTY_BODY = YES;
316 | CLANG_WARN_ENUM_CONVERSION = YES;
317 | CLANG_WARN_INT_CONVERSION = YES;
318 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
319 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
320 | COPY_PHASE_STRIP = YES;
321 | GCC_C_LANGUAGE_STANDARD = gnu99;
322 | GCC_WARN_ABOUT_RETURN_TYPE = YES;
323 | GCC_WARN_UNINITIALIZED_AUTOS = YES;
324 | GCC_WARN_UNUSED_VARIABLE = YES;
325 | IPHONEOS_DEPLOYMENT_TARGET = 6.1;
326 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1";
327 | SDKROOT = iphoneos;
328 | VALIDATE_PRODUCT = YES;
329 | };
330 | name = Release;
331 | };
332 | F819044617AC0BE5006A0896 /* Debug */ = {
333 | isa = XCBuildConfiguration;
334 | buildSettings = {
335 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
336 | GCC_PREFIX_HEADER = "TWSReleaseNotesViewSample/TWSReleaseNotesViewSample-Prefix.pch";
337 | INFOPLIST_FILE = "TWSReleaseNotesViewSample/TWSReleaseNotesViewSample-Info.plist";
338 | IPHONEOS_DEPLOYMENT_TARGET = 5.1;
339 | PRODUCT_NAME = TWSReleaseNotesViewSample;
340 | TARGETED_DEVICE_FAMILY = 1;
341 | WRAPPER_EXTENSION = app;
342 | };
343 | name = Debug;
344 | };
345 | F819044717AC0BE5006A0896 /* Release */ = {
346 | isa = XCBuildConfiguration;
347 | buildSettings = {
348 | CODE_SIGN_IDENTITY = "iPhone Distribution: Matteo Lallone (2BHJQK4UZU)";
349 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution: Matteo Lallone (2BHJQK4UZU)";
350 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
351 | GCC_PREFIX_HEADER = "TWSReleaseNotesViewSample/TWSReleaseNotesViewSample-Prefix.pch";
352 | INFOPLIST_FILE = "TWSReleaseNotesViewSample/TWSReleaseNotesViewSample-Info.plist";
353 | IPHONEOS_DEPLOYMENT_TARGET = 5.1;
354 | PRODUCT_NAME = TWSReleaseNotesViewSample;
355 | PROVISIONING_PROFILE = "9F71268A-3685-47BD-8770-868A43D83E6D";
356 | "PROVISIONING_PROFILE[sdk=iphoneos*]" = "9F71268A-3685-47BD-8770-868A43D83E6D";
357 | TARGETED_DEVICE_FAMILY = 1;
358 | WRAPPER_EXTENSION = app;
359 | };
360 | name = Release;
361 | };
362 | /* End XCBuildConfiguration section */
363 |
364 | /* Begin XCConfigurationList section */
365 | F819042317AC0BE5006A0896 /* Build configuration list for PBXProject "TWSReleaseNotesViewSample" */ = {
366 | isa = XCConfigurationList;
367 | buildConfigurations = (
368 | F819044317AC0BE5006A0896 /* Debug */,
369 | F819044417AC0BE5006A0896 /* Release */,
370 | );
371 | defaultConfigurationIsVisible = 0;
372 | defaultConfigurationName = Release;
373 | };
374 | F819044517AC0BE5006A0896 /* Build configuration list for PBXNativeTarget "TWSReleaseNotesViewSample" */ = {
375 | isa = XCConfigurationList;
376 | buildConfigurations = (
377 | F819044617AC0BE5006A0896 /* Debug */,
378 | F819044717AC0BE5006A0896 /* Release */,
379 | );
380 | defaultConfigurationIsVisible = 0;
381 | defaultConfigurationName = Release;
382 | };
383 | /* End XCConfigurationList section */
384 | };
385 | rootObject = F819042017AC0BE5006A0896 /* Project object */;
386 | }
387 |
--------------------------------------------------------------------------------
/TWSReleaseNotesViewSample/TWSReleaseNotesViewSample/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // TWSReleaseNotesViewSample
4 | //
5 | // Created by Matteo Lallone on 02/08/13.
6 | // Copyright (c) 2013 Tapwings. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface AppDelegate : UIResponder
12 |
13 | @property (strong, nonatomic) UIWindow *window;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/TWSReleaseNotesViewSample/TWSReleaseNotesViewSample/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // TWSReleaseNotesViewSample
4 | //
5 | // Created by Matteo Lallone on 02/08/13.
6 | // Copyright (c) 2013 Tapwings. All rights reserved.
7 | //
8 |
9 | #import "AppDelegate.h"
10 | #import "RootViewController.h"
11 |
12 | @implementation AppDelegate
13 |
14 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
15 | {
16 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
17 | // Override point for customization after application launch.
18 |
19 | [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackTranslucent];
20 | RootViewController *rootController = [[RootViewController alloc] initWithNibName:@"RootViewController" bundle:nil];
21 | self.window.rootViewController = rootController;
22 |
23 | self.window.backgroundColor = [UIColor whiteColor];
24 | [self.window makeKeyAndVisible];
25 |
26 | return YES;
27 | }
28 |
29 | - (void)applicationWillResignActive:(UIApplication *)application
30 | {
31 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
32 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
33 | }
34 |
35 | - (void)applicationDidEnterBackground:(UIApplication *)application
36 | {
37 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
38 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
39 | }
40 |
41 | - (void)applicationWillEnterForeground:(UIApplication *)application
42 | {
43 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
44 | }
45 |
46 | - (void)applicationDidBecomeActive:(UIApplication *)application
47 | {
48 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
49 | }
50 |
51 | - (void)applicationWillTerminate:(UIApplication *)application
52 | {
53 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
54 | }
55 |
56 | @end
57 |
--------------------------------------------------------------------------------
/TWSReleaseNotesViewSample/TWSReleaseNotesViewSample/Default-568h@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iGriever/TWSReleaseNotesView/HEAD/TWSReleaseNotesViewSample/TWSReleaseNotesViewSample/Default-568h@2x.png
--------------------------------------------------------------------------------
/TWSReleaseNotesViewSample/TWSReleaseNotesViewSample/Default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iGriever/TWSReleaseNotesView/HEAD/TWSReleaseNotesViewSample/TWSReleaseNotesViewSample/Default.png
--------------------------------------------------------------------------------
/TWSReleaseNotesViewSample/TWSReleaseNotesViewSample/Default@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iGriever/TWSReleaseNotesView/HEAD/TWSReleaseNotesViewSample/TWSReleaseNotesViewSample/Default@2x.png
--------------------------------------------------------------------------------
/TWSReleaseNotesViewSample/TWSReleaseNotesViewSample/RootViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // RootViewController.h
3 | // TWSReleaseNotesViewSample
4 | //
5 | // Created by Matteo Lallone on 02/08/13.
6 | // Copyright (c) 2013 Tapwings. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface RootViewController : UIViewController
12 |
13 | @property (weak, nonatomic) IBOutlet UIButton *localButton;
14 | @property (weak, nonatomic) IBOutlet UIButton *remoteButton;
15 | - (IBAction)showLocalButtonPressed:(id)sender;
16 | - (IBAction)showRemoteButtonPressed:(id)sender;
17 |
18 | @end
19 |
--------------------------------------------------------------------------------
/TWSReleaseNotesViewSample/TWSReleaseNotesViewSample/RootViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // RootViewController.m
3 | // TWSReleaseNotesViewSample
4 | //
5 | // Created by Matteo Lallone on 02/08/13.
6 | // Copyright (c) 2013 Tapwings. All rights reserved.
7 | //
8 |
9 | #import "RootViewController.h"
10 | #import "TWSReleaseNotesView.h"
11 |
12 | @interface RootViewController ()
13 |
14 | - (void)showLocalReleaseNotesView;
15 | - (void)showRemoteReleaseNotesView;
16 |
17 | @end
18 |
19 | @implementation RootViewController
20 |
21 | #pragma mark - Init - dealloc Methods
22 |
23 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
24 | {
25 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
26 | if (self) {
27 | // Custom initialization
28 | }
29 | return self;
30 | }
31 |
32 | #pragma mark - View lifecycle
33 |
34 | - (void)viewDidLoad
35 | {
36 | [super viewDidLoad];
37 | // Do any additional setup after loading the view from its nib.
38 |
39 | [self setWantsFullScreenLayout:YES];
40 |
41 | BOOL bDoesSupportResizableImageWithCapInsets = [[[UIImage alloc] init] respondsToSelector:@selector(resizableImageWithCapInsets:resizingMode:)];
42 | UIImage *buttonNormalImage = [UIImage imageNamed:@"btn_bg"], *buttonHighlightedImage = [UIImage imageNamed:@"btn_bg_hl"];
43 |
44 | // Setup local button
45 | [self.localButton setBackgroundColor:[UIColor clearColor]];
46 | if( bDoesSupportResizableImageWithCapInsets )
47 | {
48 | buttonNormalImage = [buttonNormalImage resizableImageWithCapInsets:UIEdgeInsetsMake(0.0f, 6.0f, 0.0f, 6.0f) resizingMode:UIImageResizingModeStretch];
49 | buttonHighlightedImage = [buttonHighlightedImage resizableImageWithCapInsets:UIEdgeInsetsMake(0.0f, 6.0f, 0.0f, 6.0f) resizingMode:UIImageResizingModeStretch];
50 | }
51 | else
52 | {
53 | //iOS 5 compatibility
54 | buttonNormalImage = [buttonNormalImage resizableImageWithCapInsets:UIEdgeInsetsMake(0.0f, 6.0f, 0.0f, 6.0f)];
55 | buttonHighlightedImage = [buttonHighlightedImage resizableImageWithCapInsets:UIEdgeInsetsMake(0.0f, 6.0f, 0.0f, 6.0f)];
56 | }
57 | [self.localButton setBackgroundImage:buttonNormalImage forState:UIControlStateNormal];
58 | [self.localButton setBackgroundImage:buttonHighlightedImage forState:UIControlStateHighlighted];
59 |
60 |
61 | // Setup remote button
62 | [self.remoteButton setBackgroundColor:[UIColor clearColor]];
63 | buttonNormalImage = [UIImage imageNamed:@"btn_bg"];
64 | buttonHighlightedImage = [UIImage imageNamed:@"btn_bg_hl"];
65 | if( bDoesSupportResizableImageWithCapInsets )
66 | {
67 | buttonNormalImage = [buttonNormalImage resizableImageWithCapInsets:UIEdgeInsetsMake(0.0f, 6.0f, 0.0f, 6.0f) resizingMode:UIImageResizingModeStretch];
68 | buttonHighlightedImage = [buttonHighlightedImage resizableImageWithCapInsets:UIEdgeInsetsMake(0.0f, 6.0f, 0.0f, 6.0f) resizingMode:UIImageResizingModeStretch];
69 | }
70 | else
71 | {
72 | //iOS 5 compatibility
73 | buttonNormalImage = [buttonNormalImage resizableImageWithCapInsets:UIEdgeInsetsMake(0.0f, 6.0f, 0.0f, 6.0f)];
74 | buttonHighlightedImage = [buttonHighlightedImage resizableImageWithCapInsets:UIEdgeInsetsMake(0.0f, 6.0f, 0.0f, 6.0f)];
75 | }
76 | [self.remoteButton setBackgroundImage:buttonNormalImage forState:UIControlStateNormal];
77 | [self.remoteButton setBackgroundImage:buttonHighlightedImage forState:UIControlStateHighlighted];
78 | }
79 |
80 | - (void)didReceiveMemoryWarning
81 | {
82 | [super didReceiveMemoryWarning];
83 | // Dispose of any resources that can be recreated.
84 | }
85 |
86 | - (void)viewDidAppear:(BOOL)animated
87 | {
88 | [super viewDidAppear:animated];
89 |
90 | // Check for app update if app is not on first launch
91 | if (![TWSReleaseNotesView isAppOnFirstLaunch] && [TWSReleaseNotesView isAppVersionUpdated])
92 | {
93 | [self showLocalReleaseNotesView];
94 | }
95 | }
96 |
97 | #pragma mark - Private Methods
98 |
99 | - (void)showLocalReleaseNotesView
100 | {
101 | // Create the release notes view
102 | NSString *currentAppVersion = [[NSBundle mainBundle] infoDictionary][@"CFBundleVersion"];
103 | TWSReleaseNotesView *releaseNotesView = [TWSReleaseNotesView viewWithReleaseNotesTitle:[NSString stringWithFormat:@"What's new in version\n%@:", currentAppVersion] text:@"• Create custom stations of your favorite podcasts that update automatically with new episodes\n• Choose whether your stations begin playing with the newest or oldest unplayed episode\n• Your stations are stored in iCloud and kept up-to-date on all of your devices\n• Create an On-The-Go playlist with your own list of episodes\n• Playlists synced from iTunes now appear in the Podcasts app\n• The Now Playing view has been redesigned with easier to use playback controls\n• Addressed an issue with resuming playback when returning to the app\n• Additional performance and stability improvements" closeButtonTitle:@"Close"];
104 |
105 | // Show the release notes view
106 | [releaseNotesView showInView:self.view];
107 | }
108 |
109 | - (void)showRemoteReleaseNotesView
110 | {
111 | NSString *currentAppVersion = [[NSBundle mainBundle] infoDictionary][@"CFBundleVersion"];
112 | [TWSReleaseNotesView setupViewWithAppIdentifier:@"329670577" releaseNotesTitle:[NSString stringWithFormat:@"What's new in version %@:", currentAppVersion] closeButtonTitle:@"Close" completionBlock:^(TWSReleaseNotesView *releaseNotesView, NSString *releaseNotesText, NSError *error){
113 | if (error)
114 | {
115 | NSLog(@"An error occurred: %@", [error localizedDescription]);
116 | }
117 | else
118 | {
119 | // Create and show release notes view
120 | [releaseNotesView showInView:self.view];
121 | }
122 | }];
123 | }
124 |
125 | #pragma mark - Control Methods
126 |
127 | - (IBAction)showLocalButtonPressed:(id)sender
128 | {
129 | [self showLocalReleaseNotesView];
130 | }
131 |
132 | - (IBAction)showRemoteButtonPressed:(id)sender
133 | {
134 | [self showRemoteReleaseNotesView];
135 | }
136 |
137 | @end
138 |
--------------------------------------------------------------------------------
/TWSReleaseNotesViewSample/TWSReleaseNotesViewSample/RootViewController.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 1552
5 | 12E55
6 | 3084
7 | 1187.39
8 | 626.00
9 |
10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin
11 | 2083
12 |
13 |
14 | IBProxyObject
15 | IBUIButton
16 | IBUIImageView
17 | IBUIView
18 |
19 |
20 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin
21 |
22 |
23 | PluginDependencyRecalculationVersion
24 |
25 |
26 |
27 |
28 | IBFilesOwner
29 | IBCocoaTouchFramework
30 |
31 |
32 | IBFirstResponder
33 | IBCocoaTouchFramework
34 |
35 |
36 |
37 | 274
38 |
39 |
40 |
41 | 306
42 | {320, 568}
43 |
44 |
45 | _NS:9
46 | 5
47 | NO
48 | IBCocoaTouchFramework
49 |
50 | NSImage
51 | background.png
52 |
53 |
54 |
55 |
56 | 269
57 | {{60, 492}, {200, 36}}
58 |
59 |
60 | _NS:9
61 |
62 | 3
63 | MAA
64 |
65 | NO
66 | IBCocoaTouchFramework
67 | 0
68 | 0
69 | -2
70 | 0.0
71 | 0.0
72 | 0.0
73 | Remote release notes
74 |
75 | 3
76 | MQA
77 |
78 |
79 |
80 | 3
81 | MCAwAA
82 |
83 |
84 | 3
85 | MC41AA
86 |
87 |
88 | 1
89 | 15
90 |
91 |
92 | Helvetica
93 | 15
94 | 16
95 |
96 |
97 |
98 |
99 | 269
100 | {{60, 440}, {200, 36}}
101 |
102 |
103 | _NS:9
104 |
105 | NO
106 | IBCocoaTouchFramework
107 | 0
108 | 0
109 | -2
110 | 0.0
111 | 0.0
112 | 0.0
113 | Local release notes
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 | {320, 568}
123 |
124 |
125 | _NS:9
126 |
127 | 3
128 | MQA
129 |
130 | 2
131 |
132 |
133 |
134 | IBUIScreenMetrics
135 |
136 | YES
137 |
138 |
139 |
140 |
141 |
142 | {320, 568}
143 | {568, 320}
144 |
145 |
146 | IBCocoaTouchFramework
147 | Retina 4 Full Screen
148 | 2
149 |
150 | IBCocoaTouchFramework
151 |
152 |
153 |
154 |
155 |
156 |
157 | view
158 |
159 |
160 |
161 | 3
162 |
163 |
164 |
165 | localButton
166 |
167 |
168 |
169 | 11
170 |
171 |
172 |
173 | remoteButton
174 |
175 |
176 |
177 | 12
178 |
179 |
180 |
181 | showRemoteButtonPressed:
182 |
183 |
184 | 7
185 |
186 | 10
187 |
188 |
189 |
190 | showLocalButtonPressed:
191 |
192 |
193 | 7
194 |
195 | 9
196 |
197 |
198 |
199 |
200 |
201 | 0
202 |
203 |
204 |
205 |
206 |
207 | -1
208 |
209 |
210 | File's Owner
211 |
212 |
213 | -2
214 |
215 |
216 |
217 |
218 | 2
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 | 4
229 |
230 |
231 |
232 |
233 | 5
234 |
235 |
236 |
237 |
238 | 7
239 |
240 |
241 |
242 |
243 |
244 |
245 | RootViewController
246 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin
247 | UIResponder
248 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin
249 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin
250 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin
251 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin
252 |
253 |
254 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 | 12
263 |
264 |
265 | 0
266 | IBCocoaTouchFramework
267 | YES
268 | 3
269 |
270 | background.png
271 | {320, 568}
272 |
273 | 2083
274 |
275 |
276 |
--------------------------------------------------------------------------------
/TWSReleaseNotesViewSample/TWSReleaseNotesViewSample/TWSReleaseNotesViewSample-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | ReleaseView
9 | CFBundleExecutable
10 | ${EXECUTABLE_NAME}
11 | CFBundleIcons
12 |
13 | CFBundlePrimaryIcon
14 |
15 | CFBundleIconFiles
16 |
17 | icon@2x.png
18 | icon.png
19 |
20 | UIPrerenderedIcon
21 |
22 |
23 | UINewsstandIcon
24 |
25 | CFBundleIconFiles
26 |
27 |
28 |
29 | UINewsstandBindingEdge
30 | UINewsstandBindingEdgeLeft
31 | UINewsstandBindingType
32 | UINewsstandBindingTypeMagazine
33 |
34 |
35 | CFBundleIdentifier
36 | com.tapwings.${PRODUCT_NAME:rfc1034identifier}
37 | CFBundleInfoDictionaryVersion
38 | 6.0
39 | CFBundleName
40 | ${PRODUCT_NAME}
41 | CFBundlePackageType
42 | APPL
43 | CFBundleShortVersionString
44 | 1.2.0
45 | CFBundleSignature
46 | ????
47 | CFBundleVersion
48 | 1.2.0
49 | LSRequiresIPhoneOS
50 |
51 | UIRequiredDeviceCapabilities
52 |
53 | armv7
54 |
55 | UISupportedInterfaceOrientations
56 |
57 | UIInterfaceOrientationPortrait
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/TWSReleaseNotesViewSample/TWSReleaseNotesViewSample/TWSReleaseNotesViewSample-Prefix.pch:
--------------------------------------------------------------------------------
1 | //
2 | // Prefix header for all source files of the 'TWSReleaseNotesViewSample' target in the 'TWSReleaseNotesViewSample' project
3 | //
4 |
5 | #import
6 |
7 | #ifndef __IPHONE_3_0
8 | #warning "This project uses features only available in iOS SDK 3.0 and later."
9 | #endif
10 |
11 | #ifdef __OBJC__
12 | #import
13 | #import
14 | #endif
15 |
--------------------------------------------------------------------------------
/TWSReleaseNotesViewSample/TWSReleaseNotesViewSample/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iGriever/TWSReleaseNotesView/HEAD/TWSReleaseNotesViewSample/TWSReleaseNotesViewSample/background.png
--------------------------------------------------------------------------------
/TWSReleaseNotesViewSample/TWSReleaseNotesViewSample/background@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iGriever/TWSReleaseNotesView/HEAD/TWSReleaseNotesViewSample/TWSReleaseNotesViewSample/background@2x.png
--------------------------------------------------------------------------------
/TWSReleaseNotesViewSample/TWSReleaseNotesViewSample/btn_bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iGriever/TWSReleaseNotesView/HEAD/TWSReleaseNotesViewSample/TWSReleaseNotesViewSample/btn_bg.png
--------------------------------------------------------------------------------
/TWSReleaseNotesViewSample/TWSReleaseNotesViewSample/btn_bg@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iGriever/TWSReleaseNotesView/HEAD/TWSReleaseNotesViewSample/TWSReleaseNotesViewSample/btn_bg@2x.png
--------------------------------------------------------------------------------
/TWSReleaseNotesViewSample/TWSReleaseNotesViewSample/btn_bg_hl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iGriever/TWSReleaseNotesView/HEAD/TWSReleaseNotesViewSample/TWSReleaseNotesViewSample/btn_bg_hl.png
--------------------------------------------------------------------------------
/TWSReleaseNotesViewSample/TWSReleaseNotesViewSample/btn_bg_hl@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iGriever/TWSReleaseNotesView/HEAD/TWSReleaseNotesViewSample/TWSReleaseNotesViewSample/btn_bg_hl@2x.png
--------------------------------------------------------------------------------
/TWSReleaseNotesViewSample/TWSReleaseNotesViewSample/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------
/TWSReleaseNotesViewSample/TWSReleaseNotesViewSample/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iGriever/TWSReleaseNotesView/HEAD/TWSReleaseNotesViewSample/TWSReleaseNotesViewSample/icon.png
--------------------------------------------------------------------------------
/TWSReleaseNotesViewSample/TWSReleaseNotesViewSample/icon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iGriever/TWSReleaseNotesView/HEAD/TWSReleaseNotesViewSample/TWSReleaseNotesViewSample/icon@2x.png
--------------------------------------------------------------------------------
/TWSReleaseNotesViewSample/TWSReleaseNotesViewSample/icon_7@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iGriever/TWSReleaseNotesView/HEAD/TWSReleaseNotesViewSample/TWSReleaseNotesViewSample/icon_7@2x.png
--------------------------------------------------------------------------------
/TWSReleaseNotesViewSample/TWSReleaseNotesViewSample/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // TWSReleaseNotesViewSample
4 | //
5 | // Created by Matteo Lallone on 02/08/13.
6 | // Copyright (c) 2013 Tapwings. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | #import "AppDelegate.h"
12 |
13 | int main(int argc, char *argv[])
14 | {
15 | @autoreleasepool {
16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/TutorialImages/sampleProject01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iGriever/TWSReleaseNotesView/HEAD/TutorialImages/sampleProject01.png
--------------------------------------------------------------------------------
/TutorialImages/sampleProject02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iGriever/TWSReleaseNotesView/HEAD/TutorialImages/sampleProject02.png
--------------------------------------------------------------------------------