NPOKit
is a native iOS library developed in Swift for interfacing with the Nederlandse Publieke Omroep's (e.g. NPO, the Dutch public broadcaster) Uitzending Gemist API. The library is specifically developed for the unofficial open source Uitzending Gemist application for Apple TV 4.
Currently the library only supports tvOS
, but support might become wider in the future.
CocoaPods is a dependency manager for Cocoa projects. You can install it with the following command:
[sudo] gem install cocoapods
CocoaPods 1.0+ is required.
To integrate NPOKit into your project, specify it in your Podfile:
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '9.0'
use_frameworks!
pod 'NPOKit', :git => 'https://github.com/4np/NPOKit.git'
Then, run the following command:
$ pod install
Carthage is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks.
You can install Carthage with Homebrew using the following command:
brew update
brew install carthage
To integrate NPOKit into your Xcode project using Carthage, specify it in your Cartfile:
github "4np/NPOKit" ~> 1.0
Run carthage update
to build the framework and drag the built NPOKit.framework
into your Xcode project.
Todo
In order to use NPOKit in your application, you need to import NPOKit in every file you want to use it in and call an API method on the NPOManager.
import NPOKit
...
NPOManager.sharedInstance.someMethodCall(...) { [weak self] in
...completion closure...
}
The APIManager
is the main manager to interact with and allows you to fetch programs, episodes and images, (un)favoriting programs, keep track of (partially) played episodes and fetch video stream URLs.
The complettion closure returns an optional array of tips (e.g. [NPOTip]?
):
NPOManager.sharedInstance.getTips() { [weak self] tips, error in
guard let tips = tips else {
DDLogError("Could not fetch tips (\(error))")
return
}
// assign tips
self?.tips = tips
}
The completion closure returns an optional array of programs (e.g. [NPOProgram]?
):
NPOManager.sharedInstance.getPrograms() { programs, error in ... }
The completion closure returns an optional program (e.g. NPOProgram?
):
NPOManager.sharedInstance.getDetails(forProgram: NPOProgram) { program, error in ... }
The completion closure returns an optional array of programs (e.g. [NPOProgram]?
):
NPOManager.sharedInstance.getFavoritePrograms() { programs, error in ... }
Same as above, but now the details for every one of these programs is fetched.
NPOManager.sharedInstance.getDetailedFavoritePrograms() { programs, error in ... }
Fetch the recent episodes for the favorite programs.
NPOManager.sharedInstance.getRecentEpisodesForFavoritePrograms() { episodes, error in ... }
The completion closure returns an optional array of episodes (e.g. [NPOEpisode]?
):
NPOManager.sharedInstance.getPopularEpisodes() { episodes, error in ... }
The completion closure returns an optional array of episodes (e.g. [NPOEpisode]?
):
NPOManager.sharedInstance.getTrendingEpisodes() { episodes, error in ... }
The completion closure returns an optional array of episodes (e.g. [NPOEpisode]?
):
NPOManager.sharedInstance.getRecentEpisodes() { episodes, error in ... }
The completion closure returns an optional program (e.g. NPOEpisode?
):
NPOManager.sharedInstance.getDetails(forEpisode: NPOEpisode) { episode, error in ... }
The function takes an argument of enum type NPOGenre
and the completion closure returns an optional array of episodes (e.g. [NPOEpisode]?
):
NPOManager.sharedInstance.getEpisodes(byGenre: NPOGenre) { episodes, error in ... }
The function takes an argument of enum type NPOBroadcaster
and the completion closure returns an optional array of episodes (e.g. [NPOEpisode]?
):
NPOManager.sharedInstance.getEpisodes(byBroadcaster: NPOBroadcaster) { episodes, error in ... }
The function takes an argument of type NSDate
and the completion closure returns an optional array of episodes (e.g. [NPOEpisode]?
) for the whole day that date falls in:
NPOManager.sharedInstance.getEpisodes(forDate: NSDate) { episodes, error in ... }
The function takes an argument of type NSProgram
and the completion closure returns an optional array of episodes (e.g. [NPOEpisode]?
):
NPOManager.sharedInstance.getEpisodes(forProgram: NSProgram) { episodes, error in ... }
The function takes an argument of type NSProgram
and the completion closure returns an optional episode (e.g. NPOEpisode?
):
NPOManager.sharedInstance.getLatestEpisode(forProgram: NSProgram) { episode, error in ... }
The function takes an argument of type NSProgram
and the completion closure returns an optional episode (e.g. NPOEpisode?
):
NPOManager.sharedInstance.getNextEpisode(forProgram: NSProgram) { episode, error in ... }
Note: as this is a future episode, there is no video stream available yet
The function takes an argument of type String
and the completion closure returns an optional array of episodes (e.g. [NPOEpisode]?
):
NPOManager.sharedInstance.getEpisodes(bySearchTerm: String) { episodes, error in ... }
The function takes an argument of type NPOProgram
and the completion closure returns an optional image (e.g. UIImage?
):
func getImage() {
let program: NPOProgram = ...
let request = program.getImage() { [weak self] image, error, request in
guard let myRequest = self?.request where request == myRequest else {
// This is the result of another request, which might for example
// happen in reusable cells in collection views. Ignore it...
// We could also cancel it via request.cancel()
return
}
self?.doSomething(withImage: image)
}
}
Note: the request is cancellable via request.cancel()
The function takes an argument of type NPOProgram
and the completion closure returns an optional image (e.g. UIImage?
):
let myImageView: UIImageView = ...
func getImage() {
let program: NPOProgram = ...
let request = program.getImage(ofSize: self.myImageView.frame.size) { [weak self] image, error, request in
guard let myRequest = self?.request where request == myRequest else {
// This is the result of another request, which might for example
// happen in reusable cells in collection views. Ignore it...
// We could also cancel it via request.cancel()
return
}
self?.myImageView.image = image
}
}
Note: the request is cancellable via request.cancel()
The function takes an argument of type NPOEpisode
and the completion closure returns an optional image (e.g. UIImage?
):
let episode: NPOEpisode = ...
let request = episode.getImage() { [weak self] image, error, request in ... }
The function takes an argument of type NPOEpisode
and the completion closure returns an optional image (e.g. UIImage?
):
let episode: NPOEpisode = ...
let request = episode.getImage(ofSize: CGSize) { [weak self] image, error, request in ... }
The completion closure returns an optional url (e.g. NSURL?
) which can be used to feed into a video player (for example into AVPlayer
):
let episode: NPOEpisode = ...
episode.getVideoStream() { url, error in ... }
The function taked an argument of enum NPOLive
and the completion closure returns an optional url (e.g. NSURL?
) which can be used to feed into a video player (for example into AVPlayer
):
NPOManager.sharedInstance.getVideoStream(forLiveChannel channel: NPOLive.NPO_1) { url, error in
...
}
The function takes an argument of an array or NPOLive
enums and a particular date and the completion closure returns and optional array of guides per channel (e.g. [NPOLive: [NPOBroadcast]]?
) and/or errors per channel (e.g. [NPOLive: NPOError]?
):
NPOManager.sharedInstance.getGuides(forChannels channels: [NPOLive], onDate date: NSDate) { guides, errors in ... }
NPOManager.sharedInstance.getDaysSinceNow(numberOfDays total: Int) -> [(from: NSDate, to: NSDate, label: String, name: String)]
hile the other API methods are all about interfacing with the NPO, NPOKit also includes convencience methods for simplifying some other tasks.
The Uitzending Gemist App uses this API method to provide version update notifications to the end user. As the app is distributed by source on Github it does not tap into the native AppStore to push version updates. To make sure users are aware of version updates this API is used to determine whether or not updates are available.
let githubUsername = "4np"
let githubRepository = "UitzendingGemist"
NPOManager.sharedInstance.getGitHubReleases(forUsername: githubUsername, andRepositoryName: githubRepository) { releases, currentVersion in
...
}
See the accompanying LICENSE and NOTICE files for more information.
Copyright 2016 Jeroen Wesbeek
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.