├── 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 | ![URL Types Screenshot](https://dl.dropboxusercontent.com/u/6225/GitHub/BDBOAuth1Manager/urltypes.png) 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 | --------------------------------------------------------------------------------