VESDK/iOS/Guides/Stickers
Smart Stickers
VideoEditor SDK for iOS provides predefined smart stickers
There are currently six predefined smart stickers available in SmartSticker.defaultItems
:
- Weekday
- Date
- Time
- Time Clock
- Weather Cloud (Requires a WeatherProvider)
- Weather Thermostat (Requires a WeatherProvider)
These smart stickers are part of the first default sticker category with the identifier "imgly_sticker_category_emoticons"
.
To enable all of the smart stickers you need to define a WeatherProvider
otherwise the weather stickers are hidden per default when StickerToolControllerOptions.weatherProvider
is not set. The following code snippet shows how to configure and use the provided OpenWeatherProvider
.
let unit = TemperatureFormat.locale// Make sure to pass in your API key to display real weather data// otherwise the sample data API is used!let weatherProvider = OpenWeatherProvider(apiKey: nil, unit: unit)weatherProvider.locationAccessRequestClosure = { locationManager inlocationManager.requestWhenInUseAuthorization()}let configuration = Configuration { builder inbuilder.configureStickerToolController { options inoptions.weatherProvider = weatherProvider}}
Example Weather Provider#
The following lists the implementation of the above used OpenWeatherProvider
that is also part of the SDK. It exemplifies how you could implement your own WeatherProvider
for your service of choice.
import CoreLocationimport Foundation/// A `WeatherProvider` for the https://openweathermap.org service.@objcMembers @objc(PESDKOpenWeatherProvider) public class OpenWeatherProvider: NSObject, WeatherProvider, CLLocationManagerDelegate {// MARK: - Properties/// The used API key. If `nil` or empty the sample API is used.public let apiKey: String?/// The minimum update interval to request new data from the service. It defaults to one hour.public var updateInterval: TimeInterval = 60 * 60// MARK: - Initializers/// Create a new `OpenWeatherProvider`./// - Parameters:/// - apiKey: The used API key. If `nil` or empty the sample API is used./// - unit: The temperature format that should be used for displaying temperature measurements to the user.public init(apiKey: String?, unit: TemperatureFormat) {self.apiKey = apiKeytemperatureFormat = unitsuper.init()locationManager.startUpdatingLocation()}deinit {locationManager.stopUpdatingLocation()}// MARK: - WeatherProviderprivate var url: URL? {guard let location = lastLocation else {return nil}let domain, appid: Stringif let apiKey = apiKey, !apiKey.isEmpty {domain = "api.openweathermap.org"appid = apiKey} else {domain = "samples.openweathermap.org"appid = "_"}let lat = location.coordinate.latitudelet lon = location.coordinate.longitudelet url = "https://\(domain)/data/2.5/weather?lat=\(lat)&lon=\(lon)&appid=\(appid)"return URL(string: url)}private var lastTemperature: Temperature?private var lastUpdate: Date?private var lastTask: URLSessionTask?private struct WeatherData: Codable {let main: Main}private struct Main: Codable {let temp: Double}/// The temperature format that should be used for displaying temperature measurements to the user.public var temperatureFormat: TemperatureFormat/// The temperature measurement.public var temperature: Temperature? { lastTemperature }/// Request to update the weather data.public func updateData() {guard let url = url else {return}if let lastTask = lastTask {switch lastTask.state {case .running:returncase .suspended:lastTask.resume()returndefault:break}}if let lastUpdate = lastUpdate, lastUpdate.timeIntervalSinceNow < updateInterval {return}let session = URLSession.sharedlet task = session.dataTask(with: url) { data, _, _ inguard let data = data, let weatherData = try? JSONDecoder().decode(WeatherData.self, from: data) else {return}DispatchQueue.main.async {self.lastUpdate = Date()self.lastTemperature = Temperature(value: weatherData.main.temp, unit: .kelvin)}}task.resume()lastTask = task}// MARK: - CoreLocationprivate var lastLocation: CLLocation?private lazy var locationManager: CLLocationManager = {let locationManager = CLLocationManager()locationManager.delegate = selflocationManager.distanceFilter = 10return locationManager}()/// When this closure is called, the SDK has determined that location access has not been granted/// to the host app yet. Within this closure you should then request appropriate permissions from/// the passed in `CLLocationManager` object. Location access is used to request weather data/// for the current location for weather stickers.////// - Attention: Starting Spring 2019, all apps submitted to the App Store that access user data/// are required to include a purpose string as soon as location permissions requests appear/// somewhere in the binary. Since we do not want to force developers integrating the SDK into/// their app to include a purpose string even with weather stickers disabled, this closure was/// introduced, so that developers can decide for themselves if it is appropriate to request/// location access. Simply set this property like this:/// ````/// openWeatherProvider.locationAccessRequestClosure = { locationManager in/// locationManager.requestWhenInUseAuthorization()/// }/// ````public var locationAccessRequestClosure: ((CLLocationManager) -> Void)? {didSet {if CLLocationManager.authorizationStatus() == .notDetermined {locationAccessRequestClosure?(locationManager)}}}/// :nodoc:public func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {lastLocation = locations.lastupdateData()}}