Created
December 17, 2015 20:45
-
-
Save wilbert/1069a44422491e0e3674 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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