Wakup SDK Library
Native iOS SDK for Wakup platform.
Installation
To start using Wakup you have to integrate the Wakup SDK in your iOS application. If you already have CocoaPods installed, you can open the sample project by executing:
pod try Wakup
This will open the project with all the dependencies already installed and ready to execute.
Using CocoaPods
CocoaPods is the easiest and most maintainable way to install Wakup SDK. If you are using CocoaPods (that you should) just follow these steps:
-
Add a reference to the Wakup pod to your
Podfile
.pod 'Wakup'
-
Install the pods executing in your command line:
pod install
Basic Wakup SDK Integration
Basic integration includes everything required to get the offers module up and running with little effort.
Import module
If you installed Wakup SDK using CocoaPods, you have to import the Wakup
module on any file accessing any Wakup class:
import Wakup
Setup Wakup SDK
In order to access to Wakup functionality, the WakupManager
has to be setup. The perfect place to do it is application: didFinishLaunchingWithOptions:
method of your application delegate.
// Setup Wakup SDK with API Key
WakupManager.manager.setup("WAKUP_API_KEY")
Replace WAKUP_API_KEY
with the configuration values for your application in app.wakup.net. The method setup
must be called before presenting any Wakup view controller.
Setting user alias
To report the user alias (or user identifier) to the server, you can use the setAlias
method.
WakupManager.manager.setAlias("[email protected]".lowercased())
User aliases are case sensitive by default. If your aliases are case insensitive, they can be lower-cased to prevent case sensitivity issues.
Present root Wakup Controller
Once configured, you can present the offer list controller anywhere in your application. Wakup gives access to the root controller through the rootController
method of WakupManager
instance. You can push this controller to any UINavigationController
of your application:
// Obtain Wakup root controller
let wakupController = WakupManager.manager.rootController()
// Enable animation zoom-in and zoom-out transitions
navigationController.delegate = NavigationControllerDelegate()
// Present the Wakup root controller in the current navigation controller
navigationManager.pushViewController(wakupController, animated: true)
Note that Wakup requires a translucent navigation bar in order to be displayed correctly.
Using embedded navigation controller
Wakup SDK also provides its own UINavigationController
with animation delegate pre-configured to make other presentation forms easier. It can be obtained by calling rootNavigationController
method of WakupManager
instance.
// Obtain Wakup root navigation controller
let wakupController = WakupManager.manager.rootNavigationController()
// Present the Wakup root navigation controller modally
presentViewController(wakupController, animated: true, completion: nil)
Wakup controller will automatically detect if it's being presented modally and add a close button to the navigation bar.
Customization
The default Wakup integration would look like this:
Most application colors, fonts and icons are easily customizable. If not customized, they will appear with the default look&feel of Wakup.
Customize colors
Wakup SDK provides some convenience methods for configuring the appearance using WakupAppearance
class. For fine tuning, most component colors are configurable using UIAppearance
proxies, the same way native components are customized. This customization must be applied before presenting any Wakup controller.
Main and secondary tint colors
In order to make color customization easier, Wakup provides a convenience method that change the color of the entire application using a main tint color and an optional secondary tint color.
It will use derived colors (darker or lighter versions of the same color) to tint the application. If the color is light, a darker color will be used as contrast, and the opposite if it's a dark color. This contrast color can also be passed as parameter.
For example, this call:
WakupManager.appearance.setTint(mainColor: UIColor(fromHexString: "#5788a9"))
Would result in the following tinted result:
You can then configure components one by one if required.
Navigation bar
Navigation bar can be customized using UINavigationBar
appearance proxy like any other iOS application. Icons and buttons will take the navigation bar tintColor
property for tinting themselves.
let navBarColor = UIColor(red:0.26, green:0.07, blue:0.25, alpha:1)
let tintColor = UIColor(red:0.56, green:0.38, blue:0.57, alpha:1)
// Using convenience method
WakupManager.appearance.setNavigationBarTint(navBarColor: navBarColor, tintColor: tintColor)
// Using UIAppearance proxy
UINavigationBar.appearance().barTintColor = navBarColor
UINavigationBar.appearance().tintColor = tintColor
UINavigationBar.appearance().titleTextAttributes = [
NSAttributedStringKey.foregroundColor: tintColor
]
NavBarIconView.appearance().iconColor = tintColor
Category and company filter bar
The category and company filter located at the top of the main scene view can be customized by using appearance proxies for the different elements. For customizing the background scroll view colors use CategoryFilterView
and CompanyFilterView
classes. Category and company buttons can be customized using the CategoryFilterButton
and CompanyFilterButton
and lastly, the small selection indicator can be customized using CompanyFilterIndicatorView
.
let backgroundColor = UIColor(red:0.26, green:0.15, blue:0.26, alpha:1)
let buttonColor = UIColor(red:0.56, green:0.38, blue:0.57, alpha:1)
// Using convenience method
WakupManager.appearance.setCategoryFilterTint(backgroundColor: backgroundColor, buttonColor: buttonColor)
// Using UIAppearance proxy
CategoryFilterButton.appearance().setTitleColor(buttonColor, for: [])
CategoryFilterButton.appearance().setTitleColor(.white, for: .selected)
CategoryFilterView.appearance().backgroundColor = backgroundColor
CompanyFilterIndicatorView.appearance().iconColor = backgroundColor
CompanyFilterView.appearance().backgroundColor = .white
Offer views
Offer cascade views can be customized using CollectionViewCell
appearance proxy, in addition to the DiscountTagView
that modifies both the list and the detail green discount tag.
let titleColor = UIColor.blackColor()
let descriptionColor = UIColor(white: 0.33, alpha: 1)
let detailsColor = UIColor(white:0.56, alpha:1)
CouponCollectionViewCell.appearance().storeNameTextColor = titleColor
CouponCollectionViewCell.appearance().descriptionTextColor = descriptionColor
CouponCollectionViewCell.appearance().distanceTextColor = detailsColor
CouponCollectionViewCell.appearance().distanceIconColor = detailsColor
CouponCollectionViewCell.appearance().expirationTextColor = detailsColor
CouponCollectionViewCell.appearance().expirationIconColor = detailsColor
let tagColor = UIColor(red:0.5, green:0.59, blue:0.1, alpha:1)
// Using convenience method
WakupManager.appearance.setDiscountTagTint(tagColor)
// Using UIAppearance proxy
DiscountTagView.appearance().backgroundColor = tagColor
DiscountTagView.appearance().labelColor = .white
Offer quick actions
Quick actions appear when a offer view is pressed for a few seconds. They can be customized using ContextItemView
appearance proxy.
let quickActionColor = UIColor(red:0.56, green:0.39, blue:0.56, alpha:1)
let quickActionHighlightedColor = UIColor(red:0.7, green:0.42, blue:0.71, alpha:1)
// Using convenience method
WakupManager.appearance.setQuickActionsTint(quickActionColor, secondaryColor: quickActionHighlightedColor)
// Using UIAppearance proxy
ContextItemView.appearance().backgroundColor = quickActionColor
ContextItemView.appearance().highlightedBackgroundColor = quickActionHighlightedColor
ContextItemView.appearance().iconColor = UIColor.whiteColor()
ContextItemView.appearance().highlightedIconColor = UIColor.whiteColor()
ContextItemView.appearance().borderColor = UIColor.whiteColor()
Offer details
Offer details view can be customized using CouponDetailHeaderView
appearance proxy. The green tag can be customized using DiscountTagView
and shares appearance with the main offer view described above.
let titleColor = UIColor.blackColor()
let descriptionColor = UIColor(white: 0.33, alpha: 1)
let detailsColor = UIColor(white:0.56, alpha:1)
CouponDetailHeaderView.appearance().companyNameTextColor = titleColor
CouponDetailHeaderView.appearance().storeAddressTextColor = detailsColor
CouponDetailHeaderView.appearance().storeDistanceTextColor = detailsColor
CouponDetailHeaderView.appearance().storeDistanceIconColor = detailsColor
CouponDetailHeaderView.appearance().couponNameTextColor = descriptionColor
CouponDetailHeaderView.appearance().couponDescriptionTextColor = detailsColor
CouponDetailHeaderView.appearance().expirationTextColor = detailsColor
CouponDetailHeaderView.appearance().expirationIconColor = detailsColor
CouponDetailHeaderView.appearance().companyDisclosureColor = detailsColor
CouponDetailHeaderView.appearance().couponDescriptionDisclosureColor = detailsColor
CouponDetailHeaderView.appearance().companyNameTextColor = detailsColor
let tagColor = UIColor(red:0.5, green:0.59, blue:0.1, alpha:1)
// Using convenience method
WakupManager.appearance.setDiscountTagTint(tagColor)
// Using UIAppearance proxy
DiscountTagView.appearance().backgroundColor = tagColor
DiscountTagView.appearance().labelColor = .white
Offer action buttons
Offer action buttons appear below the offer details and can be customized using the CouponActionButton
appearance proxy.
let actionColor = UIColor(red:0.56, green:0.38, blue:0.57, alpha:1)
// Using convenience method
WakupManager.appearance.setOfferActionButtonsTint(secondaryColor)
// Using UIAppearance proxy
CouponActionButton.appearance().iconColor = actionColor
CouponActionButton.appearance().highlightedBackgroundColor = actionColor
CouponActionButton.appearance().setTitleColor(actionColor, for: [])
CouponActionButton.appearance().normalBorderColor = actionColor
Offer tag cloud
Tag cloud appearance can be customized using WakupTagListView
appearance proxy:
let darkColor = UIColor(red:0.26, green:0.07, blue:0.25, alpha:1)
let lightColor = UIColor(red:0.56, green:0.38, blue:0.57, alpha:1)
// Using convenience method
WakupManager.appearance.setTagListTint(tintColor)
// Using UIAppearance proxy
WakupTagListView.appearance().tagBackgroundColor = lightColor
WakupTagListView.appearance().tagHighlightedBackgroundColor = darkColor
WakupTagListView.appearance().wakupBorderColor = darkColor
The tag list view can be hidden by setting the hideTagsView
property of the CouponDetailHeadersView
appearance proxy to false
:
// Disable tags view in offer details
CouponDetailHeaderView.appearance().hideTagsView = false
Offer finder
Offer finder allows customization of filter icons through SearchFilterButton
appearance proxy and result cells using SearchResultCell
.
let searchButtonColor = UIColor(red:0.56, green:0.38, blue:0.57, alpha:1)
// Using convenience method
WakupManager.appearance.setSearchTint(searchButtonColor)
// Using UIAppearance proxy
SearchFilterButton.appearance().iconColor = searchButtonColor
SearchFilterButton.appearance().highlightedBackgroundColor = searchButtonColor
SearchFilterButton.appearance().setTitleColor(searchButtonColor, for: [])
SearchFilterButton.appearance().normalBorderColor = searchButtonColor
SearchResultCell.appearance().iconColor = searchButtonColor
Category shortcuts can be replaced using searchCategories
property of WakupOptions
when configuring WakupManager
:
let options = WakupOptions()
options.searchCategories = [
OfferCategory(title: "Food", icon: "restaurant", associatedTags: ["restaurants"]),
OfferCategory(title: "Shopping", icon: "shopping", associatedTags: ["shopping"]),
OfferCategory(title: "Services", icon: "services", associatedTags: ["services"])
]
WakupManager.manager.setup("YOUR API KEY", options: options)
Will render this:
Button titles can be internationalized using NSLocalizedString
. Make sure to check the length of the title to avoid render issues.
To remove category shortcuts, simply set searchCategories
to nil
:
let options = WakupOptions()
options.searchCategories = nil
WakupManager.manager.setup("YOUR API KEY", options: options)
Offer map
Offer map view allows customization of map pin icons and colors using CouponAnnotationView
appearance proxy. Icons and colors are assigned based on offer tags. You can associate more than one tag to each group. You can also declare an empty tag group for offers not matching any previous tag:
let restaurantCategoryColor: UIColor = UIColor(red: 0.660, green: 0.133, blue: 0.159, alpha: 1.000)
let leisureCategoryColor: UIColor = UIColor(red: 0.201, green: 0.310, blue: 0.550, alpha: 1.000)
let servicesCategoryColor: UIColor = UIColor(red: 0.803, green: 0.341, blue: 0.092, alpha: 1.000)
let shoppingCategoryColor: UIColor = UIColor(red: 0.321, green: 0.498, blue: 0.190, alpha: 1.000)
CouponAnnotationView.appearance().mapPinSize = CGSize(width: 46, height: 60)
CouponAnnotationView.appearance().iconAndColorForTags = [
ColorForTags(tags: ["restaurants", "food"], mapIcon: "map-restaurant-pin", color: restaurantCategoryColor),
ColorForTags(tags: ["leisure", "cinema"], mapIcon: "map-leisure-pin", color: leisureCategoryColor),
ColorForTags(tags: ["services"], mapIcon: "map-services-pin", color: servicesCategoryColor),
ColorForTags(tags: ["shopping"], mapIcon: "map-shopping-pin", color: shoppingCategoryColor),
ColorForTags(tags: [], mapIcon: "map-pin", color: UIColor.darkGrayColor()) // Empty tag list for default pin and color
]
Customize fonts
Most fonts of the Wakup views can be customized using the same UIAppearance
proxies that are used for color customization. Take into account that font size has to be explicitly specified and some labels have minimum font scale to avoid word clipping.
This example shows how to replace most of the application fonts with the Aller family fonts:
// Navigation bar
UINavigationBar.appearance().titleTextAttributes = [
NSAttributedStringKey.font: UIFont(name: "Aller", size: 18)!
]
// Top menu and search bar
TopMenuButton.appearance().titleFont = UIFont(name: "Aller-Light", size: 14)
SearchFilterButton.appearance().titleFont = UIFont(name: "Aller", size: 10)
// Collection view cells
CouponCollectionViewCell.appearance().storeNameFont = UIFont(name: "Aller-Bold", size: 17)
CouponCollectionViewCell.appearance().descriptionTextFont = UIFont(name: "Aller-Italic", size: 15)
CouponCollectionViewCell.appearance().distanceFont = UIFont(name: "Aller-Italic", size: 11)
CouponCollectionViewCell.appearance().expirationFont = UIFont(name: "Aller-Italic", size: 11)
DiscountTagView.appearance().labelFont = UIFont(name: "AllerDisplay", size: 17)
// Offer details
CouponActionButton.appearance().titleFont = UIFont(name: "Aller", size: 10)
CouponDetailHeaderView.appearance().companyNameFont = UIFont(name: "Aller", size: 18)
CouponDetailHeaderView.appearance().storeAddressFont = UIFont(name: "Aller-LightItalic", size: 14)
CouponDetailHeaderView.appearance().storeDistanceFont = UIFont(name: "Aller-Italic", size: 11)
CouponDetailHeaderView.appearance().couponNameFont = UIFont(name: "Aller", size: 19)
CouponDetailHeaderView.appearance().couponDescriptionFont = UIFont(name: "Aller", size: 14)
CouponDetailHeaderView.appearance().expirationFont = UIFont(name: "Aller-Italic", size: 13)
if #available(iOS 9.0, *) {
let headerTitle = UILabel.appearanceWhenContainedInInstancesOfClasses([UITableViewHeaderFooterView.self])
headerTitle.font = UIFont(name: "Aller", size: 16)
let searchBarTextField = UITextField.appearanceWhenContainedInInstancesOfClasses([UISearchBar.self])
searchBarTextField.defaultTextAttributes = [
NSFontAttributeName: UIFont(name: "Aller", size: 14)!
]
}
Customize icons
Wakup SDK uses vectorial CoreGraphics methods to draw icons that allow resizing and tinting icons using native iOS functionality. All Wakup icons are packed in a 'icon library', that can be extended (or completely overriden) to replace the application icons.
To achieve it, simply subclass DefaultIconLibrary
class and return the new draw method of the desired icons.
For example, we want to override the default share icon:
with a new paper plane version:
Using vectorial icons with PaintCode
First convert the icon to CoreGraphics format using PaintCode or any other vectorial to CoreGraphics application. Remember to set the resizing mask so the icon size is relative to the frame. The generated code would look like this:
class CustomDrawMethods {
// Draw method generated using PaintCode
class func drawPaperPlane(frame frame: CGRect = CGRectMake(0, 0, 88, 87), fillColor: UIColor = UIColor(red: 0.381, green: 0.421, blue: 0.442, alpha: 1.000)) {
//// Subframes
let group: CGRect = CGRectMake(frame.minX - 0.39, frame.minY + 0.07, frame.width + 0.39, frame.height - 0.07)
//// Group
//// Bezier 86 Drawing
let bezier86Path = UIBezierPath()
bezier86Path.moveToPoint(CGPointMake(group.minX + 0.79353 * group.width, group.minY + 1.00000 * group.height))
bezier86Path.addLineToPoint(CGPointMake(group.minX + 0.51238 * group.width, group.minY + 0.77596 * group.height))
bezier86Path.addLineToPoint(CGPointMake(group.minX + 0.31396 * group.width, group.minY + 1.00000 * group.height))
bezier86Path.addLineToPoint(CGPointMake(group.minX + 0.28096 * group.width, group.minY + 0.66389 * group.height))
bezier86Path.addLineToPoint(CGPointMake(group.minX + 0.00000 * group.width, group.minY + 0.46550 * group.height))
bezier86Path.addLineToPoint(CGPointMake(group.minX + 1.00000 * group.width, group.minY + 0.00000 * group.height))
bezier86Path.addLineToPoint(CGPointMake(group.minX + 0.79353 * group.width, group.minY + 1.00000 * group.height))
bezier86Path.addLineToPoint(CGPointMake(group.minX + 0.79353 * group.width, group.minY + 1.00000 * group.height))
bezier86Path.closePath()
bezier86Path.moveToPoint(CGPointMake(group.minX + 0.49593 * group.width, group.minY + 0.66389 * group.height))
bezier86Path.addLineToPoint(CGPointMake(group.minX + 0.99177 * group.width, group.minY + 0.00861 * group.height))
bezier86Path.addLineToPoint(CGPointMake(group.minX + 0.36377 * group.width, group.minY + 0.63805 * group.height))
bezier86Path.addLineToPoint(CGPointMake(group.minX + 0.49593 * group.width, group.minY + 0.66389 * group.height))
bezier86Path.addLineToPoint(CGPointMake(group.minX + 0.49593 * group.width, group.minY + 0.66389 * group.height))
bezier86Path.closePath()
bezier86Path.miterLimit = 4;
bezier86Path.usesEvenOddFillRule = true;
fillColor.setFill()
bezier86Path.fill()
}
}
Configure Icon library
Then, subclass DefaultIconLibrary
and override drawMethodForIcon
to return the new draw method for the share
identifier (full list of available identifiers in the DefaultIconLibrary
sources)
class CustomIconLibrary: DefaultIconLibrary {
override func drawMethodForIcon(iconIdentifier: String) -> (drawMethod: IconDrawMethod, aspectRatio: CGFloat) {
switch iconIdentifier {
case "share":
// Replace share icon with a paper plane
return (CustomDrawMethods.drawPaperPlane, 88/87)
default:
// For any other method, return default draw method
return super.drawMethodForIcon(iconIdentifier: iconIdentifier)
}
}
}
Then, when setting up WakupManager
, set the iconLibrary
property of WakupOptions
to an instance of your new CustomIconLibrary
(or the name you just gave it):
let wakupOptions = WakupOptions()
wakupOptions.iconLibrary = CustomIconLibrary()
WakupManager.manager.setup("YOUR_API_TOKEN_HERE", options: wakupOptions)
Run the App and you'll see your new icon, pixel perfect regardless the size and colored as you wish:
Using non-vectorial images
Although highly recommended, converting images to vectorial format is not always available. In this case, you can fall back to using standard UIImage
images. It's recommended that you use transparent background PNG files.
They are configured exactly like vectorial code-drawn icons in your implementation of IconLibrary
, with the help of CodeIconLibrary.drawMethodForImage
utility method:
class CustomIconLibrary: DefaultIconLibrary {
override func drawMethodForIcon(iconIdentifier: String) -> (drawMethod: IconDrawMethod, aspectRatio: CGFloat) {
switch iconIdentifier {
case "share":
// Replace share icon with a paper plane
return CodeIconLibrary.drawMethodForImage(UIImage(named: "paper_plane.png")!)
default:
// For any other method, return default draw method
return super.drawMethodForIcon(iconIdentifier: iconIdentifier)
}
}
}
The provided image will be colored using the designated tint color for that icon.
If the logo should not be tinted (for example, multi-color company logos), make sure to set the tinted
parameter of drawMethodForImage
to false
:
return CodeIconLibrary.drawMethodForImage(UIImage(named: "my-logo")!, tinted: false)
Vectorial and non-vectorial images can be mixed in the same IconLibrary. But for better results, use vectorial images whenver possible.
Adding additional languages or replacing strings
Adding additional languages or replacing strings in an already existing language is very easy. Wakup SDK will find strings in a Wakup.strings
file for the current language or fall back to embedded SDK strings if the file or the specific string is not found.
Copy Wakup.strings
file from the SDK sources into your project. You can now replace the strings that you want and internationalize that file to your supported languages.
Custom method for sharing offers
When the user shares an offer from the application the default share controller is presented with some information about the offer. The footer of the text can be altered customizing the ShareOfferFooter
key in the strings file (see previous point).
For further customization, you can set a method in the WakupOptions
object when initializing the library that will be called when the user shares an offer. This method overrides the default behaviour and can be used to perform any operation. The current top-level controller and a generic loading modal presenter are provided as method parameters for easier integration. In addition, a class extension for UIViewController
is provided that will help downloading images or presenting the share controller.
This example customizes the shared text and provides a custom URL in addition to sharing the offer image:
let options = WakupOptions()
options.customShareFunction = { (offer, presenter, loadingPresenter) in
// Create a custom URL based on the offer ID
let url = URL(string: "http://mycompany.com/offer/\(offer.id)")
// Share the offer image
let imageUrl = offer.image?.sourceUrl
// Create a custom text to share
let text = "Mira esta oferta! \(offer.shortDescription) de \(offer.company.name)"
// Call the convenience method for showing the share controller
presenter.shareTextImageAndURL(text: text, imageURL: imageUrl, linkURL: url, loadingProtocol: loadingPresenter)
}
WakupManager.manager.setup(API_KEY, options: options)