├── Giphy.xcodeproj ├── project.xcworkspace │ └── contents.xcworkspacedata ├── xcshareddata │ └── xcschemes │ │ └── Giphy.xcscheme └── project.pbxproj ├── .gitignore ├── GiphyTests ├── Info.plist └── GiphyTests.swift ├── Giphy ├── Info.plist ├── Giphy.h └── Giphy.swift ├── LICENSE └── README.md /Giphy.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | *.xccheckout 14 | *.moved-aside 15 | DerivedData 16 | *.hmap 17 | *.ipa 18 | *.xcuserstate 19 | -------------------------------------------------------------------------------- /GiphyTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Giphy/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Ryan Coffman 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) 2 | # Giphy.swift 3 | A [Giphy](http://giphy.com/) API client in Swift. 4 | 5 | ## Usage 6 | 7 | ```swift 8 | 9 | let g = Giphy(apiKey: Giphy.PublicBetaAPIKey) 10 | 11 | // Search 12 | 13 | g.search("dogs", nil, offset: nil, rating: nil) { gifs, pagination, err in 14 | 15 | // Do something with gifs 16 | } 17 | 18 | // By id 19 | 20 | g.gif("1") { gifs, err in 21 | 22 | // Do something with gif 23 | } 24 | 25 | // Get multiple ids 26 | 27 | g.gifs(["asfasdf", adsfasdf]) { gifs, err in 28 | 29 | // Do something with gifs 30 | } 31 | 32 | // Translate text into a gif 33 | 34 | g.translate("cat", rating: nil) { gif, err in 35 | 36 | // Do something 37 | } 38 | 39 | // Get random gif 40 | 41 | g.random("optional tag", rating: nil) { gif, err in 42 | 43 | 44 | } 45 | 46 | // Get trending gifs 47 | 48 | g.trending(nil, offset: nil, rating: nil) { gifs, pagination, err in 49 | 50 | } 51 | ``` 52 | 53 | ## TODO 54 | - Include sticker API. 55 | - Demo application. 56 | 57 | ##License 58 | Giphy.swift is released under the MIT license. See LICENSE for details. 59 | -------------------------------------------------------------------------------- /Giphy/Giphy.h: -------------------------------------------------------------------------------- 1 | // 2 | // Giphy.h 3 | // Giphy 4 | // 5 | // Copyright (c) 2014 Ryan Coffman 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | 24 | #import 25 | 26 | //! Project version number for Giphy. 27 | FOUNDATION_EXPORT double GiphyVersionNumber; 28 | 29 | //! Project version string for Giphy. 30 | FOUNDATION_EXPORT const unsigned char GiphyVersionString[]; 31 | 32 | // In this header, you should import all the public headers of your framework using statements like #import 33 | 34 | 35 | -------------------------------------------------------------------------------- /GiphyTests/GiphyTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GiphyTests.swift 3 | // GiphyTests 4 | // 5 | // Copyright (c) 2014 Ryan Coffman 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | 24 | import Foundation 25 | import XCTest 26 | import Giphy 27 | 28 | class GiphyTests: XCTestCase { 29 | 30 | let giphy = Giphy(apiKey: "dc6zaTOxFJmzC") 31 | 32 | override func setUp() { 33 | super.setUp() 34 | } 35 | 36 | override func tearDown() { 37 | 38 | super.tearDown() 39 | } 40 | 41 | func testSearch() { 42 | 43 | let sema = dispatch_semaphore_create(0) 44 | 45 | giphy.search("fun", limit: 1, offset: nil, rating: nil) { 46 | 47 | XCTAssert($2 == nil, $2?.localizedDescription ?? "") 48 | XCTAssert($0!.count == 1, "Results weren't one") 49 | dispatch_semaphore_signal(sema) 50 | } 51 | 52 | dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER) 53 | } 54 | 55 | func testGif() { 56 | 57 | let sema = dispatch_semaphore_create(0) 58 | 59 | giphy.gif("1") { (gif, err) -> Void in 60 | print(err == nil) 61 | XCTAssert(true, "NOTTET") 62 | XCTAssert(err == nil, err?.localizedDescription ?? "") 63 | XCTAssert(gif != nil, "Gif is nil") 64 | dispatch_semaphore_signal(sema) 65 | } 66 | 67 | dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER) 68 | } 69 | 70 | func testGifs() { 71 | 72 | let sema = dispatch_semaphore_create(0) 73 | 74 | giphy.gifs(["1","12cAJO8mkO3hUA","hLaUjPEPBbRxm"]) { (gifs, err) -> Void in 75 | 76 | XCTAssert(err == nil, err?.localizedDescription ?? "") 77 | XCTAssert(gifs != nil, "Gif is nil") 78 | XCTAssert(gifs!.count == 3, "") 79 | dispatch_semaphore_signal(sema) 80 | } 81 | 82 | dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER) 83 | } 84 | 85 | func testTranslate() { 86 | 87 | let sema = dispatch_semaphore_create(0) 88 | 89 | giphy.translate("cat", rating: nil) { (gif, err) -> Void in 90 | 91 | XCTAssert(err == nil, err?.localizedDescription ?? "") 92 | XCTAssert(gif != nil, "Gif is nil") 93 | dispatch_semaphore_signal(sema) 94 | } 95 | 96 | dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER) 97 | } 98 | 99 | func testRandom() { 100 | 101 | let sema = dispatch_semaphore_create(0) 102 | 103 | giphy.random(nil, rating: nil) { 104 | 105 | XCTAssert($1 == nil, $1?.localizedDescription ?? "") 106 | XCTAssert($0 != nil, "Gif was nil") 107 | dispatch_semaphore_signal(sema) 108 | } 109 | 110 | dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER) 111 | } 112 | 113 | func testTrending() { 114 | 115 | let sema = dispatch_semaphore_create(0) 116 | 117 | giphy.trending(10, offset: 0, rating: nil) { 118 | 119 | XCTAssert($2 == nil, $2?.localizedDescription ?? "") 120 | XCTAssert($0 != nil, "Gifs is nil") 121 | XCTAssert($0!.count == 10, "Gifs count is wrong") 122 | dispatch_semaphore_signal(sema) 123 | } 124 | 125 | dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER) 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /Giphy.xcodeproj/xcshareddata/xcschemes/Giphy.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 65 | 71 | 72 | 73 | 74 | 75 | 76 | 82 | 83 | 89 | 90 | 91 | 92 | 94 | 95 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /Giphy/Giphy.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Giphy.swift 3 | // Giphy 4 | // 5 | // Copyright (c) 2014 Ryan Coffman 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | 24 | import Foundation 25 | 26 | /// Giphy API client. 27 | public class Giphy { 28 | /// The public api key for Giphy, should only be used for testing. 29 | public static let PublicBetaAPIKey = "dc6zaTOxFJmzC" 30 | 31 | static let BaseURLString = "http://api.giphy.com/v1/gifs" 32 | 33 | /// Pagination for Giphy endpoints search and trending. 34 | public struct Pagination { 35 | 36 | /// The count of the items retrieved. 37 | public let count: Int 38 | 39 | /// The offset of the first item. 40 | public let offset: Int 41 | } 42 | 43 | // Represents the gif data from an api call. 44 | public class Gif { 45 | 46 | /// The user discretion rating of a gif. 47 | public enum Rating: String { 48 | case Y = "y" 49 | case G = "g" 50 | case PG = "pg" 51 | case PG13 = "pg-13" 52 | case R = "r" 53 | } 54 | 55 | /** 56 | Different versions available for a gif. 57 | 58 | - FixedHeight: The gif with a fixed height of 200px. 59 | - FixedHeightDownsampled: The gif with a fixed height of 200px downsampled. 60 | - FixedWidth: The gif with a fixed width of 200px. 61 | - FixedWidthDownsampled: The gif with a fixed width of 200px downsampled. 62 | - Original: The original gif image. 63 | */ 64 | public enum ImageVersion: String { 65 | case FixedHeight = "fixed_height" 66 | case FixedHeightDownsampled = "fixed_height_downsampled" 67 | case FixedWidth = "fixed_width" 68 | case FixedWidthDownsampled = "fixed_width_downsampled" 69 | case Original = "original" 70 | } 71 | 72 | /// The Giphy metadata of a gif. 73 | public struct ImageMetadata { 74 | 75 | /// The url of the gif. 76 | public let URL: NSURL 77 | 78 | /// The width of the gif in pixels. 79 | public let width: Int 80 | 81 | /// The height of the gif in pixels 82 | public let height: Int 83 | 84 | /// The size of the gif in bytes, not all image versions include this. 85 | public let size: Int? 86 | 87 | /// The number of frames the gif has, not all image verions include this. 88 | public let frames: Int? 89 | 90 | /// URL to the gif in mp4 format, all image verions include this except for stills. 91 | public let mp4URL: NSURL? 92 | 93 | init(dict: [String: AnyObject]) { 94 | 95 | URL = NSURL(string: dict["url"] as! String)! 96 | width = (dict["width"]?.integerValue)! 97 | height = (dict["height"]?.integerValue)! 98 | size = dict["size"]?.integerValue 99 | frames = dict["frames"]?.integerValue 100 | if let mp4 = dict["mp4"] as? String { 101 | mp4URL = NSURL(string: mp4) 102 | } else { 103 | mp4URL = NSURL() 104 | } 105 | } 106 | } 107 | 108 | /// The raw json data from giphy for the gif object. 109 | public let json: [String:AnyObject] 110 | 111 | /// The giphy id for the gif. 112 | public var id: String { 113 | return json["id"] as! String 114 | } 115 | 116 | /// The URL to the giphy page of the gif. 117 | public var giphyURL: NSURL { 118 | return NSURL(string: json["url"] as! String)! 119 | } 120 | 121 | /// User discretion rating of the gif. 122 | public var rating: Rating { 123 | return Rating(rawValue: json["rating"] as! String)! 124 | } 125 | 126 | init(json: [String:AnyObject]) { 127 | self.json = json 128 | } 129 | 130 | /** 131 | Get the metadata for an image type. 132 | 133 | - parameter type: The image type. 134 | 135 | - parameter still: Whether the metadata should be of a still of the image version. No stills are available for downsampled versions. 136 | 137 | :return: The image metadata for the image type. 138 | */ 139 | public func gifMetadataForType(type: ImageVersion, still: Bool) -> ImageMetadata { 140 | var still = still 141 | 142 | if type == .FixedHeightDownsampled || type == .FixedWidthDownsampled { 143 | still = false 144 | } 145 | if let images = json["images"] as? [String:[String:AnyObject]] { 146 | let key = type.rawValue + (still ? "_still" : "") 147 | let image = images[key]! 148 | return ImageMetadata(dict: image) 149 | } else { 150 | 151 | var dict: [String:AnyObject] = [:] 152 | let img = json["image_url"] as! NSURL 153 | let noPath = img.URLByDeletingLastPathComponent! 154 | 155 | switch type { 156 | case .FixedHeight: 157 | dict["url"] = noPath.URLByAppendingPathComponent("200.gif") 158 | dict["width"] = Int(json["fixed_height_downsampled_width"] as! String)! 159 | dict["height"] = 200 160 | dict["mp4"] = noPath.URLByAppendingPathComponent("200.mp4") 161 | 162 | case .FixedHeightDownsampled: 163 | dict["url"] = noPath.URLByAppendingPathComponent("200_d.gif") 164 | dict["width"] = Int(json["fixed_height_downsampled_width"] as! String)! 165 | dict["height"] = 200 166 | dict["mp4"] = noPath.URLByAppendingPathComponent("200_d.mp4") 167 | case .FixedWidth: 168 | dict["url"] = noPath.URLByAppendingPathComponent("200w.gif") 169 | dict["width"] = 200 170 | dict["height"] = Int(json["fixed_width_downsampled_height"] as! String)! 171 | dict["mp4"] = noPath.URLByAppendingPathComponent("200w.mp4") 172 | case .FixedWidthDownsampled: 173 | dict["url"] = noPath.URLByAppendingPathComponent("200w_d.gif") 174 | dict["width"] = 200 175 | dict["height"] = Int(json["fixed_width_downsampled_height"] as! String)! 176 | dict["mp4"] = noPath.URLByAppendingPathComponent("200w_d.mp4") 177 | case .Original: 178 | dict["url"] = img 179 | dict["width"] = Int(json["image_width"] as! String)! 180 | dict["height"] = Int(json["image_height"] as! String)! 181 | dict["mp4"] = json["image_mp4_url"] 182 | } 183 | 184 | if still { 185 | let url = dict["url"] as! NSURL 186 | dict["url"] = url.URLByDeletingPathExtension?.URLByAppendingPathComponent("_s.gif") 187 | dict.removeValueForKey("mp4") 188 | } 189 | 190 | return ImageMetadata(dict: dict) 191 | } 192 | } 193 | } 194 | 195 | let session: NSURLSession 196 | 197 | let apiKey: String 198 | 199 | /** 200 | Initialize a new Giphy client. 201 | 202 | - parameter apiKey: Your API key from giphy. 203 | 204 | - parameter URLSessionConfiguration: The NSURLSessionConfiguration used to initiate a new session that all requests are sent with. 205 | 206 | :return: A new Giphy instance. 207 | */ 208 | public init(apiKey key: String, URLSessionConfiguration sessionConfiguration: NSURLSessionConfiguration) { 209 | 210 | session = NSURLSession(configuration: sessionConfiguration) 211 | 212 | apiKey = key 213 | } 214 | 215 | /** 216 | Initalize a new Giphy client with the default NSURLSessionConfiguration 217 | 218 | - parameter apiKey: Your Giphy API key. 219 | 220 | :return: A new Giphy instance. 221 | */ 222 | public convenience init(apiKey key: String) { 223 | self.init(apiKey: key, URLSessionConfiguration: NSURLSessionConfiguration.defaultSessionConfiguration()) 224 | } 225 | 226 | /** 227 | Perform a search request of a gif from Giphy. 228 | 229 | - parameter query: The search query. 230 | 231 | - parameter limit: Limit the number of results per page. From 1 to 100. Optional. 232 | 233 | - parameter offset: The offset in the number of the results. Optional. 234 | 235 | - parameter rating: The max user discretion rating of gifs. Optional. 236 | 237 | - parameter completionHandler: Completion handler called once the request is complete. 238 | 239 | - returns: An NSURLSessionDataTask for the request that has already been resumed. 240 | */ 241 | public func search(query: String, limit: UInt?, offset: UInt?, rating: Gif.Rating?, completionHandler: ([Gif]?, Pagination?, NSError?) -> Void) -> NSURLSessionDataTask { 242 | 243 | var params: [String : AnyObject] = ["q":query] 244 | 245 | if let lim = limit { 246 | params["limit"] = lim 247 | } 248 | 249 | if let off = offset { 250 | params["offset"] = off 251 | } 252 | 253 | if let rat = rating { 254 | params["rating"] = rat.rawValue 255 | } 256 | 257 | return performRequest("search", params: params, completionHandler: completionHandler) 258 | } 259 | 260 | /** 261 | Perform a request for a gif by its Giphy id. 262 | 263 | - parameter id: The id of the Giphy gif. 264 | 265 | - parameter completionHandler: Completion handler called once the request is complete. 266 | 267 | - returns: An NSURLSessionDataTask for the request that has already been resumed. 268 | */ 269 | public func gif(id: String, completionHandler: (Gif?, NSError?) -> Void) -> NSURLSessionDataTask { 270 | 271 | return performRequest(id, params: nil) { 272 | completionHandler($0?.first,$2) 273 | } 274 | } 275 | 276 | /** 277 | Perform a request for multiple gifs by id. 278 | 279 | - parameter ids: An array of ids. 280 | 281 | - parameter completionHandler: Completion handler called once the request is complete. 282 | 283 | - returns: An NSURLSessionDataTask for the request that has already been resumed. 284 | */ 285 | public func gifs(ids: [String], completionHandler: ([Gif]?, NSError?) -> Void) -> NSURLSessionDataTask { 286 | 287 | let params: [String : AnyObject] = ["ids" : ids.joinWithSeparator(",")] 288 | 289 | return performRequest("", params: params) { 290 | completionHandler($0,$2) 291 | } 292 | } 293 | 294 | /** 295 | Perform a translate request. 296 | 297 | - parameter term: The term to translate into a gif. 298 | 299 | - parameter rating: The max user discretion rating of gifs. Optional. 300 | 301 | - parameter completionHandler: Completion handler called once the request is complete. 302 | 303 | - returns: An NSURLSessionDataTask for the request that has already been resumed. 304 | */ 305 | public func translate(term: String, rating: Gif.Rating?, completionHandler: (Gif?, NSError?) -> Void) -> NSURLSessionDataTask { 306 | 307 | var params: [String : AnyObject] = ["s": term] 308 | 309 | if let rat = rating { 310 | params["rating"] = rat.rawValue 311 | } 312 | 313 | return performRequest("translate", params: params) { 314 | completionHandler($0?.first,$2) 315 | } 316 | } 317 | 318 | /** 319 | Perform a request for a random gif. 320 | 321 | - parameter tag: Tag that the random gif should have. Optional. 322 | 323 | - parameter rating: The max user discretion rating of gifs. Optional. 324 | 325 | - parameter completionHandler: Completion handler called once the request is complete. 326 | 327 | - returns: An NSURLSessionDataTask for the request that has already been resumed. 328 | */ 329 | public func random(tag: String?, rating: Gif.Rating?, completionHandler: (Gif?, NSError?) -> Void) -> NSURLSessionDataTask{ 330 | 331 | var params: [String : AnyObject] = [:] 332 | if let t = tag { 333 | params["tag"] = t 334 | } 335 | if let rat = rating { 336 | params["rating"] = rat.rawValue 337 | } 338 | 339 | return performRequest("random", params: params) { 340 | completionHandler($0?.first, $2) 341 | } 342 | } 343 | 344 | /** 345 | Perform a request for the trending gifs. 346 | 347 | - parameter limit: Limit the number of results per page. From 1 to 100. Optional. 348 | 349 | - parameter rating: The max user discretion rating of gifs. Optional. 350 | 351 | - parameter completionHandler: Completion handler called once the request is complete. 352 | 353 | - returns: An NSURLSessionDataTask for the request that has already been resumed. 354 | */ 355 | public func trending(limit: UInt?, offset: UInt?, rating: Gif.Rating?, completionHandler: ([Gif]?, Pagination?, NSError?) -> Void) -> NSURLSessionDataTask { 356 | 357 | var params: [String : AnyObject] = [:] 358 | if let lim = limit { 359 | params["limit"] = lim 360 | } 361 | if let rat = rating { 362 | params["rating"] = rat.rawValue 363 | } 364 | if let off = offset { 365 | params["offset"] = off 366 | } 367 | 368 | return performRequest("trending", params: params, completionHandler: completionHandler) 369 | } 370 | 371 | func performRequest(endpoint: String, params: [String: AnyObject]?, completionHandler: ([Gif]?, Pagination?, NSError?) -> Void) -> NSURLSessionDataTask { 372 | var params = params // shadowing 373 | 374 | var urlString = (Giphy.BaseURLString as NSString).stringByAppendingPathComponent(endpoint) 375 | if params == nil { 376 | params = [:] 377 | } 378 | 379 | params!["api_key"] = apiKey 380 | 381 | urlString += "?" 382 | 383 | for (i, (k, v)) in (params!).enumerate() { 384 | urlString += k.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())! 385 | urlString += "=" 386 | urlString += "\(v)".stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())! 387 | if (i != params!.count - 1) { 388 | urlString += "&" 389 | } 390 | } 391 | 392 | let dataTask = session.dataTaskWithURL(NSURL(string: urlString)!) { 393 | 394 | if $2 != nil { 395 | 396 | completionHandler(nil,nil, $2) 397 | return 398 | } 399 | 400 | var error: NSError? 401 | 402 | var json: [String:AnyObject] 403 | do { 404 | try json = NSJSONSerialization.JSONObjectWithData($0!, options: []) as! [String: AnyObject] 405 | } catch let err as NSError { 406 | completionHandler(nil, nil, err) 407 | return 408 | } 409 | 410 | let meta: [String:AnyObject]? = json["meta"] as! [String:AnyObject]? 411 | 412 | let status: Int = meta!["status"] as! Int 413 | 414 | if status != 200 { 415 | 416 | error = NSError(domain: NSURLErrorDomain, code: NSURLErrorBadServerResponse, userInfo: [NSLocalizedDescriptionKey: meta!["msg"] as! String]) 417 | 418 | completionHandler(nil, nil, error) 419 | return 420 | } 421 | 422 | var pagination: Pagination? 423 | if let p = json["pagination"] as? [String:Int] { 424 | 425 | pagination = Pagination(count: p["count"]!, offset: p["offset"]!) 426 | 427 | } 428 | var gifs: [Gif] = [] 429 | 430 | if let data = json["data"] as? [[String:AnyObject]] { 431 | 432 | for v in data { 433 | gifs.append(Gif(json: v)) 434 | } 435 | } else if let data = json["data"] as? [String:AnyObject] { 436 | gifs.append(Gif(json: data)) 437 | } 438 | 439 | completionHandler(gifs, pagination, nil) 440 | } 441 | dataTask.resume() 442 | return dataTask 443 | } 444 | } 445 | 446 | extension Giphy.Gif: CustomStringConvertible { 447 | 448 | public var description: String { 449 | return "Gif {\n\\t\(json)\n}" 450 | } 451 | } 452 | 453 | extension Giphy.Gif.Rating: CustomStringConvertible { 454 | 455 | public var description: String { 456 | return rawValue 457 | } 458 | } 459 | -------------------------------------------------------------------------------- /Giphy.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 9403D73E1A48962F008336A7 /* Giphy.h in Headers */ = {isa = PBXBuildFile; fileRef = 9403D73D1A48962F008336A7 /* Giphy.h */; settings = {ATTRIBUTES = (Public, ); }; }; 11 | 9403D7441A48962F008336A7 /* Giphy.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9403D7381A48962F008336A7 /* Giphy.framework */; }; 12 | 9403D74B1A48962F008336A7 /* GiphyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9403D74A1A48962F008336A7 /* GiphyTests.swift */; }; 13 | 9403D7551A4896B3008336A7 /* Giphy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9403D7541A4896B3008336A7 /* Giphy.swift */; }; 14 | /* End PBXBuildFile section */ 15 | 16 | /* Begin PBXContainerItemProxy section */ 17 | 9403D7451A48962F008336A7 /* PBXContainerItemProxy */ = { 18 | isa = PBXContainerItemProxy; 19 | containerPortal = 9403D72F1A48962E008336A7 /* Project object */; 20 | proxyType = 1; 21 | remoteGlobalIDString = 9403D7371A48962E008336A7; 22 | remoteInfo = Giphy; 23 | }; 24 | /* End PBXContainerItemProxy section */ 25 | 26 | /* Begin PBXFileReference section */ 27 | 9403D7381A48962F008336A7 /* Giphy.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Giphy.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 28 | 9403D73C1A48962F008336A7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 29 | 9403D73D1A48962F008336A7 /* Giphy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Giphy.h; sourceTree = ""; }; 30 | 9403D7431A48962F008336A7 /* GiphyTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = GiphyTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 31 | 9403D7491A48962F008336A7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 32 | 9403D74A1A48962F008336A7 /* GiphyTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GiphyTests.swift; sourceTree = ""; }; 33 | 9403D7541A4896B3008336A7 /* Giphy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Giphy.swift; sourceTree = ""; }; 34 | /* End PBXFileReference section */ 35 | 36 | /* Begin PBXFrameworksBuildPhase section */ 37 | 9403D7341A48962E008336A7 /* Frameworks */ = { 38 | isa = PBXFrameworksBuildPhase; 39 | buildActionMask = 2147483647; 40 | files = ( 41 | ); 42 | runOnlyForDeploymentPostprocessing = 0; 43 | }; 44 | 9403D7401A48962F008336A7 /* Frameworks */ = { 45 | isa = PBXFrameworksBuildPhase; 46 | buildActionMask = 2147483647; 47 | files = ( 48 | 9403D7441A48962F008336A7 /* Giphy.framework in Frameworks */, 49 | ); 50 | runOnlyForDeploymentPostprocessing = 0; 51 | }; 52 | /* End PBXFrameworksBuildPhase section */ 53 | 54 | /* Begin PBXGroup section */ 55 | 9403D72E1A48962E008336A7 = { 56 | isa = PBXGroup; 57 | children = ( 58 | 9403D73A1A48962F008336A7 /* Giphy */, 59 | 9403D7471A48962F008336A7 /* GiphyTests */, 60 | 9403D7391A48962F008336A7 /* Products */, 61 | ); 62 | sourceTree = ""; 63 | }; 64 | 9403D7391A48962F008336A7 /* Products */ = { 65 | isa = PBXGroup; 66 | children = ( 67 | 9403D7381A48962F008336A7 /* Giphy.framework */, 68 | 9403D7431A48962F008336A7 /* GiphyTests.xctest */, 69 | ); 70 | name = Products; 71 | sourceTree = ""; 72 | }; 73 | 9403D73A1A48962F008336A7 /* Giphy */ = { 74 | isa = PBXGroup; 75 | children = ( 76 | 9403D73D1A48962F008336A7 /* Giphy.h */, 77 | 9403D7541A4896B3008336A7 /* Giphy.swift */, 78 | 9403D73B1A48962F008336A7 /* Supporting Files */, 79 | ); 80 | path = Giphy; 81 | sourceTree = ""; 82 | }; 83 | 9403D73B1A48962F008336A7 /* Supporting Files */ = { 84 | isa = PBXGroup; 85 | children = ( 86 | 9403D73C1A48962F008336A7 /* Info.plist */, 87 | ); 88 | name = "Supporting Files"; 89 | sourceTree = ""; 90 | }; 91 | 9403D7471A48962F008336A7 /* GiphyTests */ = { 92 | isa = PBXGroup; 93 | children = ( 94 | 9403D74A1A48962F008336A7 /* GiphyTests.swift */, 95 | 9403D7481A48962F008336A7 /* Supporting Files */, 96 | ); 97 | path = GiphyTests; 98 | sourceTree = ""; 99 | }; 100 | 9403D7481A48962F008336A7 /* Supporting Files */ = { 101 | isa = PBXGroup; 102 | children = ( 103 | 9403D7491A48962F008336A7 /* Info.plist */, 104 | ); 105 | name = "Supporting Files"; 106 | sourceTree = ""; 107 | }; 108 | /* End PBXGroup section */ 109 | 110 | /* Begin PBXHeadersBuildPhase section */ 111 | 9403D7351A48962E008336A7 /* Headers */ = { 112 | isa = PBXHeadersBuildPhase; 113 | buildActionMask = 2147483647; 114 | files = ( 115 | 9403D73E1A48962F008336A7 /* Giphy.h in Headers */, 116 | ); 117 | runOnlyForDeploymentPostprocessing = 0; 118 | }; 119 | /* End PBXHeadersBuildPhase section */ 120 | 121 | /* Begin PBXNativeTarget section */ 122 | 9403D7371A48962E008336A7 /* Giphy */ = { 123 | isa = PBXNativeTarget; 124 | buildConfigurationList = 9403D74E1A48962F008336A7 /* Build configuration list for PBXNativeTarget "Giphy" */; 125 | buildPhases = ( 126 | 9403D7331A48962E008336A7 /* Sources */, 127 | 9403D7341A48962E008336A7 /* Frameworks */, 128 | 9403D7351A48962E008336A7 /* Headers */, 129 | 9403D7361A48962E008336A7 /* Resources */, 130 | ); 131 | buildRules = ( 132 | ); 133 | dependencies = ( 134 | ); 135 | name = Giphy; 136 | productName = Giphy; 137 | productReference = 9403D7381A48962F008336A7 /* Giphy.framework */; 138 | productType = "com.apple.product-type.framework"; 139 | }; 140 | 9403D7421A48962F008336A7 /* GiphyTests */ = { 141 | isa = PBXNativeTarget; 142 | buildConfigurationList = 9403D7511A48962F008336A7 /* Build configuration list for PBXNativeTarget "GiphyTests" */; 143 | buildPhases = ( 144 | 9403D73F1A48962F008336A7 /* Sources */, 145 | 9403D7401A48962F008336A7 /* Frameworks */, 146 | 9403D7411A48962F008336A7 /* Resources */, 147 | ); 148 | buildRules = ( 149 | ); 150 | dependencies = ( 151 | 9403D7461A48962F008336A7 /* PBXTargetDependency */, 152 | ); 153 | name = GiphyTests; 154 | productName = GiphyTests; 155 | productReference = 9403D7431A48962F008336A7 /* GiphyTests.xctest */; 156 | productType = "com.apple.product-type.bundle.unit-test"; 157 | }; 158 | /* End PBXNativeTarget section */ 159 | 160 | /* Begin PBXProject section */ 161 | 9403D72F1A48962E008336A7 /* Project object */ = { 162 | isa = PBXProject; 163 | attributes = { 164 | LastSwiftMigration = 0710; 165 | LastSwiftUpdateCheck = 0710; 166 | LastUpgradeCheck = 0710; 167 | ORGANIZATIONNAME = Otium; 168 | TargetAttributes = { 169 | 9403D7371A48962E008336A7 = { 170 | CreatedOnToolsVersion = 6.1.1; 171 | }; 172 | 9403D7421A48962F008336A7 = { 173 | CreatedOnToolsVersion = 6.1.1; 174 | }; 175 | }; 176 | }; 177 | buildConfigurationList = 9403D7321A48962E008336A7 /* Build configuration list for PBXProject "Giphy" */; 178 | compatibilityVersion = "Xcode 3.2"; 179 | developmentRegion = English; 180 | hasScannedForEncodings = 0; 181 | knownRegions = ( 182 | en, 183 | ); 184 | mainGroup = 9403D72E1A48962E008336A7; 185 | productRefGroup = 9403D7391A48962F008336A7 /* Products */; 186 | projectDirPath = ""; 187 | projectRoot = ""; 188 | targets = ( 189 | 9403D7371A48962E008336A7 /* Giphy */, 190 | 9403D7421A48962F008336A7 /* GiphyTests */, 191 | ); 192 | }; 193 | /* End PBXProject section */ 194 | 195 | /* Begin PBXResourcesBuildPhase section */ 196 | 9403D7361A48962E008336A7 /* Resources */ = { 197 | isa = PBXResourcesBuildPhase; 198 | buildActionMask = 2147483647; 199 | files = ( 200 | ); 201 | runOnlyForDeploymentPostprocessing = 0; 202 | }; 203 | 9403D7411A48962F008336A7 /* Resources */ = { 204 | isa = PBXResourcesBuildPhase; 205 | buildActionMask = 2147483647; 206 | files = ( 207 | ); 208 | runOnlyForDeploymentPostprocessing = 0; 209 | }; 210 | /* End PBXResourcesBuildPhase section */ 211 | 212 | /* Begin PBXSourcesBuildPhase section */ 213 | 9403D7331A48962E008336A7 /* Sources */ = { 214 | isa = PBXSourcesBuildPhase; 215 | buildActionMask = 2147483647; 216 | files = ( 217 | 9403D7551A4896B3008336A7 /* Giphy.swift in Sources */, 218 | ); 219 | runOnlyForDeploymentPostprocessing = 0; 220 | }; 221 | 9403D73F1A48962F008336A7 /* Sources */ = { 222 | isa = PBXSourcesBuildPhase; 223 | buildActionMask = 2147483647; 224 | files = ( 225 | 9403D74B1A48962F008336A7 /* GiphyTests.swift in Sources */, 226 | ); 227 | runOnlyForDeploymentPostprocessing = 0; 228 | }; 229 | /* End PBXSourcesBuildPhase section */ 230 | 231 | /* Begin PBXTargetDependency section */ 232 | 9403D7461A48962F008336A7 /* PBXTargetDependency */ = { 233 | isa = PBXTargetDependency; 234 | target = 9403D7371A48962E008336A7 /* Giphy */; 235 | targetProxy = 9403D7451A48962F008336A7 /* PBXContainerItemProxy */; 236 | }; 237 | /* End PBXTargetDependency section */ 238 | 239 | /* Begin XCBuildConfiguration section */ 240 | 9403D74C1A48962F008336A7 /* Debug */ = { 241 | isa = XCBuildConfiguration; 242 | buildSettings = { 243 | ALWAYS_SEARCH_USER_PATHS = NO; 244 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 245 | CLANG_CXX_LIBRARY = "libc++"; 246 | CLANG_ENABLE_MODULES = YES; 247 | CLANG_ENABLE_OBJC_ARC = YES; 248 | CLANG_WARN_BOOL_CONVERSION = YES; 249 | CLANG_WARN_CONSTANT_CONVERSION = YES; 250 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 251 | CLANG_WARN_EMPTY_BODY = YES; 252 | CLANG_WARN_ENUM_CONVERSION = YES; 253 | CLANG_WARN_INT_CONVERSION = YES; 254 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 255 | CLANG_WARN_UNREACHABLE_CODE = YES; 256 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 257 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 258 | COPY_PHASE_STRIP = NO; 259 | CURRENT_PROJECT_VERSION = 1; 260 | ENABLE_STRICT_OBJC_MSGSEND = YES; 261 | ENABLE_TESTABILITY = YES; 262 | GCC_C_LANGUAGE_STANDARD = gnu99; 263 | GCC_DYNAMIC_NO_PIC = NO; 264 | GCC_OPTIMIZATION_LEVEL = 0; 265 | GCC_PREPROCESSOR_DEFINITIONS = ( 266 | "DEBUG=1", 267 | "$(inherited)", 268 | ); 269 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 270 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 271 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 272 | GCC_WARN_UNDECLARED_SELECTOR = YES; 273 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 274 | GCC_WARN_UNUSED_FUNCTION = YES; 275 | GCC_WARN_UNUSED_VARIABLE = YES; 276 | IPHONEOS_DEPLOYMENT_TARGET = 8.1; 277 | MTL_ENABLE_DEBUG_INFO = YES; 278 | ONLY_ACTIVE_ARCH = YES; 279 | SDKROOT = iphoneos; 280 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 281 | TARGETED_DEVICE_FAMILY = "1,2"; 282 | VERSIONING_SYSTEM = "apple-generic"; 283 | VERSION_INFO_PREFIX = ""; 284 | }; 285 | name = Debug; 286 | }; 287 | 9403D74D1A48962F008336A7 /* Release */ = { 288 | isa = XCBuildConfiguration; 289 | buildSettings = { 290 | ALWAYS_SEARCH_USER_PATHS = NO; 291 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 292 | CLANG_CXX_LIBRARY = "libc++"; 293 | CLANG_ENABLE_MODULES = YES; 294 | CLANG_ENABLE_OBJC_ARC = YES; 295 | CLANG_WARN_BOOL_CONVERSION = YES; 296 | CLANG_WARN_CONSTANT_CONVERSION = YES; 297 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 298 | CLANG_WARN_EMPTY_BODY = YES; 299 | CLANG_WARN_ENUM_CONVERSION = YES; 300 | CLANG_WARN_INT_CONVERSION = YES; 301 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 302 | CLANG_WARN_UNREACHABLE_CODE = YES; 303 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 304 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 305 | COPY_PHASE_STRIP = YES; 306 | CURRENT_PROJECT_VERSION = 1; 307 | ENABLE_NS_ASSERTIONS = NO; 308 | ENABLE_STRICT_OBJC_MSGSEND = YES; 309 | GCC_C_LANGUAGE_STANDARD = gnu99; 310 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 311 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 312 | GCC_WARN_UNDECLARED_SELECTOR = YES; 313 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 314 | GCC_WARN_UNUSED_FUNCTION = YES; 315 | GCC_WARN_UNUSED_VARIABLE = YES; 316 | IPHONEOS_DEPLOYMENT_TARGET = 8.1; 317 | MTL_ENABLE_DEBUG_INFO = NO; 318 | SDKROOT = iphoneos; 319 | TARGETED_DEVICE_FAMILY = "1,2"; 320 | VALIDATE_PRODUCT = YES; 321 | VERSIONING_SYSTEM = "apple-generic"; 322 | VERSION_INFO_PREFIX = ""; 323 | }; 324 | name = Release; 325 | }; 326 | 9403D74F1A48962F008336A7 /* Debug */ = { 327 | isa = XCBuildConfiguration; 328 | buildSettings = { 329 | CLANG_ENABLE_MODULES = YES; 330 | DEFINES_MODULE = YES; 331 | DYLIB_COMPATIBILITY_VERSION = 1; 332 | DYLIB_CURRENT_VERSION = 1; 333 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 334 | INFOPLIST_FILE = Giphy/Info.plist; 335 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 336 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 337 | PRODUCT_BUNDLE_IDENTIFIER = "com.otium.$(PRODUCT_NAME:rfc1034identifier)"; 338 | PRODUCT_NAME = "$(TARGET_NAME)"; 339 | SKIP_INSTALL = YES; 340 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 341 | }; 342 | name = Debug; 343 | }; 344 | 9403D7501A48962F008336A7 /* Release */ = { 345 | isa = XCBuildConfiguration; 346 | buildSettings = { 347 | CLANG_ENABLE_MODULES = YES; 348 | DEFINES_MODULE = YES; 349 | DYLIB_COMPATIBILITY_VERSION = 1; 350 | DYLIB_CURRENT_VERSION = 1; 351 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 352 | INFOPLIST_FILE = Giphy/Info.plist; 353 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 354 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 355 | PRODUCT_BUNDLE_IDENTIFIER = "com.otium.$(PRODUCT_NAME:rfc1034identifier)"; 356 | PRODUCT_NAME = "$(TARGET_NAME)"; 357 | SKIP_INSTALL = YES; 358 | }; 359 | name = Release; 360 | }; 361 | 9403D7521A48962F008336A7 /* Debug */ = { 362 | isa = XCBuildConfiguration; 363 | buildSettings = { 364 | FRAMEWORK_SEARCH_PATHS = ( 365 | "$(SDKROOT)/Developer/Library/Frameworks", 366 | "$(inherited)", 367 | ); 368 | GCC_PREPROCESSOR_DEFINITIONS = ( 369 | "DEBUG=1", 370 | "$(inherited)", 371 | ); 372 | INFOPLIST_FILE = GiphyTests/Info.plist; 373 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 374 | PRODUCT_BUNDLE_IDENTIFIER = "com.otium.$(PRODUCT_NAME:rfc1034identifier)"; 375 | PRODUCT_NAME = "$(TARGET_NAME)"; 376 | }; 377 | name = Debug; 378 | }; 379 | 9403D7531A48962F008336A7 /* Release */ = { 380 | isa = XCBuildConfiguration; 381 | buildSettings = { 382 | FRAMEWORK_SEARCH_PATHS = ( 383 | "$(SDKROOT)/Developer/Library/Frameworks", 384 | "$(inherited)", 385 | ); 386 | INFOPLIST_FILE = GiphyTests/Info.plist; 387 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 388 | PRODUCT_BUNDLE_IDENTIFIER = "com.otium.$(PRODUCT_NAME:rfc1034identifier)"; 389 | PRODUCT_NAME = "$(TARGET_NAME)"; 390 | }; 391 | name = Release; 392 | }; 393 | /* End XCBuildConfiguration section */ 394 | 395 | /* Begin XCConfigurationList section */ 396 | 9403D7321A48962E008336A7 /* Build configuration list for PBXProject "Giphy" */ = { 397 | isa = XCConfigurationList; 398 | buildConfigurations = ( 399 | 9403D74C1A48962F008336A7 /* Debug */, 400 | 9403D74D1A48962F008336A7 /* Release */, 401 | ); 402 | defaultConfigurationIsVisible = 0; 403 | defaultConfigurationName = Release; 404 | }; 405 | 9403D74E1A48962F008336A7 /* Build configuration list for PBXNativeTarget "Giphy" */ = { 406 | isa = XCConfigurationList; 407 | buildConfigurations = ( 408 | 9403D74F1A48962F008336A7 /* Debug */, 409 | 9403D7501A48962F008336A7 /* Release */, 410 | ); 411 | defaultConfigurationIsVisible = 0; 412 | defaultConfigurationName = Release; 413 | }; 414 | 9403D7511A48962F008336A7 /* Build configuration list for PBXNativeTarget "GiphyTests" */ = { 415 | isa = XCConfigurationList; 416 | buildConfigurations = ( 417 | 9403D7521A48962F008336A7 /* Debug */, 418 | 9403D7531A48962F008336A7 /* Release */, 419 | ); 420 | defaultConfigurationIsVisible = 0; 421 | defaultConfigurationName = Release; 422 | }; 423 | /* End XCConfigurationList section */ 424 | }; 425 | rootObject = 9403D72F1A48962E008336A7 /* Project object */; 426 | } 427 | --------------------------------------------------------------------------------