├── BDBOAuth1ManagerDemo
├── Flickr Demo
│ ├── Supporting Files
│ │ ├── en.lproj
│ │ │ └── InfoPlist.strings
│ │ ├── Flickr Demo-Prefix.pch
│ │ ├── main.m
│ │ └── Flickr Demo-Info.plist
│ ├── Resources
│ │ ├── Flickr.xcassets
│ │ │ ├── Contents.json
│ │ │ └── AppIcon.appiconset
│ │ │ │ └── Contents.json
│ │ └── Launch Screen.xib
│ ├── Views
│ │ ├── PhotoAlbumLayout.h
│ │ ├── PhotoAlbumHeaderView.m
│ │ ├── PhotoAlbumCell.h
│ │ ├── PhotoAlbumHeaderView.h
│ │ ├── PhotoAlbumCell.m
│ │ ├── PhotoAlbumLayout.m
│ │ └── PhotoAlbumHeaderView.xib
│ ├── AppDelegate.h
│ ├── View Controllers
│ │ ├── PhotosViewController.h
│ │ └── PhotosViewController.m
│ ├── Flickr
│ │ ├── BDBFlickrPhoto.h
│ │ ├── BDBFlickrPhotoset.h
│ │ ├── BDBFlickrClient.h
│ │ ├── BDBFlickrPhoto.m
│ │ ├── BDBFlickrPhotoset.m
│ │ └── BDBFlickrClient.m
│ └── AppDelegate.m
├── Twitter Demo
│ ├── Supporting Files
│ │ ├── en.lproj
│ │ │ └── InfoPlist.strings
│ │ ├── Twitter Demo-Prefix.pch
│ │ ├── main.m
│ │ └── Twitter Demo-Info.plist
│ ├── Resources
│ │ ├── Twitter.xcassets
│ │ │ ├── Contents.json
│ │ │ └── AppIcon.appiconset
│ │ │ │ └── Contents.json
│ │ └── Launch Screen.xib
│ ├── AppDelegate.h
│ ├── View Controllers
│ │ ├── TweetsViewController.h
│ │ └── TweetsViewController.m
│ ├── Views
│ │ ├── TweetCell.h
│ │ ├── TweetCell.m
│ │ └── TweetCell.xib
│ ├── Twitter
│ │ ├── BDBTweet.h
│ │ ├── BDBTwitterClient.h
│ │ ├── BDBTweet.m
│ │ └── BDBTwitterClient.m
│ └── AppDelegate.m
├── BDBOAuth1ManagerDemo.xcodeproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ ├── BDBOAuth1RequestSerializerDemo.xccheckout
│ │ │ ├── BDBOAuth1Demo.xccheckout
│ │ │ └── BDBOAuth1Manager.xccheckout
│ └── project.pbxproj
├── Podfile
├── BDBOAuth1ManagerDemo.xcworkspace
│ └── contents.xcworkspacedata
└── Podfile.lock
├── BDBOAuth1Manager.podspec
├── LICENSE
├── .gitignore
├── BDBOAuth1Manager
├── Categories
│ ├── NSDictionary+BDBOAuth1Manager.h
│ ├── NSDictionary+BDBOAuth1Manager.m
│ ├── NSString+BDBOAuth1Manager.h
│ └── NSString+BDBOAuth1Manager.m
├── BDBOAuth1SessionManager.h
├── BDBOAuth1SessionManager.m
├── BDBOAuth1RequestSerializer.h
└── BDBOAuth1RequestSerializer.m
└── README.md
/BDBOAuth1ManagerDemo/Flickr Demo/Supporting Files/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/Twitter Demo/Supporting Files/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/Flickr Demo/Resources/Flickr.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/Twitter Demo/Resources/Twitter.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/Flickr Demo/Supporting Files/Flickr Demo-Prefix.pch:
--------------------------------------------------------------------------------
1 | @import Darwin.Availability;
2 |
3 | #ifdef __OBJC__
4 | @import UIKit;
5 | @import Foundation;
6 | #endif
7 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/Twitter Demo/Supporting Files/Twitter Demo-Prefix.pch:
--------------------------------------------------------------------------------
1 | @import Darwin.Availability;
2 |
3 | #ifdef __OBJC__
4 | @import UIKit;
5 | @import Foundation;
6 | #endif
7 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/BDBOAuth1ManagerDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/Podfile:
--------------------------------------------------------------------------------
1 | source 'https://github.com/CocoaPods/Specs.git'
2 |
3 | platform :ios, '7.0'
4 |
5 | link_with 'Twitter Demo', 'Flickr Demo'
6 |
7 | pod 'AFNetworking/UIKit', '~> 3.0.0'
8 | pod 'BBlock/UIKit', '~> 1.2.0'
9 | pod 'BDBOAuth1Manager', :path => '../'
10 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/BDBOAuth1ManagerDemo.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/BDBOAuth1Manager.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = 'BDBOAuth1Manager'
3 | s.version = '2.0.0'
4 | s.license = 'MIT'
5 | s.summary = 'AFNetworking 2.0-compatible replacement for AFOAuth1Client.'
6 | s.homepage = 'https://github.com/bdbergeron/BDBOAuth1Manager'
7 | s.social_media_url = 'https://twitter.com/bradbergeron'
8 | s.authors = { 'Bradley David Bergeron' => 'brad@bradbergeron.com' }
9 | s.source = { :git => 'https://github.com/bdbergeron/BDBOAuth1Manager.git', :tag => s.version.to_s }
10 | s.requires_arc = true
11 |
12 | s.ios.deployment_target = '7.0'
13 | s.osx.deployment_target = '10.9'
14 |
15 | s.source_files = 'BDBOAuth1Manager/**/*.{h,m}'
16 |
17 | s.dependency 'AFNetworking/NSURLSession', '~> 3.0.0'
18 | end
19 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/Flickr Demo/Resources/Flickr.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "29x29",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "40x40",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "40x40",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "60x60",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "60x60",
31 | "scale" : "3x"
32 | }
33 | ],
34 | "info" : {
35 | "version" : 1,
36 | "author" : "xcode"
37 | }
38 | }
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/Twitter Demo/Resources/Twitter.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "29x29",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "40x40",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "40x40",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "60x60",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "60x60",
31 | "scale" : "3x"
32 | }
33 | ],
34 | "info" : {
35 | "version" : 1,
36 | "author" : "xcode"
37 | }
38 | }
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - AFNetworking/NSURLSession (3.0.1):
3 | - AFNetworking/Reachability
4 | - AFNetworking/Security
5 | - AFNetworking/Serialization
6 | - AFNetworking/Reachability (3.0.1)
7 | - AFNetworking/Security (3.0.1)
8 | - AFNetworking/Serialization (3.0.1)
9 | - AFNetworking/UIKit (3.0.1):
10 | - AFNetworking/NSURLSession
11 | - BBlock/UIKit (1.2.1)
12 | - BDBOAuth1Manager (2.0.0):
13 | - AFNetworking/NSURLSession (~> 3.0.0)
14 |
15 | DEPENDENCIES:
16 | - AFNetworking/UIKit (~> 3.0.0)
17 | - BBlock/UIKit (~> 1.2.0)
18 | - BDBOAuth1Manager (from `../`)
19 |
20 | EXTERNAL SOURCES:
21 | BDBOAuth1Manager:
22 | :path: "../"
23 |
24 | SPEC CHECKSUMS:
25 | AFNetworking: 20d8749e03e45f1e5c046ad0b647e0b07bcdd91f
26 | BBlock: c56d7f72597ffe1634fcdc73836c5c0fed3271be
27 | BDBOAuth1Manager: 92d17d06f8a648602962304cd2f35ae7394fa001
28 |
29 | COCOAPODS: 0.39.0
30 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2013 Bradley David Bergeron
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 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/Flickr Demo/Resources/Launch Screen.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/Twitter Demo/Resources/Launch Screen.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/Flickr Demo/Views/PhotoAlbumLayout.h:
--------------------------------------------------------------------------------
1 | //
2 | // PhotoAlbumLayout.h
3 | //
4 | // Copyright (c) 2014 Bradley David Bergeron
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | // this software and associated documentation files (the "Software"), to deal in
8 | // the Software without restriction, including without limitation the rights to
9 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | // the Software, and to permit persons to whom the Software is furnished to do so,
11 | // subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | @import UIKit;
24 |
25 | #pragma mark -
26 | @interface PhotoAlbumLayout : UICollectionViewFlowLayout
27 |
28 | @end
29 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/Flickr Demo/Views/PhotoAlbumHeaderView.m:
--------------------------------------------------------------------------------
1 | //
2 | // PhotoAlbumHeaderView.m
3 | //
4 | // Copyright (c) 2014 Bradley David Bergeron
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | // this software and associated documentation files (the "Software"), to deal in
8 | // the Software without restriction, including without limitation the rights to
9 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | // the Software, and to permit persons to whom the Software is furnished to do so,
11 | // subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | #import "PhotoAlbumHeaderView.h"
24 |
25 | #pragma mark -
26 | @implementation PhotoAlbumHeaderView
27 |
28 | @end
29 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/Flickr Demo/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | //
4 | // Copyright (c) 2014 Bradley David Bergeron
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | // this software and associated documentation files (the "Software"), to deal in
8 | // the Software without restriction, including without limitation the rights to
9 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | // the Software, and to permit persons to whom the Software is furnished to do so,
11 | // subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | @import UIKit;
24 |
25 | #pragma mark -
26 | @interface AppDelegate : UIResponder
27 |
28 |
29 | @property (strong, nonatomic) UIWindow *window;
30 |
31 | @end
32 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/Twitter Demo/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | //
4 | // Copyright (c) 2014 Bradley David Bergeron
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | // this software and associated documentation files (the "Software"), to deal in
8 | // the Software without restriction, including without limitation the rights to
9 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | // the Software, and to permit persons to whom the Software is furnished to do so,
11 | // subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | @import UIKit;
24 |
25 | #pragma mark -
26 | @interface AppDelegate : UIResponder
27 |
28 |
29 | @property (strong, nonatomic) UIWindow *window;
30 |
31 | @end
32 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/Twitter Demo/View Controllers/TweetsViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // TweetsViewController.h
3 | //
4 | // Copyright (c) 2014 Bradley David Bergeron
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | // this software and associated documentation files (the "Software"), to deal in
8 | // the Software without restriction, including without limitation the rights to
9 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | // the Software, and to permit persons to whom the Software is furnished to do so,
11 | // subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | @import UIKit;
24 |
25 | #pragma mark -
26 | @interface TweetsViewController : UITableViewController
27 |
28 |
29 | @end
30 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/Flickr Demo/Supporting Files/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | //
4 | // Copyright (c) 2014 Bradley David Bergeron
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | // this software and associated documentation files (the "Software"), to deal in
8 | // the Software without restriction, including without limitation the rights to
9 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | // the Software, and to permit persons to whom the Software is furnished to do so,
11 | // subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | @import UIKit;
24 |
25 | #import "AppDelegate.h"
26 |
27 | int main(int argc, char *argv[])
28 | {
29 | @autoreleasepool {
30 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/Twitter Demo/Supporting Files/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | //
4 | // Copyright (c) 2014 Bradley David Bergeron
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | // this software and associated documentation files (the "Software"), to deal in
8 | // the Software without restriction, including without limitation the rights to
9 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | // the Software, and to permit persons to whom the Software is furnished to do so,
11 | // subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | @import UIKit;
24 |
25 | #import "AppDelegate.h"
26 |
27 | int main(int argc, char *argv[])
28 | {
29 | @autoreleasepool {
30 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/Flickr Demo/Views/PhotoAlbumCell.h:
--------------------------------------------------------------------------------
1 | //
2 | // PhotoAlbumCell.h
3 | //
4 | // Copyright (c) 2014 Bradley David Bergeron
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | // this software and associated documentation files (the "Software"), to deal in
8 | // the Software without restriction, including without limitation the rights to
9 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | // the Software, and to permit persons to whom the Software is furnished to do so,
11 | // subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | @import UIKit;
24 |
25 | #pragma mark -
26 | @interface PhotoAlbumCell : UICollectionViewCell
27 |
28 | @property (nonatomic) UIActivityIndicatorView *activityIndicator;
29 | @property (nonatomic) UIImageView *imageView;
30 |
31 | @end
32 |
33 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/Flickr Demo/View Controllers/PhotosViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // PhotosViewController.h
3 | //
4 | // Copyright (c) 2014 Bradley David Bergeron
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | // this software and associated documentation files (the "Software"), to deal in
8 | // the Software without restriction, including without limitation the rights to
9 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | // the Software, and to permit persons to whom the Software is furnished to do so,
11 | // subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | @import UIKit;
24 |
25 | #pragma mark -
26 | @interface PhotosViewController : UICollectionViewController
27 |
29 |
30 | - (void)loadImages;
31 |
32 | @end
33 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/Flickr Demo/Views/PhotoAlbumHeaderView.h:
--------------------------------------------------------------------------------
1 | //
2 | // PhotoAlbumHeaderView.h
3 | //
4 | // Copyright (c) 2014 Bradley David Bergeron
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | // this software and associated documentation files (the "Software"), to deal in
8 | // the Software without restriction, including without limitation the rights to
9 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | // the Software, and to permit persons to whom the Software is furnished to do so,
11 | // subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | @import UIKit;
24 |
25 | #pragma mark -
26 | @interface PhotoAlbumHeaderView : UICollectionReusableView
27 |
28 | @property (weak, nonatomic) IBOutlet UIView *backgroundView;
29 | @property (weak, nonatomic) IBOutlet UILabel *albumTitleLabel;
30 | @property (weak, nonatomic) IBOutlet UILabel *photoCountLabel;
31 |
32 | @end
33 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/Twitter Demo/Views/TweetCell.h:
--------------------------------------------------------------------------------
1 | //
2 | // TweetCell.h
3 | //
4 | // Copyright (c) 2014 Bradley David Bergeron
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | // this software and associated documentation files (the "Software"), to deal in
8 | // the Software without restriction, including without limitation the rights to
9 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | // the Software, and to permit persons to whom the Software is furnished to do so,
11 | // subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | @import UIKit;
24 |
25 | @interface TweetCell : UITableViewCell
26 |
27 | @property (weak, nonatomic) IBOutlet UIImageView *userImageView;
28 | @property (weak, nonatomic) IBOutlet UILabel *userNameLabel;
29 | @property (weak, nonatomic) IBOutlet UILabel *userScreenNameLabel;
30 | @property (weak, nonatomic) IBOutlet UILabel *tweetLabel;
31 |
32 | @end
33 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by https://www.gitignore.io/api/osx,objective-c
2 |
3 | ### OSX ###
4 | .DS_Store
5 | .AppleDouble
6 | .LSOverride
7 |
8 | # Icon must end with two \r
9 | Icon
10 |
11 |
12 | # Thumbnails
13 | ._*
14 |
15 | # Files that might appear in the root of a volume
16 | .DocumentRevisions-V100
17 | .fseventsd
18 | .Spotlight-V100
19 | .TemporaryItems
20 | .Trashes
21 | .VolumeIcon.icns
22 |
23 | # Directories potentially created on remote AFP share
24 | .AppleDB
25 | .AppleDesktop
26 | Network Trash Folder
27 | Temporary Items
28 | .apdisk
29 |
30 |
31 | ### Objective-C ###
32 | # Xcode
33 | #
34 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
35 |
36 | ## Build generated
37 | build/
38 | DerivedData
39 |
40 | ## Various settings
41 | *.pbxuser
42 | !default.pbxuser
43 | *.mode1v3
44 | !default.mode1v3
45 | *.mode2v3
46 | !default.mode2v3
47 | *.perspectivev3
48 | !default.perspectivev3
49 | xcuserdata
50 |
51 | ## Other
52 | *.xccheckout
53 | *.moved-aside
54 | *.xcuserstate
55 | *.xcscmblueprint
56 |
57 | ## Obj-C/Swift specific
58 | *.hmap
59 | *.ipa
60 |
61 | # CocoaPods
62 | #
63 | # We recommend against adding the Pods directory to your .gitignore. However
64 | # you should judge for yourself, the pros and cons are mentioned at:
65 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
66 | #
67 | Pods/
68 |
69 | # Carthage
70 | #
71 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
72 | Carthage/Checkouts
73 |
74 | Carthage/Build
75 |
76 | ### Objective-C Patch ###
77 | *.xcscmblueprint
78 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/Twitter Demo/Twitter/BDBTweet.h:
--------------------------------------------------------------------------------
1 | //
2 | // BDBTweet.h
3 | //
4 | // Copyright (c) 2014 Bradley David Bergeron
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | // this software and associated documentation files (the "Software"), to deal in
8 | // the Software without restriction, including without limitation the rights to
9 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | // the Software, and to permit persons to whom the Software is furnished to do so,
11 | // subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | @import Foundation;
24 |
25 | #pragma mark -
26 | @interface BDBTweet : NSObject
27 |
28 | @property (nonatomic, copy, readonly) NSURL *userImageURL;
29 | @property (nonatomic, copy, readonly) NSString *userName;
30 | @property (nonatomic, copy, readonly) NSString *userScreenName;
31 |
32 | @property (nonatomic, copy, readonly) NSString *tweetText;
33 |
34 | - (id)initWithDictionary:(NSDictionary *)tweetInfo;
35 |
36 | @end
37 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/Flickr Demo/Flickr/BDBFlickrPhoto.h:
--------------------------------------------------------------------------------
1 | //
2 | // BDBFlickrPhoto.h
3 | //
4 | // Copyright (c) 2014 Bradley David Bergeron
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | // this software and associated documentation files (the "Software"), to deal in
8 | // the Software without restriction, including without limitation the rights to
9 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | // the Software, and to permit persons to whom the Software is furnished to do so,
11 | // subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | @import Foundation;
24 |
25 | #pragma mark -
26 | @interface BDBFlickrPhoto : NSObject
27 |
28 | @property (nonatomic, copy, readonly) NSString *photoId;
29 | @property (nonatomic, copy, readonly) NSString *title;
30 |
31 | @property (nonatomic, readonly) NSURL *thumbnailURL;
32 | @property (nonatomic, readonly) NSURL *originalURL;
33 |
34 | - (id)initWithDictionary:(NSDictionary *)photoInfo;
35 |
36 | - (BOOL)isEqualToPhoto:(BDBFlickrPhoto *)photo;
37 |
38 | @end
39 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/Flickr Demo/Flickr/BDBFlickrPhotoset.h:
--------------------------------------------------------------------------------
1 | //
2 | // BDBFlickrPhotoset.h
3 | //
4 | // Copyright (c) 2014 Bradley David Bergeron
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | // this software and associated documentation files (the "Software"), to deal in
8 | // the Software without restriction, including without limitation the rights to
9 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | // the Software, and to permit persons to whom the Software is furnished to do so,
11 | // subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | @import Foundation;
24 |
25 | #pragma mark -
26 | @interface BDBFlickrPhotoset : NSObject
27 |
28 | @property (nonatomic, copy, readonly) NSString *setId;
29 | @property (nonatomic, copy, readonly) NSString *title;
30 |
31 | @property (nonatomic, readonly) NSDate *dateCreated;
32 | @property (nonatomic, readonly) NSDate *dateUpdated;
33 |
34 | @property (nonatomic) NSArray *photos;
35 |
36 | - (id)initWithDictionary:(NSDictionary *)photosetInfo;
37 |
38 | - (BOOL)isEqualToPhotoset:(BDBFlickrPhotoset *)photoset;
39 |
40 | @end
41 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/BDBOAuth1ManagerDemo.xcodeproj/project.xcworkspace/xcshareddata/BDBOAuth1RequestSerializerDemo.xccheckout:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDESourceControlProjectFavoriteDictionaryKey
6 |
7 | IDESourceControlProjectIdentifier
8 | C8B715F3-1A5A-46CD-ABD1-0BA9B947B8EE
9 | IDESourceControlProjectName
10 | BDBOAuth1RequestSerializerDemo
11 | IDESourceControlProjectOriginsDictionary
12 |
13 | 1E3A782D-1DB6-42FF-BBD1-DFF55747BCDF
14 | ssh://github.com/bdbergeron/BDBOAuth1RequestSerializer.git
15 |
16 | IDESourceControlProjectPath
17 | BDBOAuth1RequestSerializerDemo/BDBOAuth1RequestSerializerDemo.xcodeproj/project.xcworkspace
18 | IDESourceControlProjectRelativeInstallPathDictionary
19 |
20 | 1E3A782D-1DB6-42FF-BBD1-DFF55747BCDF
21 | ../../..
22 |
23 | IDESourceControlProjectURL
24 | ssh://github.com/bdbergeron/BDBOAuth1RequestSerializer.git
25 | IDESourceControlProjectVersion
26 | 110
27 | IDESourceControlProjectWCCIdentifier
28 | 1E3A782D-1DB6-42FF-BBD1-DFF55747BCDF
29 | IDESourceControlProjectWCConfigurations
30 |
31 |
32 | IDESourceControlRepositoryExtensionIdentifierKey
33 | public.vcs.git
34 | IDESourceControlWCCIdentifierKey
35 | 1E3A782D-1DB6-42FF-BBD1-DFF55747BCDF
36 | IDESourceControlWCCName
37 | BDBOAuth1RequestSerializer
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/Flickr Demo/Supporting Files/Flickr Demo-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | ${PRODUCT_NAME}
9 | CFBundleExecutable
10 | ${EXECUTABLE_NAME}
11 | CFBundleIcons
12 |
13 | CFBundleIcons~ipad
14 |
15 | CFBundleIdentifier
16 | $(PRODUCT_BUNDLE_IDENTIFIER)
17 | CFBundleInfoDictionaryVersion
18 | 6.0
19 | CFBundleName
20 | ${PRODUCT_NAME}
21 | CFBundlePackageType
22 | APPL
23 | CFBundleShortVersionString
24 | 1.5.0
25 | CFBundleSignature
26 | ????
27 | CFBundleURLTypes
28 |
29 |
30 | CFBundleTypeRole
31 | Editor
32 | CFBundleURLName
33 | com.bradbergeron.bdboauth1demo.flickr
34 | CFBundleURLSchemes
35 |
36 | bdboauth1demo-flickr
37 |
38 |
39 |
40 | CFBundleVersion
41 | 1
42 | LSRequiresIPhoneOS
43 |
44 | UILaunchStoryboardName
45 | Launch Screen
46 | UIRequiredDeviceCapabilities
47 |
48 | armv7
49 |
50 | UISupportedInterfaceOrientations
51 |
52 | UIInterfaceOrientationPortrait
53 |
54 | UISupportedInterfaceOrientations~ipad
55 |
56 | UIInterfaceOrientationPortrait
57 | UIInterfaceOrientationPortraitUpsideDown
58 | UIInterfaceOrientationLandscapeLeft
59 | UIInterfaceOrientationLandscapeRight
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/Twitter Demo/Views/TweetCell.m:
--------------------------------------------------------------------------------
1 | //
2 | // TweetCell.m
3 | //
4 | // Copyright (c) 2014 Bradley David Bergeron
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | // this software and associated documentation files (the "Software"), to deal in
8 | // the Software without restriction, including without limitation the rights to
9 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | // the Software, and to permit persons to whom the Software is furnished to do so,
11 | // subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | #import "TweetCell.h"
24 |
25 | #pragma mark -
26 | @implementation TweetCell
27 |
28 | - (void)awakeFromNib {
29 | self.userImageView.layer.masksToBounds = YES;
30 |
31 | if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
32 | self.userImageView.layer.cornerRadius = self.userImageView.frame.size.width / 2.0f;
33 | } else {
34 | self.userImageView.layer.cornerRadius = 5.0f;
35 | }
36 |
37 | self.userImageView.layer.rasterizationScale = [[UIScreen mainScreen] scale];
38 | self.userImageView.layer.shouldRasterize = YES;
39 | self.userImageView.clipsToBounds = YES;
40 |
41 | [self prepareForReuse];
42 | }
43 |
44 | - (void)prepareForReuse {
45 | self.userImageView.image = nil;
46 | self.userNameLabel.text = @"";
47 | self.userScreenNameLabel.text = @"@";
48 | self.tweetLabel.text = nil;
49 | }
50 |
51 | @end
52 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/Twitter Demo/Twitter/BDBTwitterClient.h:
--------------------------------------------------------------------------------
1 | //
2 | // BDBTwitterClient.h
3 | //
4 | // Copyright (c) 2014 Bradley David Bergeron
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | // this software and associated documentation files (the "Software"), to deal in
8 | // the Software without restriction, including without limitation the rights to
9 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | // the Software, and to permit persons to whom the Software is furnished to do so,
11 | // subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | @import Foundation;
24 |
25 |
26 | FOUNDATION_EXPORT NSString * const BDBTwitterClientErrorDomain;
27 |
28 | FOUNDATION_EXPORT NSString * const BDBTwitterClientDidLogInNotification;
29 | FOUNDATION_EXPORT NSString * const BDBTwitterClientDidLogOutNotification;
30 |
31 |
32 | #pragma mark -
33 | @interface BDBTwitterClient : NSObject
34 |
35 | @property (nonatomic, assign, readonly, getter = isAuthorized) BOOL authorized;
36 |
37 | #pragma mark Initialization
38 | + (instancetype)createWithConsumerKey:(NSString *)apiKey secret:(NSString *)secret;
39 | + (instancetype)sharedClient;
40 |
41 | #pragma mark Authorization
42 | - (BOOL)isAuthorized;
43 | + (BOOL)isAuthorizationCallbackURL:(NSURL *)url;
44 | - (void)authorize;
45 | - (BOOL)handleAuthorizationCallbackURL:(NSURL *)url;
46 | - (void)deauthorize;
47 |
48 | #pragma mark Tweets
49 | - (void)loadTimelineWithCompletion:(void (^)(NSArray *tweets, NSError *error))completion;
50 |
51 | @end
52 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/Flickr Demo/Views/PhotoAlbumCell.m:
--------------------------------------------------------------------------------
1 | //
2 | // PhotoAlbumCell.m
3 | //
4 | // Copyright (c) 2014 Bradley David Bergeron
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | // this software and associated documentation files (the "Software"), to deal in
8 | // the Software without restriction, including without limitation the rights to
9 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | // the Software, and to permit persons to whom the Software is furnished to do so,
11 | // subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | @import QuartzCore;
24 |
25 | #import "PhotoAlbumCell.h"
26 |
27 | #pragma mark -
28 | @implementation PhotoAlbumCell
29 |
30 | - (id)initWithFrame:(CGRect)frame {
31 | self = [super initWithFrame:frame];
32 |
33 | if (self) {
34 | self.contentView.clipsToBounds = YES;
35 |
36 | _activityIndicator = [UIActivityIndicatorView new];
37 | _activityIndicator.center = self.contentView.center;
38 | _activityIndicator.hidesWhenStopped = YES;
39 | [self.contentView addSubview:_activityIndicator];
40 |
41 | _imageView = [[UIImageView alloc] initWithFrame:self.bounds];
42 | _imageView.contentMode = UIViewContentModeScaleAspectFill;
43 | _imageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
44 | [self.contentView addSubview:_imageView];
45 | }
46 |
47 | return self;
48 | }
49 |
50 | - (void)prepareForReuse {
51 | self.imageView.image = nil;
52 | }
53 |
54 | @end
55 |
--------------------------------------------------------------------------------
/BDBOAuth1Manager/Categories/NSDictionary+BDBOAuth1Manager.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSDictionary+BDBOAuth1Manager.h
3 | //
4 | // Copyright (c) 2013-2015 Bradley David Bergeron
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | // this software and associated documentation files (the "Software"), to deal in
8 | // the Software without restriction, including without limitation the rights to
9 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | // the Software, and to permit persons to whom the Software is furnished to do so,
11 | // subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | #import
24 |
25 |
26 | /**
27 | * Additions to NSDictionary.
28 | */
29 | #pragma mark -
30 | @interface NSDictionary (BDBOAuth1Manager)
31 |
32 | /**
33 | * ---------------------------------------------------------------------------------------
34 | * @name Query String
35 | * ---------------------------------------------------------------------------------------
36 | */
37 | #pragma mark Query String
38 |
39 | /**
40 | * Create a dictionary representation of a URL query string.
41 | *
42 | * @param queryString URL query string.
43 | *
44 | * @return Dictionary containing each key-value pair in the query string.
45 | */
46 | + (instancetype)bdb_dictionaryFromQueryString:(NSString *)queryString;
47 |
48 | /**
49 | * Return each key-value pair in the dictionary as a URL query string.
50 | *
51 | * @return URL query string reperesntation of this dictionary.
52 | */
53 | - (NSString *)bdb_queryStringRepresentation;
54 |
55 | @end
56 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/BDBOAuth1ManagerDemo.xcodeproj/project.xcworkspace/xcshareddata/BDBOAuth1Demo.xccheckout:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDESourceControlProjectFavoriteDictionaryKey
6 |
7 | IDESourceControlProjectIdentifier
8 | EE2251DE-8449-442E-8CE9-62DFEE6C1DAB
9 | IDESourceControlProjectName
10 | BDBOAuth1Demo
11 | IDESourceControlProjectOriginsDictionary
12 |
13 | 5D37423A-8071-40AB-A640-633563A4D5C2
14 | https://github.com/AFNetworking/AFNetworking.git
15 | 872D3772-97C4-43E5-9568-0F489A517944
16 | ssh://github.com/bdbergeron/BDBOAuth1RequestSerializer.git
17 |
18 | IDESourceControlProjectPath
19 | BDBOAuth1Demo/BDBOAuth1Demo.xcodeproj/project.xcworkspace
20 | IDESourceControlProjectRelativeInstallPathDictionary
21 |
22 | 5D37423A-8071-40AB-A640-633563A4D5C2
23 | ../../../AFNetworking
24 | 872D3772-97C4-43E5-9568-0F489A517944
25 | ../../..
26 |
27 | IDESourceControlProjectURL
28 | ssh://github.com/bdbergeron/BDBOAuth1RequestSerializer.git
29 | IDESourceControlProjectVersion
30 | 110
31 | IDESourceControlProjectWCCIdentifier
32 | 872D3772-97C4-43E5-9568-0F489A517944
33 | IDESourceControlProjectWCConfigurations
34 |
35 |
36 | IDESourceControlRepositoryExtensionIdentifierKey
37 | public.vcs.git
38 | IDESourceControlWCCIdentifierKey
39 | 5D37423A-8071-40AB-A640-633563A4D5C2
40 | IDESourceControlWCCName
41 | AFNetworking
42 |
43 |
44 | IDESourceControlRepositoryExtensionIdentifierKey
45 | public.vcs.git
46 | IDESourceControlWCCIdentifierKey
47 | 872D3772-97C4-43E5-9568-0F489A517944
48 | IDESourceControlWCCName
49 | BDBOAuth1
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/BDBOAuth1ManagerDemo.xcodeproj/project.xcworkspace/xcshareddata/BDBOAuth1Manager.xccheckout:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDESourceControlProjectFavoriteDictionaryKey
6 |
7 | IDESourceControlProjectIdentifier
8 | E5F58138-0E32-4824-83F4-7AD44E7BDBD3
9 | IDESourceControlProjectName
10 | BDBOAuth1Manager
11 | IDESourceControlProjectOriginsDictionary
12 |
13 | 81432A26-BA80-4ABE-B240-45635B2D75C8
14 | ssh://github.com/bdbergeron/BDBOAuth1RequestSerializer.git
15 | C458A07C-16C5-464E-A45A-3F8F346FD564
16 | https://github.com/AFNetworking/AFNetworking.git
17 |
18 | IDESourceControlProjectPath
19 | BDBOAuth1ManagerDemo/BDBOAuth1Manager.xcodeproj/project.xcworkspace
20 | IDESourceControlProjectRelativeInstallPathDictionary
21 |
22 | 81432A26-BA80-4ABE-B240-45635B2D75C8
23 | ../../..
24 | C458A07C-16C5-464E-A45A-3F8F346FD564
25 | ../../../AFNetworking
26 |
27 | IDESourceControlProjectURL
28 | ssh://github.com/bdbergeron/BDBOAuth1RequestSerializer.git
29 | IDESourceControlProjectVersion
30 | 110
31 | IDESourceControlProjectWCCIdentifier
32 | 81432A26-BA80-4ABE-B240-45635B2D75C8
33 | IDESourceControlProjectWCConfigurations
34 |
35 |
36 | IDESourceControlRepositoryExtensionIdentifierKey
37 | public.vcs.git
38 | IDESourceControlWCCIdentifierKey
39 | C458A07C-16C5-464E-A45A-3F8F346FD564
40 | IDESourceControlWCCName
41 | AFNetworking
42 |
43 |
44 | IDESourceControlRepositoryExtensionIdentifierKey
45 | public.vcs.git
46 | IDESourceControlWCCIdentifierKey
47 | 81432A26-BA80-4ABE-B240-45635B2D75C8
48 | IDESourceControlWCCName
49 | BDBOAuth1Manager
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/Twitter Demo/Supporting Files/Twitter Demo-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | ${PRODUCT_NAME}
9 | CFBundleExecutable
10 | ${EXECUTABLE_NAME}
11 | CFBundleIcons
12 |
13 | CFBundleIcons~ipad
14 |
15 | CFBundleIdentifier
16 | $(PRODUCT_BUNDLE_IDENTIFIER)
17 | CFBundleInfoDictionaryVersion
18 | 6.0
19 | CFBundleName
20 | ${PRODUCT_NAME}
21 | CFBundlePackageType
22 | APPL
23 | CFBundleShortVersionString
24 | 1.5.0
25 | CFBundleSignature
26 | ????
27 | CFBundleURLTypes
28 |
29 |
30 | CFBundleTypeRole
31 | Editor
32 | CFBundleURLName
33 | com.bradbergeron.bdboauth1demo.twitter
34 | CFBundleURLSchemes
35 |
36 | bdboauth1demo-twitter
37 |
38 |
39 |
40 | CFBundleVersion
41 | 1
42 | LSRequiresIPhoneOS
43 |
44 | NSAppTransportSecurity
45 |
46 | NSExceptionDomains
47 |
48 | pbs.twimg.com
49 |
50 | NSThirdPartyExceptionAllowsInsecureHTTPLoads
51 |
52 |
53 |
54 |
55 | UILaunchStoryboardName
56 | Launch Screen
57 | UIRequiredDeviceCapabilities
58 |
59 | armv7
60 |
61 | UISupportedInterfaceOrientations
62 |
63 | UIInterfaceOrientationPortrait
64 |
65 | UISupportedInterfaceOrientations~ipad
66 |
67 | UIInterfaceOrientationPortrait
68 | UIInterfaceOrientationPortraitUpsideDown
69 | UIInterfaceOrientationLandscapeLeft
70 | UIInterfaceOrientationLandscapeRight
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/Flickr Demo/Flickr/BDBFlickrClient.h:
--------------------------------------------------------------------------------
1 | //
2 | // BDBFlickrClient.h
3 | //
4 | // Copyright (c) 2014 Bradley David Bergeron
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | // this software and associated documentation files (the "Software"), to deal in
8 | // the Software without restriction, including without limitation the rights to
9 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | // the Software, and to permit persons to whom the Software is furnished to do so,
11 | // subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | @import Foundation;
24 |
25 | @class BDBFlickrPhotoset;
26 |
27 |
28 | FOUNDATION_EXPORT NSString * const BDBFlickrClientErrorDomain;
29 |
30 | FOUNDATION_EXPORT NSString * const BDBFlickrClientDidLogInNotification;
31 | FOUNDATION_EXPORT NSString * const BDBFlickrClientDidLogOutNotification;
32 |
33 |
34 | #pragma mark -
35 | @interface BDBFlickrClient : NSObject
36 |
37 | @property (nonatomic, assign, readonly, getter = isAuthorized) BOOL authorized;
38 |
39 | #pragma mark Initialization
40 | + (instancetype)createWithAPIKey:(NSString *)apiKey secret:(NSString *)secret;
41 | + (instancetype)sharedClient;
42 |
43 | #pragma mark Authorization
44 | - (BOOL)isAuthorized;
45 | + (BOOL)isAuthorizationCallbackURL:(NSURL *)url;
46 | - (void)authorize;
47 | - (BOOL)handleAuthorizationCallbackURL:(NSURL *)url;
48 | - (void)deauthorize;
49 |
50 | #pragma mark Photosets
51 | - (void)getPhotosetsWithCompletion:(void (^)(NSSet *photosets, NSError *error))completion;
52 |
53 | #pragma mark Photos
54 | - (void)getPhotosInPhotoset:(BDBFlickrPhotoset *)photoset completion:(void (^)(NSArray *photos, NSError *error))completion;
55 |
56 | @end
57 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/Flickr Demo/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | //
4 | // Copyright (c) 2014 Bradley David Bergeron
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | // this software and associated documentation files (the "Software"), to deal in
8 | // the Software without restriction, including without limitation the rights to
9 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | // the Software, and to permit persons to whom the Software is furnished to do so,
11 | // subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | #import "AppDelegate.h"
24 | #import "BDBFlickrClient.h"
25 | #import "PhotosViewController.h"
26 |
27 | #pragma mark -
28 | @implementation AppDelegate
29 |
30 | #pragma mark Application Lifecyle
31 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
32 | // Configure BDBFlickrClient
33 | [BDBFlickrClient createWithAPIKey:@"06f28faf9b97104e367ca32103eab53b" secret:@"fa85fa7972dcea82"];
34 |
35 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
36 | self.window.backgroundColor = [UIColor whiteColor];
37 | self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:[PhotosViewController new]];
38 |
39 | [self.window makeKeyAndVisible];
40 |
41 | return YES;
42 | }
43 |
44 | - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
45 | if ([BDBFlickrClient isAuthorizationCallbackURL:url]) {
46 | return [[BDBFlickrClient sharedClient] handleAuthorizationCallbackURL:url];
47 | }
48 |
49 | return NO;
50 | }
51 |
52 | @end
53 |
--------------------------------------------------------------------------------
/BDBOAuth1Manager/Categories/NSDictionary+BDBOAuth1Manager.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSDictionary+BDBOAuth1Manager.m
3 | //
4 | // Copyright (c) 2013-2015 Bradley David Bergeron
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | // this software and associated documentation files (the "Software"), to deal in
8 | // the Software without restriction, including without limitation the rights to
9 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | // the Software, and to permit persons to whom the Software is furnished to do so,
11 | // subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | #import "NSDictionary+BDBOAuth1Manager.h"
24 | #import "NSString+BDBOAuth1Manager.h"
25 |
26 |
27 | #pragma mark -
28 | @implementation NSDictionary (BDBOAuth1Manager)
29 |
30 | #pragma mark Query String
31 | + (instancetype)bdb_dictionaryFromQueryString:(NSString *)queryString {
32 | NSArray *components = [queryString componentsSeparatedByString:@"&"];
33 | NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
34 |
35 | for (NSString *component in components) {
36 | NSArray *keyValue = [component componentsSeparatedByString:@"="];
37 | dictionary[[keyValue[0] bdb_URLDecode]] = [keyValue[1] bdb_URLDecode];
38 | }
39 |
40 | return [[[self class] alloc] initWithDictionary:dictionary];
41 | }
42 |
43 | - (NSString *)bdb_queryStringRepresentation {
44 | NSMutableArray *paramArray = [NSMutableArray array];
45 |
46 | [self enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
47 | NSString *param = [NSString stringWithFormat:@"%@=%@", [key bdb_URLEncode], [obj bdb_URLEncode]];
48 | [paramArray addObject:param];
49 | }];
50 |
51 | return [paramArray componentsJoinedByString:@"&"];
52 | }
53 |
54 | @end
55 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/Twitter Demo/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | //
4 | // Copyright (c) 2014 Bradley David Bergeron
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | // this software and associated documentation files (the "Software"), to deal in
8 | // the Software without restriction, including without limitation the rights to
9 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | // the Software, and to permit persons to whom the Software is furnished to do so,
11 | // subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | #import "AppDelegate.h"
24 | #import "Twitter/BDBTwitterClient.h"
25 | #import "View Controllers/TweetsViewController.h"
26 |
27 | #pragma mark -
28 | @implementation AppDelegate
29 |
30 | #pragma mark Application Lifecyle
31 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
32 | // Configure BDBTwitterClient
33 | [BDBTwitterClient createWithConsumerKey:@"wrou647dSAp3OinHmsVKYw" secret:@"Y1H5mOBxHMIDkW6KMeiJAd4G0VFTSA2GdVKq5SEdB4"];
34 |
35 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
36 | self.window.backgroundColor = [UIColor whiteColor];
37 | self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:[TweetsViewController new]];
38 |
39 | [self.window makeKeyAndVisible];
40 |
41 | return YES;
42 | }
43 |
44 | - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
45 | if ([BDBTwitterClient isAuthorizationCallbackURL:url]) {
46 | return [[BDBTwitterClient sharedClient] handleAuthorizationCallbackURL:url];
47 | }
48 |
49 | return NO;
50 | }
51 |
52 | @end
53 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/Twitter Demo/Twitter/BDBTweet.m:
--------------------------------------------------------------------------------
1 | //
2 | // BDBTweet.m
3 | //
4 | // Copyright (c) 2014 Bradley David Bergeron
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | // this software and associated documentation files (the "Software"), to deal in
8 | // the Software without restriction, including without limitation the rights to
9 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | // the Software, and to permit persons to whom the Software is furnished to do so,
11 | // subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | #import "BDBTweet.h"
24 |
25 |
26 | static NSString * const kBDBTweetTweetTextName = @"text";
27 | static NSString * const kBDBTweetUserInfoName = @"user";
28 | static NSString * const kBDBTweetUserImageURLName = @"profile_image_url";
29 | static NSString * const kBDBTweetUserNameName = @"name";
30 | static NSString * const kBDBTweetUserScreenNameName = @"screen_name";
31 |
32 | #pragma mark -
33 | @implementation BDBTweet
34 |
35 | - (id)initWithDictionary:(NSDictionary *)tweetInfo {
36 | self = [super init];
37 |
38 | if (self) {
39 | _tweetText = [tweetInfo[kBDBTweetTweetTextName] copy];
40 |
41 | NSDictionary *userInfo = tweetInfo[kBDBTweetUserInfoName];
42 |
43 | if (userInfo[kBDBTweetUserImageURLName]) {
44 | NSString *userImageURLString = [userInfo[kBDBTweetUserImageURLName] stringByReplacingOccurrencesOfString:@"_normal"
45 | withString:@"_bigger"];
46 | _userImageURL = [NSURL URLWithString:userImageURLString];
47 | }
48 |
49 | _userName = userInfo[kBDBTweetUserNameName];
50 | _userScreenName = userInfo[kBDBTweetUserScreenNameName];
51 | }
52 |
53 | return self;
54 | }
55 |
56 | @end
57 |
--------------------------------------------------------------------------------
/BDBOAuth1Manager/Categories/NSString+BDBOAuth1Manager.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSString+BDBOAuth1Manager.h
3 | //
4 | // Copyright (c) 2013-2015 Bradley David Bergeron
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | // this software and associated documentation files (the "Software"), to deal in
8 | // the Software without restriction, including without limitation the rights to
9 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | // the Software, and to permit persons to whom the Software is furnished to do so,
11 | // subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | #import
24 |
25 |
26 | /**
27 | * Additions to NSString.
28 | */
29 | #pragma mark -
30 | @interface NSString (BDBOAuth1Manager)
31 |
32 | /**
33 | * ---------------------------------------------------------------------------------------
34 | * @name URL Encoding/Decoding
35 | * ---------------------------------------------------------------------------------------
36 | */
37 | #pragma mark URL Encoding/Decoding
38 |
39 | /**
40 | * Returns a properly URL-decoded representation of the given string.
41 | *
42 | * See http://cybersam.com/ios-dev/proper-url-percent-encoding-in-ios for more details.
43 | *
44 | * @return URL-decoded string
45 | */
46 | - (NSString *)bdb_URLDecode;
47 |
48 | /**
49 | * Returns a properly URL-encoded representation of the given string.
50 | *
51 | * See http://cybersam.com/ios-dev/proper-url-percent-encoding-in-ios for more details.
52 | *
53 | * @return URL-encoded string
54 | */
55 |
56 | - (NSString *)bdb_URLEncode;
57 |
58 |
59 | /**
60 | * Returns the given string with the '/' and '?' characters URL-encoded.
61 | *
62 | * AFNetworking 2.6 no longer encodes '/' and '?' characters. See https://github.com/AFNetworking/AFNetworking/pull/2908
63 | *
64 | * @return '?' and '/' URL-encoded string
65 | */
66 | - (NSString *)bdb_URLEncodeSlashesAndQuestionMarks;
67 |
68 | @end
69 |
--------------------------------------------------------------------------------
/BDBOAuth1Manager/Categories/NSString+BDBOAuth1Manager.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSString+BDBOAuth1Manager.m
3 | //
4 | // Copyright (c) 2013-2015 Bradley David Bergeron
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | // this software and associated documentation files (the "Software"), to deal in
8 | // the Software without restriction, including without limitation the rights to
9 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | // the Software, and to permit persons to whom the Software is furnished to do so,
11 | // subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | #import
24 |
25 | #import "NSString+BDBOAuth1Manager.h"
26 |
27 |
28 | #pragma mark -
29 | @implementation NSString (BDBOAuth1Manager)
30 |
31 | #pragma mark URL Encoding/Decoding
32 | - (NSString *)bdb_URLEncode {
33 | return (__bridge_transfer NSString *)
34 | CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
35 | (__bridge CFStringRef)self,
36 | NULL,
37 | (__bridge CFStringRef)@"!*'\"();:@&=+$,/?%#[] ",
38 | kCFStringEncodingUTF8);
39 | }
40 |
41 | - (NSString *)bdb_URLDecode {
42 | return (__bridge_transfer NSString *)
43 | CFURLCreateStringByReplacingPercentEscapesUsingEncoding(kCFAllocatorDefault,
44 | (__bridge CFStringRef)self,
45 | (__bridge CFStringRef)@"",
46 | kCFStringEncodingUTF8);
47 | }
48 |
49 | - (NSString *)bdb_URLEncodeSlashesAndQuestionMarks {
50 | NSString *selfWithSlashesEscaped = [self stringByReplacingOccurrencesOfString:@"/" withString:@"%2F"];
51 | NSString *selfWithQuestionMarksEscaped = [selfWithSlashesEscaped stringByReplacingOccurrencesOfString:@"?" withString:@"%3F"];
52 | return selfWithQuestionMarksEscaped;
53 | }
54 |
55 | @end
56 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/Flickr Demo/Flickr/BDBFlickrPhoto.m:
--------------------------------------------------------------------------------
1 | //
2 | // BDBFlickrPhoto.m
3 | //
4 | // Copyright (c) 2014 Bradley David Bergeron
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | // this software and associated documentation files (the "Software"), to deal in
8 | // the Software without restriction, including without limitation the rights to
9 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | // the Software, and to permit persons to whom the Software is furnished to do so,
11 | // subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | #import "BDBFlickrPhoto.h"
24 |
25 | #pragma mark -
26 | @implementation BDBFlickrPhoto
27 |
28 | - (id)initWithDictionary:(NSDictionary *)photoInfo {
29 | self = [super init];
30 |
31 | if (self) {
32 | _photoId = [photoInfo[@"id"] copy];
33 | _title = [[photoInfo[@"title"] copy] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
34 |
35 | if (photoInfo[@"url_t"]) {
36 | _thumbnailURL = [NSURL URLWithString:photoInfo[@"url_t"]];
37 | }
38 |
39 | if (photoInfo[@"url_o"]) {
40 | _originalURL = [NSURL URLWithString:photoInfo[@"url_o"]];
41 | }
42 | }
43 |
44 | return self;
45 | }
46 |
47 | #pragma mark Equality
48 | - (BOOL)isEqual:(id)object {
49 | if (object == self) {
50 | return YES;
51 | }
52 |
53 | if (![object isKindOfClass:[BDBFlickrPhoto class]]) {
54 | return NO;
55 | } else {
56 | return [self isEqualToPhoto:(BDBFlickrPhoto *)object];
57 | }
58 | }
59 |
60 | - (BOOL)isEqualToPhoto:(BDBFlickrPhoto *)photo {
61 | if (!photo) {
62 | return NO;
63 | }
64 |
65 | BOOL equalId = (!self.photoId && !photo.photoId) || [self.photoId isEqualToString:photo.photoId];
66 | BOOL equalTitle = (!self.title && !photo.title) || [self.title isEqualToString:photo.title];
67 |
68 | BOOL equalThumbnailURL = (!self.thumbnailURL && !photo.thumbnailURL) || [self.thumbnailURL isEqual:photo.thumbnailURL];
69 | BOOL equalOriginalURL = (!self.originalURL && !photo.originalURL) || [self.originalURL isEqual:photo.originalURL];
70 |
71 | return (equalId && equalTitle && equalThumbnailURL && equalOriginalURL);
72 | }
73 |
74 | - (NSUInteger)hash {
75 | return (self.photoId.hash ^ self.title.hash ^ self.thumbnailURL.hash ^ self.originalURL.hash);
76 | }
77 |
78 | @end
79 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/Flickr Demo/Flickr/BDBFlickrPhotoset.m:
--------------------------------------------------------------------------------
1 | //
2 | // BDBFlickrPhotoset.m
3 | //
4 | // Copyright (c) 2014 Bradley David Bergeron
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | // this software and associated documentation files (the "Software"), to deal in
8 | // the Software without restriction, including without limitation the rights to
9 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | // the Software, and to permit persons to whom the Software is furnished to do so,
11 | // subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | #import "BDBFlickrPhotoset.h"
24 |
25 | #pragma mark -
26 | @implementation BDBFlickrPhotoset
27 |
28 | - (id)initWithDictionary:(NSDictionary *)photosetInfo {
29 | self = [super init];
30 |
31 | if (self) {
32 | _setId = [photosetInfo[@"id"] copy];
33 | _title = [photosetInfo[@"title"][@"_content"] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
34 |
35 | _dateCreated = [NSDate dateWithTimeIntervalSince1970:[photosetInfo[@"date_create"] integerValue]];
36 | _dateUpdated = [NSDate dateWithTimeIntervalSince1970:[photosetInfo[@"date_update"] integerValue]];
37 |
38 | _photos = [NSArray array];
39 | }
40 |
41 | return self;
42 | }
43 |
44 | #pragma mark Equivalency
45 | - (BOOL)isEqual:(id)object {
46 | if (object == self) {
47 | return YES;
48 | }
49 |
50 | if (![object isKindOfClass:[BDBFlickrPhotoset class]]) {
51 | return NO;
52 | } else {
53 | return [self isEqualToPhotoset:(BDBFlickrPhotoset *)object];
54 | }
55 | }
56 |
57 | - (BOOL)isEqualToPhotoset:(BDBFlickrPhotoset *)photoset {
58 | if (!photoset) {
59 | return NO;
60 | }
61 |
62 | BOOL equalId = (!self.setId && !photoset.setId) || [self.setId isEqualToString:photoset.setId];
63 | BOOL equalTitle = (!self.title && !photoset.title) || [self.title isEqualToString:photoset.title];
64 |
65 | BOOL equalDateCreated = [self.dateCreated isEqualToDate:photoset.dateCreated];
66 | BOOL equalDateUpdated = [self.dateUpdated isEqualToDate:photoset.dateUpdated];
67 |
68 | BOOL samePhotos = (!self.photos && !photoset.photos) || [self.photos isEqualToArray:photoset.photos];
69 |
70 | return (equalId && equalTitle && equalDateCreated && equalDateUpdated && samePhotos);
71 | }
72 |
73 | - (NSUInteger)hash {
74 | return (self.setId.hash ^ self.title.hash ^ self.dateCreated.hash ^ self.dateUpdated.hash ^ self.photos.hash);
75 | }
76 |
77 | @end
78 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/Flickr Demo/Views/PhotoAlbumLayout.m:
--------------------------------------------------------------------------------
1 | //
2 | // PhotoAlbumLayout.m
3 | //
4 | // Copyright (c) 2014 Bradley David Bergeron
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | // this software and associated documentation files (the "Software"), to deal in
8 | // the Software without restriction, including without limitation the rights to
9 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | // the Software, and to permit persons to whom the Software is furnished to do so,
11 | // subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 | //
23 | // Modified from http://blog.radi.ws/post/32905838158/sticky-headers-for-uicollectionview-using
24 |
25 | #import "PhotoAlbumLayout.h"
26 |
27 | #pragma mark -
28 | @implementation PhotoAlbumLayout
29 |
30 | - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
31 | NSMutableArray *answer = [[super layoutAttributesForElementsInRect:rect] mutableCopy];
32 |
33 | NSMutableIndexSet *missingSections = [NSMutableIndexSet indexSet];
34 |
35 | for (NSUInteger idx = 0; idx < [answer count]; idx++) {
36 | UICollectionViewLayoutAttributes *layoutAttributes = answer[idx];
37 |
38 | if (layoutAttributes.representedElementCategory == UICollectionElementCategoryCell) {
39 | [missingSections addIndex:layoutAttributes.indexPath.section];
40 | }
41 |
42 | if ([layoutAttributes.representedElementKind isEqualToString:UICollectionElementKindSectionHeader]) {
43 | [answer removeObjectAtIndex:idx];
44 | idx--;
45 | }
46 | }
47 |
48 | [missingSections enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
49 | NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:idx];
50 | UICollectionViewLayoutAttributes *layoutAttributes = [self layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader atIndexPath:indexPath];
51 | [answer addObject:layoutAttributes];
52 | }];
53 |
54 | return answer;
55 | }
56 |
57 | - (UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath {
58 | UICollectionViewLayoutAttributes *attributes = [super layoutAttributesForSupplementaryViewOfKind:kind atIndexPath:indexPath];
59 |
60 | if ([kind isEqualToString:UICollectionElementKindSectionHeader]) {
61 | UICollectionView * const cv = self.collectionView;
62 | CGPoint const contentOffset = cv.contentOffset;
63 | CGPoint nextHeaderOrigin = CGPointMake(INFINITY, INFINITY);
64 |
65 | if (indexPath.section + 1 < [cv numberOfSections]) {
66 | UICollectionViewLayoutAttributes *nextHeaderAttributes = [super layoutAttributesForSupplementaryViewOfKind:kind atIndexPath:[NSIndexPath indexPathForItem:0 inSection:indexPath.section + 1]];
67 | nextHeaderOrigin = nextHeaderAttributes.frame.origin;
68 | }
69 |
70 | CGRect frame = attributes.frame;
71 |
72 | if (self.scrollDirection == UICollectionViewScrollDirectionVertical) {
73 | frame.origin.y = MIN(MAX(contentOffset.y, frame.origin.y), nextHeaderOrigin.y - CGRectGetHeight(frame));
74 | } else {
75 | frame.origin.x = MIN(MAX(contentOffset.x, frame.origin.x), nextHeaderOrigin.x - CGRectGetWidth(frame));
76 | }
77 |
78 | attributes.zIndex = 1024;
79 | attributes.frame = frame;
80 | }
81 |
82 | return attributes;
83 | }
84 |
85 | - (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath {
86 | return [self layoutAttributesForSupplementaryViewOfKind:kind atIndexPath:indexPath];
87 | }
88 |
89 | - (UICollectionViewLayoutAttributes *)finalLayoutAttributesForDisappearingSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath {
90 | return [self layoutAttributesForSupplementaryViewOfKind:kind atIndexPath:indexPath];
91 | }
92 |
93 | - (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBound {
94 | return YES;
95 | }
96 |
97 | @end
98 |
--------------------------------------------------------------------------------
/BDBOAuth1Manager/BDBOAuth1SessionManager.h:
--------------------------------------------------------------------------------
1 | //
2 | // BDBOAuth1SessionManager.h
3 | //
4 | // Copyright (c) 2013-2015 Bradley David Bergeron
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | // this software and associated documentation files (the "Software"), to deal in
8 | // the Software without restriction, including without limitation the rights to
9 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | // the Software, and to permit persons to whom the Software is furnished to do so,
11 | // subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | #import
24 |
25 | #import "BDBOAuth1RequestSerializer.h"
26 |
27 | #pragma mark -
28 | @interface BDBOAuth1SessionManager : AFHTTPSessionManager
29 |
30 | /**
31 | * BDBOAuth1RequestSerializer instance used to serialize HTTP requests.
32 | */
33 | @property (nonatomic) BDBOAuth1RequestSerializer *requestSerializer;
34 |
35 |
36 | /**
37 | * ---------------------------------------------------------------------------------------
38 | * @name Initialization
39 | * ---------------------------------------------------------------------------------------
40 | */
41 | #pragma mark Initialization
42 |
43 | /**
44 | * Initialize a new BDBOAuth1SessionManager instance with the given baseURL, consumerKey, and consumerSecret.
45 | *
46 | * @param baseURL Base URL for HTTP requests.
47 | * @param consumerKey OAuth consumer key.
48 | * @param consumerSecret OAuth consumer secret.
49 | *
50 | * @return New BDBOAuth1SessionManager instance.
51 | */
52 | - (instancetype)initWithBaseURL:(NSURL *)baseURL
53 | consumerKey:(NSString *)consumerKey
54 | consumerSecret:(NSString *)consumerSecret;
55 |
56 |
57 | /**
58 | * ---------------------------------------------------------------------------------------
59 | * @name Authorization Status
60 | * ---------------------------------------------------------------------------------------
61 | */
62 | #pragma mark Authorization Status
63 |
64 | /**
65 | * Check whehter or not this manager instance has a valid access token.
66 | */
67 | @property (nonatomic, assign, readonly, getter = isAuthorized) BOOL authorized;
68 |
69 | /**
70 | * Deauthorize this manager instance and remove any associated access token from the keychain.
71 | *
72 | * @return YES if an access token was found and removed from the keychain, NO otherwise.
73 | */
74 | - (BOOL)deauthorize;
75 |
76 |
77 | /**
78 | * ---------------------------------------------------------------------------------------
79 | * @name OAuth Handshake
80 | * ---------------------------------------------------------------------------------------
81 | */
82 | #pragma mark OAuth Handshake
83 |
84 | /**
85 | * Fetch an OAuth request token.
86 | *
87 | * @param requestPath OAuth request token endpoint.
88 | * @param method HTTP method for fetching OAuth request token.
89 | * @param callbackURL The URL to be set for oauth_callback.
90 | * @param scope Authorization scope.
91 | * @param success Completion block performed upon successful acquisition of the OAuth request token.
92 | * @param failure Completion block performed if the OAuth request token could not be acquired.
93 | */
94 | - (void)fetchRequestTokenWithPath:(NSString *)requestPath
95 | method:(NSString *)method
96 | callbackURL:(NSURL *)callbackURL
97 | scope:(NSString *)scope
98 | success:(void (^)(BDBOAuth1Credential *requestToken))success
99 | failure:(void (^)(NSError *error))failure;
100 |
101 |
102 | /**
103 | * Fetch an OAuth access token using a previously-acquired request token.
104 | *
105 | * @param accessPath OAuth access token endpoint.
106 | * @param method HTTP method for fetching OAuth access token.
107 | * @param requestToken OAuth request token.
108 | * @param success Completion block performed upon successful acquisition of the OAuth access token.
109 | * @param failure Completion block performed if the OAuth access token could not be acquired.
110 | */
111 | - (void)fetchAccessTokenWithPath:(NSString *)accessPath
112 | method:(NSString *)method
113 | requestToken:(BDBOAuth1Credential *)requestToken
114 | success:(void (^)(BDBOAuth1Credential *accessToken))success
115 | failure:(void (^)(NSError *error))failure;
116 |
117 | @end
118 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/Flickr Demo/Views/PhotoAlbumHeaderView.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
26 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # BDBOAuth1Manager
2 |
3 | BDBOAuth1Manager is an OAuth 1.0a library for AFNetworking 2.x.
4 |
5 | ## Usage
6 |
7 | BDBOAuth1Manager consists of three core classes: `BDBOAuth1RequestSerializer`, `BDBOAuth1RequestOperationManger`, and `BDBOAuth1SessionManager`. Below I will provide a quick overview of each, but to really see how the three classes work together, take a look at the included demo apps. One is a simple Twitter client and the other a simple Flickr photo gallery, but they show how to get started using BDBOAuth1Manager in your projects.
8 |
9 | ### BDBOAuth1RequestOperationManger
10 |
11 | `BDBOAuth1RequestOperationManger` is a subclass of `AFHTTPRequestOperationManager` that provides methods to facilitate the OAuth 1 authentication flow.
12 |
13 | ```objective-c
14 | @property (nonatomic) BDBOAuth1RequestSerializer *requestSerializer;
15 |
16 | #pragma mark Initialization
17 | - (instancetype)initWithBaseURL:(NSURL *)baseURL
18 | consumerKey:(NSString *)consumerKey
19 | consumerSecret:(NSString *)consumerSecret;
20 |
21 | #pragma mark Authorization Status
22 | @property (nonatomic, assign, readonly, getter = isAuthorized) BOOL authorized;
23 |
24 | - (BOOL)deauthorize;
25 |
26 | #pragma mark OAuth Handshake
27 | - (void)fetchRequestTokenWithPath:(NSString *)requestPath
28 | method:(NSString *)method
29 | callbackURL:(NSURL *)callbackURL
30 | scope:(NSString *)scope
31 | success:(void (^)(BDBOAuth1Credential *requestToken))success
32 | failure:(void (^)(NSError *error))failure;
33 |
34 | - (void)fetchAccessTokenWithPath:(NSString *)accessPath
35 | method:(NSString *)method
36 | requestToken:(BDBOAuth1Credential *)requestToken
37 | success:(void (^)(BDBOAuth1Credential *accessToken))success
38 | failure:(void (^)(NSError *error))failure;
39 | ```
40 |
41 | ### BDBOAuth1SessionManager
42 |
43 | `BDBOAuth1SessionManager` is a subclass of `AFHTTPSessionManager` that has the same API as `BDBOAuth1RequestOperationManger`, which is described above.
44 |
45 | If your deployment target is either iOS 6 or OS X 10.8, you must use `BDBOAuth1RequestOperationManger`, as the underlying `NSURLSession` that is used by `AFHTTPSessionManager` is a new addition to the iOS and OS X networking frameworks for iOS 7 and OS X 10.9.
46 |
47 | ### BDBOAuth1RequestSerializer
48 |
49 | `BDBOAuth1RequestSerializer` is a subclass of `AFHTTPRequestSerializer` that handles all the networking requests performed by `BDBOAuth1RequestOperationManger` and `BDBOAuth1SessionManager`. Both classes automatically handle the creation of this serializer, so you should never have to instantiate it on your own.
50 |
51 | `BDBOAuth1RequestSerializer` also has built-in support for storing and retrieving an OAuth access token to/from the user's keychain, utilizing the service name to differentiate tokens. `BDBOAuth1RequestOperationManger` and `BDBOAuth1SessionManager` automatically set the service name to baseURL.host (e.g. api.twitter.com) when they are instantiated.
52 |
53 | ## OAuth Handshake
54 |
55 | The first step in performing the OAuth handshake is getting an OAuth request token for your application. This can be done with the `fetchRequestTokenWithPath:method:callbackURL:scope:success:failure:` method.
56 |
57 | ```objective-c
58 | [self.networkManager fetchRequestTokenWithPath:@"/oauth/request_token"
59 | method:@"POST"
60 | callbackURL:[NSURL URLWithString:@"bdboauth://request"]
61 | scope:nil
62 | success:^(BDBOAuth1Credential *requestToken) {
63 | NSString *authURL = [NSString stringWithFormat:@"https://api.twitter.com/oauth/authorize?oauth_token=%@", requestToken.token];
64 | [[UIApplication sharedApplication] openURL:[NSURL URLWithString:authURL]];
65 | }
66 | failure:^(NSError *error) {
67 | NSLog(@"Error: %@", error.localizedDescription);
68 | }];
69 | ```
70 |
71 | ### Creating a URL Type for OAuth Callbacks
72 |
73 | When calling `fetchRequestTokenWithPath:method:callbackURL:scope:success:failure:`, you must provide a unique callback URL whose scheme corresponds to a URL type you've added to your project target. This allows the OAuth provider to return the user to your app after the user has authorized it. For example, if I add a URL type to my project with the scheme `bdboauth`, my application would then respond to all URL requests that begin with `bdboauth:`. If I pass `bdboauth://request` as the callback URL, the OAuth provider would call that URL and my application would resume.
74 |
75 | 
76 |
77 | ### Responding to the OAuth Callback URL
78 |
79 | In order to respond to your application's URL scheme being called, you must implement the `-application:openURL:sourceApplication:annotation` method within your application delegate. You can do something like this:
80 |
81 | ```objective-c
82 | - (BOOL)application:(UIApplication *)application
83 | openURL:(NSURL *)url
84 | sourceApplication:(NSString *)sourceApplication
85 | annotation:(id)annotation {
86 | if ([url.scheme isEqualToString:@"bdboauth"]) {
87 | if ([url.host isEqualToString:@"request"]) {
88 | NSDictionary *parameters = [url dictionaryFromQueryString];
89 | if (parameters[@"oauth_token"] && parameters[@"oauth_verifier"]) {
90 | [self.networkManager fetchAccessTokenWithPath:@"/oauth/access_token"
91 | method:@"POST"
92 | requestToken:[BDBOAuth1Credential credentialWithQueryString:url.query]
93 | success:^(BDBOAuth1Credential *accessToken) {
94 | [self.networkManager.requestSerializer saveAccessToken:accessToken];
95 | }];
96 | }
97 | }
98 | return YES;
99 | }
100 | return NO;
101 | }
102 | ```
103 |
104 | ## Credits
105 |
106 | BDBOAuth1Manager was created by [Bradley David Bergeron](http://www.bradbergeron.com) and influenced by [AFOAuth1Client](https://github.com/AFNetworking/AFOAuth1Client). Both [AFNetworking](https://github.com/AFNetworking/AFNetworking) and [AFOAuth1Client](https://github.com/AFNetworking/AFOAuth1Client) are the awesome work of [Mattt Thompson](https://github.com/mattt).
107 |
--------------------------------------------------------------------------------
/BDBOAuth1Manager/BDBOAuth1SessionManager.m:
--------------------------------------------------------------------------------
1 | //
2 | // BDBOAuth1SessionManager.m
3 | //
4 | // Copyright (c) 2013-2015 Bradley David Bergeron
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | // this software and associated documentation files (the "Software"), to deal in
8 | // the Software without restriction, including without limitation the rights to
9 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | // the Software, and to permit persons to whom the Software is furnished to do so,
11 | // subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | #import "BDBOAuth1SessionManager.h"
24 |
25 | #pragma mark -
26 | @interface BDBOAuth1SessionManager ()
27 |
28 | @end
29 |
30 |
31 | #pragma mark -
32 | @implementation BDBOAuth1SessionManager
33 |
34 | @dynamic requestSerializer;
35 |
36 | #pragma mark Initialization
37 | - (instancetype)initWithBaseURL:(NSURL *)baseURL
38 | consumerKey:(NSString *)consumerKey
39 | consumerSecret:(NSString *)consumerSecret {
40 | self = [super initWithBaseURL:baseURL];
41 |
42 | if (self) {
43 | self.requestSerializer = [BDBOAuth1RequestSerializer serializerForService:baseURL.host
44 | withConsumerKey:consumerKey
45 | consumerSecret:consumerSecret];
46 | }
47 |
48 | return self;
49 | }
50 |
51 | #pragma mark Authorization Status
52 | - (BOOL)isAuthorized {
53 | return (self.requestSerializer.accessToken && !self.requestSerializer.accessToken.expired);
54 | }
55 |
56 | - (BOOL)deauthorize {
57 | return [self.requestSerializer removeAccessToken];
58 | }
59 |
60 | #pragma mark OAuth Handshake
61 | - (void)fetchRequestTokenWithPath:(NSString *)requestPath
62 | method:(NSString *)method
63 | callbackURL:(NSURL *)callbackURL
64 | scope:(NSString *)scope
65 | success:(void (^)(BDBOAuth1Credential *requestToken))success
66 | failure:(void (^)(NSError *error))failure {
67 | self.requestSerializer.requestToken = nil;
68 |
69 | AFHTTPResponseSerializer *defaultSerializer = self.responseSerializer;
70 | self.responseSerializer = [AFHTTPResponseSerializer serializer];
71 |
72 | NSMutableDictionary *parameters = [[self.requestSerializer OAuthParameters] mutableCopy];
73 | parameters[BDBOAuth1OAuthCallbackParameter] = [callbackURL absoluteString];
74 |
75 | if (scope && !self.requestSerializer.accessToken) {
76 | parameters[@"scope"] = scope;
77 | }
78 |
79 | NSString *URLString = [[NSURL URLWithString:requestPath relativeToURL:self.baseURL] absoluteString];
80 | NSError *error;
81 | NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:method URLString:URLString parameters:parameters error:&error];
82 |
83 | if (error) {
84 | failure(error);
85 |
86 | return;
87 | }
88 |
89 | void (^completionBlock)(NSURLResponse * __unused, id, NSError *) = ^(NSURLResponse * __unused response, id responseObject, NSError *completionError) {
90 | self.responseSerializer = defaultSerializer;
91 |
92 | if (completionError) {
93 | failure(completionError);
94 |
95 | return;
96 | }
97 |
98 | BDBOAuth1Credential *requestToken = [BDBOAuth1Credential credentialWithQueryString:[[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]];
99 | self.requestSerializer.requestToken = requestToken;
100 |
101 | success(requestToken);
102 | };
103 |
104 | NSURLSessionDataTask *task = [self dataTaskWithRequest:request completionHandler:completionBlock];
105 | [task resume];
106 | }
107 |
108 | - (void)fetchAccessTokenWithPath:(NSString *)accessPath
109 | method:(NSString *)method
110 | requestToken:(BDBOAuth1Credential *)requestToken
111 | success:(void (^)(BDBOAuth1Credential *accessToken))success
112 | failure:(void (^)(NSError *error))failure {
113 | if (!requestToken.token || !requestToken.verifier) {
114 | NSError *error = [[NSError alloc] initWithDomain:BDBOAuth1ErrorDomain
115 | code:NSURLErrorBadServerResponse
116 | userInfo:@{NSLocalizedFailureReasonErrorKey:@"Invalid OAuth response received from server."}];
117 |
118 | failure(error);
119 |
120 | return;
121 | }
122 |
123 | AFHTTPResponseSerializer *defaultSerializer = self.responseSerializer;
124 | self.responseSerializer = [AFHTTPResponseSerializer serializer];
125 |
126 | NSMutableDictionary *parameters = [[self.requestSerializer OAuthParameters] mutableCopy];
127 | parameters[BDBOAuth1OAuthTokenParameter] = requestToken.token;
128 | parameters[BDBOAuth1OAuthVerifierParameter] = requestToken.verifier;
129 |
130 | NSString *URLString = [[NSURL URLWithString:accessPath relativeToURL:self.baseURL] absoluteString];
131 | NSError *error;
132 | NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:method URLString:URLString parameters:parameters error:&error];
133 |
134 | if (error) {
135 | failure(error);
136 |
137 | return;
138 | }
139 |
140 | void (^completionBlock)(NSURLResponse * __unused, id, NSError *) = ^(NSURLResponse * __unused response, id responseObject, NSError *completionError) {
141 | self.responseSerializer = defaultSerializer;
142 | self.requestSerializer.requestToken = nil;
143 |
144 | if (completionError) {
145 | failure(completionError);
146 |
147 | return;
148 | }
149 |
150 | BDBOAuth1Credential *accessToken = [BDBOAuth1Credential credentialWithQueryString:[[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]];
151 | [self.requestSerializer saveAccessToken:accessToken];
152 |
153 | success(accessToken);
154 | };
155 |
156 | NSURLSessionDataTask *task = [self dataTaskWithRequest:request completionHandler:completionBlock];
157 | [task resume];
158 | }
159 |
160 | @end
161 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/Twitter Demo/Views/TweetCell.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
30 |
36 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/BDBOAuth1Manager/BDBOAuth1RequestSerializer.h:
--------------------------------------------------------------------------------
1 | //
2 | // BDBOAuth1RequestSerializer.h
3 | //
4 | // Copyright (c) 2013-2015 Bradley David Bergeron
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | // this software and associated documentation files (the "Software"), to deal in
8 | // the Software without restriction, including without limitation the rights to
9 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | // the Software, and to permit persons to whom the Software is furnished to do so,
11 | // subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | #import
24 |
25 |
26 | FOUNDATION_EXPORT NSString * const BDBOAuth1ErrorDomain;
27 |
28 | FOUNDATION_EXPORT NSString * const BDBOAuth1OAuthTokenParameter;
29 | FOUNDATION_EXPORT NSString * const BDBOAuth1OAuthTokenSecretParameter;
30 | FOUNDATION_EXPORT NSString * const BDBOAuth1OAuthVerifierParameter;
31 | FOUNDATION_EXPORT NSString * const BDBOAuth1OAuthTokenDurationParameter;
32 | FOUNDATION_EXPORT NSString * const BDBOAuth1OAuthSignatureParameter;
33 | FOUNDATION_EXPORT NSString * const BDBOAuth1OAuthCallbackParameter;
34 |
35 |
36 | #pragma mark -
37 | @interface BDBOAuth1Credential : NSObject
38 |
39 |
40 | /**
41 | * Token ('oauth_token')
42 | */
43 | @property (nonatomic, copy, readonly) NSString *token;
44 |
45 | /**
46 | * Token secret ('oauth_token_secret')
47 | */
48 | @property (nonatomic, copy, readonly) NSString *secret;
49 |
50 | /**
51 | * Verifier ('oauth_verifier')
52 | */
53 | @property (nonatomic, copy) NSString *verifier;
54 |
55 | /**
56 | * Check whether or not this token is expired.
57 | */
58 | @property (nonatomic, assign, readonly, getter = isExpired) BOOL expired;
59 |
60 | /**
61 | * Additional custom (non-OAuth) parameters included with this credential.
62 | */
63 | @property (nonatomic) NSDictionary *userInfo;
64 |
65 |
66 | /**
67 | * ---------------------------------------------------------------------------------------
68 | * @name Initialization
69 | * ---------------------------------------------------------------------------------------
70 | */
71 | #pragma mark Initialization
72 |
73 | /**
74 | * Create a new BDBOAuth1Credential instance with the given token, token secret, and verifier.
75 | *
76 | * @param token OAuth token ('oauth_token').
77 | * @param secret OAuth token secret ('oauth_token_secret').
78 | * @param expiration Expiration date or nil if the credential does not expire.
79 | *
80 | * @return New BDBOAuth1Credential.
81 | */
82 | + (instancetype)credentialWithToken:(NSString *)token
83 | secret:(NSString *)secret
84 | expiration:(NSDate *)expiration;
85 |
86 | /**
87 | * Instantiate a new BDBOAuth1Credential instance with the given token, token secret, and verifier.
88 | *
89 | * @param token OAuth token ('oauth_token').
90 | * @param secret OAuth token secret ('oauth_token_secret').
91 | * @param expiration Expiration date or nil if the credential does not expire.
92 | *
93 | * @return New BDBOAuth1Credential.
94 | */
95 | - (instancetype)initWithToken:(NSString *)token
96 | secret:(NSString *)secret
97 | expiration:(NSDate *)expiration;
98 |
99 | /**
100 | * Create a new BDBOAuth1Credential instance using parameters in the given URL query string.
101 | *
102 | * @param queryString URL query string containing OAuth token parameters.
103 | *
104 | * @return New BDBOAuth1Credential.
105 | */
106 | + (instancetype)credentialWithQueryString:(NSString *)queryString;
107 |
108 | /**
109 | * Instantiate a new BDBOAuth1Credential instance using parameters in the given URL query string.
110 | *
111 | * @param queryString URL query string containing OAuth token parameters.
112 | *
113 | * @return New BDBOAuth1Credential.
114 | */
115 | - (instancetype)initWithQueryString:(NSString *)queryString;
116 |
117 | @end
118 |
119 |
120 | #pragma mark -
121 | @interface BDBOAuth1RequestSerializer : AFHTTPRequestSerializer
122 |
123 | /**
124 | * OAuth request token.
125 | */
126 | @property (nonatomic, copy) BDBOAuth1Credential *requestToken;
127 |
128 | /**
129 | * OAuth access token.
130 | */
131 | @property (nonatomic, copy, readonly) BDBOAuth1Credential *accessToken;
132 |
133 |
134 | /**
135 | * ---------------------------------------------------------------------------------------
136 | * @name Initialization
137 | * ---------------------------------------------------------------------------------------
138 | */
139 | #pragma mark Initialization
140 |
141 | /**
142 | * Create a new BDBOAuth1RequestSerializer instance for the given service with its consumerKey and consumerSecret.
143 | *
144 | * @param service Service (base URL) this request serializer is used for.
145 | * @param consumerKey OAuth consumer key.
146 | * @param consumerSecret OAuth consumer secret.
147 | *
148 | * @return New BDBOAuth1RequestSerializer for the specified service.
149 | */
150 | + (instancetype)serializerForService:(NSString *)service
151 | withConsumerKey:(NSString *)consumerKey
152 | consumerSecret:(NSString *)consumerSecret;
153 |
154 | /**
155 | * Instantiate a new BDBOAuth1RequestSerializer instance for the given service with its consumerKey and consumerSecret.
156 | *
157 | * @param service Service (base URL) this request serializer is used for.
158 | * @param consumerKey OAuth consumer key.
159 | * @param consumerSecret OAuth consumer secret.
160 | *
161 | * @return New BDBOAuth1RequestSerializer for the specified service.
162 | */
163 | - (instancetype)initWithService:(NSString *)service
164 | consumerKey:(NSString *)consumerKey
165 | consumerSecret:(NSString *)consumerSecret;
166 |
167 |
168 | /**
169 | * ---------------------------------------------------------------------------------------
170 | * @name Storing the Access Token
171 | * ---------------------------------------------------------------------------------------
172 | */
173 | #pragma mark Storing the Access Token
174 |
175 | /**
176 | * Save the given OAuth access token in the user's keychain for future use with this serializer's service.
177 | *
178 | * @param accessToken OAuth access token.
179 | *
180 | * @return Success of keychain item add/update operation.
181 | */
182 | - (BOOL)saveAccessToken:(BDBOAuth1Credential *)accessToken;
183 |
184 | /**
185 | * Remove the access token currently stored in the keychain for this serializer's service.
186 | *
187 | * @return Success of keychain item removal operation.
188 | */
189 | - (BOOL)removeAccessToken;
190 |
191 |
192 | /**
193 | * ---------------------------------------------------------------------------------------
194 | * @name OAuth Parameters
195 | * ---------------------------------------------------------------------------------------
196 | */
197 | #pragma mark OAuth Parameters
198 |
199 | /**
200 | * Retrieve the set of OAuth parameters to be included in authorized HTTP requests.
201 | *
202 | * @return Dictionary of OAuth parameters.
203 | */
204 | - (NSDictionary *)OAuthParameters;
205 |
206 | @end
207 |
208 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/Twitter Demo/Twitter/BDBTwitterClient.m:
--------------------------------------------------------------------------------
1 | //
2 | // BDBTwitterClient.m
3 | //
4 | // Copyright (c) 2014 Bradley David Bergeron
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | // this software and associated documentation files (the "Software"), to deal in
8 | // the Software without restriction, including without limitation the rights to
9 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | // the Software, and to permit persons to whom the Software is furnished to do so,
11 | // subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | #import "BDBOAuth1SessionManager.h"
24 | #import "BDBTweet.h"
25 | #import "BDBTwitterClient.h"
26 |
27 | #import "NSDictionary+BDBOAuth1Manager.h"
28 |
29 |
30 | // Exported
31 | NSString * const BDBTwitterClientErrorDomain = @"BDBTwitterClientErrorDomain";
32 |
33 | NSString * const BDBTwitterClientDidLogInNotification = @"BDBTwitterClientDidLogInNotification";
34 | NSString * const BDBTwitterClientDidLogOutNotification = @"BDBTwitterClientDidLogOutNotification";
35 |
36 | // Internal
37 | static NSString * const kBDBTwitterClientAPIURL = @"https://api.twitter.com/1.1/";
38 |
39 | static NSString * const kBDBTwitterClientOAuthAuthorizeURL = @"https://api.twitter.com/oauth/authorize";
40 | static NSString * const kBDBTwitterClientOAuthCallbackURL = @"bdboauth1demo-twitter://authorize";
41 | static NSString * const kBDBTwitterClientOAuthRequestTokenPath = @"https://api.twitter.com/oauth/request_token";
42 | static NSString * const kBDBTwitterClientOAuthAccessTokenPath = @"https://api.twitter.com/oauth/access_token";
43 |
44 |
45 | #pragma mark -
46 | @interface BDBTwitterClient ()
47 |
48 | @property (nonatomic) BDBOAuth1SessionManager *networkManager;
49 |
50 | - (id)initWithConsumerKey:(NSString *)key sceret:(NSString *)secret;
51 |
52 | @end
53 |
54 | #pragma mark -
55 | @implementation BDBTwitterClient
56 |
57 | #pragma mark Initialization
58 | static BDBTwitterClient *_sharedClient = nil;
59 |
60 | + (instancetype)createWithConsumerKey:(NSString *)key secret:(NSString *)secret {
61 | static dispatch_once_t onceToken;
62 | dispatch_once(&onceToken, ^{
63 | _sharedClient = [[[self class] alloc] initWithConsumerKey:key sceret:secret];
64 | });
65 |
66 | return _sharedClient;
67 | }
68 |
69 | - (id)initWithConsumerKey:(NSString *)key sceret:(NSString *)secret {
70 | self = [super init];
71 |
72 | if (self) {
73 | NSURL *baseURL = [NSURL URLWithString:kBDBTwitterClientAPIURL];
74 | _networkManager = [[BDBOAuth1SessionManager alloc] initWithBaseURL:baseURL consumerKey:key consumerSecret:secret];
75 | }
76 |
77 | return self;
78 | }
79 |
80 | + (instancetype)sharedClient {
81 | NSAssert(_sharedClient, @"BDBTwitterClient not initialized. [BDBTwitterClient createWithConsumerKey:secret:] must be called first.");
82 |
83 | return _sharedClient;
84 | }
85 |
86 | #pragma mark Authorization
87 | + (BOOL)isAuthorizationCallbackURL:(NSURL *)url {
88 | NSURL *callbackURL = [NSURL URLWithString:kBDBTwitterClientOAuthCallbackURL];
89 |
90 | return _sharedClient && [url.scheme isEqualToString:callbackURL.scheme] && [url.host isEqualToString:callbackURL.host];
91 | }
92 |
93 | - (BOOL)isAuthorized {
94 | return self.networkManager.authorized;
95 | }
96 |
97 | - (void)authorize {
98 | [self.networkManager fetchRequestTokenWithPath:kBDBTwitterClientOAuthRequestTokenPath
99 | method:@"POST"
100 | callbackURL:[NSURL URLWithString:kBDBTwitterClientOAuthCallbackURL]
101 | scope:nil
102 | success:^(BDBOAuth1Credential *requestToken) {
103 | // Perform Authorization via MobileSafari
104 | NSString *authURLString = [kBDBTwitterClientOAuthAuthorizeURL stringByAppendingFormat:@"?oauth_token=%@", requestToken.token];
105 |
106 | [[UIApplication sharedApplication] openURL:[NSURL URLWithString:authURLString]];
107 | }
108 | failure:^(NSError *error) {
109 | NSLog(@"Error: %@", error.localizedDescription);
110 |
111 | dispatch_async(dispatch_get_main_queue(), ^{
112 | [[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Error", nil)
113 | message:NSLocalizedString(@"Could not acquire OAuth request token. Please try again later.", nil)
114 | delegate:self
115 | cancelButtonTitle:NSLocalizedString(@"Dismiss", nil)
116 | otherButtonTitles:nil] show];
117 | });
118 | }];
119 | }
120 |
121 | - (BOOL)handleAuthorizationCallbackURL:(NSURL *)url {
122 | NSDictionary *parameters = [NSDictionary bdb_dictionaryFromQueryString:url.query];
123 |
124 | if (parameters[BDBOAuth1OAuthTokenParameter] && parameters[BDBOAuth1OAuthVerifierParameter]) {
125 | [self.networkManager fetchAccessTokenWithPath:kBDBTwitterClientOAuthAccessTokenPath
126 | method:@"POST"
127 | requestToken:[BDBOAuth1Credential credentialWithQueryString:url.query]
128 | success:^(BDBOAuth1Credential *accessToken) {
129 | [[NSNotificationCenter defaultCenter] postNotificationName:BDBTwitterClientDidLogInNotification
130 | object:self
131 | userInfo:accessToken.userInfo];
132 | }
133 | failure:^(NSError *error) {
134 | NSLog(@"Error: %@", error.localizedDescription);
135 |
136 | dispatch_async(dispatch_get_main_queue(), ^{
137 | [[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Error", nil)
138 | message:NSLocalizedString(@"Could not acquire OAuth access token. Please try again later.", nil)
139 | delegate:self
140 | cancelButtonTitle:NSLocalizedString(@"Dismiss", nil)
141 | otherButtonTitles:nil] show];
142 | });
143 | }];
144 |
145 | return YES;
146 | }
147 |
148 | return NO;
149 | }
150 |
151 | - (void)deauthorize {
152 | [self.networkManager deauthorize];
153 |
154 | [[NSNotificationCenter defaultCenter] postNotificationName:BDBTwitterClientDidLogOutNotification object:self];
155 | }
156 |
157 | #pragma mark Tweets
158 | - (void)loadTimelineWithCompletion:(void (^)(NSArray *, NSError *))completion {
159 | static NSString *timelinePath = @"statuses/home_timeline.json?count=100";
160 |
161 | [self.networkManager GET:timelinePath
162 | parameters:nil
163 | progress:nil
164 | success:^(NSURLSessionDataTask *task, id responseObject) {
165 | [self parseTweetsFromAPIResponse:responseObject completion:completion];
166 | }
167 | failure:^(NSURLSessionDataTask *task, NSError *error) {
168 | completion(nil, error);
169 | }];
170 | }
171 |
172 | - (void)parseTweetsFromAPIResponse:(id)responseObject completion:(void (^)(NSArray *, NSError *))completion {
173 | if (![responseObject isKindOfClass:[NSArray class]]) {
174 | NSError *error = [NSError errorWithDomain:BDBTwitterClientErrorDomain
175 | code:1000
176 | userInfo:@{NSLocalizedDescriptionKey:NSLocalizedString(@"Unexpected response received from Twitter API.", nil)}];
177 |
178 | return completion(nil, error);
179 | }
180 |
181 | NSArray *response = responseObject;
182 |
183 | NSMutableArray *tweets = [NSMutableArray array];
184 |
185 | for (NSDictionary *tweetInfo in response) {
186 | BDBTweet *tweet = [[BDBTweet alloc] initWithDictionary:tweetInfo];
187 | [tweets addObject:tweet];
188 | }
189 |
190 | completion(tweets, nil);
191 | }
192 |
193 | @end
194 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/Twitter Demo/View Controllers/TweetsViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // TweetsViewController.m
3 | //
4 | // Copyright (c) 2014 Bradley David Bergeron
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | // this software and associated documentation files (the "Software"), to deal in
8 | // the Software without restriction, including without limitation the rights to
9 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | // the Software, and to permit persons to whom the Software is furnished to do so,
11 | // subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | #import "AppDelegate.h"
24 | #import "BDBTweet.h"
25 | #import "BDBTwitterClient.h"
26 | #import "TweetCell.h"
27 | #import "TweetsViewController.h"
28 |
29 | #import "AFNetworking/UIKit+AFNetworking.h"
30 | #import "BBlock/UIKit+BBlock.h"
31 |
32 |
33 | static NSString * const kTweetCellName = @"TweetCell";
34 |
35 |
36 | #pragma mark -
37 | @interface TweetsViewController ()
38 |
39 | @property (nonatomic) NSMutableDictionary *offscreenCells;
40 | @property (nonatomic) NSArray *tweets;
41 |
42 | - (void)logInOut;
43 |
44 | @end
45 |
46 | #pragma mark -
47 | @implementation TweetsViewController
48 |
49 | - (id)init {
50 | self = [super init];
51 |
52 | if (self) {
53 | _offscreenCells = [NSMutableDictionary dictionary];
54 | _tweets = [NSArray array];
55 |
56 | self.refreshControl = [UIRefreshControl new];
57 | [self.refreshControl addTarget:self action:@selector(loadTweets) forControlEvents:UIControlEventValueChanged];
58 |
59 | self.tableView.rowHeight = 90.0f;
60 |
61 | if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0f) {
62 | self.tableView.separatorInset = UIEdgeInsetsZero;
63 | }
64 |
65 | [[NSNotificationCenter defaultCenter] addObserverForName:BDBTwitterClientDidLogInNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
66 | [self loadTweets];
67 |
68 | [self.navigationItem.rightBarButtonItem setTitle:NSLocalizedString(@"Log Out", nil)];
69 | }];
70 |
71 | [[NSNotificationCenter defaultCenter] addObserverForName:BDBTwitterClientDidLogOutNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
72 | self.tweets = [NSArray array];
73 |
74 | [self.tableView reloadData];
75 |
76 | [self.navigationItem.rightBarButtonItem setTitle:NSLocalizedString(@"Log In", nil)];
77 | }];
78 | }
79 |
80 | return self;
81 | }
82 |
83 | - (void)viewDidLoad {
84 | [super viewDidLoad];
85 |
86 | self.title = NSLocalizedString(@"Tweets", nil);
87 |
88 | UINib *tableCellNib = [UINib nibWithNibName:kTweetCellName bundle:nil];
89 | [self.tableView registerNib:tableCellNib forCellReuseIdentifier:kTweetCellName];
90 |
91 | NSString *logInOutString = ([[BDBTwitterClient sharedClient] isAuthorized]) ?
92 | NSLocalizedString(@"Log Out", nil) : NSLocalizedString(@"Log In", nil);
93 |
94 | self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:logInOutString
95 | style:UIBarButtonItemStylePlain
96 | target:self
97 | action:@selector(logInOut)];
98 | }
99 |
100 | - (void)viewDidAppear:(BOOL)animated {
101 | [super viewDidAppear:animated];
102 |
103 | if ([[BDBTwitterClient sharedClient] isAuthorized]) {
104 | [self loadTweets];
105 | }
106 | }
107 |
108 | - (void)dealloc {
109 | [[NSNotificationCenter defaultCenter] removeObserver:self];
110 | }
111 |
112 | #pragma mark Authorization
113 | - (void)logInOut {
114 | if ([[BDBTwitterClient sharedClient] isAuthorized]) {
115 | dispatch_async(dispatch_get_main_queue(), ^{
116 | [[[UIActionSheet alloc] initWithTitle:NSLocalizedString(@"Are you sure you want to log out?", nil)
117 | cancelButtonTitle:NSLocalizedString(@"Cancel", nil)
118 | destructiveButtonTitle:NSLocalizedString(@"Log Out", nil)
119 | otherButtonTitle:nil
120 | completionBlock:^(NSInteger buttonIndex, UIActionSheet *actionSheet) {
121 | if (buttonIndex == actionSheet.destructiveButtonIndex) {
122 | [[BDBTwitterClient sharedClient] deauthorize];
123 | }
124 | }]
125 | showInView:self.view];
126 | });
127 | } else {
128 | [[BDBTwitterClient sharedClient] authorize];
129 | }
130 | }
131 |
132 | #pragma mark Load Tweets
133 | - (void)loadTweets {
134 | if (![[BDBTwitterClient sharedClient] isAuthorized]) {
135 | dispatch_async(dispatch_get_main_queue(), ^{
136 | [[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Not Logged In", nil)
137 | message:NSLocalizedString(@"You have to log in before you can view your timeline!", nil)
138 | cancelButtonTitle:NSLocalizedString(@"Cancel", nil)
139 | otherButtonTitle:NSLocalizedString(@"Log In", nil)
140 | completionBlock:^(NSInteger buttonIndex, UIAlertView *alertView) {
141 | if (buttonIndex == alertView.cancelButtonIndex + 1) {
142 | [[BDBTwitterClient sharedClient] authorize];
143 | }
144 | }]
145 | show];
146 | });
147 |
148 | [self.refreshControl endRefreshing];
149 |
150 | return;
151 | }
152 |
153 | if (!self.refreshControl.isRefreshing) {
154 | [self.tableView setContentOffset:CGPointMake(0, self.tableView.contentOffset.y - self.refreshControl.frame.size.height)
155 | animated:NO];
156 | [self.refreshControl beginRefreshing];
157 | }
158 |
159 | [[BDBTwitterClient sharedClient] loadTimelineWithCompletion:^(NSArray *tweets, NSError *error) {
160 | if (error) {
161 | NSLog(@"Error: %@", error.localizedDescription);
162 |
163 | dispatch_async(dispatch_get_main_queue(), ^{
164 | [[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Error", nil)
165 | message:error.localizedDescription
166 | delegate:self
167 | cancelButtonTitle:NSLocalizedString(@"Dismiss", nil)
168 | otherButtonTitles:nil] show];
169 | });
170 | } else {
171 | self.tweets = tweets;
172 |
173 | [self.tableView reloadData];
174 | }
175 |
176 | [self.refreshControl endRefreshing];
177 | }];
178 | }
179 |
180 | #pragma mark TableView Data Source
181 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
182 | return 1;
183 | }
184 |
185 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
186 | return self.tweets.count;
187 | }
188 |
189 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
190 | TweetCell *cell = [tableView dequeueReusableCellWithIdentifier:kTweetCellName forIndexPath:indexPath];
191 |
192 | BDBTweet *tweet = self.tweets[indexPath.row];
193 |
194 | cell.userNameLabel.text = tweet.userName;
195 | cell.userScreenNameLabel.text = [NSString stringWithFormat:@"@%@", tweet.userScreenName];
196 | cell.tweetLabel.text = tweet.tweetText;
197 |
198 | NSURL *userImageURL = tweet.userImageURL;
199 |
200 | if (userImageURL) {
201 | __weak TweetCell *weakCell = cell;
202 | [weakCell.userImageView setImageWithURLRequest:[NSURLRequest requestWithURL:tweet.userImageURL]
203 | placeholderImage:nil
204 | success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
205 | weakCell.userImageView.image = image;
206 | }
207 | failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
208 | NSLog(@"Failed to load image for cell. %@", error.localizedDescription);
209 | }];
210 | }
211 |
212 | [cell setNeedsUpdateConstraints];
213 | [cell updateConstraintsIfNeeded];
214 |
215 | return cell;
216 | }
217 |
218 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
219 | TweetCell *cell = [self.offscreenCells objectForKey:kTweetCellName];
220 |
221 | if (!cell) {
222 | cell = [[[UINib nibWithNibName:kTweetCellName bundle:nil] instantiateWithOwner:nil options:nil] objectAtIndex:0];
223 | [self.offscreenCells setObject:cell forKey:kTweetCellName];
224 | }
225 |
226 | BDBTweet *tweet = self.tweets[indexPath.row];
227 |
228 | cell.userNameLabel.text = tweet.userName;
229 | cell.userScreenNameLabel.text = [NSString stringWithFormat:@"@%@", tweet.userScreenName];
230 | cell.tweetLabel.text = tweet.tweetText;
231 |
232 | [cell setNeedsUpdateConstraints];
233 | [cell updateConstraintsIfNeeded];
234 |
235 | cell.bounds = CGRectMake(0.0f, 0.0f, CGRectGetWidth(tableView.bounds), CGRectGetHeight(cell.bounds));
236 |
237 | [cell setNeedsLayout];
238 | [cell layoutIfNeeded];
239 |
240 | CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
241 |
242 | return height + 1.0f;
243 | }
244 |
245 | @end
246 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/Flickr Demo/Flickr/BDBFlickrClient.m:
--------------------------------------------------------------------------------
1 | //
2 | // BDBFlickrClient.m
3 | //
4 | // Copyright (c) 2014 Bradley David Bergeron
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | // this software and associated documentation files (the "Software"), to deal in
8 | // the Software without restriction, including without limitation the rights to
9 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | // the Software, and to permit persons to whom the Software is furnished to do so,
11 | // subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | #import "BDBFlickrClient.h"
24 | #import "BDBFlickrPhoto.h"
25 | #import "BDBFlickrPhotoset.h"
26 | #import "BDBOAuth1SessionManager.h"
27 |
28 | #import "NSDictionary+BDBOAuth1Manager.h"
29 |
30 |
31 | // Exported
32 | NSString * const BDBFlickrClientErrorDomain = @"BDBFlickrClientErrorDomain";
33 |
34 | NSString * const BDBFlickrClientDidLogInNotification = @"BDBFlickrClientDidLogInNotification";
35 | NSString * const BDBFlickrClientDidLogOutNotification = @"BDBFlickrClientDidLogOutNotification";
36 |
37 | // Internal
38 | static NSString * const kBDBFlickrClientAPIURL = @"https://api.flickr.com/services/";
39 |
40 | static NSString * const kBDBFlickrClientOAuthAuthorizeURL = @"https://www.flickr.com/services/oauth/authorize";
41 | static NSString * const kBDBFlickrClientOAuthCallbackURL = @"bdboauth1demo-flickr://authorize";
42 | static NSString * const kBDBFlickrClientOAuthRequestTokenPath = @"https://www.flickr.com/services/oauth/request_token";
43 | static NSString * const kBDBFlickrClientOAuthAccessTokenPath = @"https://www.flickr.com/services/oauth/access_token";
44 |
45 |
46 | #pragma mark -
47 | @interface BDBFlickrClient ()
48 |
49 | @property (nonatomic, copy) NSString *apiKey;
50 |
51 | @property (nonatomic) BDBOAuth1SessionManager *networkManager;
52 |
53 | - (id)initWithAPIKey:(NSString *)apiKey sceret:(NSString *)secret;
54 |
55 | - (NSDictionary *)defaultRequestParameters;
56 |
57 | @end
58 |
59 | #pragma mark -
60 | @implementation BDBFlickrClient
61 |
62 | #pragma mark Initialization
63 | static BDBFlickrClient *_sharedClient = nil;
64 |
65 | + (instancetype)createWithAPIKey:(NSString *)apiKey secret:(NSString *)secret {
66 | static dispatch_once_t onceToken;
67 | dispatch_once(&onceToken, ^{
68 | _sharedClient = [[[self class] alloc] initWithAPIKey:apiKey sceret:secret];
69 | });
70 |
71 | return _sharedClient;
72 | }
73 |
74 | - (id)initWithAPIKey:(NSString *)apiKey sceret:(NSString *)secret {
75 | self = [super init];
76 |
77 | if (self) {
78 | _apiKey = [apiKey copy];
79 |
80 | NSURL *baseURL = [NSURL URLWithString:kBDBFlickrClientAPIURL];
81 | _networkManager = [[BDBOAuth1SessionManager alloc] initWithBaseURL:baseURL consumerKey:apiKey consumerSecret:secret];
82 | }
83 |
84 | return self;
85 | }
86 |
87 | + (instancetype)sharedClient {
88 | NSAssert(_sharedClient, @"BDBFlickrClient not initialized. [BDBFlickrClient createWithAPIKey:secret:] must be called first.");
89 |
90 | return _sharedClient;
91 | }
92 |
93 | #pragma mark Authorization
94 | + (BOOL)isAuthorizationCallbackURL:(NSURL *)url {
95 | NSURL *callbackURL = [NSURL URLWithString:kBDBFlickrClientOAuthCallbackURL];
96 |
97 | return _sharedClient && [url.scheme isEqualToString:callbackURL.scheme] && [url.host isEqualToString:callbackURL.host];
98 | }
99 |
100 | - (BOOL)isAuthorized {
101 | return self.networkManager.authorized;
102 | }
103 |
104 | - (void)authorize {
105 | [self.networkManager fetchRequestTokenWithPath:kBDBFlickrClientOAuthRequestTokenPath
106 | method:@"POST"
107 | callbackURL:[NSURL URLWithString:kBDBFlickrClientOAuthCallbackURL]
108 | scope:nil
109 | success:^(BDBOAuth1Credential *requestToken) {
110 | // Perform Authorization via MobileSafari
111 | NSString *authURLString = [kBDBFlickrClientOAuthAuthorizeURL stringByAppendingFormat:@"?oauth_token=%@", requestToken.token];
112 |
113 | [[UIApplication sharedApplication] openURL:[NSURL URLWithString:authURLString]];
114 | }
115 | failure:^(NSError *error) {
116 | NSLog(@"Error: %@", error.localizedDescription);
117 |
118 | dispatch_async(dispatch_get_main_queue(), ^{
119 | [[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Error", nil)
120 | message:NSLocalizedString(@"Could not acquire OAuth request token. Please try again later.", nil)
121 | delegate:self
122 | cancelButtonTitle:NSLocalizedString(@"Dismiss", nil)
123 | otherButtonTitles:nil] show];
124 | });
125 | }];
126 | }
127 |
128 | - (BOOL)handleAuthorizationCallbackURL:(NSURL *)url {
129 | NSDictionary *parameters = [NSDictionary bdb_dictionaryFromQueryString:url.query];
130 |
131 | if (parameters[BDBOAuth1OAuthTokenParameter] && parameters[BDBOAuth1OAuthVerifierParameter]) {
132 | [self.networkManager fetchAccessTokenWithPath:kBDBFlickrClientOAuthAccessTokenPath
133 | method:@"POST"
134 | requestToken:[BDBOAuth1Credential credentialWithQueryString:url.query]
135 | success:^(BDBOAuth1Credential *accessToken) {
136 | [[NSNotificationCenter defaultCenter] postNotificationName:BDBFlickrClientDidLogInNotification
137 | object:self
138 | userInfo:accessToken.userInfo];
139 | }
140 | failure:^(NSError *error) {
141 | NSLog(@"Error: %@", error.localizedDescription);
142 |
143 | dispatch_async(dispatch_get_main_queue(), ^{
144 | [[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Error", nil)
145 | message:NSLocalizedString(@"Could not acquire OAuth access token. Please try again later.", nil)
146 | delegate:self
147 | cancelButtonTitle:NSLocalizedString(@"Dismiss", nil)
148 | otherButtonTitles:nil] show];
149 | });
150 | }];
151 |
152 | return YES;
153 | }
154 |
155 | return NO;
156 | }
157 |
158 | - (void)deauthorize {
159 | [self.networkManager deauthorize];
160 |
161 | [[NSNotificationCenter defaultCenter] postNotificationName:BDBFlickrClientDidLogOutNotification object:self];
162 | }
163 |
164 | #pragma mark Helpers
165 | - (NSDictionary *)defaultRequestParameters {
166 | return @{@"api_key": self.apiKey,
167 | @"format": @"json",
168 | @"nojsoncallback": @(1)};
169 | }
170 |
171 | #pragma mark Photosets
172 | - (void)getPhotosetsWithCompletion:(void (^)(NSSet *, NSError *))completion {
173 | NSAssert(self.apiKey, @"API key not set.");
174 |
175 | NSMutableDictionary *params = [NSMutableDictionary dictionaryWithDictionary:[self defaultRequestParameters]];
176 | params[@"method"] = @"flickr.photosets.getList";
177 |
178 | static NSString *path = @"rest";
179 |
180 | [self.networkManager GET:path parameters:params progress:nil success:^(NSURLSessionDataTask *task, id responseObject) {
181 | [self parsePhotosetsFromAPIResponseObject:responseObject completion:completion];
182 | } failure:^(NSURLSessionDataTask *task, NSError *error) {
183 | completion(nil, error);
184 | }];
185 | }
186 |
187 | - (void)parsePhotosetsFromAPIResponseObject:(id)responseObject completion:(void (^)(NSSet *, NSError *))completion {
188 | if (![responseObject isKindOfClass:[NSDictionary class]]) {
189 | NSError *error = [NSError errorWithDomain:BDBFlickrClientErrorDomain
190 | code:1000
191 | userInfo:@{NSLocalizedDescriptionKey:NSLocalizedString(@"Unexpected response received from Flickr API.", nil)}];
192 |
193 | return completion(nil, error);
194 | }
195 |
196 | NSDictionary *response = responseObject;
197 |
198 | if (![response[@"stat"] isEqualToString:@"ok"]) {
199 | NSError *error = [NSError errorWithDomain:BDBFlickrClientErrorDomain
200 | code:1100
201 | userInfo:@{NSLocalizedDescriptionKey:response[@"message"]}];
202 |
203 | return completion(nil, error);
204 | }
205 |
206 | response = response[@"photosets"];
207 | NSMutableSet *photosets = [NSMutableSet set];
208 |
209 | for (NSDictionary *setInfo in response[@"photoset"]) {
210 | BDBFlickrPhotoset *set = [[BDBFlickrPhotoset alloc] initWithDictionary:setInfo];
211 | [photosets addObject:set];
212 | }
213 |
214 | completion(photosets, nil);
215 | }
216 |
217 | #pragma mark Photos
218 | - (void)getPhotosInPhotoset:(BDBFlickrPhotoset *)photoset completion:(void (^)(NSArray *, NSError *))completion {
219 | NSAssert(self.apiKey, @"API key not set.");
220 |
221 | NSMutableDictionary *params = [NSMutableDictionary dictionaryWithDictionary:[self defaultRequestParameters]];
222 | params[@"method"] = @"flickr.photosets.getPhotos";
223 | params[@"photoset_id"] = photoset.setId;
224 | params[@"extras"] = @"url_t, url_o";
225 |
226 | static NSString *path = @"rest";
227 |
228 | [self.networkManager GET:path parameters:params progress:nil success:^(NSURLSessionDataTask *task, id responseObject) {
229 | [self parsePhotosFromAPIResponseObject:responseObject completion:completion];
230 | } failure:^(NSURLSessionDataTask *task, NSError *error) {
231 | completion(nil, error);
232 | }];
233 | }
234 |
235 | - (void)parsePhotosFromAPIResponseObject:(id)responseObject completion:(void (^)(NSArray *, NSError *))completion {
236 | if (![responseObject isKindOfClass:[NSDictionary class]]) {
237 | NSError *error = [NSError errorWithDomain:BDBFlickrClientErrorDomain
238 | code:1000
239 | userInfo:@{NSLocalizedDescriptionKey:NSLocalizedString(@"Unexpected response received from Flickr API.", nil)}];
240 |
241 | return completion(nil, error);
242 | }
243 |
244 | NSDictionary *response = responseObject;
245 |
246 | if (![response[@"stat"] isEqualToString:@"ok"]) {
247 | NSError *error = [NSError errorWithDomain:BDBFlickrClientErrorDomain
248 | code:1100
249 | userInfo:@{NSLocalizedDescriptionKey:response[@"message"]}];
250 |
251 | return completion(nil, error);
252 | }
253 |
254 | response = response[@"photoset"];
255 | NSMutableArray *photos = [NSMutableArray array];
256 |
257 | for (NSDictionary *photoInfo in response[@"photo"]) {
258 | BDBFlickrPhoto *photo = [[BDBFlickrPhoto alloc] initWithDictionary:photoInfo];
259 | [photos addObject:photo];
260 | }
261 |
262 | completion(photos, nil);
263 | }
264 |
265 | @end
266 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/Flickr Demo/View Controllers/PhotosViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // PhotosViewController.m
3 | //
4 | // Copyright (c) 2014 Bradley David Bergeron
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | // this software and associated documentation files (the "Software"), to deal in
8 | // the Software without restriction, including without limitation the rights to
9 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | // the Software, and to permit persons to whom the Software is furnished to do so,
11 | // subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | #import "AppDelegate.h"
24 | #import "BDBFlickrClient.h"
25 | #import "BDBFlickrPhoto.h"
26 | #import "BDBFlickrPhotoset.h"
27 | #import "PhotoAlbumCell.h"
28 | #import "PhotoAlbumHeaderView.h"
29 | #import "PhotoAlbumLayout.h"
30 | #import "PhotosViewController.h"
31 |
32 | #import "AFNetworking/UIImageView+AFNetworking.h"
33 | #import "BBlock/UIKit+BBlock.h"
34 |
35 |
36 | static NSString * const kPhotoAlbumHeaderViewReuseIdentifier = @"PhotoAlbumHeaderView";
37 | static NSString * const kPhotoAlbumPhotoCellReuseIdentifier = @"PhotoAlbumCell";
38 |
39 |
40 | #pragma mark -
41 | @interface PhotosViewController ()
42 |
43 | @property (nonatomic) UIRefreshControl *refreshControl;
44 |
45 | @property (nonatomic) UINib *photoAlbumHeaderNib;
46 | @property (nonatomic) PhotoAlbumHeaderView *photoAlbumHeader;
47 |
48 | @property (nonatomic) NSSet *photosets;
49 | @property (nonatomic) NSArray *sortedPhotosets;
50 | @property (nonatomic) NSUInteger numberOfSetsLoading;
51 |
52 | @property (nonatomic) NSUInteger imagesPerRow;
53 |
54 | - (void)logInOut;
55 |
56 | @end
57 |
58 | #pragma mark -
59 | @implementation PhotosViewController
60 |
61 | - (id)init {
62 | PhotoAlbumLayout *photosLayout = [PhotoAlbumLayout new];
63 | photosLayout.scrollDirection = UICollectionViewScrollDirectionVertical;
64 |
65 | self = [super initWithCollectionViewLayout:photosLayout];
66 |
67 | if (self) {
68 | // Instantiate ivars
69 | _photosets = [NSSet set];
70 | _sortedPhotosets = [NSArray array];
71 | _numberOfSetsLoading = 0;
72 |
73 | _refreshControl = [UIRefreshControl new];
74 | [_refreshControl addTarget:self action:@selector(loadImages) forControlEvents:UIControlEventValueChanged];
75 | [self.collectionView addSubview:_refreshControl];
76 |
77 | // Configure collection view
78 | self.collectionView.backgroundColor = [UIColor whiteColor];
79 | self.collectionView.alwaysBounceVertical = YES;
80 |
81 | if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
82 | self.edgesForExtendedLayout = UIRectEdgeNone;
83 | }
84 |
85 | // Register for notifications
86 | [[NSNotificationCenter defaultCenter] addObserverForName:BDBFlickrClientDidLogInNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
87 | [self loadImages];
88 |
89 | [self updateLogInOutButton];
90 | }];
91 |
92 | [[NSNotificationCenter defaultCenter] addObserverForName:BDBFlickrClientDidLogOutNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
93 | self.photosets = [NSMutableSet set];
94 | self.sortedPhotosets = [NSArray array];
95 |
96 | [self.collectionView reloadData];
97 |
98 | [self updateLogInOutButton];
99 | }];
100 | }
101 |
102 | return self;
103 | }
104 |
105 | - (void)viewDidLoad {
106 | [super viewDidLoad];
107 |
108 | self.title = NSLocalizedString(@"Photos", nil);
109 |
110 | self.photoAlbumHeaderNib = [UINib nibWithNibName:kPhotoAlbumHeaderViewReuseIdentifier bundle:[NSBundle mainBundle]];
111 | self.photoAlbumHeader = [self.photoAlbumHeaderNib instantiateWithOwner:nil options:nil][0];
112 | [self.collectionView registerNib:self.photoAlbumHeaderNib
113 | forSupplementaryViewOfKind:UICollectionElementKindSectionHeader
114 | withReuseIdentifier:kPhotoAlbumHeaderViewReuseIdentifier];
115 |
116 | [self.collectionView registerClass:[PhotoAlbumCell class] forCellWithReuseIdentifier:kPhotoAlbumPhotoCellReuseIdentifier];
117 |
118 | [self updateLogInOutButton];
119 | }
120 |
121 | - (void)viewDidAppear:(BOOL)animated {
122 | [super viewDidAppear:animated];
123 |
124 | if ([[BDBFlickrClient sharedClient] isAuthorized]) {
125 | [self loadImages];
126 | }
127 | }
128 |
129 | - (void)viewWillLayoutSubviews {
130 | [super viewWillLayoutSubviews];
131 |
132 | if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
133 | self.imagesPerRow = 4;
134 | } else if (UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation])) {
135 | self.imagesPerRow = 6;
136 | } else {
137 | self.imagesPerRow = 10;
138 | }
139 | }
140 |
141 | - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
142 | [self.collectionViewLayout invalidateLayout];
143 | }
144 |
145 | - (void)dealloc {
146 | [[NSNotificationCenter defaultCenter] removeObserver:self];
147 | }
148 |
149 | #pragma mark Authorization
150 | - (void)logInOut {
151 | if ([[BDBFlickrClient sharedClient] isAuthorized]) {
152 | dispatch_async(dispatch_get_main_queue(), ^{
153 | [[[UIActionSheet alloc] initWithTitle:NSLocalizedString(@"Are you sure you want to log out?", nil)
154 | cancelButtonTitle:NSLocalizedString(@"Cancel", nil)
155 | destructiveButtonTitle:NSLocalizedString(@"Log Out", nil)
156 | otherButtonTitle:nil
157 | completionBlock:^(NSInteger buttonIndex, UIActionSheet *actionSheet) {
158 | if (buttonIndex == actionSheet.destructiveButtonIndex) {
159 | [[BDBFlickrClient sharedClient] deauthorize];
160 | }
161 | }]
162 | showInView:self.view];
163 | });
164 | } else {
165 | [[BDBFlickrClient sharedClient] authorize];
166 | }
167 | }
168 |
169 | - (void)updateLogInOutButton {
170 | NSString *logInOutString = ([[BDBFlickrClient sharedClient] isAuthorized]) ?
171 | NSLocalizedString(@"Log Out", nil) : NSLocalizedString(@"Log In", nil);
172 |
173 | if (self.navigationItem.rightBarButtonItem) {
174 | [self.navigationItem.rightBarButtonItem setTitle:logInOutString];
175 | } else {
176 | self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:logInOutString
177 | style:UIBarButtonItemStylePlain
178 | target:self
179 | action:@selector(logInOut)];
180 | }
181 | }
182 |
183 | #pragma mark Load Images
184 | - (void)loadImages {
185 | if (![[BDBFlickrClient sharedClient] isAuthorized]) {
186 | dispatch_async(dispatch_get_main_queue(), ^{
187 | [[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Not Logged In", nil)
188 | message:NSLocalizedString(@"You have to log in before you can view your photos!", nil)
189 | cancelButtonTitle:NSLocalizedString(@"Cancel", nil)
190 | otherButtonTitle:NSLocalizedString(@"Log In", nil)
191 | completionBlock:^(NSInteger buttonIndex, UIAlertView *alertView) {
192 | if (buttonIndex == alertView.cancelButtonIndex + 1) {
193 | [[BDBFlickrClient sharedClient] authorize];
194 | }
195 | }]
196 | show];
197 | });
198 |
199 | [self.refreshControl endRefreshing];
200 |
201 | return;
202 | }
203 |
204 | if (!self.refreshControl.isRefreshing) {
205 | [self.collectionView setContentOffset:CGPointMake(0, self.collectionView.contentOffset.y - self.refreshControl.frame.size.height)
206 | animated:NO];
207 | [self.refreshControl beginRefreshing];
208 | }
209 |
210 | [self loadPhotosets];
211 | }
212 |
213 | - (void)loadPhotosets {
214 | [[BDBFlickrClient sharedClient] getPhotosetsWithCompletion:^(NSSet *photosets, NSError *error) {
215 | if (!error) {
216 | self.photosets = photosets;
217 | self.numberOfSetsLoading = photosets.count;
218 |
219 | for (BDBFlickrPhotoset *photoset in photosets) {
220 | [self loadPhotosInSet:photoset];
221 | }
222 | } else {
223 | NSLog(@"Error: %@", error.localizedDescription);
224 |
225 | dispatch_async(dispatch_get_main_queue(), ^{
226 | [[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Error", nil)
227 | message:error.localizedDescription
228 | delegate:self
229 | cancelButtonTitle:NSLocalizedString(@"Dismiss", nil)
230 | otherButtonTitles:nil] show];
231 | });
232 | }
233 | }];
234 | }
235 |
236 | - (void)loadPhotosInSet:(BDBFlickrPhotoset *)photoset {
237 | [[BDBFlickrClient sharedClient] getPhotosInPhotoset:photoset completion:^(NSArray *photos, NSError *error) {
238 | self.numberOfSetsLoading--;
239 |
240 | if (!error) {
241 | photoset.photos = photos;
242 | } else {
243 | NSLog(@"Error: %@", error.localizedDescription);
244 |
245 | dispatch_async(dispatch_get_main_queue(), ^{
246 | [[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Error", nil)
247 | message:error.localizedDescription
248 | delegate:self
249 | cancelButtonTitle:NSLocalizedString(@"Dismiss", nil)
250 | otherButtonTitles:nil] show];
251 | });
252 | }
253 |
254 | if (self.numberOfSetsLoading == 0) {
255 | [self sortPhotosets];
256 | }
257 | }];
258 | }
259 |
260 | - (void)sortPhotosets {
261 | self.sortedPhotosets = [self.photosets.allObjects sortedArrayUsingComparator:^NSComparisonResult(BDBFlickrPhotoset *set1, BDBFlickrPhotoset *set2) {
262 | return [set1.dateCreated compare:set2.dateCreated];
263 | }];
264 |
265 | [self.collectionView reloadData];
266 | self.collectionView.scrollEnabled = YES;
267 |
268 | [self.refreshControl endRefreshing];
269 | }
270 |
271 | #pragma mark CollectionView DataSource
272 | - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
273 | return self.sortedPhotosets.count;
274 | }
275 |
276 | - (NSInteger)collectionView:(UICollectionView *)collectionView
277 | numberOfItemsInSection:(NSInteger)section {
278 | BDBFlickrPhotoset *photoset = self.sortedPhotosets[section];
279 |
280 | return photoset.photos.count;
281 | }
282 |
283 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
284 | cellForItemAtIndexPath:(NSIndexPath *)indexPath {
285 | PhotoAlbumCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kPhotoAlbumPhotoCellReuseIdentifier
286 | forIndexPath:indexPath];
287 |
288 | BDBFlickrPhotoset *photosetForCell = self.sortedPhotosets[indexPath.section];
289 | BDBFlickrPhoto *photo = photosetForCell.photos[indexPath.row];
290 |
291 | [cell.activityIndicator startAnimating];
292 |
293 | __weak PhotoAlbumCell *weakCell = cell;
294 | [weakCell.imageView setImageWithURLRequest:[NSURLRequest requestWithURL:photo.thumbnailURL]
295 | placeholderImage:nil
296 | success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
297 | weakCell.imageView.image = image;
298 |
299 | [weakCell.activityIndicator stopAnimating];
300 | }
301 | failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
302 | NSLog(@"Failed to load image for cell. %@", error.localizedDescription);
303 |
304 | [weakCell.activityIndicator stopAnimating];
305 | }];
306 |
307 | return cell;
308 | }
309 |
310 | - (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView
311 | viewForSupplementaryElementOfKind:(NSString *)kind
312 | atIndexPath:(NSIndexPath *)indexPath {
313 | BDBFlickrPhotoset *photosetForCell = self.sortedPhotosets[indexPath.section];
314 |
315 | PhotoAlbumHeaderView *headerView = [collectionView dequeueReusableSupplementaryViewOfKind:kind
316 | withReuseIdentifier:kPhotoAlbumHeaderViewReuseIdentifier
317 | forIndexPath:indexPath];
318 |
319 | headerView.albumTitleLabel.text = photosetForCell.title;
320 | headerView.photoCountLabel.text = [NSString stringWithFormat:NSLocalizedString(@"%lu photos", nil), (unsigned long)photosetForCell.photos.count];
321 |
322 | return headerView;
323 | }
324 |
325 | #pragma mark CollectionView Layout Delegate
326 | - (CGSize)collectionView:(UICollectionView *)collectionView
327 | layout:(UICollectionViewLayout *)collectionViewLayout
328 | sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
329 | CGFloat padding = [self collectionView:collectionView
330 | layout:collectionViewLayout
331 | minimumInteritemSpacingForSectionAtIndex:indexPath.section];
332 |
333 | CGFloat collectionWidth = self.view.bounds.size.width - padding * (self.imagesPerRow - 1);
334 | CGFloat imageWidth = collectionWidth / self.imagesPerRow;
335 |
336 | return CGSizeMake(imageWidth, imageWidth);
337 | }
338 |
339 | - (CGSize)collectionView:(UICollectionView *)collectionView
340 | layout:(UICollectionViewLayout *)collectionViewLayout
341 | referenceSizeForHeaderInSection:(NSInteger)section {
342 | return self.photoAlbumHeader.bounds.size;
343 | }
344 |
345 | - (UIEdgeInsets)collectionView:(UICollectionView *)collectionView
346 | layout:(UICollectionViewLayout *)collectionViewLayout
347 | insetForSectionAtIndex:(NSInteger)section {
348 | return UIEdgeInsetsMake(0, 0, 0, 0);
349 | }
350 |
351 | - (CGFloat)collectionView:(UICollectionView *)collectionView
352 | layout:(UICollectionViewLayout *)collectionViewLayout
353 | minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {
354 | return 3.0;
355 | }
356 |
357 | - (CGFloat)collectionView:(UICollectionView *)collectionView
358 | layout:(UICollectionViewLayout *)collectionViewLayout
359 | minimumLineSpacingForSectionAtIndex:(NSInteger)section {
360 | return [self collectionView:collectionView layout:collectionViewLayout minimumInteritemSpacingForSectionAtIndex:section];
361 | }
362 |
363 | @end
364 |
--------------------------------------------------------------------------------
/BDBOAuth1Manager/BDBOAuth1RequestSerializer.m:
--------------------------------------------------------------------------------
1 | //
2 | // BDBOAuth1RequestSerializer.m
3 | //
4 | // Copyright (c) 2013-2015 Bradley David Bergeron
5 | //
6 | // Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | // this software and associated documentation files (the "Software"), to deal in
8 | // the Software without restriction, including without limitation the rights to
9 | // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | // the Software, and to permit persons to whom the Software is furnished to do so,
11 | // subject to the following conditions:
12 | //
13 | // The above copyright notice and this permission notice shall be included in all
14 | // copies or substantial portions of the Software.
15 | //
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
23 | #import
24 |
25 | #import "BDBOAuth1RequestSerializer.h"
26 |
27 | #import "NSDictionary+BDBOAuth1Manager.h"
28 | #import "NSString+BDBOAuth1Manager.h"
29 |
30 |
31 | // Exported
32 | NSString * const BDBOAuth1ErrorDomain = @"BDBOAuth1ErrorDomain";
33 |
34 | NSString * const BDBOAuth1OAuthTokenParameter = @"oauth_token";
35 | NSString * const BDBOAuth1OAuthTokenSecretParameter = @"oauth_token_secret";
36 | NSString * const BDBOAuth1OAuthVerifierParameter = @"oauth_verifier";
37 | NSString * const BDBOAuth1OAuthTokenDurationParameter = @"oauth_token_duration";
38 | NSString * const BDBOAuth1OAuthSignatureParameter = @"oauth_signature";
39 | NSString * const BDBOAuth1OAuthCallbackParameter = @"oauth_callback";
40 |
41 | // Internal
42 | NSString * const BDBOAuth1SignatureVersionParameter = @"oauth_version";
43 | NSString * const BDBOAuth1SignatureConsumerKeyParameter = @"oauth_consumer_key";
44 | NSString * const BDBOAuth1SignatureTimestampParameter = @"oauth_timestamp";
45 | NSString * const BDBOAuth1SignatureMethodParameter = @"oauth_signature_method";
46 | NSString * const BDBOAuth1SignatureNonceParameter = @"oauth_nonce";
47 |
48 |
49 | #pragma mark -
50 | @interface BDBOAuth1Credential ()
51 |
52 | @property (nonatomic, copy, readwrite) NSString *token;
53 | @property (nonatomic, copy, readwrite) NSString *secret;
54 |
55 | @property (nonatomic) NSDate *expiration;
56 |
57 | @end
58 |
59 |
60 | #pragma mark -
61 | @implementation BDBOAuth1Credential
62 |
63 | #pragma mark Initialization
64 | + (instancetype)credentialWithToken:(NSString *)token
65 | secret:(NSString *)secret
66 | expiration:(NSDate *)expiration {
67 | return [[[self class] alloc] initWithToken:token
68 | secret:secret
69 | expiration:expiration];
70 | }
71 |
72 | - (instancetype)initWithToken:(NSString *)token
73 | secret:(NSString *)secret
74 | expiration:(NSDate *)expiration {
75 | NSParameterAssert(token);
76 |
77 | self = [super init];
78 |
79 | if (self) {
80 | _token = token;
81 | _secret = secret;
82 | _expiration = expiration;
83 | }
84 |
85 | return self;
86 | }
87 |
88 | + (instancetype)credentialWithQueryString:(NSString *)queryString {
89 | return [[[self class] alloc] initWithQueryString:queryString];
90 | }
91 |
92 | - (instancetype)initWithQueryString:(NSString *)queryString {
93 | NSDictionary *attributes = [NSDictionary bdb_dictionaryFromQueryString:queryString];
94 |
95 | NSString *token = attributes[BDBOAuth1OAuthTokenParameter];
96 | NSString *secret = attributes[BDBOAuth1OAuthTokenSecretParameter];
97 | NSString *verifier = attributes[BDBOAuth1OAuthVerifierParameter];
98 |
99 | NSDate *expiration = nil;
100 |
101 | if (attributes[BDBOAuth1OAuthTokenDurationParameter]) {
102 | expiration = [NSDate dateWithTimeIntervalSinceNow:[attributes[BDBOAuth1OAuthTokenDurationParameter] doubleValue]];
103 | }
104 |
105 | self = [self initWithToken:token secret:secret expiration:expiration];
106 |
107 | if (self) {
108 | _verifier = verifier;
109 |
110 | NSMutableDictionary *mutableUserInfo = [attributes mutableCopy];
111 | [mutableUserInfo removeObjectsForKeys:@[BDBOAuth1OAuthTokenParameter,
112 | BDBOAuth1OAuthTokenSecretParameter,
113 | BDBOAuth1OAuthVerifierParameter,
114 | BDBOAuth1OAuthTokenDurationParameter]];
115 |
116 | if (mutableUserInfo.count > 0) {
117 | _userInfo = [NSDictionary dictionaryWithDictionary:mutableUserInfo];
118 | }
119 | }
120 |
121 | return self;
122 | }
123 |
124 | #pragma mark Properties
125 | - (BOOL)isExpired {
126 | if (!self.expiration) {
127 | return NO;
128 | } else {
129 | return [self.expiration compare:[NSDate date]] == NSOrderedAscending;
130 | }
131 | }
132 |
133 | #pragma mark NSCoding
134 | - (id)initWithCoder:(NSCoder *)decoder {
135 | self = [super init];
136 |
137 | if (self) {
138 | _token = [decoder decodeObjectForKey:NSStringFromSelector(@selector(token))];
139 | _secret = [decoder decodeObjectForKey:NSStringFromSelector(@selector(secret))];
140 | _verifier = [decoder decodeObjectForKey:NSStringFromSelector(@selector(verifier))];
141 | _expiration = [decoder decodeObjectForKey:NSStringFromSelector(@selector(expiration))];
142 | _userInfo = [decoder decodeObjectForKey:NSStringFromSelector(@selector(userInfo))];
143 | }
144 |
145 | return self;
146 | }
147 |
148 | - (void)encodeWithCoder:(NSCoder *)coder {
149 | [coder encodeObject:self.token forKey:NSStringFromSelector(@selector(token))];
150 | [coder encodeObject:self.secret forKey:NSStringFromSelector(@selector(secret))];
151 | [coder encodeObject:self.verifier forKey:NSStringFromSelector(@selector(verifier))];
152 | [coder encodeObject:self.expiration forKey:NSStringFromSelector(@selector(expiration))];
153 | [coder encodeObject:self.userInfo forKey:NSStringFromSelector(@selector(userInfo))];
154 | }
155 |
156 | #pragma mark NSCopying
157 | - (id)copyWithZone:(NSZone *)zone {
158 | BDBOAuth1Credential *copy = [[[self class] allocWithZone:zone] initWithToken:self.token
159 | secret:self.secret
160 | expiration:self.expiration];
161 | copy.verifier = self.verifier;
162 | copy.userInfo = self.userInfo;
163 |
164 | return copy;
165 | }
166 |
167 | @end
168 |
169 |
170 | #pragma mark -
171 | @interface BDBOAuth1RequestSerializer ()
172 |
173 | @property (nonatomic, copy) NSString *service;
174 | @property (nonatomic, copy) NSString *consumerKey;
175 | @property (nonatomic, copy) NSString *consumerSecret;
176 |
177 | - (NSString *)OAuthSignatureForMethod:(NSString *)method
178 | URLString:(NSString *)URLString
179 | parameters:(NSDictionary *)parameters
180 | error:(NSError *__autoreleasing *)error;
181 | - (NSString *)OAuthAuthorizationHeaderForMethod:(NSString *)method
182 | URLString:(NSString *)URLString
183 | parameters:(NSDictionary *)parameters
184 | error:(NSError *__autoreleasing *)error;
185 |
186 | @end
187 |
188 |
189 | #pragma mark -
190 | @implementation BDBOAuth1RequestSerializer
191 |
192 | #pragma mark Initialization
193 | + (instancetype)serializerForService:(NSString *)service
194 | withConsumerKey:(NSString *)consumerKey
195 | consumerSecret:(NSString *)consumerSecret {
196 | return [[[self class] alloc] initWithService:service
197 | consumerKey:consumerKey
198 | consumerSecret:consumerSecret];
199 | }
200 |
201 | - (instancetype)initWithService:(NSString *)service
202 | consumerKey:(NSString *)consumerKey
203 | consumerSecret:(NSString *)consumerSecret {
204 | self = [super init];
205 |
206 | if (self) {
207 | _service = service;
208 | _consumerKey = consumerKey;
209 | _consumerSecret = consumerSecret;
210 |
211 | _accessToken = [self readAccessTokenFromKeychain];
212 | }
213 |
214 | return self;
215 | }
216 |
217 | #pragma mark Storing the Access Token
218 | static NSDictionary *OAuthKeychainDictionaryForService(NSString *service) {
219 | return @{(__bridge id)kSecClass:(__bridge id)kSecClassGenericPassword,
220 | (__bridge id)kSecAttrService:service};
221 | }
222 |
223 | - (BDBOAuth1Credential *)readAccessTokenFromKeychain {
224 | NSMutableDictionary *dictionary = [OAuthKeychainDictionaryForService(self.service) mutableCopy];
225 | dictionary[(__bridge id)kSecReturnData] = (__bridge id)kCFBooleanTrue;
226 | dictionary[(__bridge id)kSecMatchLimit] = (__bridge id)kSecMatchLimitOne;
227 |
228 | CFDataRef result = nil;
229 | OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)dictionary, (CFTypeRef *)&result);
230 | NSData *data = (__bridge_transfer NSData *)result;
231 |
232 | if (status == noErr && data) {
233 | @try {
234 | NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
235 | [unarchiver setClass:[BDBOAuth1Credential class] forClassName:@"BDBOAuthToken"];
236 |
237 | return [unarchiver decodeObjectForKey:NSKeyedArchiveRootObjectKey];
238 | }
239 | @catch (NSException *exception) {
240 | return nil;
241 | }
242 | }
243 |
244 | return nil;
245 | }
246 |
247 | - (BOOL)saveAccessToken:(BDBOAuth1Credential *)accessToken {
248 | NSMutableDictionary *dictionary = [OAuthKeychainDictionaryForService(self.service) mutableCopy];
249 |
250 | NSMutableDictionary *updateDictionary = [NSMutableDictionary dictionary];
251 | NSData *data = [NSKeyedArchiver archivedDataWithRootObject:accessToken];
252 | updateDictionary[(__bridge id)kSecValueData] = data;
253 |
254 | OSStatus status;
255 |
256 | if (self.accessToken) {
257 | status = SecItemUpdate((__bridge CFDictionaryRef)dictionary, (__bridge CFDictionaryRef)updateDictionary);
258 | } else {
259 | [dictionary addEntriesFromDictionary:updateDictionary];
260 | status = SecItemAdd((__bridge CFDictionaryRef)dictionary, NULL);
261 | }
262 |
263 | _accessToken = accessToken;
264 |
265 | if (status == noErr) {
266 | return YES;
267 | }
268 |
269 | return NO;
270 | }
271 |
272 | - (BOOL)removeAccessToken {
273 | OSStatus status = SecItemDelete((__bridge CFDictionaryRef)OAuthKeychainDictionaryForService(self.service));
274 |
275 | _accessToken = nil;
276 |
277 | if (status == noErr) {
278 | return YES;
279 | }
280 |
281 | return NO;
282 | }
283 |
284 | #pragma mark OAuth Parameters
285 | - (NSDictionary *)OAuthParameters {
286 | NSMutableDictionary *parameters = [NSMutableDictionary dictionary];
287 | parameters[BDBOAuth1SignatureVersionParameter] = @"1.0";
288 | parameters[BDBOAuth1SignatureConsumerKeyParameter] = self.consumerKey;
289 | parameters[BDBOAuth1SignatureTimestampParameter] = [@(floor([[NSDate date] timeIntervalSince1970])) stringValue];
290 | parameters[BDBOAuth1SignatureMethodParameter] = @"HMAC-SHA1";
291 |
292 | CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault);
293 | CFUUIDBytes uuidBytes = CFUUIDGetUUIDBytes(uuid);
294 | CFRelease(uuid);
295 |
296 | #if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000) || (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090)
297 | parameters[BDBOAuth1SignatureNonceParameter] = [[NSData dataWithBytes:&uuidBytes length:sizeof(uuidBytes)] base64EncodedStringWithOptions:0];
298 | #else
299 | parameters[BDBOAuth1SignatureNonceParameter] = [[NSData dataWithBytes:&uuidBytes length:sizeof(uuidBytes)] base64Encoding];
300 | #endif
301 |
302 | return parameters;
303 | }
304 |
305 | - (NSString *)OAuthSignatureForMethod:(NSString *)method
306 | URLString:(NSString *)URLString
307 | parameters:(NSDictionary *)parameters
308 | error:(NSError *__autoreleasing *)error {
309 | NSMutableURLRequest *request = [super requestWithMethod:@"GET" URLString:URLString parameters:parameters error:error];
310 |
311 | [request setHTTPMethod:method];
312 |
313 | NSString *secret = @"";
314 |
315 | if (self.accessToken) {
316 | secret = self.accessToken.secret;
317 | } else if (self.requestToken) {
318 | secret = self.requestToken.secret;
319 | }
320 |
321 | NSString *secretString = [[self.consumerSecret bdb_URLEncode] stringByAppendingFormat:@"&%@", [secret bdb_URLEncode]];
322 | NSData *secretData = [secretString dataUsingEncoding:NSUTF8StringEncoding];
323 |
324 | /**
325 | * Create signature from request data
326 | *
327 | * 1. Convert the HTTP Method to uppercase and set the output string equal to this value.
328 | * 2. Append the '&' character to the output string.
329 | * 3. Percent encode the URL and append it to the output string.
330 | * 4. Append the '&' character to the output string.
331 | * 5. Percent encode the query string and append it to the output string.
332 | */
333 | NSString *requestMethod = [[request HTTPMethod] uppercaseString];
334 | NSString *requestURL = [[[[request URL] absoluteString] componentsSeparatedByString:@"?"][0] bdb_URLEncode];
335 |
336 | NSArray *sortedQueryString = [[[[request URL] query] componentsSeparatedByString:@"&"] sortedArrayUsingSelector:@selector(compare:)];
337 | NSString *queryString = [[[sortedQueryString componentsJoinedByString:@"&"] bdb_URLEncodeSlashesAndQuestionMarks] bdb_URLEncode];
338 |
339 | NSString *requestString = [NSString stringWithFormat:@"%@&%@&%@", requestMethod, requestURL, queryString];
340 | NSData *requestData = [requestString dataUsingEncoding:NSUTF8StringEncoding];
341 |
342 | uint8_t digest[CC_SHA1_DIGEST_LENGTH];
343 | CCHmacContext context;
344 | CCHmacInit(&context, kCCHmacAlgSHA1, [secretData bytes], [secretData length]);
345 | CCHmacUpdate(&context, [requestData bytes], [requestData length]);
346 | CCHmacFinal(&context, digest);
347 |
348 | #if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000) || (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090)
349 | return [[NSData dataWithBytes:digest length:CC_SHA1_DIGEST_LENGTH] base64EncodedStringWithOptions:0];
350 | #else
351 | return [[NSData dataWithBytes:digest length:CC_SHA1_DIGEST_LENGTH] base64Encoding];
352 | #endif
353 | }
354 |
355 | - (NSString *)OAuthAuthorizationHeaderForMethod:(NSString *)method
356 | URLString:(NSString *)URLString
357 | parameters:(NSDictionary *)parameters
358 | error:(NSError *__autoreleasing *)error {
359 | NSParameterAssert(method);
360 | NSParameterAssert(URLString);
361 |
362 | NSMutableDictionary *mutableParameters;
363 |
364 | if (parameters) {
365 | mutableParameters = [parameters mutableCopy];
366 | } else {
367 | mutableParameters = [NSMutableDictionary dictionary];
368 | }
369 |
370 | NSMutableDictionary *mutableAuthorizationParameters = [NSMutableDictionary dictionary];
371 |
372 | if (self.consumerKey && self.consumerSecret) {
373 | [mutableAuthorizationParameters addEntriesFromDictionary:[self OAuthParameters]];
374 |
375 | NSString *token = self.accessToken.token;
376 |
377 | if (token) {
378 | mutableAuthorizationParameters[BDBOAuth1OAuthTokenParameter] = token;
379 | }
380 | }
381 |
382 | [mutableParameters enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
383 | if ([key isKindOfClass:[NSString class]] && [key hasPrefix:@"oauth_"]) {
384 | mutableAuthorizationParameters[key] = obj;
385 | }
386 | }];
387 |
388 | [mutableParameters addEntriesFromDictionary:mutableAuthorizationParameters];
389 | mutableAuthorizationParameters[BDBOAuth1OAuthSignatureParameter] = [self OAuthSignatureForMethod:method
390 | URLString:URLString
391 | parameters:mutableParameters
392 | error:error];
393 |
394 | NSArray *sortedComponents = [[[mutableAuthorizationParameters bdb_queryStringRepresentation] componentsSeparatedByString:@"&"] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
395 |
396 | NSMutableArray *mutableComponents = [NSMutableArray array];
397 |
398 | for (NSString *component in sortedComponents) {
399 | NSArray *subcomponents = [component componentsSeparatedByString:@"="];
400 |
401 | if ([subcomponents count] == 2) {
402 | [mutableComponents addObject:[NSString stringWithFormat:@"%@=\"%@\"", subcomponents[0], subcomponents[1]]];
403 | }
404 | }
405 |
406 | return [NSString stringWithFormat:@"OAuth %@", [mutableComponents componentsJoinedByString:@", "]];
407 | }
408 |
409 | #pragma mark URL Requests
410 | - (NSMutableURLRequest *)requestWithMethod:(NSString *)method
411 | URLString:(NSString *)URLString
412 | parameters:(NSDictionary *)parameters
413 | error:(NSError *__autoreleasing *)error {
414 | NSMutableDictionary *mutableParameters = [parameters mutableCopy];
415 |
416 | for (NSString *key in parameters) {
417 | if ([key hasPrefix:@"oauth_"]) {
418 | [mutableParameters removeObjectForKey:key];
419 | }
420 | }
421 |
422 | NSMutableURLRequest *request = [super requestWithMethod:method
423 | URLString:URLString
424 | parameters:mutableParameters
425 | error:error];
426 |
427 | // Only use parameters in the request entity body (with a content-type of `application/x-www-form-urlencoded`).
428 | // See RFC 5849, Section 3.4.1.3.1 http://tools.ietf.org/html/rfc5849#section-3.4
429 | NSDictionary *authorizationParameters = parameters;
430 |
431 | if (![self.HTTPMethodsEncodingParametersInURI containsObject:method.uppercaseString]) {
432 | if (![[request valueForHTTPHeaderField:@"Content-Type"] hasPrefix:@"application/x-www-form-urlencoded"]) {
433 | authorizationParameters = nil;
434 | }
435 | }
436 |
437 | [request setValue:[self OAuthAuthorizationHeaderForMethod:method
438 | URLString:URLString
439 | parameters:authorizationParameters
440 | error:error] forHTTPHeaderField:@"Authorization"];
441 | [request setHTTPShouldHandleCookies:NO];
442 |
443 | return request;
444 | }
445 |
446 | - (NSMutableURLRequest *)multipartFormRequestWithMethod:(NSString *)method
447 | URLString:(NSString *)URLString
448 | parameters:(NSDictionary *)parameters
449 | constructingBodyWithBlock:(void (^)(id))block
450 | error:(NSError *__autoreleasing *)error {
451 | NSMutableDictionary *mutableParameters = [parameters mutableCopy];
452 |
453 | for (NSString *key in parameters) {
454 | if ([key hasPrefix:@"oauth_"]) {
455 | [mutableParameters removeObjectForKey:key];
456 | }
457 | }
458 |
459 | NSMutableURLRequest *request = [super multipartFormRequestWithMethod:method
460 | URLString:URLString
461 | parameters:mutableParameters
462 | constructingBodyWithBlock:block
463 | error:error];
464 |
465 | // Only use parameters in the request entity body (with a content-type of `application/x-www-form-urlencoded`).
466 | // See RFC 5849, Section 3.4.1.3.1 http://tools.ietf.org/html/rfc5849#section-3.4
467 | NSDictionary *authorizationParameters = parameters;
468 |
469 | if (!([self.HTTPMethodsEncodingParametersInURI containsObject:method.uppercaseString])) {
470 | if (![[request valueForHTTPHeaderField:@"Content-Type"] hasPrefix:@"application/x-www-form-urlencoded"]) {
471 | authorizationParameters = nil;
472 | }
473 | }
474 |
475 | [request setValue:[self OAuthAuthorizationHeaderForMethod:method
476 | URLString:URLString
477 | parameters:authorizationParameters
478 | error:error] forHTTPHeaderField:@"Authorization"];
479 | [request setHTTPShouldHandleCookies:NO];
480 |
481 | return request;
482 | }
483 |
484 | @end
485 |
--------------------------------------------------------------------------------
/BDBOAuth1ManagerDemo/BDBOAuth1ManagerDemo.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 7B50EFDB2936607FA87A794E /* (null) in Frameworks */ = {isa = PBXBuildFile; settings = {ATTRIBUTES = (Weak, ); }; };
11 | 8D7A2DB0C746C903C5229408 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 9933D252FFDAB621FA733223 /* libPods.a */; };
12 | E816CAD519565291009877A6 /* BDBTwitterClient.m in Sources */ = {isa = PBXBuildFile; fileRef = E816CAD419565291009877A6 /* BDBTwitterClient.m */; };
13 | E81E4E34B39A39E45479B4A5 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 9933D252FFDAB621FA733223 /* libPods.a */; };
14 | E8284C8518464EF900B3C6AA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = E8284C6918464ED900B3C6AA /* AppDelegate.m */; };
15 | E8284C8F18464EF900B3C6AA /* PhotosViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E8284C7418464ED900B3C6AA /* PhotosViewController.m */; };
16 | E8284C9F18464EF900B3C6AA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = E8284C7118464ED900B3C6AA /* main.m */; };
17 | E8284CA618464EF900B3C6AA /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = E8284C6D18464ED900B3C6AA /* InfoPlist.strings */; };
18 | E8284CB01846500000B3C6AA /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = E8F376351808769B00C40148 /* InfoPlist.strings */; };
19 | E847027019D4DD2E00C10210 /* Flickr.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E847026F19D4DD2E00C10210 /* Flickr.xcassets */; };
20 | E88595A8184A751500BD7AEC /* BDBFlickrClient.m in Sources */ = {isa = PBXBuildFile; fileRef = E88595A7184A751500BD7AEC /* BDBFlickrClient.m */; };
21 | E8C6BAA119D4DDC300A2102A /* Launch Screen.xib in Resources */ = {isa = PBXBuildFile; fileRef = E8C6BAA019D4DDC300A2102A /* Launch Screen.xib */; };
22 | E8C6BAA319D4E02E00A2102A /* Twitter.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E8C6BAA219D4E02E00A2102A /* Twitter.xcassets */; };
23 | E8C6BAA519D4E05A00A2102A /* Launch Screen.xib in Resources */ = {isa = PBXBuildFile; fileRef = E8C6BAA419D4E05A00A2102A /* Launch Screen.xib */; };
24 | E8D381E319592A5C00284883 /* BDBTweet.m in Sources */ = {isa = PBXBuildFile; fileRef = E8D381E11959276400284883 /* BDBTweet.m */; };
25 | E8D8E0BF180884DD00CDCB7D /* TweetsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E8D8E0BE180884DD00CDCB7D /* TweetsViewController.m */; };
26 | E8E54C20180C830A00010143 /* TweetCell.m in Sources */ = {isa = PBXBuildFile; fileRef = E8E54C1F180C830A00010143 /* TweetCell.m */; };
27 | E8F0016919618C7C00980015 /* TweetCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = E8F0016819618C7C00980015 /* TweetCell.xib */; };
28 | E8F375D91808743300C40148 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = E8F375D81808743300C40148 /* AppDelegate.m */; };
29 | E8F3763C1808769B00C40148 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = E8F376391808769B00C40148 /* main.m */; };
30 | E8F616881846555D008D9DC5 /* PhotoAlbumCell.m in Sources */ = {isa = PBXBuildFile; fileRef = E8F616821846555D008D9DC5 /* PhotoAlbumCell.m */; };
31 | E8F616891846555D008D9DC5 /* PhotoAlbumHeaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = E8F616841846555D008D9DC5 /* PhotoAlbumHeaderView.m */; };
32 | E8F6168A1846555D008D9DC5 /* PhotoAlbumHeaderView.xib in Resources */ = {isa = PBXBuildFile; fileRef = E8F616851846555D008D9DC5 /* PhotoAlbumHeaderView.xib */; };
33 | E8F6168B1846555D008D9DC5 /* PhotoAlbumLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = E8F616871846555D008D9DC5 /* PhotoAlbumLayout.m */; };
34 | E8F6169218496326008D9DC5 /* BDBFlickrPhotoset.m in Sources */ = {isa = PBXBuildFile; fileRef = E8F6169118496326008D9DC5 /* BDBFlickrPhotoset.m */; };
35 | E8F6169518496578008D9DC5 /* BDBFlickrPhoto.m in Sources */ = {isa = PBXBuildFile; fileRef = E8F6169418496578008D9DC5 /* BDBFlickrPhoto.m */; };
36 | /* End PBXBuildFile section */
37 |
38 | /* Begin PBXFileReference section */
39 | 3C23EA492A8642587406840B /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = ""; };
40 | 9933D252FFDAB621FA733223 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; };
41 | D4E42A9BCC3D91597BD0D127 /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = ""; };
42 | E816CAD319565291009877A6 /* BDBTwitterClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BDBTwitterClient.h; path = Twitter/BDBTwitterClient.h; sourceTree = ""; };
43 | E816CAD419565291009877A6 /* BDBTwitterClient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BDBTwitterClient.m; path = Twitter/BDBTwitterClient.m; sourceTree = ""; };
44 | E8284C6818464ED900B3C6AA /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
45 | E8284C6918464ED900B3C6AA /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
46 | E8284C6E18464ED900B3C6AA /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; };
47 | E8284C6F18464ED900B3C6AA /* Flickr Demo-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Flickr Demo-Info.plist"; sourceTree = ""; };
48 | E8284C7018464ED900B3C6AA /* Flickr Demo-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Flickr Demo-Prefix.pch"; sourceTree = ""; };
49 | E8284C7118464ED900B3C6AA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
50 | E8284C7318464ED900B3C6AA /* PhotosViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PhotosViewController.h; sourceTree = ""; };
51 | E8284C7418464ED900B3C6AA /* PhotosViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PhotosViewController.m; sourceTree = ""; };
52 | E8284CAE18464EF900B3C6AA /* Flickr Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Flickr Demo.app"; sourceTree = BUILT_PRODUCTS_DIR; };
53 | E847026F19D4DD2E00C10210 /* Flickr.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Flickr.xcassets; sourceTree = ""; };
54 | E88595A6184A751500BD7AEC /* BDBFlickrClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BDBFlickrClient.h; sourceTree = ""; };
55 | E88595A7184A751500BD7AEC /* BDBFlickrClient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BDBFlickrClient.m; sourceTree = ""; };
56 | E8C6BAA019D4DDC300A2102A /* Launch Screen.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = "Launch Screen.xib"; sourceTree = ""; };
57 | E8C6BAA219D4E02E00A2102A /* Twitter.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Twitter.xcassets; sourceTree = ""; };
58 | E8C6BAA419D4E05A00A2102A /* Launch Screen.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = "Launch Screen.xib"; sourceTree = ""; };
59 | E8D381E01959276400284883 /* BDBTweet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BDBTweet.h; path = Twitter/BDBTweet.h; sourceTree = ""; };
60 | E8D381E11959276400284883 /* BDBTweet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BDBTweet.m; path = Twitter/BDBTweet.m; sourceTree = ""; };
61 | E8D8E0BD180884DD00CDCB7D /* TweetsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TweetsViewController.h; sourceTree = ""; };
62 | E8D8E0BE180884DD00CDCB7D /* TweetsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TweetsViewController.m; sourceTree = ""; };
63 | E8E54C1E180C830A00010143 /* TweetCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TweetCell.h; sourceTree = ""; };
64 | E8E54C1F180C830A00010143 /* TweetCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TweetCell.m; sourceTree = ""; };
65 | E8F0016819618C7C00980015 /* TweetCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = TweetCell.xib; sourceTree = ""; };
66 | E8F375C51808743300C40148 /* Twitter Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Twitter Demo.app"; sourceTree = BUILT_PRODUCTS_DIR; };
67 | E8F375D71808743300C40148 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
68 | E8F375D81808743300C40148 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
69 | E8F376361808769B00C40148 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; };
70 | E8F376371808769B00C40148 /* Twitter Demo-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Twitter Demo-Info.plist"; sourceTree = ""; };
71 | E8F376381808769B00C40148 /* Twitter Demo-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Twitter Demo-Prefix.pch"; sourceTree = ""; };
72 | E8F376391808769B00C40148 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
73 | E8F616811846555D008D9DC5 /* PhotoAlbumCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PhotoAlbumCell.h; sourceTree = ""; };
74 | E8F616821846555D008D9DC5 /* PhotoAlbumCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PhotoAlbumCell.m; sourceTree = ""; };
75 | E8F616831846555D008D9DC5 /* PhotoAlbumHeaderView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PhotoAlbumHeaderView.h; sourceTree = ""; };
76 | E8F616841846555D008D9DC5 /* PhotoAlbumHeaderView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PhotoAlbumHeaderView.m; sourceTree = ""; };
77 | E8F616851846555D008D9DC5 /* PhotoAlbumHeaderView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = PhotoAlbumHeaderView.xib; sourceTree = ""; };
78 | E8F616861846555D008D9DC5 /* PhotoAlbumLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PhotoAlbumLayout.h; sourceTree = ""; };
79 | E8F616871846555D008D9DC5 /* PhotoAlbumLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PhotoAlbumLayout.m; sourceTree = ""; };
80 | E8F6169018496326008D9DC5 /* BDBFlickrPhotoset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BDBFlickrPhotoset.h; sourceTree = ""; };
81 | E8F6169118496326008D9DC5 /* BDBFlickrPhotoset.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BDBFlickrPhotoset.m; sourceTree = ""; };
82 | E8F6169318496578008D9DC5 /* BDBFlickrPhoto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BDBFlickrPhoto.h; sourceTree = ""; };
83 | E8F6169418496578008D9DC5 /* BDBFlickrPhoto.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BDBFlickrPhoto.m; sourceTree = ""; };
84 | /* End PBXFileReference section */
85 |
86 | /* Begin PBXFrameworksBuildPhase section */
87 | E8284CA118464EF900B3C6AA /* Frameworks */ = {
88 | isa = PBXFrameworksBuildPhase;
89 | buildActionMask = 2147483647;
90 | files = (
91 | 7B50EFDB2936607FA87A794E /* (null) in Frameworks */,
92 | 8D7A2DB0C746C903C5229408 /* libPods.a in Frameworks */,
93 | );
94 | runOnlyForDeploymentPostprocessing = 0;
95 | };
96 | E8F375C21808743300C40148 /* Frameworks */ = {
97 | isa = PBXFrameworksBuildPhase;
98 | buildActionMask = 2147483647;
99 | files = (
100 | E81E4E34B39A39E45479B4A5 /* libPods.a in Frameworks */,
101 | );
102 | runOnlyForDeploymentPostprocessing = 0;
103 | };
104 | /* End PBXFrameworksBuildPhase section */
105 |
106 | /* Begin PBXGroup section */
107 | 9A6043C13D226C0657EA52EE /* Frameworks */ = {
108 | isa = PBXGroup;
109 | children = (
110 | 9933D252FFDAB621FA733223 /* libPods.a */,
111 | );
112 | name = Frameworks;
113 | sourceTree = "";
114 | };
115 | E816CAD21956525D009877A6 /* Twitter */ = {
116 | isa = PBXGroup;
117 | children = (
118 | E816CAD319565291009877A6 /* BDBTwitterClient.h */,
119 | E816CAD419565291009877A6 /* BDBTwitterClient.m */,
120 | E8D381E01959276400284883 /* BDBTweet.h */,
121 | E8D381E11959276400284883 /* BDBTweet.m */,
122 | );
123 | name = Twitter;
124 | sourceTree = "";
125 | };
126 | E8284C6718464ED900B3C6AA /* Flickr Demo */ = {
127 | isa = PBXGroup;
128 | children = (
129 | E88595A3184A28A800BD7AEC /* Resources */,
130 | E8F6168F18496326008D9DC5 /* Flickr */,
131 | E8284C7518464ED900B3C6AA /* Views */,
132 | E8284C7218464ED900B3C6AA /* View Controllers */,
133 | E8284C6818464ED900B3C6AA /* AppDelegate.h */,
134 | E8284C6918464ED900B3C6AA /* AppDelegate.m */,
135 | E8284C6C18464ED900B3C6AA /* Supporting Files */,
136 | );
137 | path = "Flickr Demo";
138 | sourceTree = "";
139 | };
140 | E8284C6C18464ED900B3C6AA /* Supporting Files */ = {
141 | isa = PBXGroup;
142 | children = (
143 | E8284C6D18464ED900B3C6AA /* InfoPlist.strings */,
144 | E8284C6F18464ED900B3C6AA /* Flickr Demo-Info.plist */,
145 | E8284C7018464ED900B3C6AA /* Flickr Demo-Prefix.pch */,
146 | E8284C7118464ED900B3C6AA /* main.m */,
147 | );
148 | path = "Supporting Files";
149 | sourceTree = "";
150 | };
151 | E8284C7218464ED900B3C6AA /* View Controllers */ = {
152 | isa = PBXGroup;
153 | children = (
154 | E8284C7318464ED900B3C6AA /* PhotosViewController.h */,
155 | E8284C7418464ED900B3C6AA /* PhotosViewController.m */,
156 | );
157 | path = "View Controllers";
158 | sourceTree = "";
159 | };
160 | E8284C7518464ED900B3C6AA /* Views */ = {
161 | isa = PBXGroup;
162 | children = (
163 | E8F616811846555D008D9DC5 /* PhotoAlbumCell.h */,
164 | E8F616821846555D008D9DC5 /* PhotoAlbumCell.m */,
165 | E8F616831846555D008D9DC5 /* PhotoAlbumHeaderView.h */,
166 | E8F616841846555D008D9DC5 /* PhotoAlbumHeaderView.m */,
167 | E8F616851846555D008D9DC5 /* PhotoAlbumHeaderView.xib */,
168 | E8F616861846555D008D9DC5 /* PhotoAlbumLayout.h */,
169 | E8F616871846555D008D9DC5 /* PhotoAlbumLayout.m */,
170 | );
171 | path = Views;
172 | sourceTree = "";
173 | };
174 | E88595A0184A289300BD7AEC /* Resources */ = {
175 | isa = PBXGroup;
176 | children = (
177 | E8C6BAA419D4E05A00A2102A /* Launch Screen.xib */,
178 | E8C6BAA219D4E02E00A2102A /* Twitter.xcassets */,
179 | );
180 | path = Resources;
181 | sourceTree = "";
182 | };
183 | E88595A3184A28A800BD7AEC /* Resources */ = {
184 | isa = PBXGroup;
185 | children = (
186 | E8C6BAA019D4DDC300A2102A /* Launch Screen.xib */,
187 | E847026F19D4DD2E00C10210 /* Flickr.xcassets */,
188 | );
189 | path = Resources;
190 | sourceTree = "";
191 | };
192 | E8D8E0C0180884E100CDCB7D /* View Controllers */ = {
193 | isa = PBXGroup;
194 | children = (
195 | E8D8E0BD180884DD00CDCB7D /* TweetsViewController.h */,
196 | E8D8E0BE180884DD00CDCB7D /* TweetsViewController.m */,
197 | );
198 | path = "View Controllers";
199 | sourceTree = "";
200 | };
201 | E8E54C1A180C81EA00010143 /* Views */ = {
202 | isa = PBXGroup;
203 | children = (
204 | E8E54C1E180C830A00010143 /* TweetCell.h */,
205 | E8E54C1F180C830A00010143 /* TweetCell.m */,
206 | E8F0016819618C7C00980015 /* TweetCell.xib */,
207 | );
208 | path = Views;
209 | sourceTree = "";
210 | };
211 | E8F375BC1808743300C40148 = {
212 | isa = PBXGroup;
213 | children = (
214 | E8284C6718464ED900B3C6AA /* Flickr Demo */,
215 | E8F375CE1808743300C40148 /* Twitter Demo */,
216 | E8F375C61808743300C40148 /* Products */,
217 | FC3EB9D2479E3EF337045269 /* Pods */,
218 | 9A6043C13D226C0657EA52EE /* Frameworks */,
219 | );
220 | sourceTree = "";
221 | };
222 | E8F375C61808743300C40148 /* Products */ = {
223 | isa = PBXGroup;
224 | children = (
225 | E8F375C51808743300C40148 /* Twitter Demo.app */,
226 | E8284CAE18464EF900B3C6AA /* Flickr Demo.app */,
227 | );
228 | name = Products;
229 | sourceTree = "";
230 | };
231 | E8F375CE1808743300C40148 /* Twitter Demo */ = {
232 | isa = PBXGroup;
233 | children = (
234 | E88595A0184A289300BD7AEC /* Resources */,
235 | E816CAD21956525D009877A6 /* Twitter */,
236 | E8E54C1A180C81EA00010143 /* Views */,
237 | E8D8E0C0180884E100CDCB7D /* View Controllers */,
238 | E8F375D71808743300C40148 /* AppDelegate.h */,
239 | E8F375D81808743300C40148 /* AppDelegate.m */,
240 | E8F376341808769B00C40148 /* Supporting Files */,
241 | );
242 | path = "Twitter Demo";
243 | sourceTree = "";
244 | };
245 | E8F376341808769B00C40148 /* Supporting Files */ = {
246 | isa = PBXGroup;
247 | children = (
248 | E8F376351808769B00C40148 /* InfoPlist.strings */,
249 | E8F376371808769B00C40148 /* Twitter Demo-Info.plist */,
250 | E8F376381808769B00C40148 /* Twitter Demo-Prefix.pch */,
251 | E8F376391808769B00C40148 /* main.m */,
252 | );
253 | path = "Supporting Files";
254 | sourceTree = "";
255 | };
256 | E8F6168F18496326008D9DC5 /* Flickr */ = {
257 | isa = PBXGroup;
258 | children = (
259 | E88595A6184A751500BD7AEC /* BDBFlickrClient.h */,
260 | E88595A7184A751500BD7AEC /* BDBFlickrClient.m */,
261 | E8F6169018496326008D9DC5 /* BDBFlickrPhotoset.h */,
262 | E8F6169118496326008D9DC5 /* BDBFlickrPhotoset.m */,
263 | E8F6169318496578008D9DC5 /* BDBFlickrPhoto.h */,
264 | E8F6169418496578008D9DC5 /* BDBFlickrPhoto.m */,
265 | );
266 | path = Flickr;
267 | sourceTree = "";
268 | };
269 | FC3EB9D2479E3EF337045269 /* Pods */ = {
270 | isa = PBXGroup;
271 | children = (
272 | D4E42A9BCC3D91597BD0D127 /* Pods.debug.xcconfig */,
273 | 3C23EA492A8642587406840B /* Pods.release.xcconfig */,
274 | );
275 | name = Pods;
276 | sourceTree = "";
277 | };
278 | /* End PBXGroup section */
279 |
280 | /* Begin PBXNativeTarget section */
281 | E8284C8118464EF900B3C6AA /* Flickr Demo */ = {
282 | isa = PBXNativeTarget;
283 | buildConfigurationList = E8284CAB18464EF900B3C6AA /* Build configuration list for PBXNativeTarget "Flickr Demo" */;
284 | buildPhases = (
285 | 5DD86A06D72F47E49726F4A5 /* Check Pods Manifest.lock */,
286 | E8284C8218464EF900B3C6AA /* Sources */,
287 | E8284CA118464EF900B3C6AA /* Frameworks */,
288 | E8284CA418464EF900B3C6AA /* Resources */,
289 | B7F71007CEE3472886B6578E /* Copy Pods Resources */,
290 | BAD9DA1CD21FA90113543637 /* Embed Pods Frameworks */,
291 | );
292 | buildRules = (
293 | );
294 | dependencies = (
295 | );
296 | name = "Flickr Demo";
297 | productName = Demo;
298 | productReference = E8284CAE18464EF900B3C6AA /* Flickr Demo.app */;
299 | productType = "com.apple.product-type.application";
300 | };
301 | E8F375C41808743300C40148 /* Twitter Demo */ = {
302 | isa = PBXNativeTarget;
303 | buildConfigurationList = E8F375F11808743300C40148 /* Build configuration list for PBXNativeTarget "Twitter Demo" */;
304 | buildPhases = (
305 | 118105407888433EA4AC19B1 /* Check Pods Manifest.lock */,
306 | E8F375C11808743300C40148 /* Sources */,
307 | E8F375C21808743300C40148 /* Frameworks */,
308 | E8F375C31808743300C40148 /* Resources */,
309 | 30BA89E5E3B946A8871684DF /* Copy Pods Resources */,
310 | 97C6D696DC5DD55918A5A729 /* Embed Pods Frameworks */,
311 | );
312 | buildRules = (
313 | );
314 | dependencies = (
315 | );
316 | name = "Twitter Demo";
317 | productName = Demo;
318 | productReference = E8F375C51808743300C40148 /* Twitter Demo.app */;
319 | productType = "com.apple.product-type.application";
320 | };
321 | /* End PBXNativeTarget section */
322 |
323 | /* Begin PBXProject section */
324 | E8F375BD1808743300C40148 /* Project object */ = {
325 | isa = PBXProject;
326 | attributes = {
327 | LastUpgradeCheck = 0700;
328 | ORGANIZATIONNAME = "Bradley David Bergeron";
329 | };
330 | buildConfigurationList = E8F375C01808743300C40148 /* Build configuration list for PBXProject "BDBOAuth1ManagerDemo" */;
331 | compatibilityVersion = "Xcode 3.2";
332 | developmentRegion = English;
333 | hasScannedForEncodings = 0;
334 | knownRegions = (
335 | en,
336 | Base,
337 | );
338 | mainGroup = E8F375BC1808743300C40148;
339 | productRefGroup = E8F375C61808743300C40148 /* Products */;
340 | projectDirPath = "";
341 | projectRoot = "";
342 | targets = (
343 | E8F375C41808743300C40148 /* Twitter Demo */,
344 | E8284C8118464EF900B3C6AA /* Flickr Demo */,
345 | );
346 | };
347 | /* End PBXProject section */
348 |
349 | /* Begin PBXResourcesBuildPhase section */
350 | E8284CA418464EF900B3C6AA /* Resources */ = {
351 | isa = PBXResourcesBuildPhase;
352 | buildActionMask = 2147483647;
353 | files = (
354 | E847027019D4DD2E00C10210 /* Flickr.xcassets in Resources */,
355 | E8C6BAA119D4DDC300A2102A /* Launch Screen.xib in Resources */,
356 | E8F6168A1846555D008D9DC5 /* PhotoAlbumHeaderView.xib in Resources */,
357 | E8284CA618464EF900B3C6AA /* InfoPlist.strings in Resources */,
358 | );
359 | runOnlyForDeploymentPostprocessing = 0;
360 | };
361 | E8F375C31808743300C40148 /* Resources */ = {
362 | isa = PBXResourcesBuildPhase;
363 | buildActionMask = 2147483647;
364 | files = (
365 | E8C6BAA319D4E02E00A2102A /* Twitter.xcassets in Resources */,
366 | E8C6BAA519D4E05A00A2102A /* Launch Screen.xib in Resources */,
367 | E8284CB01846500000B3C6AA /* InfoPlist.strings in Resources */,
368 | E8F0016919618C7C00980015 /* TweetCell.xib in Resources */,
369 | );
370 | runOnlyForDeploymentPostprocessing = 0;
371 | };
372 | /* End PBXResourcesBuildPhase section */
373 |
374 | /* Begin PBXShellScriptBuildPhase section */
375 | 118105407888433EA4AC19B1 /* Check Pods Manifest.lock */ = {
376 | isa = PBXShellScriptBuildPhase;
377 | buildActionMask = 2147483647;
378 | files = (
379 | );
380 | inputPaths = (
381 | );
382 | name = "Check Pods Manifest.lock";
383 | outputPaths = (
384 | );
385 | runOnlyForDeploymentPostprocessing = 0;
386 | shellPath = /bin/sh;
387 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
388 | showEnvVarsInLog = 0;
389 | };
390 | 30BA89E5E3B946A8871684DF /* Copy Pods Resources */ = {
391 | isa = PBXShellScriptBuildPhase;
392 | buildActionMask = 2147483647;
393 | files = (
394 | );
395 | inputPaths = (
396 | );
397 | name = "Copy Pods Resources";
398 | outputPaths = (
399 | );
400 | runOnlyForDeploymentPostprocessing = 0;
401 | shellPath = /bin/sh;
402 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n";
403 | showEnvVarsInLog = 0;
404 | };
405 | 5DD86A06D72F47E49726F4A5 /* Check Pods Manifest.lock */ = {
406 | isa = PBXShellScriptBuildPhase;
407 | buildActionMask = 2147483647;
408 | files = (
409 | );
410 | inputPaths = (
411 | );
412 | name = "Check Pods Manifest.lock";
413 | outputPaths = (
414 | );
415 | runOnlyForDeploymentPostprocessing = 0;
416 | shellPath = /bin/sh;
417 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
418 | showEnvVarsInLog = 0;
419 | };
420 | 97C6D696DC5DD55918A5A729 /* Embed Pods Frameworks */ = {
421 | isa = PBXShellScriptBuildPhase;
422 | buildActionMask = 2147483647;
423 | files = (
424 | );
425 | inputPaths = (
426 | );
427 | name = "Embed Pods Frameworks";
428 | outputPaths = (
429 | );
430 | runOnlyForDeploymentPostprocessing = 0;
431 | shellPath = /bin/sh;
432 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-frameworks.sh\"\n";
433 | showEnvVarsInLog = 0;
434 | };
435 | B7F71007CEE3472886B6578E /* Copy Pods Resources */ = {
436 | isa = PBXShellScriptBuildPhase;
437 | buildActionMask = 2147483647;
438 | files = (
439 | );
440 | inputPaths = (
441 | );
442 | name = "Copy Pods Resources";
443 | outputPaths = (
444 | );
445 | runOnlyForDeploymentPostprocessing = 0;
446 | shellPath = /bin/sh;
447 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n";
448 | showEnvVarsInLog = 0;
449 | };
450 | BAD9DA1CD21FA90113543637 /* Embed Pods Frameworks */ = {
451 | isa = PBXShellScriptBuildPhase;
452 | buildActionMask = 2147483647;
453 | files = (
454 | );
455 | inputPaths = (
456 | );
457 | name = "Embed Pods Frameworks";
458 | outputPaths = (
459 | );
460 | runOnlyForDeploymentPostprocessing = 0;
461 | shellPath = /bin/sh;
462 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-frameworks.sh\"\n";
463 | showEnvVarsInLog = 0;
464 | };
465 | /* End PBXShellScriptBuildPhase section */
466 |
467 | /* Begin PBXSourcesBuildPhase section */
468 | E8284C8218464EF900B3C6AA /* Sources */ = {
469 | isa = PBXSourcesBuildPhase;
470 | buildActionMask = 2147483647;
471 | files = (
472 | E8F6168B1846555D008D9DC5 /* PhotoAlbumLayout.m in Sources */,
473 | E8284C8518464EF900B3C6AA /* AppDelegate.m in Sources */,
474 | E8284C8F18464EF900B3C6AA /* PhotosViewController.m in Sources */,
475 | E8F6169518496578008D9DC5 /* BDBFlickrPhoto.m in Sources */,
476 | E8F616881846555D008D9DC5 /* PhotoAlbumCell.m in Sources */,
477 | E8F6169218496326008D9DC5 /* BDBFlickrPhotoset.m in Sources */,
478 | E88595A8184A751500BD7AEC /* BDBFlickrClient.m in Sources */,
479 | E8F616891846555D008D9DC5 /* PhotoAlbumHeaderView.m in Sources */,
480 | E8284C9F18464EF900B3C6AA /* main.m in Sources */,
481 | );
482 | runOnlyForDeploymentPostprocessing = 0;
483 | };
484 | E8F375C11808743300C40148 /* Sources */ = {
485 | isa = PBXSourcesBuildPhase;
486 | buildActionMask = 2147483647;
487 | files = (
488 | E8F3763C1808769B00C40148 /* main.m in Sources */,
489 | E8E54C20180C830A00010143 /* TweetCell.m in Sources */,
490 | E816CAD519565291009877A6 /* BDBTwitterClient.m in Sources */,
491 | E8F375D91808743300C40148 /* AppDelegate.m in Sources */,
492 | E8D381E319592A5C00284883 /* BDBTweet.m in Sources */,
493 | E8D8E0BF180884DD00CDCB7D /* TweetsViewController.m in Sources */,
494 | );
495 | runOnlyForDeploymentPostprocessing = 0;
496 | };
497 | /* End PBXSourcesBuildPhase section */
498 |
499 | /* Begin PBXVariantGroup section */
500 | E8284C6D18464ED900B3C6AA /* InfoPlist.strings */ = {
501 | isa = PBXVariantGroup;
502 | children = (
503 | E8284C6E18464ED900B3C6AA /* en */,
504 | );
505 | name = InfoPlist.strings;
506 | sourceTree = "";
507 | };
508 | E8F376351808769B00C40148 /* InfoPlist.strings */ = {
509 | isa = PBXVariantGroup;
510 | children = (
511 | E8F376361808769B00C40148 /* en */,
512 | );
513 | name = InfoPlist.strings;
514 | sourceTree = "";
515 | };
516 | /* End PBXVariantGroup section */
517 |
518 | /* Begin XCBuildConfiguration section */
519 | E8284CAC18464EF900B3C6AA /* Debug */ = {
520 | isa = XCBuildConfiguration;
521 | baseConfigurationReference = D4E42A9BCC3D91597BD0D127 /* Pods.debug.xcconfig */;
522 | buildSettings = {
523 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
524 | CODE_SIGN_IDENTITY = "iPhone Developer";
525 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
526 | GCC_PREFIX_HEADER = "Flickr Demo/Supporting Files/Flickr Demo-Prefix.pch";
527 | INFOPLIST_FILE = "$(SRCROOT)/Flickr Demo/Supporting Files/Flickr Demo-Info.plist";
528 | PRODUCT_BUNDLE_IDENTIFIER = com.bradbergeron.bdboauth1demo.flickr;
529 | PRODUCT_NAME = "Flickr Demo";
530 | TARGETED_DEVICE_FAMILY = "1,2";
531 | WARNING_CFLAGS = "-Wall";
532 | WRAPPER_EXTENSION = app;
533 | };
534 | name = Debug;
535 | };
536 | E8284CAD18464EF900B3C6AA /* Release */ = {
537 | isa = XCBuildConfiguration;
538 | baseConfigurationReference = 3C23EA492A8642587406840B /* Pods.release.xcconfig */;
539 | buildSettings = {
540 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
541 | CODE_SIGN_IDENTITY = "iPhone Developer";
542 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
543 | GCC_PREFIX_HEADER = "Flickr Demo/Supporting Files/Flickr Demo-Prefix.pch";
544 | INFOPLIST_FILE = "$(SRCROOT)/Flickr Demo/Supporting Files/Flickr Demo-Info.plist";
545 | PRODUCT_BUNDLE_IDENTIFIER = com.bradbergeron.bdboauth1demo.flickr;
546 | PRODUCT_NAME = "Flickr Demo";
547 | TARGETED_DEVICE_FAMILY = "1,2";
548 | WARNING_CFLAGS = "-Wall";
549 | WRAPPER_EXTENSION = app;
550 | };
551 | name = Release;
552 | };
553 | E8F375EF1808743300C40148 /* Debug */ = {
554 | isa = XCBuildConfiguration;
555 | buildSettings = {
556 | ALWAYS_SEARCH_USER_PATHS = NO;
557 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
558 | CLANG_CXX_LIBRARY = "libc++";
559 | CLANG_ENABLE_MODULES = YES;
560 | CLANG_ENABLE_OBJC_ARC = YES;
561 | CLANG_WARN_BOOL_CONVERSION = YES;
562 | CLANG_WARN_CONSTANT_CONVERSION = YES;
563 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
564 | CLANG_WARN_EMPTY_BODY = YES;
565 | CLANG_WARN_ENUM_CONVERSION = YES;
566 | CLANG_WARN_INT_CONVERSION = YES;
567 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
568 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
569 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
570 | COPY_PHASE_STRIP = NO;
571 | ENABLE_TESTABILITY = YES;
572 | GCC_C_LANGUAGE_STANDARD = gnu99;
573 | GCC_DYNAMIC_NO_PIC = NO;
574 | GCC_OPTIMIZATION_LEVEL = 0;
575 | GCC_PREPROCESSOR_DEFINITIONS = (
576 | "DEBUG=1",
577 | "$(inherited)",
578 | );
579 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
580 | GCC_TREAT_WARNINGS_AS_ERRORS = YES;
581 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
582 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
583 | GCC_WARN_UNDECLARED_SELECTOR = YES;
584 | GCC_WARN_UNINITIALIZED_AUTOS = YES;
585 | GCC_WARN_UNUSED_FUNCTION = YES;
586 | GCC_WARN_UNUSED_VARIABLE = YES;
587 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
588 | MACOSX_DEPLOYMENT_TARGET = 10.9;
589 | ONLY_ACTIVE_ARCH = YES;
590 | SDKROOT = iphoneos;
591 | TARGETED_DEVICE_FAMILY = "1,2";
592 | WARNING_CFLAGS = "-Wall";
593 | };
594 | name = Debug;
595 | };
596 | E8F375F01808743300C40148 /* Release */ = {
597 | isa = XCBuildConfiguration;
598 | buildSettings = {
599 | ALWAYS_SEARCH_USER_PATHS = NO;
600 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
601 | CLANG_CXX_LIBRARY = "libc++";
602 | CLANG_ENABLE_MODULES = YES;
603 | CLANG_ENABLE_OBJC_ARC = YES;
604 | CLANG_WARN_BOOL_CONVERSION = YES;
605 | CLANG_WARN_CONSTANT_CONVERSION = YES;
606 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
607 | CLANG_WARN_EMPTY_BODY = YES;
608 | CLANG_WARN_ENUM_CONVERSION = YES;
609 | CLANG_WARN_INT_CONVERSION = YES;
610 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
611 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
612 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
613 | COPY_PHASE_STRIP = YES;
614 | ENABLE_NS_ASSERTIONS = NO;
615 | GCC_C_LANGUAGE_STANDARD = gnu99;
616 | GCC_TREAT_WARNINGS_AS_ERRORS = YES;
617 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
618 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
619 | GCC_WARN_UNDECLARED_SELECTOR = YES;
620 | GCC_WARN_UNINITIALIZED_AUTOS = YES;
621 | GCC_WARN_UNUSED_FUNCTION = YES;
622 | GCC_WARN_UNUSED_VARIABLE = YES;
623 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
624 | MACOSX_DEPLOYMENT_TARGET = 10.9;
625 | SDKROOT = iphoneos;
626 | TARGETED_DEVICE_FAMILY = "1,2";
627 | VALIDATE_PRODUCT = YES;
628 | WARNING_CFLAGS = "-Wall";
629 | };
630 | name = Release;
631 | };
632 | E8F375F21808743300C40148 /* Debug */ = {
633 | isa = XCBuildConfiguration;
634 | baseConfigurationReference = D4E42A9BCC3D91597BD0D127 /* Pods.debug.xcconfig */;
635 | buildSettings = {
636 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
637 | CODE_SIGN_IDENTITY = "iPhone Developer";
638 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
639 | GCC_PREFIX_HEADER = "Twitter Demo/Supporting Files/Twitter Demo-Prefix.pch";
640 | INFOPLIST_FILE = "$(SRCROOT)/Twitter Demo/Supporting Files/Twitter Demo-Info.plist";
641 | PRODUCT_BUNDLE_IDENTIFIER = com.bradbergeron.bdboauth1demo.twitter;
642 | PRODUCT_NAME = "Twitter Demo";
643 | TARGETED_DEVICE_FAMILY = 1;
644 | WARNING_CFLAGS = "-Wall";
645 | WRAPPER_EXTENSION = app;
646 | };
647 | name = Debug;
648 | };
649 | E8F375F31808743300C40148 /* Release */ = {
650 | isa = XCBuildConfiguration;
651 | baseConfigurationReference = 3C23EA492A8642587406840B /* Pods.release.xcconfig */;
652 | buildSettings = {
653 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
654 | CODE_SIGN_IDENTITY = "iPhone Developer";
655 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
656 | GCC_PREFIX_HEADER = "Twitter Demo/Supporting Files/Twitter Demo-Prefix.pch";
657 | INFOPLIST_FILE = "$(SRCROOT)/Twitter Demo/Supporting Files/Twitter Demo-Info.plist";
658 | PRODUCT_BUNDLE_IDENTIFIER = com.bradbergeron.bdboauth1demo.twitter;
659 | PRODUCT_NAME = "Twitter Demo";
660 | TARGETED_DEVICE_FAMILY = 1;
661 | WARNING_CFLAGS = "-Wall";
662 | WRAPPER_EXTENSION = app;
663 | };
664 | name = Release;
665 | };
666 | /* End XCBuildConfiguration section */
667 |
668 | /* Begin XCConfigurationList section */
669 | E8284CAB18464EF900B3C6AA /* Build configuration list for PBXNativeTarget "Flickr Demo" */ = {
670 | isa = XCConfigurationList;
671 | buildConfigurations = (
672 | E8284CAC18464EF900B3C6AA /* Debug */,
673 | E8284CAD18464EF900B3C6AA /* Release */,
674 | );
675 | defaultConfigurationIsVisible = 0;
676 | defaultConfigurationName = Release;
677 | };
678 | E8F375C01808743300C40148 /* Build configuration list for PBXProject "BDBOAuth1ManagerDemo" */ = {
679 | isa = XCConfigurationList;
680 | buildConfigurations = (
681 | E8F375EF1808743300C40148 /* Debug */,
682 | E8F375F01808743300C40148 /* Release */,
683 | );
684 | defaultConfigurationIsVisible = 0;
685 | defaultConfigurationName = Release;
686 | };
687 | E8F375F11808743300C40148 /* Build configuration list for PBXNativeTarget "Twitter Demo" */ = {
688 | isa = XCConfigurationList;
689 | buildConfigurations = (
690 | E8F375F21808743300C40148 /* Debug */,
691 | E8F375F31808743300C40148 /* Release */,
692 | );
693 | defaultConfigurationIsVisible = 0;
694 | defaultConfigurationName = Release;
695 | };
696 | /* End XCConfigurationList section */
697 | };
698 | rootObject = E8F375BD1808743300C40148 /* Project object */;
699 | }
700 |
--------------------------------------------------------------------------------