Compare commits

...

5 Commits

Author SHA1 Message Date
Duraid Abdul a1275a7f49 Update LCManager.swift 2022-01-22 00:09:49 -08:00
Duraid Abdul e08d439d2b Various Improvements 2022-01-22 00:06:35 -08:00
Duraid Abdul da9d78f559 Merge branch 'main' of https://github.com/duraidabdul/LocalConsole 2022-01-21 12:47:53 -08:00
Duraid Abdul 50e4ce4e03 Update LCManager.swift 2022-01-21 12:47:50 -08:00
Duraid Abdul ae73be37b4 Update README.md 2022-01-17 12:08:39 -08:00
3 changed files with 124 additions and 35 deletions
+1 -1
View File
@@ -21,7 +21,7 @@ let consoleManager = LCManager.shared
```
## **Usage**
Once prepared, the localConsole can be used throughout your project.
Once prepared, the consoleManager can be used throughout your project.
```swift
// Activate the console view.
+97 -23
View File
@@ -532,12 +532,34 @@ public class LCManager: NSObject, UIGestureRecognizerDelegate {
}
}
var hasShortened = false
public var isCharacterLimitDisabled = false
public var isCharacterLimitWarningDisabled = false
/// Print items to the console view.
public func print(_ items: Any) {
if currentText == "" {
currentText = "\(items)"
let _currentText: String = {
if currentText == "" {
return "\(items)"
} else {
return currentText + "\n\(items)"
}
}()
// Cut down string if it exceeds 50,000 characters to keep text view running smoothly.
if _currentText.count > 50000 && !isCharacterLimitDisabled {
if !hasShortened && !isCharacterLimitWarningDisabled {
hasShortened = true
Swift.print("LocalConsole's content has exceeded 50,000 characters.\nTo maintain performance, LCManager cuts down the beginning of the printed content. To disable this behaviour, set LCManager.shared.isCharacterLimitDisabled to true.\nTo disable this warning, set LCManager.shared.isCharacterLimitWarningDisabled = true.")
}
let shortenedString = String(_currentText.suffix(50000))
currentText = shortenedString.stringAfterFirstOccurenceOf(delimiter: "\n") ?? shortenedString
} else {
currentText = currentText + "\n\(items)"
currentText = _currentText
}
}
@@ -867,12 +889,15 @@ public class LCManager: NSObject, UIGestureRecognizerDelegate {
}
}
let consolePiPPanner_frameRateRequest = FrameRateRequest()
var consolePiPPanner_frameRateRequestID: UUID?
@objc func consolePiPPanner(recognizer: UIPanGestureRecognizer) {
if recognizer.state == .began {
consolePiPPanner_frameRateRequest.isActive = true
if #available(iOS 15, *) {
consolePiPPanner_frameRateRequestID = UUID()
FrameRateRequest.shared.activate(id: consolePiPPanner_frameRateRequestID!)
}
initialViewLocation = consoleView.center
}
@@ -894,8 +919,12 @@ public class LCManager: NSObject, UIGestureRecognizerDelegate {
case .ended, .cancelled:
consolePiPPanner_frameRateRequest.isActive = false
FrameRateRequest().perform(duration: 0.5)
if #available(iOS 15, *), let id = consolePiPPanner_frameRateRequestID {
consolePiPPanner_frameRateRequestID = nil
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
FrameRateRequest.shared.deactivate(id: id)
}
}
// After the PiP is thrown, determine the best corner and re-target it there.
let decelerationRate = UIScrollView.DecelerationRate.normal.rawValue
@@ -1134,7 +1163,7 @@ class InvertedTextView: UITextView {
var pendingOffsetChange = false
// Thanks to WWDC21 Lab!
// Thanks to WWDC21 UIKit Lab!
override func layoutSubviews() {
super.layoutSubviews()
@@ -1166,6 +1195,14 @@ extension UIDevice {
}
}
extension String {
func stringAfterFirstOccurenceOf(delimiter: String) -> String? {
guard let upperIndex = (self.range(of: delimiter)?.upperBound) else { return nil }
let trailingString: String = .init(self.suffix(from: upperIndex))
return trailingString
}
}
extension TimeInterval {
var formattedString: String? {
let formatter = DateComponentsFormatter()
@@ -1249,40 +1286,77 @@ An object that allows you to manually request an increased display refresh rate
```
// Example
let request = FrameRateRequest(preferredFrameRate: 120,
duration: 0.4)
FrameRateRequest.shared.perform(duration: 0.5)
request.perform()
```
*/
class FrameRateRequest {
@available(iOS 15, *)
final class FrameRateRequest {
static let shared = FrameRateRequest()
lazy private var displayLink = CADisplayLink(target: self, selector: #selector(dummyFunction))
var isActive: Bool = false {
private var requestIdentifiers: [UUID] = [] {
didSet {
guard #available(iOS 15, *) else { return }
guard isActive != oldValue else { return }
isActive = requestIdentifiers.count > 0
}
}
private var isActive: Bool = false {
didSet {
guard isActive != oldValue, UIScreen.main.maximumFramesPerSecond > 60 else { return }
if isActive {
displayLink.add(to: .current, forMode: .common)
} else {
displayLink.remove(from: .current, forMode: .common)
displayLink.invalidate()
}
}
}
/// Prepares your frame rate request parameters.
init(preferredFrameRate: Float = Float(UIScreen.main.maximumFramesPerSecond)) {
if #available(iOS 15, *) {
displayLink.preferredFrameRateRange = CAFrameRateRange(minimum: 30, maximum: Float(UIScreen.main.maximumFramesPerSecond), preferred: preferredFrameRate)
}
private init() {
guard UIScreen.main.maximumFramesPerSecond > 60 else { return }
displayLink.preferredFrameRateRange = CAFrameRateRange(minimum: 90, maximum: Float(UIScreen.main.maximumFramesPerSecond), preferred: Float(UIScreen.main.maximumFramesPerSecond))
// Ensure the DisplayLink stops when the app enters the background, or else the system will shut high frame rate capabilities until the app is suspended and relaunched.
NotificationCenter.default.addObserver(self, selector: #selector(willEnterForeground),
name: UIApplication.willEnterForegroundNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(didEnterBackground),
name: UIApplication.didEnterBackgroundNotification, object: nil)
}
/// Perform frame rate request.
func perform(duration: Double) {
isActive = true
public func perform(duration: Double) {
guard UIScreen.main.maximumFramesPerSecond > 60 else { return }
let id = UUID()
requestIdentifiers.append(id)
DispatchQueue.main.asyncAfter(deadline: .now() + duration) { [self] in
isActive = false
requestIdentifiers = requestIdentifiers.filter { $0 != id }
}
}
public func activate(id: UUID) {
requestIdentifiers.append(id)
}
public func deactivate(id: UUID) {
requestIdentifiers = requestIdentifiers.filter { $0 != id }
}
@objc private func willEnterForeground() {
if isActive {
displayLink.add(to: .current, forMode: .common)
}
}
@objc private func didEnterBackground() {
if isActive {
displayLink.invalidate()
}
}
+26 -11
View File
@@ -119,7 +119,9 @@ class ResizeController {
// Ensure initial autolayout is performed unanimated.
LCManager.shared.consoleWindow?.layoutIfNeeded()
FrameRateRequest().perform(duration: 1.5)
if #available(iOS 15, *) {
FrameRateRequest.shared.perform(duration: 1.5)
}
if isActive {
@@ -207,7 +209,7 @@ class ResizeController {
static let kMinConsoleHeight: CGFloat = 108
static let kMaxConsoleHeight: CGFloat = 346
let verticalPanner_frameRateRequest = FrameRateRequest()
var verticalPanner_frameRateRequestID: UUID?
@objc func verticalPanner(recognizer: UIPanGestureRecognizer) {
@@ -218,7 +220,10 @@ class ResizeController {
switch recognizer.state {
case .began:
verticalPanner_frameRateRequest.isActive = true
if #available(iOS 15, *) {
verticalPanner_frameRateRequestID = UUID()
FrameRateRequest.shared.activate(id: verticalPanner_frameRateRequestID!)
}
initialHeight = LCManager.shared.consoleSize.height
@@ -251,9 +256,13 @@ class ResizeController {
LCManager.shared.consoleView.center.y = consoleCenterPoint.y
case .ended, .cancelled:
verticalPanner_frameRateRequest.isActive = false
FrameRateRequest().perform(duration: 0.4)
if #available(iOS 15, *), let id = verticalPanner_frameRateRequestID {
verticalPanner_frameRateRequestID = nil
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
FrameRateRequest.shared.deactivate(id: id)
}
}
UIViewPropertyAnimator(duration: 0.4, dampingRatio: 0.7) {
if LCManager.shared.consoleSize.height > maxHeight {
@@ -284,7 +293,7 @@ class ResizeController {
static let kMinConsoleWidth: CGFloat = 112
static let kMaxConsoleWidth: CGFloat = [UIScreen.portraitSize.width, UIScreen.portraitSize.height].min()! - 56
let horizontalPanner_frameRateRequest = FrameRateRequest()
var horizontalPanner_frameRateRequestID: UUID?
@objc func horizontalPanner(recognizer: UIPanGestureRecognizer) {
@@ -295,7 +304,10 @@ class ResizeController {
switch recognizer.state {
case .began:
horizontalPanner_frameRateRequest.isActive = true
if #available(iOS 15, *) {
horizontalPanner_frameRateRequestID = UUID()
FrameRateRequest.shared.activate(id: horizontalPanner_frameRateRequestID!)
}
initialWidth = LCManager.shared.consoleSize.width
@@ -328,9 +340,12 @@ class ResizeController {
case .ended, .cancelled:
horizontalPanner_frameRateRequest.isActive = false
FrameRateRequest().perform(duration: 0.4)
if #available(iOS 15, *), let id = horizontalPanner_frameRateRequestID {
horizontalPanner_frameRateRequestID = nil
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
FrameRateRequest.shared.deactivate(id: id)
}
}
UIViewPropertyAnimator(duration: 0.4, dampingRatio: 0.7) {
if LCManager.shared.consoleSize.width > maxWidth {