diff --git a/PopcornTime.xcodeproj/project.pbxproj b/PopcornTime.xcodeproj/project.pbxproj index 7659fe4..5fc4a32 100644 --- a/PopcornTime.xcodeproj/project.pbxproj +++ b/PopcornTime.xcodeproj/project.pbxproj @@ -385,11 +385,13 @@ CLASSPREFIX = ""; LastSwiftMigration = 0700; LastSwiftUpdateCheck = 0700; - LastUpgradeCheck = 0720; + LastUpgradeCheck = 0820; ORGANIZATIONNAME = PopcornTime; TargetAttributes = { 7F8824C61A227A0100E2710A = { CreatedOnToolsVersion = 6.1; + DevelopmentTeam = DBR2MMCRF5; + LastSwiftMigration = 0820; }; }; }; @@ -550,8 +552,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; @@ -561,6 +565,7 @@ ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", @@ -594,8 +599,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; @@ -604,6 +611,7 @@ ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -613,6 +621,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 8.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; VALIDATE_PRODUCT = YES; }; name = Release; @@ -625,6 +634,7 @@ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; + DEVELOPMENT_TEAM = DBR2MMCRF5; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)", @@ -639,6 +649,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "PopcornTime/PopcornTime-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = "1,2"; VALID_ARCHS = "arm64 armv7 armv7s"; }; @@ -652,6 +663,7 @@ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; + DEVELOPMENT_TEAM = DBR2MMCRF5; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)", @@ -664,6 +676,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.popcorntime.ios.dk; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "PopcornTime/PopcornTime-Bridging-Header.h"; + SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = "1,2"; VALID_ARCHS = "arm64 armv7 armv7s"; }; diff --git a/PopcornTime.xcodeproj/xcshareddata/xcschemes/PopcornTime.xcscheme b/PopcornTime.xcodeproj/xcshareddata/xcschemes/PopcornTime.xcscheme index 991b5be..132393c 100644 --- a/PopcornTime.xcodeproj/xcshareddata/xcschemes/PopcornTime.xcscheme +++ b/PopcornTime.xcodeproj/xcshareddata/xcschemes/PopcornTime.xcscheme @@ -1,6 +1,6 @@ Void in + PTAPIManager.shared().showInfo(with: .anime, withId: item.identifier, success: { (item) -> Void in + guard let item = item else { return } self.anime.update(item) self.collectionView?.reloadData() }, failure: nil) @@ -36,25 +37,25 @@ class AnimeDetailsViewController: BaseDetailsViewController { return anime.seasons.count } - override func numberOfEpisodesInSeason(seasonsIndex: Int) -> Int { + override func numberOfEpisodesInSeason(_ seasonsIndex: Int) -> Int { return anime.seasons[seasonsIndex].episodes.count } - override func setupCell(cell: EpisodeCell, seasonIndex: Int, episodeIndex: Int) { + override func setupCell(_ cell: EpisodeCell, seasonIndex: Int, episodeIndex: Int) { let episode = anime.seasons[seasonIndex].episodes[episodeIndex] cell.titleLabel.text = "\(episode.episodeNumber)" } - override func setupSeasonHeader(header: SeasonHeader, seasonIndex: Int) { + override func setupSeasonHeader(_ header: SeasonHeader, seasonIndex: Int) { } - override func cellWasPressed(cell: UICollectionViewCell, seasonIndex: Int, episodeIndex: Int) { + override func cellWasPressed(_ cell: UICollectionViewCell, seasonIndex: Int, episodeIndex: Int) { let episode = anime.seasons[seasonIndex].episodes[episodeIndex] showVideoPickerPopupForEpisode(episode, basicInfo: self.item, fromView: cell) } - override func cellWasLongPressed(cell: UICollectionViewCell, seasonIndex: Int, episodeIndex: Int) { + override func cellWasLongPressed(_ cell: UICollectionViewCell, seasonIndex: Int, episodeIndex: Int) { // let episode = anime.episodeFor(seasonIndex: seasonIndex, episodeIndex: episodeIndex) // let seasonEpisodes = anime.episodesFor(seasonIndex: seasonIndex) } diff --git a/PopcornTime/Controllers/AnimeViewController.swift b/PopcornTime/Controllers/AnimeViewController.swift index 42888b1..3827dd9 100644 --- a/PopcornTime/Controllers/AnimeViewController.swift +++ b/PopcornTime/Controllers/AnimeViewController.swift @@ -12,35 +12,35 @@ class AnimeViewController: PagedViewController { override var showType: PTItemType { get { - return .Anime + return .anime } } - override func map(response: [AnyObject]) -> [BasicInfo] { - return response.map({ Anime(dictionary: $0 as! NSDictionary) }) + override func map(_ response: [AnyObject]) -> [BasicInfo] { + return response.map({ Anime(dictionary: $0 as! [AnyHashable: Any]) }) } - func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) { + func collectionView(_ collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: IndexPath) { - if let cell = collectionView.cellForItemAtIndexPath(indexPath){ + if let cell = collectionView.cellForItem(at: indexPath){ //Check if cell is MoreShowsCell if let _ = cell as? MoreShowsCollectionViewCell{ loadMore() } else { - performSegueWithIdentifier("showDetails", sender: cell) + performSegue(withIdentifier: "showDetails", sender: cell) } } } - override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { - super.prepareForSegue(segue, sender: sender) + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + super.prepare(for: segue, sender: sender) if segue.identifier == "showDetails"{ - if let episodesVC = segue.destinationViewController as? AnimeDetailsViewController{ + if let episodesVC = segue.destination as? AnimeDetailsViewController{ if let senderCell = sender as? UICollectionViewCell{ - if let indexPath = collectionView!.indexPathForCell(senderCell){ + if let indexPath = collectionView!.indexPath(for: senderCell){ var item: BasicInfo! - if (searchController!.active) { + if (searchController!.isActive) { item = searchResults[indexPath.row] } else { item = items[indexPath.row] diff --git a/PopcornTime/Controllers/BarHidingViewController.swift b/PopcornTime/Controllers/BarHidingViewController.swift index 59a1f77..67f1c41 100644 --- a/PopcornTime/Controllers/BarHidingViewController.swift +++ b/PopcornTime/Controllers/BarHidingViewController.swift @@ -10,11 +10,11 @@ import UIKit class BarHidingViewController: UIViewController { - private var barsVisible:Bool = true { + fileprivate var barsVisible:Bool = true { willSet { - self.tabBarController?.tabBar.hidden = !newValue - self.navigationController?.navigationBar.hidden = !newValue - UIApplication.sharedApplication().setStatusBarHidden(!newValue, withAnimation: .Fade) + self.tabBarController?.tabBar.isHidden = !newValue + self.navigationController?.navigationBar.isHidden = !newValue + UIApplication.shared.setStatusBarHidden(!newValue, with: .fade) } } @@ -23,7 +23,7 @@ class BarHidingViewController: UIViewController { //Hide bars if needed let sizeClass = (horizontal: self.view.traitCollection.horizontalSizeClass, vertical: self.view.traitCollection.verticalSizeClass) switch sizeClass{ - case (_,.Compact): + case (_,.compact): self.barsVisible = false default: self.barsVisible = true } diff --git a/PopcornTime/Controllers/BaseCollectionViewController.swift b/PopcornTime/Controllers/BaseCollectionViewController.swift index dc2779b..5aaa9f0 100644 --- a/PopcornTime/Controllers/BaseCollectionViewController.swift +++ b/PopcornTime/Controllers/BaseCollectionViewController.swift @@ -14,7 +14,7 @@ let reuseIdentifierMore = "MoreShowsCell" ///Base class for displaying collection of shows, subclass MUST override reloadData() and set self.shows in it class BaseCollectionViewController: BarHidingViewController, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource, UICollectionViewDelegate { - private struct Constants{ + fileprivate struct Constants{ static let desirediPadCellWidth = 160 static let desirediPadCellHeight = 205 static let numberOfLinesiPhonePortrait = 2 @@ -40,8 +40,8 @@ class BaseCollectionViewController: BarHidingViewController, UICollectionViewDel override func viewDidLoad() { super.viewDidLoad() - self.collectionView!.registerNib(UINib(nibName: "ShowCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: reuseIdentifierShow) - self.collectionView!.registerNib(UINib(nibName: "MoreShowsCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: reuseIdentifierMore) + self.collectionView!.register(UINib(nibName: "ShowCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: reuseIdentifierShow) + self.collectionView!.register(UINib(nibName: "MoreShowsCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: reuseIdentifierMore) self.collectionView?.delegate = self self.collectionView?.collectionViewLayout.invalidateLayout() @@ -49,35 +49,35 @@ class BaseCollectionViewController: BarHidingViewController, UICollectionViewDel } // MARK: UICollectionViewDataSource - func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { let additionalCellsCount = self.showLoadMoreCell ? 1 : 0 return (items.count + additionalCellsCount) } - func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell { + func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { if (self.showLoadMoreCell && indexPath.row == items.count) { //Last cell - let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifierMore, forIndexPath: indexPath) as! MoreShowsCollectionViewCell + let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifierMore, for: indexPath) as! MoreShowsCollectionViewCell return cell } else { //Ordinary show cell - let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifierShow, forIndexPath: indexPath) as! ShowCollectionViewCell + let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifierShow, for: indexPath) as! ShowCollectionViewCell let item = items[indexPath.row] cell.title = item.title let imageItem = item.smallImage switch imageItem?.status { - case .New?: - imageItem?.status = .Downloading + case .new?: + imageItem?.status = .downloading ImageProvider.sharedInstance.imageFromURL(URL: imageItem?.URL) { (downloadedImage) -> () in imageItem?.image = downloadedImage - imageItem?.status = .Finished + imageItem?.status = .finished - collectionView.reloadItemsAtIndexPaths([indexPath]) + collectionView.reloadItems(at: [indexPath]) } - case .Finished?: + case .finished?: cell.image = imageItem?.image default: break } @@ -87,9 +87,9 @@ class BaseCollectionViewController: BarHidingViewController, UICollectionViewDel } // MARK: UICollectionViewDelegateFlowLayout & UICollectionViewDelegate - func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize { + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { - let visibleAreaHeight = collectionView.bounds.height - navigationController!.navigationBar.bounds.height - UIApplication.sharedApplication().statusBarFrame.height - self.tabBarController!.tabBar.bounds.height + let visibleAreaHeight = collectionView.bounds.height - navigationController!.navigationBar.bounds.height - UIApplication.shared.statusBarFrame.height - self.tabBarController!.tabBar.bounds.height let visibleAreaWidth = collectionView.bounds.width //Set cell size based on size class. @@ -97,16 +97,16 @@ class BaseCollectionViewController: BarHidingViewController, UICollectionViewDel if let flowLayout = collectionViewLayout as? UICollectionViewFlowLayout{ switch sizeClass{ - case (.Compact,.Regular): + case (.compact,.regular): //iPhone portrait let cellWidth = ((visibleAreaWidth - CGFloat(Constants.numberOfItemsiPhonePortrait - 1)*flowLayout.minimumInteritemSpacing - flowLayout.sectionInset.top - flowLayout.sectionInset.bottom)/CGFloat(Constants.numberOfItemsiPhonePortrait)) let cellHeight = ((visibleAreaHeight - CGFloat(Constants.numberOfLinesiPhonePortrait - 1)*flowLayout.minimumLineSpacing - flowLayout.sectionInset.left - flowLayout.sectionInset.right)/CGFloat(Constants.numberOfLinesiPhonePortrait)) - return CGSizeMake(cellWidth, cellHeight) - case (_,.Compact): + return CGSize(width: cellWidth, height: cellHeight) + case (_,.compact): //iPhone landscape let cellWidth = ((collectionView.bounds.width - CGFloat(Constants.numberOfItemsiPhoneLandscape - 1)*flowLayout.minimumInteritemSpacing - flowLayout.sectionInset.top - flowLayout.sectionInset.bottom)/CGFloat(Constants.numberOfItemsiPhoneLandscape)) let cellHeight = ((collectionView.bounds.height - CGFloat(Constants.numberOfLinesiPhoneLandscape - 1)*flowLayout.minimumLineSpacing - flowLayout.sectionInset.left - flowLayout.sectionInset.right)/CGFloat(Constants.numberOfLinesiPhoneLandscape)) - return CGSizeMake(cellWidth, cellHeight) + return CGSize(width: cellWidth, height: cellHeight) case (_,_): // iPad. Calculate cell size based on desired size let numberOfLines = Int(visibleAreaHeight) / Constants.desirediPadCellHeight @@ -116,11 +116,11 @@ class BaseCollectionViewController: BarHidingViewController, UICollectionViewDel let adjustedHeight = (visibleAreaHeight - betweenLinesSpaceSum - sectionInsetsVerticalSum)/CGFloat(numberOfLines) let adjustedWidth = adjustedHeight * CGFloat(Constants.desirediPadCellWidth) / CGFloat(Constants.desirediPadCellHeight) - return CGSizeMake(adjustedWidth, adjustedHeight) + return CGSize(width: adjustedWidth, height: adjustedHeight) } } - return CGSizeMake(50, 50) + return CGSize(width: 50, height: 50) } // MARK: - ShowsCollectionViewController diff --git a/PopcornTime/Controllers/BaseDetailsViewController.swift b/PopcornTime/Controllers/BaseDetailsViewController.swift index 7b5a797..4fccf5a 100644 --- a/PopcornTime/Controllers/BaseDetailsViewController.swift +++ b/PopcornTime/Controllers/BaseDetailsViewController.swift @@ -11,11 +11,11 @@ import UIKit /// With this protocol we encapsulate calls of collectionView indexPathes. For now we have one extra section at the top (empty one with stratchy header), this way if anything changes here we will change all logic here, and all users of this protocol will not have to hcange anything. So it's a good idea to use seasonIndex, episodeIndex instead of indexPathes. protocol DetailViewControllerDataSource { func numberOfSeasons() -> Int - func numberOfEpisodesInSeason(seasonsIndex: Int) -> Int - func setupCell(cell: EpisodeCell, seasonIndex: Int, episodeIndex: Int) - func setupSeasonHeader(header: SeasonHeader, seasonIndex: Int) - func cellWasPressed(cell: UICollectionViewCell, seasonIndex: Int, episodeIndex: Int) - func cellWasLongPressed(cell: UICollectionViewCell, seasonIndex: Int, episodeIndex: Int) + func numberOfEpisodesInSeason(_ seasonsIndex: Int) -> Int + func setupCell(_ cell: EpisodeCell, seasonIndex: Int, episodeIndex: Int) + func setupSeasonHeader(_ header: SeasonHeader, seasonIndex: Int) + func cellWasPressed(_ cell: UICollectionViewCell, seasonIndex: Int, episodeIndex: Int) + func cellWasLongPressed(_ cell: UICollectionViewCell, seasonIndex: Int, episodeIndex: Int) } class BaseDetailsViewController: BarHidingViewController, VDLPlaybackViewControllerDelegate, LoadingViewControllerDelegate, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, DetailViewControllerDataSource { @@ -55,9 +55,9 @@ class BaseDetailsViewController: BarHidingViewController, VDLPlaybackViewControl collectionView.alwaysBounceVertical = true collectionView.dataSource = self collectionView.delegate = self - collectionView.registerNib(UINib(nibName: "StratchyHeader", bundle: nil), forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: firstHeaderReuseIdentifier) - collectionView.registerNib(UINib(nibName: "SeasonHeader", bundle: nil), forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: otherHeadersReuseIdentifier) - collectionView.registerNib(UINib(nibName: "EpisodeCell", bundle: nil), forCellWithReuseIdentifier: episodeCellReuseIdentifier) + collectionView.register(UINib(nibName: "StratchyHeader", bundle: nil), forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: firstHeaderReuseIdentifier) + collectionView.register(UINib(nibName: "SeasonHeader", bundle: nil), forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: otherHeadersReuseIdentifier) + collectionView.register(UINib(nibName: "EpisodeCell", bundle: nil), forCellWithReuseIdentifier: episodeCellReuseIdentifier) layout = collectionView.collectionViewLayout as? StratchyHeaderLayout } } @@ -69,19 +69,19 @@ class BaseDetailsViewController: BarHidingViewController, VDLPlaybackViewControl configureFavoriteBarButton() - let longPress = UILongPressGestureRecognizer(target: self, action: Selector("longPress:")) + let longPress = UILongPressGestureRecognizer(target: self, action: #selector(BaseDetailsViewController.longPress(_:))) longPress.minimumPressDuration = 0.5 longPress.delaysTouchesBegan = true collectionView.addGestureRecognizer(longPress) } - final func longPress(gesture: UILongPressGestureRecognizer) { - if gesture.state == .Ended { + final func longPress(_ gesture: UILongPressGestureRecognizer) { + if gesture.state == .ended { return } - let p = gesture.locationInView(collectionView) - if let indexPath = collectionView.indexPathForItemAtPoint(p) { - if let cell = collectionView.cellForItemAtIndexPath(indexPath) { + let p = gesture.location(in: collectionView) + if let indexPath = collectionView.indexPathForItem(at: p) { + if let cell = collectionView.cellForItem(at: indexPath) { cellWasLongPressed(cell, seasonIndex: indexPath.section - 1, episodeIndex: indexPath.item) } } @@ -90,10 +90,10 @@ class BaseDetailsViewController: BarHidingViewController, VDLPlaybackViewControl func configureFavoriteBarButton() { if (item.isFavorite) { self.navigationItem.rightBarButtonItem = UIBarButtonItem(image: UIImage.removeFromFavoritesImage(), - style: .Done, target: self, action: "removeFromFavorites") + style: .done, target: self, action: #selector(BaseDetailsViewController.removeFromFavorites)) } else { self.navigationItem.rightBarButtonItem = UIBarButtonItem(image: UIImage.addToFavoritesImage(), - style: .Done, target: self, action: "addToFavorites") + style: .done, target: self, action: #selector(BaseDetailsViewController.addToFavorites)) } } @@ -121,16 +121,16 @@ class BaseDetailsViewController: BarHidingViewController, VDLPlaybackViewControl } - func startPlayback(episode: Episode, basicInfo: BasicInfo, magnetLink: String, loadingTitle: String) { + func startPlayback(_ episode: Episode, basicInfo: BasicInfo, magnetLink: String, loadingTitle: String) { - let loadingVC = self.storyboard?.instantiateViewControllerWithIdentifier("loadingViewController") as! LoadingViewController + let loadingVC = self.storyboard?.instantiateViewController(withIdentifier: "loadingViewController") as! LoadingViewController loadingVC.delegate = self loadingVC.status = "Downloading..." loadingVC.loadingTitle = loadingTitle - loadingVC.modalPresentationStyle = UIModalPresentationStyle.OverCurrentContext - self.tabBarController?.presentViewController(loadingVC, animated: true, completion: nil) + loadingVC.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext + self.tabBarController?.present(loadingVC, animated: true, completion: nil) - PTTorrentStreamer.sharedStreamer().startStreamingFromFileOrMagnetLink(magnetLink, progress: { (status) -> Void in + PTTorrentStreamer.shared().startStreaming(fromFileOrMagnetLink: magnetLink, progress: { (status) -> Void in loadingVC.progress = status.bufferingProgress loadingVC.speed = Int(status.downloadSpeed) @@ -138,35 +138,35 @@ class BaseDetailsViewController: BarHidingViewController, VDLPlaybackViewControl loadingVC.peers = Int(status.peers) }, readyToPlay: { (url) -> Void in - loadingVC.dismissViewControllerAnimated(false, completion: nil) + loadingVC.dismiss(animated: false, completion: nil) let vdl = VDLPlaybackViewController(nibName: "VDLPlaybackViewController", bundle: nil) vdl.delegate = self - self.navigationController?.presentViewController(vdl, animated: true, completion: nil) - vdl.playMediaFromURL(url) + self.navigationController?.present(vdl, animated: true, completion: nil) + vdl.playMedia(from: url) }, failure: { (error) -> Void in - loadingVC.dismissViewControllerAnimated(true, completion: nil) + loadingVC.dismiss(animated: true, completion: nil) }) } // MARK: - VDLPlaybackViewControllerDelegate - func playbackControllerDidFinishPlayback(playbackController: VDLPlaybackViewController!) { - self.navigationController?.dismissViewControllerAnimated(true, completion: nil) - PTTorrentStreamer.sharedStreamer().cancelStreaming() + func playbackControllerDidFinishPlayback(_ playbackController: VDLPlaybackViewController!) { + self.navigationController?.dismiss(animated: true, completion: nil) + PTTorrentStreamer.shared().cancelStreaming() } // MARK: - LoadingViewControllerDelegate - func didCancelLoading(controller: LoadingViewController) { - PTTorrentStreamer.sharedStreamer().cancelStreaming() - controller.dismissViewControllerAnimated(true, completion: nil) + func didCancelLoading(_ controller: LoadingViewController) { + PTTorrentStreamer.shared().cancelStreaming() + controller.dismiss(animated: true, completion: nil) } // MARK: - UICollectionViewDataSource - final func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + final func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { switch section { case 0: return 0 default: @@ -175,29 +175,29 @@ class BaseDetailsViewController: BarHidingViewController, VDLPlaybackViewControl } } - final func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int { + final func numberOfSections(in collectionView: UICollectionView) -> Int { return self.numberOfSeasons() + 1 // extra section for header } - final func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell { + final func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let seasonIndex = indexPath.section - 1 let episode = indexPath.item - let cell = collectionView.dequeueReusableCellWithReuseIdentifier(cellReuseIdentifier, forIndexPath: indexPath) as! EpisodeCell + let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellReuseIdentifier, for: indexPath) as! EpisodeCell self.setupCell(cell, seasonIndex: seasonIndex, episodeIndex: episode) return cell } - final func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { + final func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { switch section { case 0: return headerSize - default : return CGSizeMake(collectionView.bounds.width, preferedOtherHeadersHeight) + default : return CGSize(width: collectionView.bounds.width, height: preferedOtherHeadersHeight) } } - func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView { + func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { if indexPath.section == 0 { if (header == nil){ - header = (collectionView.dequeueReusableSupplementaryViewOfKind(kind, withReuseIdentifier: firstHeaderReuseIdentifier, forIndexPath: indexPath) as! StratchyHeader) + header = (collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: firstHeaderReuseIdentifier, for: indexPath) as! StratchyHeader) header?.delegate = layout if let image = item.bigImage?.image { @@ -221,7 +221,7 @@ class BaseDetailsViewController: BarHidingViewController, VDLPlaybackViewControl header!.synopsisTextView.text = item.synopsis return header! } else { - let otherHeader = (collectionView.dequeueReusableSupplementaryViewOfKind(kind, withReuseIdentifier: otherHeadersReuseIdentifier, forIndexPath: indexPath) as! SeasonHeader) + let otherHeader = (collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: otherHeadersReuseIdentifier, for: indexPath) as! SeasonHeader) let seasonIndex = (indexPath.section - 1) self.setupSeasonHeader(otherHeader, seasonIndex: seasonIndex) return otherHeader @@ -230,19 +230,19 @@ class BaseDetailsViewController: BarHidingViewController, VDLPlaybackViewControl // MARK: - UICollectionViewDelegate - final func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) { - if let cell = collectionView.cellForItemAtIndexPath(indexPath) { + final func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { + if let cell = collectionView.cellForItem(at: indexPath) { cellWasPressed(cell, seasonIndex: indexPath.section - 1, episodeIndex: indexPath.item) } } - func showVideoPickerPopupForEpisode(episode: Episode, basicInfo: BasicInfo, fromView view: UIView) { + func showVideoPickerPopupForEpisode(_ episode: Episode, basicInfo: BasicInfo, fromView view: UIView) { let videos = episode.videos if (videos.count > 0) { - let actionSheetController = UIAlertController(title: episode.title, message: episode.desc, preferredStyle: UIAlertControllerStyle.ActionSheet) + let actionSheetController = UIAlertController(title: episode.title, message: episode.desc, preferredStyle: UIAlertControllerStyle.actionSheet) - let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel, handler: nil) + let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil) actionSheetController.addAction(cancelAction) for video in videos { @@ -254,7 +254,7 @@ class BaseDetailsViewController: BarHidingViewController, VDLPlaybackViewControl title += quality } - let action = UIAlertAction(title: title, style: UIAlertActionStyle.Default, handler: { (action) -> Void in + let action = UIAlertAction(title: title, style: UIAlertActionStyle.default, handler: { (action) -> Void in let magnetLink = video.magnetLink let episodeTitle = episode.title ?? "" let loadingTitle = "\(episodeTitle) - \(title)" @@ -267,9 +267,9 @@ class BaseDetailsViewController: BarHidingViewController, VDLPlaybackViewControl let popOver = actionSheetController.popoverPresentationController popOver?.sourceView = view popOver?.sourceRect = view.bounds - popOver?.permittedArrowDirections = UIPopoverArrowDirection.Any + popOver?.permittedArrowDirections = UIPopoverArrowDirection.any - self.presentViewController(actionSheetController, animated: true, completion: nil) + self.present(actionSheetController, animated: true, completion: nil) } } @@ -279,24 +279,24 @@ class BaseDetailsViewController: BarHidingViewController, VDLPlaybackViewControl return 0 } - func numberOfEpisodesInSeason(seasonsIndex: Int) -> Int { + func numberOfEpisodesInSeason(_ seasonsIndex: Int) -> Int { assertionFailure("Should be overriden by subclass") return 0 } - func setupCell(cell: EpisodeCell, seasonIndex: Int, episodeIndex: Int) { + func setupCell(_ cell: EpisodeCell, seasonIndex: Int, episodeIndex: Int) { assertionFailure("Should be overriden by subclass") } - func setupSeasonHeader(header: SeasonHeader, seasonIndex: Int) { + func setupSeasonHeader(_ header: SeasonHeader, seasonIndex: Int) { assertionFailure("Should be overriden by subclass") } - func cellWasPressed(cell: UICollectionViewCell, seasonIndex: Int, episodeIndex: Int) { + func cellWasPressed(_ cell: UICollectionViewCell, seasonIndex: Int, episodeIndex: Int) { assertionFailure("Should be overriden by subclass") } - func cellWasLongPressed(cell: UICollectionViewCell, seasonIndex: Int, episodeIndex: Int) { + func cellWasLongPressed(_ cell: UICollectionViewCell, seasonIndex: Int, episodeIndex: Int) { } } diff --git a/PopcornTime/Controllers/ColorfullTabBarController.swift b/PopcornTime/Controllers/ColorfullTabBarController.swift index e03b0da..7ea38d9 100644 --- a/PopcornTime/Controllers/ColorfullTabBarController.swift +++ b/PopcornTime/Controllers/ColorfullTabBarController.swift @@ -11,7 +11,7 @@ import UIKit class ColorfullTabBarController: UITabBarController, UITabBarControllerDelegate { - private struct ColorConstants { + fileprivate struct ColorConstants { static let favoritesTintColor = UIColor(red: 235/255, green: 66/255, blue: 69/255, alpha: 1.0) static let moviesTintColor = UIColor(red: 66/255, green: 166/255, blue: 235/255, alpha: 1.0) static let showsTintColor = UIColor(red: 33/255, green: 181/255, blue: 42/255, alpha: 1.0) @@ -24,20 +24,20 @@ class ColorfullTabBarController: UITabBarController, UITabBarControllerDelegate } deinit { - NSNotificationCenter.defaultCenter().removeObserver(self) + NotificationCenter.default.removeObserver(self) } - override func viewWillAppear(animated: Bool) { + override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) assignColors() } - override func viewDidAppear(animated: Bool) { + override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) assignColors() } - private func assignColors() { + fileprivate func assignColors() { switch selectedIndex { case 0: view.window?.tintColor = ColorConstants.favoritesTintColor case 1: view.window?.tintColor = ColorConstants.moviesTintColor @@ -50,7 +50,7 @@ class ColorfullTabBarController: UITabBarController, UITabBarControllerDelegate // MARK: - UITabBarControllerDelegate - func tabBarController(tabBarController: UITabBarController, didSelectViewController viewController: UIViewController) { + func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) { self.assignColors() } diff --git a/PopcornTime/Controllers/FavoritesViewController.swift b/PopcornTime/Controllers/FavoritesViewController.swift index ea6c09f..9193b86 100644 --- a/PopcornTime/Controllers/FavoritesViewController.swift +++ b/PopcornTime/Controllers/FavoritesViewController.swift @@ -31,26 +31,26 @@ class FavoritesViewController: PagedViewController { self.searchController = nil self.navigationItem.titleView = nil - NSNotificationCenter.defaultCenter().addObserver( + NotificationCenter.default.addObserver( self, - selector: "favoritesDidChange:", - name: Notifications.FavoritesDidChangeNotification, + selector: #selector(FavoritesViewController.favoritesDidChange(_:)), + name: NSNotification.Name(rawValue: Notifications.FavoritesDidChangeNotification), object: nil ) } deinit { - NSNotificationCenter.defaultCenter().removeObserver(self) + NotificationCenter.default.removeObserver(self) } // MARK: - Navigation - override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if let item = sender as? BasicInfo { - if let episodesVC = segue.destinationViewController as? BaseDetailsViewController { + if let episodesVC = segue.destination as? BaseDetailsViewController { switch item { case item as Anime: episodesVC.item = item as! Anime @@ -67,23 +67,23 @@ class FavoritesViewController: PagedViewController { // MARK: - Notifications - func favoritesDidChange(notification: NSNotification) { + func favoritesDidChange(_ notification: Notification) { self.reloadData() } // MARK: - UICollectionViewDelegate - func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) { + func collectionView(_ collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: IndexPath) { let item = self.items[indexPath.row] switch item { case item as Anime: - performSegueWithIdentifier("showDetailsForFavoriteAnime", sender: item) + performSegue(withIdentifier: "showDetailsForFavoriteAnime", sender: item) case item as Show: - performSegueWithIdentifier("showDetailsForFavoriteShow", sender: item) + performSegue(withIdentifier: "showDetailsForFavoriteShow", sender: item) case item as Movie: - performSegueWithIdentifier("showDetailsForFavoriteMovie", sender: item) + performSegue(withIdentifier: "showDetailsForFavoriteMovie", sender: item) default: break } diff --git a/PopcornTime/Controllers/LoadingViewController.swift b/PopcornTime/Controllers/LoadingViewController.swift index 5f29b7b..d6602f6 100644 --- a/PopcornTime/Controllers/LoadingViewController.swift +++ b/PopcornTime/Controllers/LoadingViewController.swift @@ -9,20 +9,20 @@ import UIKit protocol LoadingViewControllerDelegate { - func didCancelLoading(controller: LoadingViewController) + func didCancelLoading(_ controller: LoadingViewController) } class LoadingViewController: UIViewController { var delegate: LoadingViewControllerDelegate? - @IBOutlet private weak var statusLabel: UILabel! - @IBOutlet private weak var progressLabel: UILabel! - @IBOutlet private weak var progressView: UIProgressView! - @IBOutlet private weak var speedLabel: UILabel! - @IBOutlet private weak var seedsLabel: UILabel! - @IBOutlet private weak var peersLabel: UILabel! - @IBOutlet private weak var titleLabel: UILabel! + @IBOutlet fileprivate weak var statusLabel: UILabel! + @IBOutlet fileprivate weak var progressLabel: UILabel! + @IBOutlet fileprivate weak var progressView: UIProgressView! + @IBOutlet fileprivate weak var speedLabel: UILabel! + @IBOutlet fileprivate weak var seedsLabel: UILabel! + @IBOutlet fileprivate weak var peersLabel: UILabel! + @IBOutlet fileprivate weak var titleLabel: UILabel! var status: String? = nil { didSet { @@ -41,7 +41,7 @@ class LoadingViewController: UIViewController { var speed: Int = 0 { // bytes/s didSet { - let formattedSpeed = NSByteCountFormatter.stringFromByteCount(Int64(speed), countStyle: .Binary) + "/s" + let formattedSpeed = ByteCountFormatter.string(fromByteCount: Int64(speed), countStyle: .binary) + "/s" speedLabel.text = String(format:"Speed: %@", formattedSpeed) } } @@ -78,18 +78,18 @@ class LoadingViewController: UIViewController { seeds = 0 peers = 0 - UIApplication.sharedApplication().idleTimerDisabled = true; + UIApplication.shared.isIdleTimerDisabled = true; } - override func viewDidDisappear(animated: Bool) { + override func viewDidDisappear(_ animated: Bool) { super.viewDidLoad() - UIApplication.sharedApplication().idleTimerDisabled = false; + UIApplication.shared.isIdleTimerDisabled = false; } // MARK: - Actions - @IBAction private func cancelButtonPressed(sender: AnyObject) { + @IBAction fileprivate func cancelButtonPressed(_ sender: AnyObject) { delegate?.didCancelLoading(self) } diff --git a/PopcornTime/Controllers/MovieDetailsViewController.swift b/PopcornTime/Controllers/MovieDetailsViewController.swift index e01cfb7..5c9a4e5 100644 --- a/PopcornTime/Controllers/MovieDetailsViewController.swift +++ b/PopcornTime/Controllers/MovieDetailsViewController.swift @@ -26,7 +26,8 @@ class MovieDetailsViewController: BaseDetailsViewController { // MARK: - BaseDetailsViewController override func reloadData() { - PTAPIManager.sharedManager().showInfoWithType(.Movie, withId: item.identifier, success: { (item) -> Void in + PTAPIManager.shared().showInfo(with: .movie, withId: item.identifier, success: { (item) -> Void in + guard let item = item else { return } self.movie.update(item) self.collectionView?.reloadData() }, failure: nil) @@ -37,11 +38,11 @@ class MovieDetailsViewController: BaseDetailsViewController { return 1 } - override func numberOfEpisodesInSeason(seasonsIndex: Int) -> Int { + override func numberOfEpisodesInSeason(_ seasonsIndex: Int) -> Int { return movie.videos.count } - override func setupCell(cell: EpisodeCell, seasonIndex: Int, episodeIndex: Int) { + override func setupCell(_ cell: EpisodeCell, seasonIndex: Int, episodeIndex: Int) { let video = movie.videos[episodeIndex] var title = "" if let quality = video.quality { @@ -53,10 +54,10 @@ class MovieDetailsViewController: BaseDetailsViewController { cell.titleLabel.text = title } - override func setupSeasonHeader(header: SeasonHeader, seasonIndex: Int) { + override func setupSeasonHeader(_ header: SeasonHeader, seasonIndex: Int) { } - override func cellWasPressed(cell: UICollectionViewCell, seasonIndex: Int, episodeIndex: Int) { + override func cellWasPressed(_ cell: UICollectionViewCell, seasonIndex: Int, episodeIndex: Int) { let video = movie.videos[episodeIndex] let magnetLink = video.magnetLink let title = movie.title ?? "" diff --git a/PopcornTime/Controllers/MoviesViewController.swift b/PopcornTime/Controllers/MoviesViewController.swift index df7fb50..c0136b8 100644 --- a/PopcornTime/Controllers/MoviesViewController.swift +++ b/PopcornTime/Controllers/MoviesViewController.swift @@ -12,36 +12,36 @@ class MoviesViewController: PagedViewController { override var showType: PTItemType { get { - return .Movie + return .movie } } - override func map(response: [AnyObject]) -> [BasicInfo] { - let items = response.map({ Movie(dictionary: $0 as! NSDictionary) }) as [BasicInfo] + override func map(_ response: [AnyObject]) -> [BasicInfo] { + let items = response.map({ Movie(dictionary: $0 as! [AnyHashable: Any]) }) as [BasicInfo] return items } - func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) { + func collectionView(_ collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: IndexPath) { - if let cell = collectionView.cellForItemAtIndexPath(indexPath){ + if let cell = collectionView.cellForItem(at: indexPath){ //Check if cell is MoreShowsCell if let _ = cell as? MoreShowsCollectionViewCell{ loadMore() } else { - performSegueWithIdentifier("showDetails", sender: cell) + performSegue(withIdentifier: "showDetails", sender: cell) } } } - override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { - super.prepareForSegue(segue, sender: sender) + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + super.prepare(for: segue, sender: sender) if segue.identifier == "showDetails"{ - if let episodesVC = segue.destinationViewController as? MovieDetailsViewController{ + if let episodesVC = segue.destination as? MovieDetailsViewController{ if let senderCell = sender as? UICollectionViewCell{ - if let indexPath = collectionView!.indexPathForCell(senderCell) { + if let indexPath = collectionView!.indexPath(for: senderCell) { var item: BasicInfo! - if (searchController!.active) { + if (searchController!.isActive) { item = searchResults[indexPath.row] } else { item = items[indexPath.row] diff --git a/PopcornTime/Controllers/OAuthViewController.swift b/PopcornTime/Controllers/OAuthViewController.swift index a8e9787..703d728 100644 --- a/PopcornTime/Controllers/OAuthViewController.swift +++ b/PopcornTime/Controllers/OAuthViewController.swift @@ -9,7 +9,7 @@ import UIKit protocol OAuthViewControllerDelegate { - func oauthViewControllerDidFinish(controller: OAuthViewController, token: String?, error: NSError?) + func oauthViewControllerDidFinish(_ controller: OAuthViewController, token: String?, error: NSError?) } class OAuthViewController: UIViewController, UIWebViewDelegate { @@ -17,7 +17,7 @@ class OAuthViewController: UIViewController, UIWebViewDelegate { @IBOutlet weak var webView: UIWebView! @IBOutlet weak var navigationBar: UINavigationBar! var delegate: OAuthViewControllerDelegate? - var URL: NSURL? + var URL: Foundation.URL? // MARK: - View Life Cycle @@ -25,14 +25,14 @@ class OAuthViewController: UIViewController, UIWebViewDelegate { super.viewDidLoad() if let URL = URL { - webView.loadRequest(NSURLRequest(URL: URL)) + webView.loadRequest(URLRequest(url: URL)) } } // MARK: - UIWebViewDelegate - func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool { - if let code = request.URL?.lastPathComponent { + func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool { + if let code = request.url?.lastPathComponent { if code.characters.count == 64 { // PTAPIManager.sharedManager().accessTokenWithAuthorizationCode(code, success: { (accessToken) -> Void in // println("OAuth access token: \(accessToken)") @@ -46,21 +46,21 @@ class OAuthViewController: UIViewController, UIWebViewDelegate { return true; } - func webViewDidStartLoad(webView: UIWebView) { + func webViewDidStartLoad(_ webView: UIWebView) { } - func webViewDidFinishLoad(webView: UIWebView) { + func webViewDidFinishLoad(_ webView: UIWebView) { } - func webView(webView: UIWebView, didFailLoadWithError error: NSError?) { - delegate?.oauthViewControllerDidFinish(self, token: nil, error: error) + func webView(_ webView: UIWebView, didFailLoadWithError error: Error) { + delegate?.oauthViewControllerDidFinish(self, token: nil, error: error as NSError?) } // MARK: - Actions - @IBAction func cancelButtonPressed(sender: AnyObject) { + @IBAction func cancelButtonPressed(_ sender: AnyObject) { delegate?.oauthViewControllerDidFinish(self, token: nil, error: nil) } diff --git a/PopcornTime/Controllers/PagedViewController.swift b/PopcornTime/Controllers/PagedViewController.swift index 8b7fe5f..36fdc2d 100644 --- a/PopcornTime/Controllers/PagedViewController.swift +++ b/PopcornTime/Controllers/PagedViewController.swift @@ -10,16 +10,16 @@ import UIKit class PagedViewController: BaseCollectionViewController, UISearchBarDelegate, UISearchResultsUpdating { - private var contentPage: UInt = 0 + fileprivate var contentPage: UInt = 0 var searchResults = [BasicInfo]() var searchController: UISearchController? - var searchTimer: NSTimer? + var searchTimer: Timer? var showType: PTItemType { get { assert(false, "this must be overriden by subclass") - return .Movie + return .movie } } @@ -31,13 +31,13 @@ class PagedViewController: BaseCollectionViewController, UISearchBarDelegate, UI setupSearch() } - override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) { - super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator) + override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { + super.viewWillTransition(to: size, with: coordinator) collectionViewLayout?.invalidateLayout() } - private func setupSearch() { + fileprivate func setupSearch() { self.definesPresentationContext = true @@ -48,7 +48,7 @@ class PagedViewController: BaseCollectionViewController, UISearchBarDelegate, UI let searchBar = searchController!.searchBar searchBar.delegate = self - searchBar.barStyle = .Black + searchBar.barStyle = .black searchBar.backgroundImage = UIImage() @@ -58,36 +58,37 @@ class PagedViewController: BaseCollectionViewController, UISearchBarDelegate, UI navigationItem.titleView = searchBarContainer let views = ["searchBar" : searchBar] - searchBarContainer.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-0-[searchBar]-0-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views)) - searchBarContainer.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-0-[searchBar]-0-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views)) + searchBarContainer.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[searchBar]-0-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views)) + searchBarContainer.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[searchBar]-0-|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views)) } // MARK: - func map(response: [AnyObject]) -> [BasicInfo] { + func map(_ response: [AnyObject]) -> [BasicInfo] { return [BasicInfo]() } override func reloadData() { - PTAPIManager.sharedManager().topShowsWithType(showType, withPage: contentPage, success: { (items) -> Void in + PTAPIManager.shared().topShows(with: showType, withPage: contentPage, success: { (items) -> Void in self.showLoadMoreCell = true if let items = items { - self.items = self.map(items) + self.items = self.map(items as [AnyObject]) self.collectionView?.reloadData() } }, failure: nil) } func loadMore() { - PTAPIManager.sharedManager().topShowsWithType(showType, withPage: contentPage+1, success: { (items) -> Void in + PTAPIManager.shared().topShows(with: showType, withPage: contentPage+1, success: { (items) -> Void in if let items = items { - self.contentPage++ - let newItems = self.map(items) - var counter = 0 - let newShowsIndexPathes = newItems.map({ item in NSIndexPath(forRow: (self.items.count + counter++), inSection: 0) } ) + self.contentPage += 1 + let newItems = self.map(items as [AnyObject]) + let newShowsIndexPathes = newItems.enumerated().map({ (index, item) in + return IndexPath(row: (self.items.count + index), section: 0) + }) self.items += newItems - self.collectionView?.insertItemsAtIndexPaths(newShowsIndexPathes) + self.collectionView?.insertItems(at: newShowsIndexPathes) } }, failure: nil) } @@ -95,12 +96,12 @@ class PagedViewController: BaseCollectionViewController, UISearchBarDelegate, UI func performSearch() { let text = searchController!.searchBar.text if text!.characters.count > 0 { - PTAPIManager.sharedManager().searchForShowWithType(showType, name: text, success: { (items) -> Void in + PTAPIManager.shared().searchForShow(with: showType, name: text, success: { (items) -> Void in self.showLoadMoreCell = false if let items = items { - self.searchResults = self.map(items) + self.searchResults = self.map(items as [AnyObject]) } else { - self.searchResults.removeAll(keepCapacity: false) + self.searchResults.removeAll(keepingCapacity: false) } self.collectionView?.reloadData() }, failure: nil) @@ -109,44 +110,44 @@ class PagedViewController: BaseCollectionViewController, UISearchBarDelegate, UI // MARK: UICollectionViewDataSource - override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { - if searchController != nil && searchController!.active { + override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + if searchController != nil && searchController!.isActive { return searchResults.count } return super.collectionView(collectionView, numberOfItemsInSection: section) } - override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell { - if searchController != nil && searchController!.active { + override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + if searchController != nil && searchController!.isActive { //Ordinary show cell - let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifierShow, forIndexPath: indexPath) as! ShowCollectionViewCell + let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifierShow, for: indexPath) as! ShowCollectionViewCell let item = searchResults[indexPath.row] cell.title = item.title let imageItem = item.smallImage switch imageItem?.status { - case .New?: - imageItem?.status = .Downloading + case .new?: + imageItem?.status = .downloading ImageProvider.sharedInstance.imageFromURL(URL: imageItem?.URL) { (downloadedImage) -> () in imageItem?.image = downloadedImage - imageItem?.status = .Finished + imageItem?.status = .finished - collectionView.reloadItemsAtIndexPaths([indexPath]) + collectionView.reloadItems(at: [indexPath]) } - case .Finished?: + case .finished?: cell.image = imageItem?.image default: break } return cell } - return super.collectionView(collectionView, cellForItemAtIndexPath: indexPath) + return super.collectionView(collectionView, cellForItemAt: indexPath) } // MARK: UICollectionViewDelegate - func collectionView(collectionView: UICollectionView, willDisplayCell cell: UICollectionViewCell, forItemAtIndexPath indexPath: NSIndexPath) { + func collectionView(_ collectionView: UICollectionView, willDisplayCell cell: UICollectionViewCell, forItemAtIndexPath indexPath: IndexPath) { if indexPath.row == items.count { loadMore() } @@ -154,28 +155,28 @@ class PagedViewController: BaseCollectionViewController, UISearchBarDelegate, UI // MARK: UISearchBarDelegate - func searchBarSearchButtonClicked(searchBar: UISearchBar) { + func searchBarSearchButtonClicked(_ searchBar: UISearchBar) { self.searchTimer?.invalidate() self.searchTimer = nil performSearch() } - func searchBarCancelButtonClicked(searchBar: UISearchBar) { + func searchBarCancelButtonClicked(_ searchBar: UISearchBar) { self.showLoadMoreCell = true self.searchTimer?.invalidate() self.searchTimer = nil - searchResults.removeAll(keepCapacity: false) + searchResults.removeAll(keepingCapacity: false) self.collectionView.reloadData() } // MARK: UISearchResultsUpdating - func updateSearchResultsForSearchController(searchController: UISearchController) { + func updateSearchResults(for searchController: UISearchController) { self.searchTimer?.invalidate() self.collectionView.reloadData() - self.searchTimer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "performSearch", userInfo: nil, repeats: false) + self.searchTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(PagedViewController.performSearch), userInfo: nil, repeats: false) } } diff --git a/PopcornTime/Controllers/SettingsViewController.swift b/PopcornTime/Controllers/SettingsViewController.swift index 191f742..2141603 100644 --- a/PopcornTime/Controllers/SettingsViewController.swift +++ b/PopcornTime/Controllers/SettingsViewController.swift @@ -19,27 +19,27 @@ class SettingsViewController: UIViewController, UITableViewDataSource, UITableVi // MARK: - func appInfoString() -> String { - let displayName = NSBundle.mainBundle().infoDictionary?["CFBundleDisplayName"] as! String - let version = NSBundle.mainBundle().infoDictionary?["CFBundleVersion"] as! String - let shortVersion = NSBundle.mainBundle().infoDictionary?["CFBundleShortVersionString"] as! String + let displayName = Bundle.main.infoDictionary?["CFBundleDisplayName"] as! String + let version = Bundle.main.infoDictionary?["CFBundleVersion"] as! String + let shortVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as! String return "\(displayName) \(shortVersion) (\(version))" } // MARK: - UITableViewDataSource - func numberOfSectionsInTableView(tableView: UITableView) -> Int { + func numberOfSections(in tableView: UITableView) -> Int { return 1 } - func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 1 } - func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let identifier = "SettingsCell" - var cell: UITableViewCell! = tableView.dequeueReusableCellWithIdentifier("SettingsCell") + var cell: UITableViewCell! = tableView.dequeueReusableCell(withIdentifier: "SettingsCell") if cell == nil { - cell = UITableViewCell(style: .Default, reuseIdentifier: identifier) + cell = UITableViewCell(style: .default, reuseIdentifier: identifier) } cell.textLabel?.text = "Hello, PopcornTime!" @@ -47,26 +47,26 @@ class SettingsViewController: UIViewController, UITableViewDataSource, UITableVi return cell } - func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? { - let label = UILabel(frame: CGRect(x: 0.0, y: 0.0, width: CGRectGetWidth(tableView.bounds), height: 0.0)) - label.backgroundColor = UIColor.clearColor() - label.font = UIFont.systemFontOfSize(14.0) + func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? { + let label = UILabel(frame: CGRect(x: 0.0, y: 0.0, width: tableView.bounds.width, height: 0.0)) + label.backgroundColor = UIColor.clear + label.font = UIFont.systemFont(ofSize: 14.0) label.text = appInfoString() - label.textAlignment = .Center + label.textAlignment = .center return label } - func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { + func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { return 30.0 } // MARK: - UITableViewDelegate - func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { - tableView .deselectRowAtIndexPath(indexPath, animated: true) + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + tableView .deselectRow(at: indexPath, animated: true) } - @IBAction func doneButtonTapped(sender: AnyObject) { - self.dismissViewControllerAnimated(true, completion: nil) + @IBAction func doneButtonTapped(_ sender: AnyObject) { + self.dismiss(animated: true, completion: nil) } } diff --git a/PopcornTime/Controllers/ShowDetailsViewController.swift b/PopcornTime/Controllers/ShowDetailsViewController.swift index e56519c..fcf4df9 100644 --- a/PopcornTime/Controllers/ShowDetailsViewController.swift +++ b/PopcornTime/Controllers/ShowDetailsViewController.swift @@ -19,11 +19,10 @@ class ShowDetailsViewController: BaseDetailsViewController { // MARK: - BaseDetailsViewController override func reloadData() { - PTAPIManager.sharedManager().showInfoWithType(.Show, withId: show.identifier, success: { (item) -> Void in - if let item = item { - self.show.update(item) - self.collectionView?.reloadData() - } + PTAPIManager.shared().showInfo(with: .show, withId: show.identifier, success: { (item) -> Void in + guard let item = item else { return } + self.show.update(item) + self.collectionView?.reloadData() }, failure: nil) } @@ -32,11 +31,11 @@ class ShowDetailsViewController: BaseDetailsViewController { return show.seasons.count } - override func numberOfEpisodesInSeason(seasonsIndex: Int) -> Int { + override func numberOfEpisodesInSeason(_ seasonsIndex: Int) -> Int { return show.seasons[seasonsIndex].episodes.count } - override func setupCell(cell: EpisodeCell, seasonIndex: Int, episodeIndex: Int) { + override func setupCell(_ cell: EpisodeCell, seasonIndex: Int, episodeIndex: Int) { let episode = show.seasons[seasonIndex].episodes[episodeIndex] if let title = episode.title { cell.titleLabel.text = "S\(episode.seasonNumber)E\(episode.episodeNumber): \(title)" @@ -45,17 +44,17 @@ class ShowDetailsViewController: BaseDetailsViewController { } } - override func setupSeasonHeader(header: SeasonHeader, seasonIndex: Int) { + override func setupSeasonHeader(_ header: SeasonHeader, seasonIndex: Int) { let seasonNumber = self.show.seasons[seasonIndex].seasonNumber header.titleLabel.text = "Season \(seasonNumber)" } - override func cellWasPressed(cell: UICollectionViewCell, seasonIndex: Int, episodeIndex: Int) { + override func cellWasPressed(_ cell: UICollectionViewCell, seasonIndex: Int, episodeIndex: Int) { let episode = show.episodeFor(seasonIndex: seasonIndex, episodeIndex: episodeIndex) showVideoPickerPopupForEpisode(episode, basicInfo: self.item, fromView: cell) } - override func cellWasLongPressed(cell: UICollectionViewCell, seasonIndex: Int, episodeIndex: Int) { + override func cellWasLongPressed(_ cell: UICollectionViewCell, seasonIndex: Int, episodeIndex: Int) { // let episode = show.episodeFor(seasonIndex: seasonIndex, episodeIndex: episodeIndex) // let seasonEpisodes = show.episodesFor(seasonIndex: seasonIndex) } diff --git a/PopcornTime/Controllers/ShowsViewController.swift b/PopcornTime/Controllers/ShowsViewController.swift index 9fab242..3bf15c4 100644 --- a/PopcornTime/Controllers/ShowsViewController.swift +++ b/PopcornTime/Controllers/ShowsViewController.swift @@ -12,35 +12,35 @@ class ShowsViewController: PagedViewController { override var showType: PTItemType { get { - return .Show + return .show } } - override func map(response: [AnyObject]) -> [BasicInfo] { - return response.map({ Show(dictionary: $0 as! NSDictionary) }) + override func map(_ response: [AnyObject]) -> [BasicInfo] { + return response.map({ Show(dictionary: $0 as! [AnyHashable: Any]) }) } - func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) { + func collectionView(_ collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: IndexPath) { - if let cell = collectionView.cellForItemAtIndexPath(indexPath){ + if let cell = collectionView.cellForItem(at: indexPath){ //Check if cell is MoreShowsCell if let _ = cell as? MoreShowsCollectionViewCell { loadMore() } else { - performSegueWithIdentifier("showDetails", sender: cell) + performSegue(withIdentifier: "showDetails", sender: cell) } } } - override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { - super.prepareForSegue(segue, sender: sender) + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + super.prepare(for: segue, sender: sender) if segue.identifier == "showDetails" { - if let episodesVC = segue.destinationViewController as? ShowDetailsViewController { + if let episodesVC = segue.destination as? ShowDetailsViewController { if let senderCell = sender as? UICollectionViewCell { - if let indexPath = collectionView!.indexPathForCell(senderCell) { + if let indexPath = collectionView!.indexPath(for: senderCell) { var item: BasicInfo! - if (searchController!.active) { + if (searchController!.isActive) { item = searchResults[indexPath.row] } else { item = items[indexPath.row] diff --git a/PopcornTime/Models/Anime.swift b/PopcornTime/Models/Anime.swift index e6b57d0..896d709 100644 --- a/PopcornTime/Models/Anime.swift +++ b/PopcornTime/Models/Anime.swift @@ -11,7 +11,7 @@ import Foundation class Anime: BasicInfo { var seasons = [Season]() - required init(dictionary: NSDictionary) { + required init(dictionary: [AnyHashable: Any]) { super.init(dictionary: dictionary) let id = dictionary["id"] as! Int @@ -22,12 +22,12 @@ class Anime: BasicInfo { if let poster = dictionary["malimg"] as? String { images = [Image]() - let URL = NSURL(string: poster) - let image = Image(URL: URL!, type: .Poster) + let URL = Foundation.URL(string: poster) + let image = Image(URL: URL!, type: .poster) images.append(image) } - smallImage = images.filter({$0.type == ImageType.Poster}).first + smallImage = images.filter({$0.type == ImageType.poster}).first bigImage = smallImage } @@ -35,17 +35,17 @@ class Anime: BasicInfo { super.init(coder: aDecoder)! } - override func update(dictionary: NSDictionary) { - seasons.removeAll(keepCapacity: true) + override func update(_ dictionary: [AnyHashable: Any]) { + seasons.removeAll(keepingCapacity: true) - let episodesDicts = dictionary["episodes"] as! [NSDictionary] + let episodesDicts = dictionary["episodes"] as! [[AnyHashable: Any]] let seasonNumber:UInt = 0 var videosContainer = [Int: [Video]]() var episodesContainer = [Int: Episode]() synopsis = dictionary["synopsis"] as? String if let sps = synopsis { - synopsis = sps.stringByReplacingOccurrencesOfString("oatRightHeader\">EditSynopsis\n", withString: "") + synopsis = sps.replacingOccurrences(of: "oatRightHeader\">EditSynopsis\n", with: "") } @@ -86,7 +86,7 @@ class Anime: BasicInfo { } - let episodes = Array(episodesContainer.values).sort { (a, b) -> Bool in + let episodes = Array(episodesContainer.values).sorted { (a, b) -> Bool in return a.episodeNumber > b.episodeNumber } @@ -94,8 +94,8 @@ class Anime: BasicInfo { seasons.append(season) } - private func numbersFromAnimeTitle(title: String) -> [Int]{ - let components = title.componentsSeparatedByCharactersInSet(NSCharacterSet(charactersInString: "[]_() ")) + fileprivate func numbersFromAnimeTitle(_ title: String) -> [Int]{ + let components = title.components(separatedBy: CharacterSet(charactersIn: "[]_() ")) var numbers = [Int]() for component in components { if let number = Int(component) { @@ -109,12 +109,12 @@ class Anime: BasicInfo { } extension Anime: ContainsEpisodes { - func episodeFor(seasonIndex seasonIndex: Int, episodeIndex: Int) -> Episode { + func episodeFor(seasonIndex: Int, episodeIndex: Int) -> Episode { let episode = seasons[seasonIndex].episodes[episodeIndex] return episode } - func episodesFor(seasonIndex seasonIndex: Int) -> [Episode] { + func episodesFor(seasonIndex: Int) -> [Episode] { return seasons[seasonIndex].episodes } -} \ No newline at end of file +} diff --git a/PopcornTime/Models/AppDelegate.swift b/PopcornTime/Models/AppDelegate.swift index 97f7048..12f688b 100644 --- a/PopcornTime/Models/AppDelegate.swift +++ b/PopcornTime/Models/AppDelegate.swift @@ -18,7 +18,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? - func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { #if RELEASE Fabric.with([Crashlytics()]) #endif diff --git a/PopcornTime/Models/BasicInfo.swift b/PopcornTime/Models/BasicInfo.swift index 616335f..515f3f7 100755 --- a/PopcornTime/Models/BasicInfo.swift +++ b/PopcornTime/Models/BasicInfo.swift @@ -9,8 +9,8 @@ import Foundation protocol ContainsEpisodes { - func episodeFor(seasonIndex seasonIndex: Int, episodeIndex: Int) -> Episode - func episodesFor(seasonIndex seasonIndex: Int) -> [Episode] + func episodeFor(seasonIndex: Int, episodeIndex: Int) -> Episode + func episodesFor(seasonIndex: Int) -> [Episode] } protocol BasicInfoProtocol { @@ -22,8 +22,8 @@ protocol BasicInfoProtocol { var bigImage: Image? {get} var isFavorite: Bool {get} - init(dictionary: NSDictionary) - func update(dictionary: NSDictionary) + init(dictionary: [AnyHashable: Any]) + func update(_ dictionary: [AnyHashable: Any]) } class BasicInfo: NSObject, BasicInfoProtocol, NSCoding { @@ -48,29 +48,29 @@ class BasicInfo: NSObject, BasicInfoProtocol, NSCoding { } } - required init(dictionary: NSDictionary) { + required init(dictionary: [AnyHashable: Any]) { // fatalError("init(dictionary:) has not been implemented") } - func update(dictionary: NSDictionary) { + func update(_ dictionary: [AnyHashable: Any]) { fatalError("update(dictionary:) has not been implemented") } // MARK: - NSCoding required init?(coder aDecoder: NSCoder) { - identifier = aDecoder.decodeObjectForKey("identifier") as! String - title = aDecoder.decodeObjectForKey("title") as? String - year = aDecoder.decodeObjectForKey("year") as? String - smallImage = aDecoder.decodeObjectForKey("smallImage") as? Image - bigImage = aDecoder.decodeObjectForKey("bigImage") as? Image + identifier = aDecoder.decodeObject(forKey: "identifier") as! String + title = aDecoder.decodeObject(forKey: "title") as? String + year = aDecoder.decodeObject(forKey: "year") as? String + smallImage = aDecoder.decodeObject(forKey: "smallImage") as? Image + bigImage = aDecoder.decodeObject(forKey: "bigImage") as? Image } - func encodeWithCoder(aCoder: NSCoder) { - aCoder.encodeObject(identifier, forKey: "identifier") - aCoder.encodeObject(title, forKey: "title") - aCoder.encodeObject(year, forKey: "year") - aCoder.encodeObject(smallImage, forKey: "smallImage") - aCoder.encodeObject(bigImage, forKey: "bigImage") + func encode(with aCoder: NSCoder) { + aCoder.encode(identifier, forKey: "identifier") + aCoder.encode(title, forKey: "title") + aCoder.encode(year, forKey: "year") + aCoder.encode(smallImage, forKey: "smallImage") + aCoder.encode(bigImage, forKey: "bigImage") } -} \ No newline at end of file +} diff --git a/PopcornTime/Models/DataManager.swift b/PopcornTime/Models/DataManager.swift index 6d866a5..27b6ac4 100644 --- a/PopcornTime/Models/DataManager.swift +++ b/PopcornTime/Models/DataManager.swift @@ -13,16 +13,16 @@ struct Notifications { } class DataManager { - let documentsDirectory = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first! as String + let documentsDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first! as String let fileName = "Favorites.plist" var filePath: String { get { - return fileURL.path! + return fileURL.path } } - var fileURL: NSURL { - let url = NSURL(fileURLWithPath: documentsDirectory, isDirectory: true) - return url.URLByAppendingPathComponent(fileName) + var fileURL: URL { + let url = URL(fileURLWithPath: documentsDirectory, isDirectory: true) + return url.appendingPathComponent(fileName) } var favorites: [BasicInfo]? @@ -35,26 +35,26 @@ class DataManager { return Static.instance } - private func loadFavorites() -> [BasicInfo]? { - if NSFileManager.defaultManager().fileExistsAtPath(filePath) { - let data = NSData(contentsOfFile:filePath) + fileprivate func loadFavorites() -> [BasicInfo]? { + if FileManager.default.fileExists(atPath: filePath) { + let data = try? Data(contentsOf: URL(fileURLWithPath: filePath)) if let data = data { - self.favorites = NSKeyedUnarchiver.unarchiveObjectWithData(data) as! [BasicInfo]? + self.favorites = NSKeyedUnarchiver.unarchiveObject(with: data) as! [BasicInfo]? return self.favorites } } return nil } - private func saveFavorites(items: [BasicInfo]) { - let data = NSKeyedArchiver.archivedDataWithRootObject(items) - data.writeToFile(filePath, atomically: true) + fileprivate func saveFavorites(_ items: [BasicInfo]) { + let data = NSKeyedArchiver.archivedData(withRootObject: items) + try? data.write(to: URL(fileURLWithPath: filePath), options: [.atomic]) self.favorites = items } // MARK: - - func isFavorite(item: BasicInfo) -> Bool { + func isFavorite(_ item: BasicInfo) -> Bool { let favoriteItem = self.favorites?.filter({ $0.identifier == item.identifier }).first if favoriteItem != nil { return true @@ -62,7 +62,7 @@ class DataManager { return false } - func addToFavorites(item: BasicInfo) { + func addToFavorites(_ item: BasicInfo) { var items = [BasicInfo]() if let favorites = loadFavorites() { items += favorites @@ -70,22 +70,22 @@ class DataManager { items.append(item) saveFavorites(items) - NSNotificationCenter.defaultCenter().postNotificationName(Notifications.FavoritesDidChangeNotification, object: nil) + NotificationCenter.default.post(name: Notification.Name(rawValue: Notifications.FavoritesDidChangeNotification), object: nil) } - func removeFromFavorites(item: BasicInfo) { + func removeFromFavorites(_ item: BasicInfo) { let items = loadFavorites() if var items = items { let favoriteItem = items.filter({ $0.identifier == item.identifier }).first if let favoriteItem = favoriteItem { - let idx = items.indexOf(favoriteItem) - items.removeAtIndex(idx!) + let idx = items.index(of: favoriteItem) + items.remove(at: idx!) saveFavorites(items) - NSNotificationCenter.defaultCenter().postNotificationName(Notifications.FavoritesDidChangeNotification, object: nil) + NotificationCenter.default.post(name: Notification.Name(rawValue: Notifications.FavoritesDidChangeNotification), object: nil) } } } } - \ No newline at end of file + diff --git a/PopcornTime/Models/Image.swift b/PopcornTime/Models/Image.swift index 0c1bbf6..389ff3d 100644 --- a/PopcornTime/Models/Image.swift +++ b/PopcornTime/Models/Image.swift @@ -9,20 +9,20 @@ import UIKit enum ImageType: Int { - case Banner, Poster, Fanart + case banner, poster, fanart } enum ImageStatus { - case New, Downloading, Finished + case new, downloading, finished } class Image: NSObject, NSCoding { - let URL: NSURL + let URL: Foundation.URL var image: UIImage? let type: ImageType - var status: ImageStatus = .New + var status: ImageStatus = .new - init(URL: NSURL, type: ImageType) { + init(URL: Foundation.URL, type: ImageType) { self.URL = URL self.type = type } @@ -30,13 +30,13 @@ class Image: NSObject, NSCoding { // MARK: - NSCoding required init?(coder aDecoder: NSCoder) { - URL = aDecoder.decodeObjectForKey("URL") as! NSURL - let typeRaw = aDecoder.decodeObjectForKey("type") as! Int + URL = aDecoder.decodeObject(forKey: "URL") as! Foundation.URL + let typeRaw = aDecoder.decodeObject(forKey: "type") as! Int type = ImageType(rawValue: typeRaw)! } - func encodeWithCoder(aCoder: NSCoder) { - aCoder.encodeObject(URL, forKey: "URL") - aCoder.encodeObject(type.rawValue, forKey: "type") + func encode(with aCoder: NSCoder) { + aCoder.encode(URL, forKey: "URL") + aCoder.encode(type.rawValue, forKey: "type") } } diff --git a/PopcornTime/Models/ImageProvider.swift b/PopcornTime/Models/ImageProvider.swift index d26e034..20c1080 100644 --- a/PopcornTime/Models/ImageProvider.swift +++ b/PopcornTime/Models/ImageProvider.swift @@ -12,15 +12,15 @@ class ImageProvider: NSObject { static let sharedInstance = ImageProvider() - func imageFromURL(URL URL: NSURL?, completionBlock: (downloadedImage: UIImage?)->()) { + func imageFromURL(URL: Foundation.URL?, completionBlock: @escaping (_ downloadedImage: UIImage?)->()) { guard let URL = URL else { return } - SDWebImageDownloader.sharedDownloader().downloadImageWithURL(URL, options: [SDWebImageDownloaderOptions.UseNSURLCache], progress: nil) { + SDWebImageDownloader.shared().downloadImage(with: URL, options: [SDWebImageDownloaderOptions.useNSURLCache], progress: nil) { (image, data, error, finished) -> Void in - if let _ = error { NSLog("\(__FUNCTION__): \(error)") } + if let _ = error { NSLog("\(#function): \(error)") } - dispatch_async(dispatch_get_main_queue(), { - completionBlock(downloadedImage: image) + DispatchQueue.main.async(execute: { + completionBlock(image) }) } } diff --git a/PopcornTime/Models/Movie.swift b/PopcornTime/Models/Movie.swift index 07741fd..ce8850f 100755 --- a/PopcornTime/Models/Movie.swift +++ b/PopcornTime/Models/Movie.swift @@ -11,27 +11,27 @@ import Foundation class Movie: BasicInfo { var videos = [Video]() - required init(dictionary: NSDictionary) { + required init(dictionary: [AnyHashable: Any]) { super.init(dictionary: dictionary) let id = (dictionary["id"] as! NSString).intValue identifier = "\(id)" title = dictionary["title"] as? String - year = String(dictionary["year"]) + year = String(describing: dictionary["year"]) images = [Image]() if let cover = dictionary["poster_med"] as? String { - let image = Image(URL: NSURL(string: cover)!, type: .Poster) + let image = Image(URL: URL(string: cover)!, type: .poster) images.append(image) } if let cover = dictionary["poster_big"] as? String { - let image = Image(URL: NSURL(string: cover)!, type: .Banner) + let image = Image(URL: URL(string: cover)!, type: .banner) images.append(image) } - smallImage = self.images.filter({$0.type == ImageType.Poster}).first - bigImage = self.images.filter({$0.type == ImageType.Banner}).first + smallImage = self.images.filter({$0.type == ImageType.poster}).first + bigImage = self.images.filter({$0.type == ImageType.banner}).first synopsis = dictionary["description"] as? String } @@ -39,20 +39,19 @@ class Movie: BasicInfo { super.init(coder: aDecoder)! } - override func update(dictionary: NSDictionary) { - videos.removeAll(keepCapacity: true) + override func update(_ dictionary: [AnyHashable: Any]) { + videos.removeAll(keepingCapacity: true) let title = dictionary["title"] as! String - if let movieList = dictionary["items"] as? NSArray { - for movieDict in movieList { - let quality = movieDict["quality"] as! String - let magnetLink = movieDict["torrent_magnet"] as! String - let size = movieDict["size_bytes"] as! UInt + guard let movieList = dictionary["items"] as? [[AnyHashable: Any]] else { return } + for movieDict in movieList { + let quality = movieDict["quality"] as! String + let magnetLink = movieDict["torrent_magnet"] as! String + let size = movieDict["size_bytes"] as! UInt - let video = Video(name: title, quality: quality, size: size, duration: 0, subGroup: nil, magnetLink: magnetLink) - videos.append(video) - } + let video = Video(name: title, quality: quality, size: size, duration: 0, subGroup: nil, magnetLink: magnetLink) + videos.append(video) } } -} \ No newline at end of file +} diff --git a/PopcornTime/Models/PTAPIManager.m b/PopcornTime/Models/PTAPIManager.m index 3139d5f..841a84f 100755 --- a/PopcornTime/Models/PTAPIManager.m +++ b/PopcornTime/Models/PTAPIManager.m @@ -12,7 +12,7 @@ NSUInteger const PTAPIManagerResultsLimit = 30; NSString *const PTAPIManagerMoviesEndPoint = @"http://api.torrentsapi.com/"; -NSString *const PTAPIManagerShowsEndPoint = @"http://popcorntime.ws/api/eztv/"; +NSString *const PTAPIManagerShowsEndPoint = @"https://api-fetch.website/tv/"; NSString *const PTAPIManagerAnimeEndPoint = @"http://ptp.haruhichan.com"; @implementation PTAPIManager @@ -183,7 +183,7 @@ - (void)topTVSeriesWithPage:(NSUInteger)page success:(PTAPIManagerSuccessItems)success failure:(PTAPIManagerFailure)failure { - NSString *path = [NSString stringWithFormat:@"shows/%ld?limit=%lu&order=desc&sort=seeds", (long)page + 1, (long)PTAPIManagerResultsLimit]; + NSString *path = [NSString stringWithFormat:@"shows/%ld?limit=%lu", (long)page + 1, (long)PTAPIManagerResultsLimit]; NSString *URLString = [PTAPIManagerShowsEndPoint stringByAppendingPathComponent:path]; [self dataFromURL:[NSURL URLWithString:URLString] success:^(id JSONObject) { if (success) { diff --git a/PopcornTime/Models/Show.swift b/PopcornTime/Models/Show.swift index 601a797..4a9e8a5 100644 --- a/PopcornTime/Models/Show.swift +++ b/PopcornTime/Models/Show.swift @@ -11,12 +11,12 @@ import Foundation class Show: BasicInfo { var seasons = [Season]() - func thumbnail(original: String) -> String { - return original.stringByReplacingOccurrencesOfString("original", withString: "thumb", - options: NSStringCompareOptions.CaseInsensitiveSearch, range: nil) + func thumbnail(_ original: String) -> String { + return original.replacingOccurrences(of: "original", with: "thumb", + options: NSString.CompareOptions.caseInsensitive, range: nil) } - required init(dictionary: NSDictionary) { + required init(dictionary: [AnyHashable: Any]) { super.init(dictionary: dictionary) identifier = dictionary["imdb_id"] as! String @@ -26,23 +26,23 @@ class Show: BasicInfo { if let imagesDict = dictionary["images"] as? NSDictionary { images = [Image]() if let banner = imagesDict["banner"] as? String { - let URL = NSURL(string: thumbnail(banner)) - let image = Image(URL: URL!, type: .Banner) + let URL = Foundation.URL(string: thumbnail(banner)) + let image = Image(URL: URL!, type: .banner) images.append(image) } if let fanart = imagesDict["fanart"] as? String { - let URL = NSURL(string: thumbnail(fanart)) - let image = Image(URL: URL!, type: .Fanart) + let URL = Foundation.URL(string: thumbnail(fanart)) + let image = Image(URL: URL!, type: .fanart) images.append(image) } if let poster = imagesDict["poster"] as? String { - let URL = NSURL(string: thumbnail(poster)) - let image = Image(URL: URL!, type: .Poster) + let URL = Foundation.URL(string: thumbnail(poster)) + let image = Image(URL: URL!, type: .poster) images.append(image) } - smallImage = images.filter({$0.type == ImageType.Poster}).first - bigImage = images.filter({$0.type == ImageType.Fanart}).first + smallImage = images.filter({$0.type == ImageType.poster}).first + bigImage = images.filter({$0.type == ImageType.fanart}).first } } @@ -50,37 +50,38 @@ class Show: BasicInfo { super.init(coder: aDecoder)! } - override func update(dictionary: NSDictionary) { + override func update(_ dictionary: [AnyHashable: Any]) { synopsis = dictionary["synopsis"] as? String - seasons.removeAll(keepCapacity: true) + seasons.removeAll(keepingCapacity: true) var allEpisodes = [Episode]() var allSeasonsNumbers = [UInt:Bool]() - let episodesDicts = dictionary["episodes"] as! [NSDictionary]! - for episodeDict in episodesDicts{ + guard let episodesDicts = dictionary["episodes"] as? [[AnyHashable: Any]] else { return } + for episodeDict in episodesDicts { var videos = [Video]() - let torrents = episodeDict["torrents"] as! [String : NSDictionary] - for torrent in torrents{ - let quality = torrent.0 - if quality == "0" { - continue + if let torrents = episodeDict["torrents"] as? [String : NSDictionary] { + for torrent in torrents { + let quality = torrent.0 + if quality == "0" { + continue + } + + let url = torrent.1["url"] as! String + + let video = Video(name: nil, quality: quality, size: 0, duration: 0, subGroup: nil, magnetLink: url) + videos.append(video) } - - let url = torrent.1["url"] as! String - - let video = Video(name: nil, quality: quality, size: 0, duration: 0, subGroup: nil, magnetLink: url) - videos.append(video) } - videos = videos.sort({ (a, b) -> Bool in + videos = videos.sorted(by: { (a, b) -> Bool in var aQuality: Int = 0 - NSScanner(string: a.quality!).scanInteger(&aQuality) + Scanner(string: a.quality!).scanInt(&aQuality) var bQuality: Int = 0 - NSScanner(string: b.quality!).scanInteger(&bQuality) + Scanner(string: b.quality!).scanInt(&bQuality) return aQuality < bQuality }) @@ -99,7 +100,7 @@ class Show: BasicInfo { } var seasonsNumbers = Array(allSeasonsNumbers.keys) - seasonsNumbers.sortInPlace({ (a, b) -> Bool in + seasonsNumbers.sort(by: { (a, b) -> Bool in return a < b }) @@ -117,12 +118,12 @@ class Show: BasicInfo { } extension Show: ContainsEpisodes { - func episodeFor(seasonIndex seasonIndex: Int, episodeIndex: Int) -> Episode { + func episodeFor(seasonIndex: Int, episodeIndex: Int) -> Episode { let episode = seasons[seasonIndex].episodes[episodeIndex] return episode } - func episodesFor(seasonIndex seasonIndex: Int) -> [Episode] { + func episodesFor(seasonIndex: Int) -> [Episode] { return seasons[seasonIndex].episodes } } diff --git a/PopcornTime/Resources/Images.xcassets/AppIcon.appiconset/Contents.json b/PopcornTime/Resources/Images.xcassets/AppIcon.appiconset/Contents.json index bea1e07..113d7cb 100644 --- a/PopcornTime/Resources/Images.xcassets/AppIcon.appiconset/Contents.json +++ b/PopcornTime/Resources/Images.xcassets/AppIcon.appiconset/Contents.json @@ -1,5 +1,15 @@ { "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, { "idiom" : "iphone", "size" : "29x29", @@ -31,6 +41,16 @@ "size" : "60x60", "scale" : "3x" }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" + }, { "idiom" : "ipad", "size" : "29x29", diff --git a/PopcornTime/Views/ShowCollectionViewCell.swift b/PopcornTime/Views/ShowCollectionViewCell.swift index 9536773..de2079e 100644 --- a/PopcornTime/Views/ShowCollectionViewCell.swift +++ b/PopcornTime/Views/ShowCollectionViewCell.swift @@ -10,13 +10,13 @@ import UIKit class ShowCollectionViewCell: UICollectionViewCell { - @IBOutlet weak private var imageView: UIImageView! - @IBOutlet weak private var titleLabel: UILabel! + @IBOutlet weak fileprivate var imageView: UIImageView! + @IBOutlet weak fileprivate var titleLabel: UILabel! var image: UIImage? { didSet { self.imageView?.image = image - self.titleLabel.hidden = image != nil + self.titleLabel.isHidden = image != nil } } diff --git a/PopcornTime/Views/StratchyHeader.swift b/PopcornTime/Views/StratchyHeader.swift index be5d011..1a2040c 100644 --- a/PopcornTime/Views/StratchyHeader.swift +++ b/PopcornTime/Views/StratchyHeader.swift @@ -10,7 +10,7 @@ import UIKit protocol StratchyHeaderDelegate: class { ///Triggers when header max stratch value is recalculated - func stratchyHeader(header: StratchyHeader, didResetMaxStratchValue value: CGFloat) + func stratchyHeader(_ header: StratchyHeader, didResetMaxStratchValue value: CGFloat) } @@ -37,8 +37,8 @@ class StratchyHeader: UICollectionReusableView { } // MARK: - UICollectionReusableView - override func applyLayoutAttributes(layoutAttributes: UICollectionViewLayoutAttributes) { - super.applyLayoutAttributes(layoutAttributes) + override func apply(_ layoutAttributes: UICollectionViewLayoutAttributes) { + super.apply(layoutAttributes) let attributes = layoutAttributes as! StratchyLayoutAttributes @@ -59,33 +59,33 @@ class StratchyHeader: UICollectionReusableView { } // MARK: - Private - @IBOutlet weak private var widthConstraint: NSLayoutConstraint! - @IBOutlet weak private var heightConstraint: NSLayoutConstraint! - @IBOutlet weak private var backgroundImageView: UIImageView! + @IBOutlet weak fileprivate var widthConstraint: NSLayoutConstraint! + @IBOutlet weak fileprivate var heightConstraint: NSLayoutConstraint! + @IBOutlet weak fileprivate var backgroundImageView: UIImageView! @IBOutlet weak var foregroundView: UIView! @IBOutlet weak var foregroundImage: UIImageView! @IBOutlet weak var synopsisTextView: UILabel! - private var maxStratch: CGFloat = 0 + fileprivate var maxStratch: CGFloat = 0 - private var zoomWidthCoef: CGFloat { + fileprivate var zoomWidthCoef: CGFloat { get { let headerAspectRatio = headerSize.height / headerSize.width return (1.7 * headerAspectRatio) / 0.5325 // Experimentally calculated value :] } } - private var imageAspectRatio: CGFloat = 0 - private var imageViewActualWidth: CGFloat { + fileprivate var imageAspectRatio: CGFloat = 0 + fileprivate var imageViewActualWidth: CGFloat { return headerSize.width * zoomWidthCoef } - private var imageViewActualHeight: CGFloat { + fileprivate var imageViewActualHeight: CGFloat { return imageViewActualWidth * imageAspectRatio } - private var previousHeight: CGFloat = 0 + fileprivate var previousHeight: CGFloat = 0 - private func updateImageViewConstraints() { + fileprivate func updateImageViewConstraints() { // let dX = fabs(headerSize.height - imageViewActualHeight)/2 let dY = fabs(headerSize.width - imageViewActualWidth)/2 diff --git a/PopcornTime/Views/StratchyHeaderLayout.swift b/PopcornTime/Views/StratchyHeaderLayout.swift index b5e3e06..1d2c643 100644 --- a/PopcornTime/Views/StratchyHeaderLayout.swift +++ b/PopcornTime/Views/StratchyHeaderLayout.swift @@ -11,15 +11,15 @@ import UIKit class StratchyLayoutAttributes: UICollectionViewLayoutAttributes { var deltaY: CGFloat = 0 - var maxDelta: CGFloat = CGFloat.max + var maxDelta: CGFloat = CGFloat.greatestFiniteMagnitude - override func copyWithZone(zone: NSZone) -> AnyObject { - let copy = super.copyWithZone(zone) as! StratchyLayoutAttributes + override func copy(with zone: NSZone?) -> Any { + let copy = super.copy(with: zone) as! StratchyLayoutAttributes copy.deltaY = deltaY return copy } - override func isEqual(object: AnyObject?) -> Bool { + override func isEqual(_ object: Any?) -> Bool { if let attributes = object as? StratchyLayoutAttributes { if attributes.deltaY == deltaY { return super.isEqual(object) @@ -31,16 +31,16 @@ class StratchyLayoutAttributes: UICollectionViewLayoutAttributes { class StratchyHeaderLayout: UICollectionViewFlowLayout, StratchyHeaderDelegate { - var headerSize = CGSizeZero - var maxDelta: CGFloat = CGFloat.max + var headerSize = CGSize.zero + var maxDelta: CGFloat = CGFloat.greatestFiniteMagnitude let minCellWidth: CGFloat = 300 let cellAspectRatio: CGFloat = 370/46 - override class func layoutAttributesClass() -> AnyClass { + override class var layoutAttributesClass : AnyClass { return StratchyLayoutAttributes.self } - override func collectionViewContentSize() -> CGSize { + override var collectionViewContentSize : CGSize { sectionInset.bottom = 15.0 sectionInset.top = 5.0 @@ -51,22 +51,22 @@ class StratchyHeaderLayout: UICollectionViewFlowLayout, StratchyHeaderDelegate { let numberOfColumns = Int(width / minCellWidth) let cellWidth = CGFloat((Int(width) - Int(minimumInteritemSpacing) * (numberOfColumns - 1)) / numberOfColumns) let cellHeight = cellWidth / cellAspectRatio - self.itemSize = CGSizeMake(cellWidth, cellHeight) + self.itemSize = CGSize(width: cellWidth, height: cellHeight) - return super.collectionViewContentSize() + return super.collectionViewContentSize } - override func shouldInvalidateLayoutForBoundsChange(newBounds: CGRect) -> Bool { + override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool { return true } - override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? { + override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? { let insets = collectionView!.contentInset let offset = collectionView!.contentOffset let minY = -insets.top - let attributes = super.layoutAttributesForElementsInRect(rect) + let attributes = super.layoutAttributesForElements(in: rect) if let stratchyAttributes = attributes as? [StratchyLayoutAttributes] { // Check if we've pulled below past the lowest position @@ -79,7 +79,7 @@ class StratchyHeaderLayout: UICollectionViewFlowLayout, StratchyHeaderDelegate { if (kind == UICollectionElementKindSectionHeader) { var headerRect = attribute.frame headerRect.size.height = min(headerSize.height + maxDelta, max(minY, headerSize.height + deltaY)); - headerRect.origin.y = CGRectGetMinY(headerRect) - deltaY; + headerRect.origin.y = headerRect.minY - deltaY; attribute.frame = headerRect attribute.deltaY = deltaY attribute.maxDelta = maxDelta @@ -94,7 +94,7 @@ class StratchyHeaderLayout: UICollectionViewFlowLayout, StratchyHeaderDelegate { } // MARK: - StratchyHeaderDelegate - func stratchyHeader(header: StratchyHeader, didResetMaxStratchValue value: CGFloat) { + func stratchyHeader(_ header: StratchyHeader, didResetMaxStratchValue value: CGFloat) { maxDelta = value }