### GiphyGridController Setup and Customization Source: https://github.com/giphy/giphy-ios-sdk/blob/main/Docs.md Explains how to set up and customize the GiphyGridController for displaying content in a grid format. ```APIDOC ## GiphyGridController Setup and Customization ### Description The `GiphyGridController` manages requesting, loading, caching, and rendering Giphy content in a customizable grid. It offers more control over the grid's appearance compared to `GiphyViewController`. ### Setup Create a new grid controller: ```swift let gridController = GiphyGridController() ``` Customize grid appearance: ```swift // Space between cells gridController.cellPadding = 2.0 // Scroll direction (vertical or horizontal) gridController.direction = .vertical // Number of columns (vertical) or rows (horizontal) gridController.numberOfTracks = 3 // Hide checkered background for stickers gridController.showCheckeredBackground = false // Set background color gridController.view.backgroundColor = .lightGray // Make cells square (applies to Stickers only) gridController.fixedSizeCells = true ``` ### Presentation Embed the `GiphyGridController` within another `UIViewController`: ```swift addChild(gridController) view.addSubview(gridController.view) gridController.view.translatesAutoresizingMaskIntoConstraints = false gridController.view.leftAnchor.constraint(equalTo: view.safeLeftAnchor).isActive = true gridController.view.rightAnchor.constraint(equalTo: view.safeRightAnchor).isActive = true gridController.view.topAnchor.constraint(equalTo: view.safeTopAnchor).isActive = true gridController.view.bottomAnchor.constraint(equalTo: view.safeBottomAnchor).isActive = true gridController.didMove(toParent: self) ``` **Important:** Create a new `GiphyGridController` instance for each presentation and set it to `nil` upon dismissal. Avoid multiple instances on the same screen. ``` -------------------------------- ### Prepare Giphy Clip Preview for Grids Source: https://github.com/giphy/giphy-ios-sdk/blob/main/clips.md Use `prepareMedia` to load a clip preview into a view for grids, reducing CPU consumption compared to auto-playing. Call `loadMedia` to start playback. ```swift videoPlayer.prepareMedia(media: media, view: videoView) ``` ```swift if playClipOnLoad { videoPlayer.loadMedia(media: media, muteOnPlay: true, view: videoView) } else { videoPlayer.prepareMedia(media: media, view: videoView) } ``` -------------------------------- ### Get Media URLs Source: https://github.com/giphy/giphy-ios-sdk/blob/main/Docs.md Obtain URLs for a GPHMedia object in various formats (webp, gif, mp4) and renditions. The example shows how to get a fixed-width GIF URL. ```swift let webpURL = media.url(rendition: .original, fileType: .webp) let gifURL = media.url(rendition: .fixedWidth, fileType: .gif) let vidURL = media.url(rendition: .fixedWidth, fileType: .mp4) let url = URL(string: gifURL) ``` -------------------------------- ### Create Example Theme with Dynamic Colors Source: https://github.com/giphy/giphy-ios-sdk/blob/main/Docs.md Create a custom theme that adjusts colors based on the current mode (dark or light). The 'mode' variable determines the effective theme type, considering the .automatic setting. ```swift public class ExampleTheme: GPHTheme { public override init() { super.init() self.type = .automatic } public override var searchPlaceholderTextColor: UIColor { switch mode { case .dark, .darkBlur: return .blue case .light, .lightBlur: return .green default: return .clear } } var mode: GPHThemeType { if case .automatic = type { if isDarkMode { return .dark } return .light } return type } } ``` -------------------------------- ### Install Giphy SDK via CocoaPods Source: https://context7.com/giphy/giphy-ios-sdk/llms.txt Add the Giphy SDK to your project using CocoaPods. For pure Objective-C projects, ensure you have a bridging header. ```ruby target "YourAppTarget" do pod 'Giphy' end # For pure Objective-C projects, add an empty Swift file to your target and choose **Create Bridging Header** when prompted. ``` -------------------------------- ### Create Custom Giphy Theme Source: https://github.com/giphy/giphy-ios-sdk/blob/main/Docs.md Subclass GPHTheme to override visual properties like font and colors to match your app's visual language. This example customizes the text field font and text color. ```swift public class CustomTheme: GPHTheme { public override init() { super.init() self.type = .light } public override var textFieldFont: UIFont? { return UIFont.italicSystemFont(ofSize: 15.0) } public override var textColor: UIColor { return .black } } ``` -------------------------------- ### Get Media Aspect Ratio Source: https://github.com/giphy/giphy-ios-sdk/blob/main/Docs.md Retrieve the aspect ratio of a GPHMedia object, which can be used to correctly size a media view. ```swift let aspectRatio = media.aspectRatio ``` -------------------------------- ### Get Recently Picked GIFs Source: https://github.com/giphy/giphy-ios-sdk/blob/main/Docs.md Retrieve a list of GIFs that the user has previously selected. This is useful for displaying a 'recents' tab. ```swift let recentlyPicked = GPHContent.recents ``` -------------------------------- ### Grid-Only Integration with GiphyGridController Source: https://context7.com/giphy/giphy-ios-sdk/llms.txt Embed `GiphyGridController` as a child view controller for flexible layout. Ensure a new instance is created each time it's shown and the reference is nilled out on dismissal. This example configures the grid for a vertical waterfall layout with a light theme and search content. ```swift import GiphyUISDK class SearchViewController: UIViewController, GPHGridDelegate { private var gridController: GiphyGridController? override func viewDidLoad() { super.viewDidLoad() showGrid(query: "hello") } func showGrid(query: String) { let grid = GiphyGridController() grid.cellPadding = 2 grid.direction = .vertical grid.numberOfTracks = 3 // columns for vertical layout grid.fixedSizeCells = false // waterfall (aspect-ratio) sizing grid.renditionType = .fixedWidth grid.theme = GPHTheme(type: .light) grid.content = GPHContent.search(withQuery: query, mediaType: .gif, language: .english) grid.delegate = self addChild(grid) view.addSubview(grid.view) grid.view.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ grid.view.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), grid.view.bottomAnchor.constraint(equalTo: view.bottomAnchor), grid.view.leadingAnchor.constraint(equalTo: view.leadingAnchor), grid.view.trailingAnchor.constraint(equalTo: view.trailingAnchor), ]) grid.didMove(toParent: self) grid.update() gridController = grid } // MARK: - GPHGridDelegate func contentDidUpdate(resultCount: Int, error: Error?) { print("Grid loaded \(resultCount) results, error: \(String(describing: error))") } func didSelectMedia(media: GPHMedia, cell: UICollectionViewCell) { print("Tapped:", media.id, "type:", media.type) } func didSelectMoreByYou(query: String) {} func didScroll(offset: CGFloat) {} } ``` -------------------------------- ### Initialize GIPHY SDK Source: https://context7.com/giphy/giphy-ios-sdk/llms.txt Configure the SDK once at app launch using your GIPHY API key. A separate key is required for each platform. ```swift import GiphyUISDK @main struct MyApp: App { init() { Giphy.configure(apiKey: "YOUR_IOS_SDK_API_KEY") } var body: some Scene { WindowGroup { ContentView() } } } ``` ```objectivec // Objective-C equivalent // [Giphy configureWithApiKey:@"YOUR_IOS_SDK_API_KEY" verificationMode:NO metadata:@{}]; ``` -------------------------------- ### Get Number of Recents Source: https://github.com/giphy/giphy-ios-sdk/blob/main/Docs.md Determine the count of recently picked GIFs. This can be used to conditionally display a 'recents' tab. ```swift let numberOfRecents = GPHRecents.count ``` -------------------------------- ### Initialize GiphyViewController Source: https://github.com/giphy/giphy-ios-sdk/blob/main/Docs.md Instantiate the GiphyViewController to present the Giphy interface. It is recommended to create a new instance each time you display Giphy to avoid potential issues. ```APIDOC ### GiphyViewController Create a new `GiphyViewController`, which takes care of most of the magic. ```swift let giphy = GiphyViewController() ``` Create a new `GiphyViewController` every time you want to show GIPHY (maintaining a reference to the same `GiphyViewController` object isn't necesssary and can impact performance and lead to unexpected results) ``` -------------------------------- ### Initialize GiphyViewController Source: https://github.com/giphy/giphy-ios-sdk/blob/main/Docs.md Create an instance of GiphyViewController to present the Giphy interface. It's recommended to create a new instance each time it's presented. ```swift let giphy = GiphyViewController() ``` -------------------------------- ### Initialize GiphyGridController Source: https://github.com/giphy/giphy-ios-sdk/blob/main/Docs.md Create a new instance of the GiphyGridController to manage and display content in a customizable grid. ```swift let gridController = GiphyGridController() ``` -------------------------------- ### Pre-built Picker — `GiphyViewController` Source: https://context7.com/giphy/giphy-ios-sdk/llms.txt Use `GiphyViewController` for a fully self-contained UI that presents a tray with search, trending, recents, and category tabs for various media types. It's recommended to create a new instance each time it's presented. ```APIDOC ## Pre-built Picker — `GiphyViewController` `GiphyViewController` is a fully self-contained UIViewController that presents a tray containing search, trending, recents, and category tabs for GIFs, Stickers, Clips, Text, and Emoji. Create a new instance every time it is presented to avoid state and performance issues. ```swift import GiphyUISDK class ChatViewController: UIViewController, GiphyDelegate { func openGiphyPicker() { let giphy = GiphyViewController() giphy.mediaTypeConfig = [.gifs, .stickers, .clips, .text, .emoji, .recents] giphy.theme = GPHTheme(type: .darkBlur) giphy.rating = .ratedPG13 giphy.renditionType = .fixedWidth giphy.stickerColumnCount = .three giphy.showConfirmationScreen = false giphy.shouldLocalizeSearch = false GiphyViewController.trayHeightMultiplier = 0.7 giphy.delegate = self present(giphy, animated: true) } // MARK: - GiphyDelegate func didSelectMedia(giphyViewController: GiphyViewController, media: GPHMedia) { giphyViewController.dismiss(animated: true) // Use media.id to send in a message, or render immediately print("Selected GIF id:", media.id) } func didDismiss(controller: GiphyViewController?) { // User closed picker without selecting } } ``` ``` -------------------------------- ### GPHCache Management Source: https://github.com/giphy/giphy-ios-sdk/blob/main/Docs.md Demonstrates how to set cache capacities and manually clear the cache using GPHCache. ```APIDOC ## GPHCache Management ### Description Manages media asset caching to reduce network requests and improve loading times. You can set custom disk and memory capacities and manually clear the cache. ### Usage Set cache capacities (e.g., to 300 MB): ```swift GPHCache.shared.cache.diskCapacity = 300 * 1000 * 1000 GPHCache.shared.cache.memoryCapacity = 300 * 1000 * 1000 ``` Manually clear the cache: ```swift GPHCache.shared.clear() ``` Retrieve raw image data: ```swift guard let url = media.url(rendition: .fixedWidth, fileType: .webp) else { return } GPHCache.shared.downloadAssetData(url) { (data, error) in // Handle data or error } ``` ``` -------------------------------- ### Initialize and Load GPHVideoPlayer for Clips Source: https://github.com/giphy/giphy-ios-sdk/blob/main/clips.md Use `GPHVideoPlayerView` and `GPHVideoPlayer` to play GIPHY Clips. Load media with `loadMedia`, specifying whether to auto-play and mute. ```swift let playerView = GPHVideoPlayerView() let videoPlayer = GPHVideoPlayer() videoPlayer.loadMedia(media: media, autoPlay: true, muteOnPlay: true, view: videoPlayerView, repeatable: true) ``` -------------------------------- ### SDK Initialization Source: https://context7.com/giphy/giphy-ios-sdk/llms.txt Configure the GIPHY SDK once at app launch using your iOS-specific API key. This is essential for the SDK to function correctly. ```APIDOC ## SDK Initialization — `Giphy.configure(apiKey:)` Configure the SDK once at app launch with your iOS-specific API key obtained from the [GIPHY Developer Portal](https://developers.giphy.com/dashboard/). A separate key is required for each platform (iOS, Android, Web). ```swift import GiphyUISDK @main struct MyApp: App { init() { Giphy.configure(apiKey: "YOUR_IOS_SDK_API_KEY") } var body: some Scene { WindowGroup { ContentView() } } } // Objective-C equivalent // [Giphy configureWithApiKey:@"YOUR_IOS_SDK_API_KEY" verificationMode:NO metadata:@{}]; ``` ``` -------------------------------- ### Open Giphy Picker with Customizations Source: https://context7.com/giphy/giphy-ios-sdk/llms.txt Present the `GiphyViewController` to allow users to select media. Configure media types, theme, rating, rendition, sticker columns, confirmation screen, and localization. ```swift import GiphyUISDK class ChatViewController: UIViewController, GiphyDelegate { func openGiphyPicker() { let giphy = GiphyViewController() giphy.mediaTypeConfig = [.gifs, .stickers, .clips, .text, .emoji, .recents] giphy.theme = GPHTheme(type: .darkBlur) giphy.rating = .ratedPG13 giphy.renditionType = .fixedWidth giphy.stickerColumnCount = .three giphy.showConfirmationScreen = false giphy.shouldLocalizeSearch = false GiphyViewController.trayHeightMultiplier = 0.7 giphy.delegate = self present(giphy, animated: true) } // MARK: - GiphyDelegate func didSelectMedia(giphyViewController: GiphyViewController, media: GPHMedia) { giphyViewController.dismiss(animated: true) // Use media.id to send in a message, or render immediately print("Selected GIF id:", media.id) } func didDismiss(controller: GiphyViewController?) { // User closed picker without selecting } } ``` -------------------------------- ### Configure Media Types for Dynamic Text Source: https://github.com/giphy/giphy-ios-sdk/blob/main/animate.md Ensure the `.text` content type is included in your `mediaTypeConfig` array to enable dynamic text results. ```swift giphyViewController.mediaTypeConfig = [.gifs, .stickers, .text] ``` -------------------------------- ### GiphyGridController Integration Source: https://context7.com/giphy/giphy-ios-sdk/llms.txt Demonstrates how to integrate and configure GiphyGridController to display a paginated, waterfall-layout collection view of Giphy content. It covers initialization, setting properties, and handling delegate callbacks for selection and updates. ```APIDOC ## Grid-Only Integration — `GiphyGridController` `GiphyGridController` renders a paginated, waterfall-layout collection view of GIPHY content and delegates selection handling entirely to your code. Embed it as a child view controller for maximum layout flexibility. Always create a new instance each time it is shown and nil-out the reference on dismissal. ```swift import GiphyUISDK class SearchViewController: UIViewController, GPHGridDelegate { private var gridController: GiphyGridController? override func viewDidLoad() { super.viewDidLoad() showGrid(query: "hello") } func showGrid(query: String) { let grid = GiphyGridController() grid.cellPadding = 2 grid.direction = .vertical grid.numberOfTracks = 3 // columns for vertical layout grid.fixedSizeCells = false // waterfall (aspect-ratio) sizing grid.renditionType = .fixedWidth grid.theme = GPHTheme(type: .light) grid.content = GPHContent.search(withQuery: query, mediaType: .gif, language: .english) grid.delegate = self addChild(grid) view.addSubview(grid.view) grid.view.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ grid.view.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), grid.view.bottomAnchor.constraint(equalTo: view.bottomAnchor), grid.view.leadingAnchor.constraint(equalTo: view.leadingAnchor), grid.view.trailingAnchor.constraint(equalTo: view.trailingAnchor), ]) grid.didMove(toParent: self) grid.update() gridController = grid } // MARK: - GPHGridDelegate func contentDidUpdate(resultCount: Int, error: Error?) { print("Grid loaded \(resultCount) results, error: \(String(describing: error))") } func didSelectMedia(media: GPHMedia, cell: UICollectionViewCell) { print("Tapped:", media.id, "type:", media.type) } func didSelectMoreByYou(query: String) {} func didScroll(offset: CGFloat) {} } ``` ``` -------------------------------- ### Create and Set GPHMediaView Source: https://github.com/giphy/giphy-ios-sdk/blob/main/Docs.md Instantiate a GPHMediaView and assign a GPHMedia object to its 'media' property to display the GIF. ```swift let mediaView = GPHMediaView() mediaView.media = media ``` -------------------------------- ### Configure API Key Source: https://github.com/giphy/giphy-ios-sdk/blob/main/Docs.md Import the GiphyUISDK and configure your application with your Giphy API key. Ensure you obtain a separate key for the iOS SDK from the Giphy Developer Portal. ```APIDOC ## Configure your API key First things first, be sure to import: ```swift import GiphyUISDK ``` Configure your API key. Apply for a new __iOS SDK__ key [here](https://developers.giphy.com/dashboard/). Please remember, you should use a separate key for every platform (Android, iOS, Web) you add our SDKs to. ```swift Giphy.configure(apiKey: "your ios sdk key here") ``` ``` -------------------------------- ### Implement GPHGridDelegate Source: https://github.com/giphy/giphy-ios-sdk/blob/main/Docs.md Conform to the GPHGridDelegate protocol to handle content updates and media selection events from the Giphy grid. ```swift extension ViewController: GPHGridDelegate { func contentDidUpdate(resultCount: Int) { print("content did update") } func didSelectMedia(media: GPHMedia, cell: UICollectionViewCell) { print("did select media") } } ``` -------------------------------- ### Integrate dSYM for App Store Uploads Source: https://context7.com/giphy/giphy-ios-sdk/llms.txt Add dSYM files for device and simulator builds to avoid App Store Connect warnings. Requires GIPHY SDK v2.2.15+. Follow the steps to download dSYM files and add a run script phase in Xcode. ```bash # 1. Download and unzip dSYM files from the release page: # https://github.com/Giphy/giphy-ios-sdk/releases/tag/2.2.15 # 2. In Xcode: Target → Build Phases → + → New Run Script Phase # Insert the following script and fill in the two paths: ``` ```sh DSYM_PATH_DEVICE="/path/to/GiphyUISDK.framework.dSYM" DSYM_PATH_SIMULATOR="/path/to/GiphyUISDK-simulator.framework.dSYM" if [ "$PLATFORM_NAME" == "iphoneos" ]; then echo "Including dSYM in Device build..." if [ -d "$DSYM_PATH_DEVICE" ]; then cp -R "$DSYM_PATH_DEVICE" "${DWARF_DSYM_FOLDER_PATH}" else echo "dSYM file not found!"; exit 1 fi elif [ "$PLATFORM_NAME" == "iphonesimulator" ]; then echo "Including dSYM in Simulator build..." if [ -d "$DSYM_PATH_SIMULATOR" ]; then cp -R "$DSYM_PATH_SIMULATOR" "${DWARF_DSYM_FOLDER_PATH}" else echo "dSYM file not found!"; exit 1 fi else echo "Unknown platform: $PLATFORM_NAME" fi ``` -------------------------------- ### Enable Animated Text Creation Source: https://context7.com/giphy/giphy-ios-sdk/llms.txt Dynamically generate animated text results when no matching GIFs are found. Enable in GiphyViewController or use GPHContent.animate(_:) with GiphyGridController. Requires SDK v2.0.5+ and a special SDK key. Dynamic media cannot be re-fetched by id. ```swift import GiphyUISDK // Enable in GiphyViewController let giphy = GiphyViewController() giphy.mediaTypeConfig = [.gifs, .stickers, .text] giphy.enableDynamicText = true // Handle dynamic media in the delegate extension ChatViewController: GiphyDelegate { func didSelectMedia(giphyViewController: GiphyViewController, media: GPHMedia) { giphyViewController.dismiss(animated: true) if media.isDynamic { // Must store/send URL, not the id let assetURL = media.url(rendition: .fixedWidth, fileType: .webp) sendMessage(assetURL: assetURL) } else { sendMessage(gifID: media.id) } } func didDismiss(controller: GiphyViewController?) {} } // Use in GiphyGridController let gridController = GiphyGridController() gridController.content = GPHContent.animate("you're the best!") gridController.update() ``` -------------------------------- ### Handle Dynamic Media Assets Source: https://github.com/giphy/giphy-ios-sdk/blob/main/animate.md Check the `isDynamic` property of `GPHMedia` to identify dynamically generated assets. For these, use the asset URL instead of the `id` as it cannot be fetched directly. ```swift if media.isDynamic { // handle accordingly } ``` -------------------------------- ### GPHContent for Giphy API Requests Source: https://github.com/giphy/giphy-ios-sdk/blob/main/Docs.md Shows how to create `GPHContent` objects to request different types of content from the Giphy API. ```APIDOC ## GPHContent for Giphy API Requests ### Description The `GPHContent` class is used to define content requests to the Giphy API. You can create `GPHContent` objects for trending media, emoji, or specific search queries. ### Usage Request trending GIFs: ```swift let trendingGIFs = GPHContent.trending(mediaType: .gif) ``` Request trending Stickers: ```swift let trendingStickers = GPHContent.trending(mediaType: .sticker) ``` Request trending Text: ```swift let trendingText = GPHContent.trending(mediaType: .text) ``` Request Emoji: ```swift let emoji = GPHContent.emoji ``` Search for GIFs: ```swift let search = GPHContent.search(withQuery: "Hello", mediaType: .gif, language: .english) ``` ``` -------------------------------- ### Enable Confirmation Screen Source: https://github.com/giphy/giphy-ios-sdk/blob/main/Docs.md Set to true to display a secondary confirmation screen showing a larger rendition of the GIF when the user taps on it. ```swift giphy.showConfirmationScreen = true ``` -------------------------------- ### Import GiphyUISDK Source: https://github.com/giphy/giphy-ios-sdk/blob/main/Docs.md Import the GiphyUISDK into your Swift file to access its functionalities. ```swift import GiphyUISDK ``` -------------------------------- ### Create Animated Text Content Source: https://github.com/giphy/giphy-ios-sdk/blob/main/animate.md Use the `.animate` constructor on `GPHContent` to create animated text results based on a given string. This is analogous to `.search` and `.trending`. ```swift let trending = GPHContent.trending(mediaType: .sticker) let search = GPHContent.search(withQuery: "hello", mediaType: .gif, language: .english) // new: let animatedText = GPHContent.animate("hey what up! hope this all makes sense.") ``` -------------------------------- ### Implement Giphy Delegate Methods Source: https://github.com/giphy/giphy-ios-sdk/blob/main/Docs.md Conform to the GiphyDelegate protocol to handle user interactions. Implement 'didSelectMedia' to process a selected GIF and 'didDismiss' for controller dismissal. ```swift extension YourController: GiphyDelegate { func didSelectMedia(giphyViewController: GiphyViewController, media: GPHMedia) { // your user tapped a GIF! giphyViewController.dismiss(animated: true, completion: nil) } func didDismiss(controller: GiphyViewController?) { // your user dismissed the controller without selecting a GIF. } } ``` -------------------------------- ### Caching Media Assets with GPHCache Source: https://context7.com/giphy/giphy-ios-sdk/llms.txt The SDK utilizes URLCache for media assets with default limits of 300 MB for disk and memory. You can adjust these limits and manually clear the cache. It also allows downloading raw asset data for custom rendering. ```APIDOC ## Caching — `GPHCache` The SDK uses `URLCache` for all media assets. Limits default to 300 MB for both disk and memory. Clear the cache manually when needed (it is not cleared automatically on picker dismissal). ```swift import GiphyUISDK // Adjust cache limits (set at app startup) GPHCache.shared.cache.diskCapacity = 500 * 1_000 * 1_000 // 500 MB GPHCache.shared.cache.memoryCapacity = 100 * 1_000 * 1_000 // 100 MB // Clear entire cache (e.g., in response to a memory warning) GPHCache.shared.clear() // Download raw asset data for custom rendering func loadRawData(for media: GPHMedia) { guard let url = media.url(rendition: .fixedWidth, fileType: .webp) else { return } GPHCache.shared.downloadAssetData(url) { data, error in if let data = data { print("Downloaded \(data.count) bytes") // Use Data to render with a custom image library } } } ``` ``` -------------------------------- ### Subscribe to Giphy Video Player Events Source: https://github.com/giphy/giphy-ios-sdk/blob/main/clips.md Add a listener to the `GPHVideoPlayer` to subscribe to state changes and events. ```swift videoPlayer.addListener(GPHVideoPlayerStateListener) ``` -------------------------------- ### Configure Giphy API Key Source: https://github.com/giphy/giphy-ios-sdk/blob/main/Docs.md Configure the GIPHY SDK with your unique iOS SDK API key. Obtain this key from the Giphy Developer Portal. ```swift Giphy.configure(apiKey: "your ios sdk key here") ``` -------------------------------- ### Sending Clips & Renditions Source: https://github.com/giphy/giphy-ios-sdk/blob/main/clips.md It is recommended to use GIPHY IDs for Clips instead of URLs. Video URLs can be accessed via the `video` property of `GPHMedia`. Be aware of rendition limitations for Clips and use `clipsPreviewRenditionType`. ```APIDOC ### Sending Clips & Renditions As with sending / storing GIFs and Stickers, it's best practice to use GIPHY IDs to represent GIPHY Clips, rather than asset urls, and use the `gifByID` or `gifsByID` endpoints to retrieve the associated `GPHMedia`(s). More Info [here](https://github.com/Giphy/giphy-ios-sdk/blob/main/Docs.md#media-ids). Video urls (`.mp4`) may be accessed directly within the `video` property (with type `GPHVideo`) of the encompassing `GPHMedia`. ### Rendition Limitations Certain renditions (cases of the `GPHRenditionType` enum) are not available for Clips. These include: - `preview` - `previewGif` - `looping` - `fixedWidthSmall` - `fixedWidthSmallStill` - `fixedHeightSmall` - `fixedHeighSmallStill` - `downsizedSmall` - `downsizedStill` - `downsized` As a result, if you set the `renditionType` property of `GiphyViewController` or `GiphyGridController` to any of these, clips previews may not play back correctly in the grid. To account for this limitation, we created a new property specifically for clips call `clipsPreviewRenditionType` which is available as a property of both `GiphyViewController` and `GiphyGridController`. Setting this property to one of the above `GPHRenditionType` options will throw an exception. As with `renditionType` the default for `clipsPreviewRenditionType` is the `GPHRenditionType` option `.fixedWidth`. ``` -------------------------------- ### Configure GiphyViewController for Clips Source: https://github.com/giphy/giphy-ios-sdk/blob/main/clips.md Add the `.clips` content type to your `mediaTypeConfig` to enable GIPHY Clips. A console warning may appear for this new feature; disable it using `disableClipsWarning`. ```swift giphyViewController.mediaTypeConfig = [.gifs, .stickers, .clips] ``` -------------------------------- ### Create Search Content Request Source: https://github.com/giphy/giphy-ios-sdk/blob/main/Docs.md Generate a content request for searching Giphy. Specify the query, media type, and language. ```swift let search = GPHContent.search(withQuery: "Hello", mediaType: .gif, language: .english) ``` -------------------------------- ### Configure Giphy SDK Cache Capacity Source: https://github.com/giphy/giphy-ios-sdk/blob/main/Docs.md Set the disk and memory capacities for the Giphy SDK's cache. The default is 300MB for both. ```swift // set to 300 mb GPHCache.shared.cache.diskCapacity = 300 * 1000 * 1000 GPHCache.shared.cache.memoryCapacity = 300 * 1000 * 1000 ``` -------------------------------- ### Enable Dynamic Text Feature Source: https://github.com/giphy/giphy-ios-sdk/blob/main/animate.md Set the `enableDynamicText` flag to `true` in the `GiphyViewController` to activate the GIPHY Text creation experience. ```swift giphyViewController.enableDynamicText = true ``` -------------------------------- ### Play GIPHY Clips with GPHVideoPlayerView Source: https://github.com/giphy/giphy-ios-sdk/blob/main/clips.md Use `GPHVideoPlayerView` and `GPHVideoPlayer` to play GIPHY Clip video assets. You can control playback, prepare media to reduce CPU usage, and subscribe to player events. ```APIDOC ### GPHVideoPlayer + GPHVideoPlayerView Similar to the [`GPHMediaView`](https://github.com/Giphy/giphy-ios-sdk/blob/main/Docs.md#gphmediaview) which works for GIFs, Stickers, and Text, the `GPHVideoPlayerView` is a component that makes it easy to play back `GPHMedia` clips video assets. The `GPHVideoPlayerView` will only work for `GPHMedia` which has `type` property `.video`. Create and load a `GPHVideoPlayer + GPHVideoPlayerView` with a `GPHMedia`: ```swift let playerView = GPHVideoPlayerView() let videoPlayer = GPHVideoPlayer() videoPlayer.loadMedia(media: media, autoPlay: true, muteOnPlay: true, view: videoPlayerView, repeatable: true) ``` To use `GPHVideoPlayerView` in grids: ```swift videoPlayer.prepareMedia(media: media, view: videoView) ``` Use it to reduce CPU consumption. It prepares a view with a clip preview instead of automatically loading and playing it. Use `videoPlayer.loadMedia` only to start playback: ```swift if playClipOnLoad { videoPlayer.loadMedia(media: media, muteOnPlay: true, view: videoView) } else { videoPlayer.prepareMedia(media: media, view: videoView) } ``` Play, Stop, Pause, Mute, Unmute: ```swift videoPlayer.play() videoPlayer.stop() videoPlayer.pause() videoPlayer.mute(true) videoPlayer.mute(false) ``` To subscribe to `GPHVideoPlayer` events: ```swift videoPlayer.addListener(GPHVideoPlayerStateListener) ``` It's preferable to use only one `GPHVideoPlayer` instance and share it between `GPHVideoPlayerView`(s). ``` -------------------------------- ### Fetching Media by ID with GiphyCore Source: https://context7.com/giphy/giphy-ios-sdk/llms.txt Fetch media by its ID to reconstruct a GPHMedia object. This is useful for messaging apps where sending only the media ID is more efficient than sending full URLs or assets. Batch fetching of multiple IDs is also supported. ```APIDOC ## Fetching Media by ID — `GiphyCore` In messaging apps send only media `id` strings rather than full URLs or assets. On the receiving end, reconstruct a `GPHMedia` from the stored id using `GiphyCore.shared.gifByID(_:)`. ```swift import GiphyUISDK // Send side: extract the id func sendGIF(_ media: GPHMedia, via chat: ChatService) { // Dynamic (animated text) assets cannot be re-fetched by id — send the URL if media.isDynamic { let url = media.url(rendition: .fixedWidth, fileType: .webp) chat.send(assetURL: url) } else { chat.send(gifID: media.id) } } // Receive side: reconstruct GPHMedia from id func displayReceivedGIF(id: String, in mediaView: GPHMediaView) { GiphyCore.shared.gifByID(id) { response, error in if let error = error { print("Error fetching GIF:", error.localizedDescription) return } guard let media = response?.data else { return } DispatchQueue.main.async { mediaView.media = media } } } // Batch fetch multiple IDs GiphyCore.shared.gifsByIDs(["id1", "id2", "id3"]) { response, error in guard let medias = response?.data else { return } print("Fetched \(medias.count) GIFs") } ``` ``` -------------------------------- ### Download Raw Image Data from Cache Source: https://github.com/giphy/giphy-ios-sdk/blob/main/Docs.md Retrieve the raw image data for a media asset from the cache. This is useful for accessing the underlying data, such as webp files. ```swift guard let url = media.url(rendition: .fixedWidth, fileType: .webp) else { return } GPHCache.shared.downloadAssetData(url) { (data, error) in } ``` -------------------------------- ### Update Content Grid Source: https://github.com/giphy/giphy-ios-sdk/blob/main/Docs.md Set the content for a grid controller, such as search results, and then refresh the grid's display. ```swift gridController.content = GPHContent.search(withQuery: "Sup", mediaType: .text, language: .english) gridController.update() ``` -------------------------------- ### Fetch Trending and Search Clips Source: https://github.com/giphy/giphy-ios-sdk/blob/main/clips.md Use GPHContent to fetch trending video clips or search for clips by query and language. Ensure mediaType is set to .video. ```swift let trending = GPHContent.trending(mediaType: .video) let search = GPHContent.search(withQuery: "hello", mediaType: .video, language: .english) ``` -------------------------------- ### Manage Cache with GPHCache Source: https://context7.com/giphy/giphy-ios-sdk/llms.txt Adjust default cache limits for disk and memory at app startup. Clear the entire cache manually when necessary, such as in response to a memory warning. You can also download raw asset data for custom rendering. ```swift import GiphyUISDK // Adjust cache limits (set at app startup) GPHCache.shared.cache.diskCapacity = 500 * 1_000 * 1_000 // 500 MB GPHCache.shared.cache.memoryCapacity = 100 * 1_000 * 1_000 // 100 MB // Clear entire cache (e.g., in response to a memory warning) GPHCache.shared.clear() // Download raw asset data for custom rendering func loadRawData(for media: GPHMedia) { guard let url = media.url(rendition: .fixedWidth, fileType: .webp) else { return } GPHCache.shared.downloadAssetData(url) { data, error in if let data = data { print("Downloaded \(data.count) bytes") // Use Data to render with a custom image library } } } ``` -------------------------------- ### GiphyGridController: GPHGridDelegate Source: https://github.com/giphy/giphy-ios-sdk/blob/main/Docs.md Implement the GPHGridDelegate to respond to GIF selection events in the grid. ```APIDOC ## GiphyGridController: GPHGridDelegate ### Description Similar to the `GiphyDelegate`, the `GPHGridDelegate` is the mechanism for responding to gif selection events in the grid. Conform to the `GPHGridDelegate` and set the delegate. ### Set Delegate ```swift gridController.delegate = self ``` ### Delegate Implementation ```swift extension ViewController: GPHGridDelegate { func contentDidUpdate(resultCount: Int) { print("content did update") } func didSelectMedia(media: GPHMedia, cell: UICollectionViewCell) { print("did select media") } } ``` ``` -------------------------------- ### Set Media Types in Objective-C Source: https://github.com/giphy/giphy-ios-sdk/blob/main/Docs.md Configure the types of media content (GIFs, Stickers, Text, Emoji) to be displayed in the Giphy interface using Objective-C. ```objective-c [giphy setMediaConfigWithTypes: [[NSMutableArray alloc] initWithObjects: @(GPHContentTypeGifs), @(GPHContentTypeStickers), @(GPHContentTypeText), @(GPHContentTypeEmoji), nil ] ] ``` -------------------------------- ### Enable GIPHY Clips in GiphyViewController Source: https://github.com/giphy/giphy-ios-sdk/blob/main/clips.md To display GIPHY Clips in the GiphyViewController, add the `.clips` media type to the `mediaTypeConfig` array. A console warning may appear for this new feature, which can be disabled. ```APIDOC ## Showing Clips in the GiphyViewController Add the new `.clips` `GPHContentType` to your `mediaTypeConfig` array. ```swift giphyViewController.mediaTypeConfig = [.gifs, .stickers, .clips] ``` Adding `.clips` to your `mediaTypeConfig` may produce a print statement in the console noting that Clips is a brand new feature which may not be ready for production releases. Disable the log by setting the `disableClipsWarning` of your `GiphyViewController`. ``` -------------------------------- ### Present Giphy View Controller Source: https://github.com/giphy/giphy-ios-sdk/blob/main/Docs.md Present the GiphyViewController to allow users to browse and select GIFs. ```swift present(giphy, animated: true, completion: nil) ``` -------------------------------- ### Enable Search Localization Source: https://github.com/giphy/giphy-ios-sdk/blob/main/Docs.md Determine whether to localize search results based on device settings. If false, the language defaults to 'en'. ```swift giphy.shouldLocalizeSearch = false ``` -------------------------------- ### Set Rendition Type Source: https://github.com/giphy/giphy-ios-sdk/blob/main/Docs.md Choose the rendition type for displaying GIFs in the grid. The default is .fixedWidth. ```swift giphy.renditionType = .fixedWidth ``` -------------------------------- ### Set Media Types in Swift Source: https://github.com/giphy/giphy-ios-sdk/blob/main/Docs.md Configure the types of media content (GIFs, Stickers, Text, Emoji) to be displayed in the Giphy interface by setting the mediaTypeConfig property. ```swift giphy.mediaTypeConfig = [.gifs, .stickers, .text, .emoji] ``` -------------------------------- ### Play GIPHY Clips with GPHVideoPlayer Source: https://context7.com/giphy/giphy-ios-sdk/llms.txt Use GPHVideoPlayer and GPHVideoPlayerView for playback of video-based media. One GPHVideoPlayer instance can be shared across multiple GPHVideoPlayerView instances. Requires GIPHY SDK v2.1.9+. ```swift import GiphyUISDK class ClipsViewController: UIViewController, GPHVideoPlayerStateListener { let videoPlayerView = GPHVideoPlayerView() let videoPlayer = GPHVideoPlayer() // share one player override func viewDidLoad() { super.viewDidLoad() view.addSubview(videoPlayerView) // ... (add constraints) ... // Enable Clips in GiphyViewController let giphy = GiphyViewController() giphy.mediaTypeConfig = [.gifs, .stickers, .clips] giphy.disableClipsWarning = true // suppress beta console log giphy.clipsPreviewRenditionType = .fixedWidth giphy.delegate = self present(giphy, animated: true) } func playClip(_ media: GPHMedia) { guard media.type == .video else { return } videoPlayer.addListener(self) videoPlayer.loadMedia(media: media, autoPlay: true, muteOnPlay: false, view: videoPlayerView, repeatable: true) } func prepareClipInGrid(_ media: GPHMedia) { // Use prepareMedia for silent thumbnail in a collection view videoPlayer.prepareMedia(media: media, view: videoPlayerView) } // MARK: - Playback controls func pause() { videoPlayer.pause() } func resume() { videoPlayer.resume() } func stop() { videoPlayer.stop() } func mute(_ on: Bool) { videoPlayer.mute(on) } // MARK: - GPHVideoPlayerStateListener func playerStateDidChange(_ state: GPHVideoPlayerState) { switch state { case .playing: print("Playing") case .paused: print("Paused") case .readyToPlay: print("Ready") default: break } } func playerDidFail(_ description: String?) { print("Playback error:", description ?? "unknown") } } ``` -------------------------------- ### Set Sticker Column Count Source: https://github.com/giphy/giphy-ios-sdk/blob/main/Docs.md Configure the number of columns displayed for stickers and text. Recommended values are 3 or 4 when using blur theme types. ```swift giphy.stickerColumnCount = GPHStickerColumnCount.three ``` -------------------------------- ### Add GiphyUISDK via CocoaPods Source: https://github.com/giphy/giphy-ios-sdk/blob/main/Docs.md Integrate the GiphyUISDK into your Xcode project by adding it to your Podfile. Ensure you have a bridging header for Objective-C projects. ```swift target "YourAppTarget" do pod 'Giphy' end ``` -------------------------------- ### Display Media with GPHMediaView Source: https://context7.com/giphy/giphy-ios-sdk/llms.txt Use GPHMediaView to display GIF, Sticker, and Text assets. Assign a GPHMedia object directly to the view for automatic fetching and animation. You can also access raw asset URLs for custom loading. ```swift import GiphyUISDK class MediaCell: UICollectionViewCell { let mediaView = GPHMediaView() override init(frame: CGRect) { super.init(frame: frame) contentView.addSubview(mediaView) mediaView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ mediaView.topAnchor.constraint(equalTo: contentView.topAnchor), mediaView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), mediaView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor), mediaView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor), ]) } func configure(with media: GPHMedia) { // Assign media — automatically fetches and animates mediaView.media = media // Size the view using the media's native aspect ratio let aspectRatio = media.aspectRatio // CGFloat (width/height) mediaView.heightAnchor.constraint( equalTo: mediaView.widthAnchor, multiplier: 1.0 / aspectRatio ).isActive = true // Or access raw asset URLs yourself if let webpURL = media.url(rendition: .fixedWidth, fileType: .webp) { print("WebP URL:", webpURL) } if let mp4URL = media.url(rendition: .fixedWidth, fileType: .mp4) { print("MP4 URL:", mp4URL) } } required init?(coder: NSCoder) { fatalError() } } ``` -------------------------------- ### Identify GIPHY Clips Media Type Source: https://github.com/giphy/giphy-ios-sdk/blob/main/clips.md The `.video` type for a `GPHMedia` instance indicates that it is a GIPHY Clip and should be played back with sound. ```APIDOC ## New GPHMediaType: .video The new `video` type signifies that a `GPHMedia` instance is a GIPHY Clip, and is intended to be played back as a video with sound. ```swift if media.type == .video { // Handle GIPHY Clip } switch media.type { case .video: // Handle GIPHY Clip break default: // Handle other media types break } ``` ``` -------------------------------- ### Identify Giphy Media Type as Video Source: https://github.com/giphy/giphy-ios-sdk/blob/main/clips.md Use the `.video` media type to determine if a `GPHMedia` instance is a GIPHY Clip intended for playback with sound. ```swift if media.type == .video { } ``` ```swift switch media.type { case .video: break default: break } ``` -------------------------------- ### Fetch Media by ID with GiphyCore Source: https://context7.com/giphy/giphy-ios-sdk/llms.txt Reconstruct GPHMedia objects from their IDs on the receiving end of a messaging app. Dynamic assets cannot be re-fetched by ID and require sending the URL instead. ```swift import GiphyUISDK // Send side: extract the id func sendGIF(_ media: GPHMedia, via chat: ChatService) { // Dynamic (animated text) assets cannot be re-fetched by id — send the URL if media.isDynamic { let url = media.url(rendition: .fixedWidth, fileType: .webp) chat.send(assetURL: url) } else { chat.send(gifID: media.id) } } // Receive side: reconstruct GPHMedia from id func displayReceivedGIF(id: String, in mediaView: GPHMediaView) { GiphyCore.shared.gifByID(id) { response, error in if let error = error { print("Error fetching GIF:", error.localizedDescription) return } guard let media = response?.data else { return } DispatchQueue.main.async { mediaView.media = media } } } // Batch fetch multiple IDs GiphyCore.shared.gifsByIDs(["id1", "id2", "id3"]) { response, error in guard let medias = response?.data else { return } print("Fetched \(medias.count) GIFs") } ``` -------------------------------- ### Add dSYM Files via Xcode Run Script Source: https://github.com/giphy/giphy-ios-sdk/blob/main/dsym.md Use this script in a new Run Script Build Phase in Xcode. It conditionally includes dSYM files for device or simulator builds. Ensure you set the DSYM_PATH_DEVICE and DSYM_PATH_SIMULATOR variables with the correct paths to your unzipped dSYM files. ```shell DSYM_PATH_DEVICE="" DSYM_PATH_SIMULATOR="" if [ "$PLATFORM_NAME" == "iphoneos" ]; then echo "Including dSYM in Device build..." if [ -d "$DSYM_PATH_DEVICE" ]; then cp -R "$DSYM_PATH_DEVICE" "${DWARF_DSYM_FOLDER_PATH}" else echo "dSYM file not found!" exit 1 fi elif [ "$PLATFORM_NAME" == "iphonesimulator" ]; then echo "Including dSYM in Simulator build..." if [ -d "$DSYM_PATH_SIMULATOR" ]; then cp -R "$DSYM_PATH_SIMULATOR" "${DWARF_DSYM_FOLDER_PATH}" else echo "dSYM file not found!" exit 1 fi else echo "Unknown platform: $PLATFORM_NAME" fi ``` -------------------------------- ### Updating Content Source: https://github.com/giphy/giphy-ios-sdk/blob/main/Docs.md Update the content displayed in the grid controller with new search results. ```APIDOC ## Updating the content ### Description Set the grid controller's `content` property and call update. ### Code ```swift gridController.content = GPHContent.search(withQuery: "Sup", mediaType: .text, language: .english) gridController.update() ``` ``` -------------------------------- ### Recents Source: https://github.com/giphy/giphy-ios-sdk/blob/main/Docs.md Retrieve and manage recently picked GIFs. Only show a 'recents' tab if there are any recents. ```APIDOC ## Recents ### Description Show GIFs that the user has previously picked. ### Code ```swift let recentlyPicked = GPHContent.recents ``` ### Count Get the number of recents via: ### Code ```swift let numberOfRecents = GPHRecents.count ``` ### Clear Optionally, we also provide the option to clear the set of recents: ### Code ```swift GPHRecents.clear() ``` ```