Skip to content

Instantly share code, notes, and snippets.

@wilbert
Created December 17, 2015 20:45
Show Gist options
  • Save wilbert/1069a44422491e0e3674 to your computer and use it in GitHub Desktop.
Save wilbert/1069a44422491e0e3674 to your computer and use it in GitHub Desktop.
//
// SoccerRealtimeController.swift
// espnsync
//
// Created by Wilbert Kelyson Gomes Ribeiro on 04/07/15.
// Copyright (c) 2015 ESPN Brasil. All rights reserved.
//
import Foundation
import UIKit
import MBProgressHUD
import PubNub
import Alamofire
import mopub_ios_sdk
class CompetitionRealtimeController: UITableViewController,
PNObjectEventListener,
MPTableViewAdPlacerDelegate,
MPInterstitialAdControllerDelegate,
MopubNativeAdsProtocol,
MopubInterstitialProtocol {
private var client : PubNub!
private var currentPage: Int = 1
private var stopFetch: Bool = false
private var refreshing: Bool = false
private var selectedIndex: NSIndexPath?
var restoredTimelineEventId: Int?
var timelineEvents: NSMutableArray = []
var competition: Competition!
var playingIndexes: [Int] = []
var timelineChannel: String!
var placer: MPTableViewAdPlacer!
var interstitial: MPInterstitialAdController!
// MARK: Setup code
override func viewDidLoad() {
super.viewDidLoad()
self.stylizeNavigationBar()
print("Realtime for event: \(self.competition.id)")
_ = MBProgressHUD.showHUDAddedTo(self.navigationController?.view, animated: true)
self.navigationController?.navigationBar.topItem?.title = ""
// Set auto height for cells
self.tableView.estimatedRowHeight = 80
self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.contentInset = UIEdgeInsetsMake(0, 0, 50, 0)
// Setup refresh
self.refreshControl!.addTarget(self, action: "refresh:", forControlEvents: UIControlEvents.ValueChanged)
// Setup Ads
self.loadNativeADS()
self.loadInterstitialADS()
}
override func viewWillAppear(animated: Bool) {
// Subscribe in PubNub for timeline
subscribeToEventChannels()
// Load event updates from server
self.loadCompetition(competition.match.id)
// Load timeline ventso from server
self.loadRealtimeEvents()
self.loadDidEnd()
}
func setup() {
self.navigationItem.titleView = self.setupTitleView(competition.competitionTitle())
self.tableView.reloadData()
}
func restoreTimelineEvent() {
if let id = restoredTimelineEventId {
if let array = timelineEvents as NSArray as? [TimelineEvent] {
if let index = array.indexOf({$0.id == id}) {
selectedIndex = NSIndexPath(forRow: index, inSection: 1)
tableView.reloadData()
tableView.scrollToRowAtIndexPath(selectedIndex!, atScrollPosition: UITableViewScrollPosition.Top, animated: false)
}
}
}
}
override func viewWillDisappear(animated: Bool) {
// Unsubscribe when user get out of timeline
client.unsubscribeFromChannels([timelineChannel], withPresence: false)
for playingIndex in playingIndexes {
if let cell = tableView.cellForRowAtIndexPath(NSIndexPath(forRow: playingIndex, inSection: 1)) as? VideoCell {
cell.player.pause()
}
}
}
// MARK: Table view delegate methods
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 2
}
override func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
if section == 0 {
return 0
} else {
return 40
}
}
override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
if section > 0 {
var identifier: String! = "ActionCell"
let sportIdentifiers = ["soccer": "SoccerActionCell", "mma": "MMAActionCell"]
if sportIdentifiers.keys.contains(competition.match.sportName()) {
identifier = sportIdentifiers[competition.match.sportName()]
}
return self.tableView.dequeueReusableCellWithIdentifier(identifier)
}
return nil
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var identifier = "TimelineQuarterScoreCell"
if indexPath.section == 0 && !competition.match.isMMA() {
if competition.match.isSoccer() {
identifier = "TimelineScoreCell"
}
} else {
let timelineEvent = self.timelineEvents[indexPath.row] as! TimelineEvent
identifier = timelineEvent.timelineEventType.matchCellIdentifier()
}
let cell = self.tableView.mp_dequeueReusableCellWithIdentifier(identifier, forIndexPath: indexPath) as! UITableViewCell
// print(NSStringFromClass(cell.dynamicType).componentsSeparatedByString(".").last!)
if let timelineCell = cell as? TimelineScoreCell {
timelineCell.competition = competition
timelineCell.update()
}
if let timelineCell = cell as? TimelineEventCell {
let timelineEvent = self.timelineEvents[indexPath.row] as! TimelineEvent
timelineEvent.competition = competition
timelineCell.timelineEvent = timelineEvent
timelineCell.competitionRealtimeController = self
timelineCell.row = indexPath.row
timelineCell.update()
}
return cell
}
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return false
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
if competition.match.isMMA() {
return 0
} else {
return 1
}
} else {
return timelineEvents.count
}
}
override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
let nextPage = self.timelineEvents.count - 5
if indexPath.row == nextPage && !stopFetch {
currentPage++
self.loadRealtimeEvents()
}
}
// MARK: Api loads
func loadRealtimeEvent(id: Int) {
TimelineEvent.get(id, completionHandler: { (response: Response<TimelineEvent, NSError>) -> Void in
if response.result.isSuccess {
let timelineEvent = response.result.value!
let array = self.timelineEvents as AnyObject as! [TimelineEvent]
let existentTimelineEvents = array.filter({ $0.id == id })
if existentTimelineEvents.count > 0 {
let existentTimelineEvent = existentTimelineEvents.first
let existentIndex = self.timelineEvents.indexOfObject(existentTimelineEvent!)
self.timelineEvents.replaceObjectAtIndex(existentIndex, withObject: timelineEvent)
} else {
self.timelineEvents.insertObject(timelineEvent, atIndex: 0)
}
self.tableView.reloadData()
}
})
}
func loadCompetition(id: Int) {
Match.get(id, completionHandler: { (response: Response<Match, NSError>) -> Void in
if response.result.isSuccess {
let match = response.result.value!
self.competition = match.primaryCompetition()
self.setup()
}
})
}
func loadRealtimeEvents() {
let params: [String: String] = ["page": currentPage.description]
competition.get("timeline_events", parameters: params, completionHandler: { (response: Response<[TimelineEvent], NSError>) in
if response.result.isSuccess {
let timelineEvents = response.result.value!
if timelineEvents.isEmpty {
self.stopFetch = true
} else {
if self.refreshing {
self.timelineEvents = NSMutableArray(array: timelineEvents)
self.refreshing = false
} else {
self.timelineEvents.addObjectsFromArray(timelineEvents)
}
self.restoreTimelineEvent()
self.tableView.reloadData()
}
if self.timelineEvents.count == 0 {
self.tableView.addEmptyMessage(NSLocalizedString("EMPTY_LIST", comment: "Empty list message"))
}
} else {
self.showNetWorkError(response.result.error!)
}
MBProgressHUD.hideAllHUDsForView(self.navigationController?.view, animated: true)
self.refreshControl!.endRefreshing()
})
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let destination = segue.destinationViewController as? CompetitionStatsNavigationController {
destination.competition = competition
}
if let destination = segue.destinationViewController as? ChatNavigationController {
destination.competition = competition
}
if let destination = segue.destinationViewController as? LineupNavigationController {
destination.competition = competition
}
if let destination = segue.destinationViewController as? MatchCompetitionNavigationController {
destination.match = competition.match
}
if let destination = segue.destinationViewController as? PhotoGalleryController {
if let index = tableView.indexPathForSelectedRow {
let timelineEvent = self.timelineEvents[index.row] as! TimelineEvent
destination.photoGallery = timelineEvent.photoGallery
}
}
}
@IBAction func closeController(sender: UIBarButtonItem) {
self.dismissViewControllerAnimated(true, completion: nil)
}
func refresh(sender:AnyObject) {
self.currentPage = 1
self.stopFetch = false
self.refreshing = true
self.loadRealtimeEvents()
}
// MARK: PubNub settings
func subscribeToEventChannels() {
client = PubNub.clientWithConfiguration(self.pubNubConfig())
if let notificationChannels = competition.notificationChannels {
if let channel = notificationChannels["timeline"] {
timelineChannel = channel
client.subscribeToChannels([timelineChannel], withPresence: false)
client.addListener(self)
}
}
}
func client(client: PubNub!, didReceiveMessage message: PNMessageResult!) {
if let timelineEventId = message.data.message["id"] {
loadRealtimeEvent(timelineEventId as! Int)
}
}
// MARK: Mopub
func getNativeAdsTag() -> String {
return competition.match.nativeTag()
}
func getInterstitialAdsTag() -> String {
return competition.match.interstitialTimelineTag()
}
func loadNativeADS() {
let adUnitId = getAdUnitFor(self.getNativeAdsTag())
// Create the Static Native Ad renderer configuration.
let staticSettings = MPStaticNativeAdRendererSettings()
staticSettings.renderingViewClass = MopubAdsCell.self
staticSettings.viewSizeHandler = { (maxWidth: CGFloat) -> CGSize in
return CGSizeMake(312.0, 312.0)
}
let staticConfiguration = MPStaticNativeAdRenderer.rendererConfigurationWithRendererSettings(staticSettings)
// Setup the ad placer.
placer = MPTableViewAdPlacer(tableView: tableView, viewController: self, rendererConfigurations: [staticConfiguration])
placer.delegate = self
// Add targeting parameters.
let targeting = MPNativeAdRequestTargeting()
targeting.desiredAssets = Set([kAdMainImageKey, kAdCTATextKey, kAdTextKey, kAdTitleKey])
// Begin loading ads and placing them into your feed, using the ad unit ID.
placer.loadAdsForAdUnitID(adUnitId, targeting: targeting)
}
func loadInterstitialADS() {
let adUnitId = getAdUnitFor(self.getInterstitialAdsTag())
self.interstitial = MPInterstitialAdController(forAdUnitId: adUnitId)
self.interstitial.loadAd()
}
func loadDidEnd() {
// if self.interstitial.ready {
self.interstitial.showFromViewController(self.navigationController)
// }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment