Merge branch 'feature/ios11' into develop
This commit is contained in:
commit
c16562c8ca
@ -1,11 +1,11 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12120" systemVersion="16E195" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="SPq-Bk-fQl">
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13196" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="SPq-Bk-fQl">
|
||||||
<device id="retina4_7" orientation="portrait">
|
<device id="retina4_7" orientation="portrait">
|
||||||
<adaptation id="fullscreen"/>
|
<adaptation id="fullscreen"/>
|
||||||
</device>
|
</device>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="iOS"/>
|
<deployment identifier="iOS"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12088"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13173"/>
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<scenes>
|
<scenes>
|
||||||
@ -31,8 +31,8 @@
|
|||||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="trailing" secondItem="tmn-gd-5UN" secondAttribute="trailing" id="9Rq-HM-vqk"/>
|
<constraint firstAttribute="trailing" secondItem="tmn-gd-5UN" secondAttribute="trailing" id="9Rq-HM-vqk"/>
|
||||||
<constraint firstItem="0om-QB-N5a" firstAttribute="top" secondItem="tmn-gd-5UN" secondAttribute="bottom" id="DV5-hh-1VN"/>
|
|
||||||
<constraint firstItem="tmn-gd-5UN" firstAttribute="leading" secondItem="3Bk-k3-7J9" secondAttribute="leading" id="f1f-sa-dBA"/>
|
<constraint firstItem="tmn-gd-5UN" firstAttribute="leading" secondItem="3Bk-k3-7J9" secondAttribute="leading" id="f1f-sa-dBA"/>
|
||||||
|
<constraint firstAttribute="bottom" secondItem="tmn-gd-5UN" secondAttribute="bottom" id="ifM-Wa-u9y"/>
|
||||||
<constraint firstItem="tmn-gd-5UN" firstAttribute="top" secondItem="3Bk-k3-7J9" secondAttribute="top" id="nhS-aC-rUR"/>
|
<constraint firstItem="tmn-gd-5UN" firstAttribute="top" secondItem="3Bk-k3-7J9" secondAttribute="top" id="nhS-aC-rUR"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
</view>
|
</view>
|
||||||
@ -57,7 +57,7 @@
|
|||||||
<scene sceneID="qNA-NP-TiF">
|
<scene sceneID="qNA-NP-TiF">
|
||||||
<objects>
|
<objects>
|
||||||
<collectionViewController storyboardIdentifier="gameCollectionViewController" clearsSelectionOnViewWillAppear="NO" id="kqu-75-owz" customClass="GameCollectionViewController" customModule="Delta" customModuleProvider="target" sceneMemberID="viewController">
|
<collectionViewController storyboardIdentifier="gameCollectionViewController" clearsSelectionOnViewWillAppear="NO" id="kqu-75-owz" customClass="GameCollectionViewController" customModule="Delta" customModuleProvider="target" sceneMemberID="viewController">
|
||||||
<collectionView key="view" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="prototypes" id="OIq-Z8-kxO">
|
<collectionView key="view" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" indicatorStyle="white" dataMode="prototypes" id="OIq-Z8-kxO">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
@ -183,12 +183,11 @@
|
|||||||
<toolbarItems/>
|
<toolbarItems/>
|
||||||
<nil key="simulatedBottomBarMetrics"/>
|
<nil key="simulatedBottomBarMetrics"/>
|
||||||
<navigationBar key="navigationBar" contentMode="scaleToFill" id="wj9-1e-eev">
|
<navigationBar key="navigationBar" contentMode="scaleToFill" id="wj9-1e-eev">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
<rect key="frame" x="0.0" y="20" width="375" height="44"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
</navigationBar>
|
</navigationBar>
|
||||||
<nil name="viewControllers"/>
|
<nil name="viewControllers"/>
|
||||||
<toolbar key="toolbar" opaque="NO" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="M4r-sO-G4H">
|
<toolbar key="toolbar" opaque="NO" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="M4r-sO-G4H">
|
||||||
<rect key="frame" x="0.0" y="556" width="600" height="44"/>
|
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
</toolbar>
|
</toolbar>
|
||||||
<connections>
|
<connections>
|
||||||
@ -213,7 +212,7 @@
|
|||||||
<navigationController storyboardIdentifier="saveStatesNavigationController" automaticallyAdjustsScrollViewInsets="NO" id="MPk-bF-nkj" sceneMemberID="viewController">
|
<navigationController storyboardIdentifier="saveStatesNavigationController" automaticallyAdjustsScrollViewInsets="NO" id="MPk-bF-nkj" sceneMemberID="viewController">
|
||||||
<toolbarItems/>
|
<toolbarItems/>
|
||||||
<navigationBar key="navigationBar" contentMode="scaleToFill" id="twH-3X-6DV">
|
<navigationBar key="navigationBar" contentMode="scaleToFill" id="twH-3X-6DV">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
|
<rect key="frame" x="0.0" y="20" width="375" height="44"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
</navigationBar>
|
</navigationBar>
|
||||||
<nil name="viewControllers"/>
|
<nil name="viewControllers"/>
|
||||||
|
|||||||
@ -504,10 +504,12 @@ extension GameCollectionViewController: SaveStatesViewControllerDelegate
|
|||||||
/// ImportControllerDelegate
|
/// ImportControllerDelegate
|
||||||
extension GameCollectionViewController: ImportControllerDelegate
|
extension GameCollectionViewController: ImportControllerDelegate
|
||||||
{
|
{
|
||||||
func importController(_ importController: ImportController, didImportItemsAt urls: Set<URL>)
|
func importController(_ importController: ImportController, didImportItemsAt urls: Set<URL>, errors: [Error])
|
||||||
{
|
{
|
||||||
guard let game = self._changingArtworkGame else { return }
|
guard let game = self._changingArtworkGame else { return }
|
||||||
|
|
||||||
|
var errors = errors
|
||||||
|
|
||||||
var imageURL: URL?
|
var imageURL: URL?
|
||||||
|
|
||||||
if let url = urls.first
|
if let url = urls.first
|
||||||
@ -533,7 +535,7 @@ extension GameCollectionViewController: ImportControllerDelegate
|
|||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
print(error)
|
errors.append(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -542,6 +544,11 @@ extension GameCollectionViewController: ImportControllerDelegate
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for error in errors
|
||||||
|
{
|
||||||
|
print(error)
|
||||||
|
}
|
||||||
|
|
||||||
if let imageURL = imageURL
|
if let imageURL = imageURL
|
||||||
{
|
{
|
||||||
// Remove previous artwork from cache.
|
// Remove previous artwork from cache.
|
||||||
|
|||||||
@ -109,11 +109,15 @@ extension GamesViewController
|
|||||||
{
|
{
|
||||||
super.viewDidLayoutSubviews()
|
super.viewDidLayoutSubviews()
|
||||||
|
|
||||||
if let viewControllers = self.pageViewController.viewControllers as? [GameCollectionViewController]
|
if #available(iOS 11.0, *) {}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
for viewController in viewControllers
|
if let viewControllers = self.pageViewController.viewControllers as? [GameCollectionViewController]
|
||||||
{
|
{
|
||||||
viewController.collectionView?.contentInset.top = self.topLayoutGuide.length
|
for viewController in viewControllers
|
||||||
|
{
|
||||||
|
viewController.collectionView?.contentInset.top = self.topLayoutGuide.length
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -190,8 +194,12 @@ private extension GamesViewController
|
|||||||
viewController.theme = self.theme
|
viewController.theme = self.theme
|
||||||
viewController.activeEmulatorCore = self.activeEmulatorCore
|
viewController.activeEmulatorCore = self.activeEmulatorCore
|
||||||
|
|
||||||
// Need to set content inset here AND willTransitionTo callback to ensure its correct for all edge cases
|
if #available(iOS 11.0, *) {}
|
||||||
viewController.collectionView?.contentInset.top = self.topLayoutGuide.length
|
else
|
||||||
|
{
|
||||||
|
// Need to set content inset here AND willTransitionTo callback to ensure its correct for all edge cases
|
||||||
|
viewController.collectionView?.contentInset.top = self.topLayoutGuide.length
|
||||||
|
}
|
||||||
|
|
||||||
return viewController
|
return viewController
|
||||||
}
|
}
|
||||||
@ -283,8 +291,13 @@ extension GamesViewController: ImportControllerDelegate
|
|||||||
self.present(importController, animated: true, completion: nil)
|
self.present(importController, animated: true, completion: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func importController(_ importController: ImportController, didImportItemsAt urls: Set<URL>)
|
func importController(_ importController: ImportController, didImportItemsAt urls: Set<URL>, errors: [Error])
|
||||||
{
|
{
|
||||||
|
for error in errors
|
||||||
|
{
|
||||||
|
print(error)
|
||||||
|
}
|
||||||
|
|
||||||
let gameURLs = urls.filter { $0.pathExtension.lowercased() != "deltaskin" }
|
let gameURLs = urls.filter { $0.pathExtension.lowercased() != "deltaskin" }
|
||||||
DatabaseManager.shared.importGames(at: Set(gameURLs)) { (games, errors) in
|
DatabaseManager.shared.importGames(at: Set(gameURLs)) { (games, errors) in
|
||||||
if errors.count > 0
|
if errors.count > 0
|
||||||
@ -361,9 +374,13 @@ extension GamesViewController: UIPageViewControllerDataSource, UIPageViewControl
|
|||||||
{
|
{
|
||||||
guard let viewControllers = pendingViewControllers as? [GameCollectionViewController] else { return }
|
guard let viewControllers = pendingViewControllers as? [GameCollectionViewController] else { return }
|
||||||
|
|
||||||
for viewController in viewControllers
|
if #available(iOS 11.0, *) {}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
viewController.collectionView?.contentInset.top = self.topLayoutGuide.length
|
for viewController in viewControllers
|
||||||
|
{
|
||||||
|
viewController.collectionView?.contentInset.top = self.topLayoutGuide.length
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -16,7 +16,7 @@ import Roxas
|
|||||||
|
|
||||||
protocol ImportControllerDelegate
|
protocol ImportControllerDelegate
|
||||||
{
|
{
|
||||||
func importController(_ importController: ImportController, didImportItemsAt urls: Set<URL>)
|
func importController(_ importController: ImportController, didImportItemsAt urls: Set<URL>, errors: [Error])
|
||||||
|
|
||||||
/** Optional **/
|
/** Optional **/
|
||||||
func importControllerDidCancel(_ importController: ImportController)
|
func importControllerDidCancel(_ importController: ImportController)
|
||||||
@ -37,63 +37,91 @@ class ImportController: NSObject
|
|||||||
var delegate: ImportControllerDelegate?
|
var delegate: ImportControllerDelegate?
|
||||||
var importOptions: [ImportOption]?
|
var importOptions: [ImportOption]?
|
||||||
|
|
||||||
|
fileprivate weak var presentingViewController: UIViewController?
|
||||||
|
|
||||||
|
// Store presentedViewController separately, since when we dismiss we don't know if it has already been dismissed.
|
||||||
|
// Calling dismiss on presentingViewController in that case would dismiss presentingViewController, which is bad.
|
||||||
|
fileprivate weak var presentedViewController: UIViewController?
|
||||||
|
|
||||||
|
fileprivate let importQueue: OperationQueue
|
||||||
|
fileprivate let fileCoordinator: NSFileCoordinator
|
||||||
|
|
||||||
init(documentTypes: Set<String>)
|
init(documentTypes: Set<String>)
|
||||||
{
|
{
|
||||||
self.documentTypes = documentTypes
|
self.documentTypes = documentTypes
|
||||||
|
|
||||||
|
let dispatchQueue = DispatchQueue(label: "com.rileytestut.Delta.ImportController.dispatchQueue", qos: .userInitiated, attributes: .concurrent)
|
||||||
|
|
||||||
|
self.importQueue = OperationQueue()
|
||||||
|
self.importQueue.name = "com.rileytestut.Delta.ImportController.importQueue"
|
||||||
|
self.importQueue.underlyingQueue = dispatchQueue
|
||||||
|
|
||||||
|
self.fileCoordinator = NSFileCoordinator(filePresenter: nil)
|
||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
}
|
}
|
||||||
|
|
||||||
fileprivate weak var presentingViewController: UIViewController?
|
|
||||||
|
|
||||||
fileprivate func presentImportController(from presentingViewController: UIViewController, animated: Bool, completionHandler: ((Void) -> Void)?)
|
fileprivate func presentImportController(from presentingViewController: UIViewController, animated: Bool, completionHandler: ((Void) -> Void)?)
|
||||||
{
|
{
|
||||||
self.presentingViewController = presentingViewController
|
self.presentingViewController = presentingViewController
|
||||||
|
|
||||||
#if IMPACTOR
|
#if IMPACTOR
|
||||||
|
|
||||||
let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
|
let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
|
||||||
alertController.addAction(UIAlertAction.cancel)
|
alertController.addAction(UIAlertAction.cancel)
|
||||||
|
|
||||||
if let importOptions = self.importOptions
|
if let importOptions = self.importOptions
|
||||||
{
|
|
||||||
for importOption in importOptions
|
|
||||||
{
|
{
|
||||||
alertController.add(importOption, completionHandler: finish(with:))
|
for importOption in importOptions
|
||||||
|
{
|
||||||
|
alertController.add(importOption) { [unowned self] (urls) in
|
||||||
|
self.finish(with: urls, errors: [])
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
self.presentedViewController = alertController
|
||||||
self.presentingViewController?.present(alertController, animated: true, completion: nil)
|
self.presentingViewController?.present(alertController, animated: true, completion: nil)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
let documentMenuController = UIDocumentMenuViewController(documentTypes: Array(self.documentTypes), in: .import)
|
let documentMenuController = UIDocumentMenuViewController(documentTypes: Array(self.documentTypes), in: .import)
|
||||||
documentMenuController.delegate = self
|
documentMenuController.delegate = self
|
||||||
|
|
||||||
if let reversedImportOptions = self.importOptions?.reversed()
|
if let reversedImportOptions = self.importOptions?.reversed()
|
||||||
{
|
|
||||||
for importOption in reversedImportOptions
|
|
||||||
{
|
{
|
||||||
documentMenuController.add(importOption, order: .first, completionHandler: finish(with:))
|
for importOption in reversedImportOptions
|
||||||
|
{
|
||||||
|
documentMenuController.add(importOption, order: .first) { [unowned self] (urls) in
|
||||||
|
self.finish(with: urls, errors: [])
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
self.presentedViewController = documentMenuController
|
||||||
self.presentingViewController?.present(documentMenuController, animated: true, completion: nil)
|
self.presentingViewController?.present(documentMenuController, animated: true, completion: nil)
|
||||||
#endif
|
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
fileprivate func finish(with urls: Set<URL>?)
|
@objc fileprivate func cancel()
|
||||||
|
{
|
||||||
|
self.finish(with: nil, errors: [])
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate func finish(with urls: Set<URL>?, errors: [Error])
|
||||||
{
|
{
|
||||||
if let urls = urls
|
if let urls = urls
|
||||||
{
|
{
|
||||||
self.delegate?.importController(self, didImportItemsAt: urls)
|
self.delegate?.importController(self, didImportItemsAt: urls, errors: errors)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
self.delegate?.importControllerDidCancel(self)
|
self.delegate?.importControllerDidCancel(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.presentedViewController?.dismiss(animated: true)
|
||||||
|
|
||||||
self.presentingViewController?.importController = nil
|
self.presentingViewController?.importController = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -103,13 +131,32 @@ extension ImportController: UIDocumentMenuDelegate
|
|||||||
{
|
{
|
||||||
func documentMenu(_ documentMenu: UIDocumentMenuViewController, didPickDocumentPicker documentPicker: UIDocumentPickerViewController)
|
func documentMenu(_ documentMenu: UIDocumentMenuViewController, didPickDocumentPicker documentPicker: UIDocumentPickerViewController)
|
||||||
{
|
{
|
||||||
documentPicker.delegate = self
|
if #available(iOS 11.0, *)
|
||||||
self.presentingViewController?.present(documentPicker, animated: true, completion: nil)
|
{
|
||||||
|
let cancelButton = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(ImportController.cancel))
|
||||||
|
|
||||||
|
let documentBrowserViewController = UIDocumentBrowserViewController(forOpeningFilesWithContentTypes: Array(self.documentTypes))
|
||||||
|
documentBrowserViewController.delegate = self
|
||||||
|
documentBrowserViewController.browserUserInterfaceStyle = .dark
|
||||||
|
documentBrowserViewController.allowsPickingMultipleItems = true
|
||||||
|
documentBrowserViewController.allowsDocumentCreation = false
|
||||||
|
documentBrowserViewController.additionalTrailingNavigationBarButtonItems = [cancelButton]
|
||||||
|
|
||||||
|
self.presentedViewController = documentBrowserViewController
|
||||||
|
self.presentingViewController?.present(documentBrowserViewController, animated: true, completion: nil)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
documentPicker.delegate = self
|
||||||
|
|
||||||
|
self.presentedViewController = documentPicker
|
||||||
|
self.presentingViewController?.present(documentPicker, animated: true, completion: nil)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func documentMenuWasCancelled(_ documentMenu: UIDocumentMenuViewController)
|
func documentMenuWasCancelled(_ documentMenu: UIDocumentMenuViewController)
|
||||||
{
|
{
|
||||||
self.finish(with: nil)
|
self.finish(with: nil, errors: [])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,15 +164,66 @@ extension ImportController: UIDocumentPickerDelegate
|
|||||||
{
|
{
|
||||||
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL)
|
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL)
|
||||||
{
|
{
|
||||||
self.finish(with: [url])
|
self.finish(with: [url], errors: [])
|
||||||
|
}
|
||||||
|
|
||||||
|
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL])
|
||||||
|
{
|
||||||
|
self.finish(with: Set(urls), errors: [])
|
||||||
}
|
}
|
||||||
|
|
||||||
func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController)
|
func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController)
|
||||||
{
|
{
|
||||||
self.finish(with: nil)
|
self.finish(with: nil, errors: [])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@available(iOS 11.0, *)
|
||||||
|
extension ImportController: UIDocumentBrowserViewControllerDelegate
|
||||||
|
{
|
||||||
|
func documentBrowser(_ controller: UIDocumentBrowserViewController, didPickDocumentURLs documentURLs: [URL])
|
||||||
|
{
|
||||||
|
var coordinatedURLs = Set<URL>()
|
||||||
|
var errors = [Error]()
|
||||||
|
|
||||||
|
let dispatchGroup = DispatchGroup()
|
||||||
|
|
||||||
|
for url in documentURLs
|
||||||
|
{
|
||||||
|
dispatchGroup.enter()
|
||||||
|
|
||||||
|
let intent = NSFileAccessIntent.readingIntent(with: url)
|
||||||
|
self.fileCoordinator.coordinate(with: [intent], queue: self.importQueue) { (error) in
|
||||||
|
if let error = error
|
||||||
|
{
|
||||||
|
errors.append(error)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
let temporaryURL = FileManager.default.temporaryDirectory.appendingPathComponent(url.lastPathComponent)
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
// Always access intent.url, as the system may have updated it when requesting access.
|
||||||
|
try FileManager.default.copyItem(at: intent.url, to: temporaryURL)
|
||||||
|
|
||||||
|
coordinatedURLs.insert(temporaryURL)
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
errors.append(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatchGroup.leave()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatchGroup.notify(queue: self.importQueue.underlyingQueue!) {
|
||||||
|
self.finish(with: coordinatedURLs, errors: errors)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private var ImportControllerKey: UInt8 = 0
|
private var ImportControllerKey: UInt8 = 0
|
||||||
|
|
||||||
|
|||||||
@ -17,13 +17,17 @@ protocol PauseInfoProviding
|
|||||||
|
|
||||||
class PausePresentationController: UIPresentationController
|
class PausePresentationController: UIPresentationController
|
||||||
{
|
{
|
||||||
|
let presentationAnimator: UIViewPropertyAnimator
|
||||||
|
|
||||||
private let blurringView: UIVisualEffectView
|
private let blurringView: UIVisualEffectView
|
||||||
private let vibrancyView: UIVisualEffectView
|
private let vibrancyView: UIVisualEffectView
|
||||||
|
|
||||||
private var contentView: UIView!
|
private var contentView: UIView!
|
||||||
@IBOutlet private weak var pauseLabel: UILabel!
|
|
||||||
@IBOutlet private weak var pauseIconImageView: UIImageView!
|
// Must not be weak, or else may result in crash when deallocating.
|
||||||
@IBOutlet private weak var stackView: UIStackView!
|
@IBOutlet private var pauseLabel: UILabel!
|
||||||
|
@IBOutlet private var pauseIconImageView: UIImageView!
|
||||||
|
@IBOutlet private var stackView: UIStackView!
|
||||||
|
|
||||||
override var frameOfPresentedViewInContainerView: CGRect
|
override var frameOfPresentedViewInContainerView: CGRect
|
||||||
{
|
{
|
||||||
@ -45,8 +49,10 @@ class PausePresentationController: UIPresentationController
|
|||||||
return frame
|
return frame
|
||||||
}
|
}
|
||||||
|
|
||||||
override init(presentedViewController: UIViewController, presenting presentingViewController: UIViewController?)
|
init(presentedViewController: UIViewController, presenting presentingViewController: UIViewController?, presentationAnimator: UIViewPropertyAnimator)
|
||||||
{
|
{
|
||||||
|
self.presentationAnimator = presentationAnimator
|
||||||
|
|
||||||
self.blurringView = UIVisualEffectView(effect: nil)
|
self.blurringView = UIVisualEffectView(effect: nil)
|
||||||
self.vibrancyView = UIVisualEffectView(effect: nil)
|
self.vibrancyView = UIVisualEffectView(effect: nil)
|
||||||
|
|
||||||
@ -83,16 +89,18 @@ class PausePresentationController: UIPresentationController
|
|||||||
self.contentView.alpha = 0.0
|
self.contentView.alpha = 0.0
|
||||||
self.vibrancyView.contentView.addSubview(self.contentView)
|
self.vibrancyView.contentView.addSubview(self.contentView)
|
||||||
|
|
||||||
self.presentingViewController.transitionCoordinator?.animate(alongsideTransition: { context in
|
self.presentationAnimator.addAnimations {
|
||||||
|
|
||||||
let blurEffect = UIBlurEffect(style: .dark)
|
let blurEffect = UIBlurEffect(style: .dark)
|
||||||
|
|
||||||
self.blurringView.effect = blurEffect
|
self.blurringView.effect = blurEffect
|
||||||
self.vibrancyView.effect = UIVibrancyEffect(blurEffect: blurEffect)
|
self.vibrancyView.effect = UIVibrancyEffect(blurEffect: blurEffect)
|
||||||
|
|
||||||
self.contentView.alpha = 1.0
|
self.contentView.alpha = 1.0
|
||||||
|
}
|
||||||
}, completion: nil)
|
|
||||||
|
// I have absolutely no clue why animating with transition coordinator results in no animation on iOS 11.
|
||||||
|
// Spent far too long trying to fix it, so just use the presentation animator.
|
||||||
|
// self.presentingViewController.transitionCoordinator?.animate(alongsideTransition: { context in }, completion: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func dismissalTransitionWillBegin()
|
override func dismissalTransitionWillBegin()
|
||||||
|
|||||||
@ -18,7 +18,7 @@ class PauseStoryboardSegue: UIStoryboardSegue
|
|||||||
let timingParameters = UISpringTimingParameters(mass: 3.0, stiffness: 750, damping: 65, initialVelocity: CGVector(dx: 0, dy: 0))
|
let timingParameters = UISpringTimingParameters(mass: 3.0, stiffness: 750, damping: 65, initialVelocity: CGVector(dx: 0, dy: 0))
|
||||||
self.animator = UIViewPropertyAnimator(duration: 0, timingParameters: timingParameters)
|
self.animator = UIViewPropertyAnimator(duration: 0, timingParameters: timingParameters)
|
||||||
|
|
||||||
self.presentationController = PausePresentationController(presentedViewController: destination, presenting: source)
|
self.presentationController = PausePresentationController(presentedViewController: destination, presenting: source, presentationAnimator: self.animator)
|
||||||
|
|
||||||
super.init(identifier: identifier, source: source, destination: destination)
|
super.init(identifier: identifier, source: source, destination: destination)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -37,6 +37,13 @@ class PauseTransitionCoordinator: NSObject, UIViewControllerAnimatedTransitionin
|
|||||||
|
|
||||||
destinationViewController.view.layoutIfNeeded()
|
destinationViewController.view.layoutIfNeeded()
|
||||||
|
|
||||||
|
if let navigationController = destinationViewController.navigationController
|
||||||
|
{
|
||||||
|
// Layout before animation to prevent strange bar button item layout during animation.
|
||||||
|
navigationController.view.setNeedsLayout()
|
||||||
|
navigationController.view.layoutIfNeeded()
|
||||||
|
}
|
||||||
|
|
||||||
UIView.animate(withDuration: self.transitionDuration(using: transitionContext), delay:0, options:RSTSystemTransitionAnimationCurve, animations: {
|
UIView.animate(withDuration: self.transitionDuration(using: transitionContext), delay:0, options:RSTSystemTransitionAnimationCurve, animations: {
|
||||||
|
|
||||||
sourceViewController.view.frame.origin.y = self.presenting ? -sourceViewController.view.bounds.height : transitionContext.containerView.bounds.height
|
sourceViewController.view.frame.origin.y = self.presenting ? -sourceViewController.view.bounds.height : transitionContext.containerView.bounds.height
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user