From 23bc497ec01ee23e3c75fb1ccdbd38f3596101cb Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Tue, 28 Jul 2020 14:12:08 +0200 Subject: [PATCH] Upgrade to Swift 5.3 and require iOS 14 or later --- .swiftlint.yml | 3 +-- Blear.xcodeproj/project.pbxproj | 10 ++++--- Blear/AppDelegate.swift | 2 +- Blear/ContentView.swift | 20 +++++++------- Blear/ImagePickerButton.swift | 46 +++++++-------------------------- Blear/Utilities.swift | 37 ++++++++++++++------------ Blear/ViewController.swift | 25 +++++++++--------- readme.md | 2 +- 8 files changed, 61 insertions(+), 84 deletions(-) diff --git a/.swiftlint.yml b/.swiftlint.yml index 6e5abf6..9f7d391 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -125,7 +125,6 @@ whitelist_rules: - unneeded_parentheses_in_closure_argument - unowned_variable_capture - untyped_error_in_catch - - unused_capture_list - unused_closure_parameter - unused_control_flow_label - unused_enumerated @@ -169,7 +168,7 @@ identifier_name: - 'y1' - 'y2' deployment_target: - iOS_deployment_target: '13.5' + iOS_deployment_target: '14' custom_rules: no_nsrect: regex: '\bNSRect\b' diff --git a/Blear.xcodeproj/project.pbxproj b/Blear.xcodeproj/project.pbxproj index dafa626..cc042be 100644 --- a/Blear.xcodeproj/project.pbxproj +++ b/Blear.xcodeproj/project.pbxproj @@ -143,7 +143,7 @@ isa = PBXProject; attributes = { CLASSPREFIX = ""; - LastUpgradeCheck = 1020; + LastUpgradeCheck = 1200; ORGANIZATIONNAME = "Sindre Sorhus"; TargetAttributes = { E3A0364517E5E7AE00892B76 = { @@ -244,6 +244,7 @@ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -267,7 +268,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 13.5; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; SWIFT_VERSION = 5.0; @@ -298,6 +299,7 @@ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -314,7 +316,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 13.5; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; SDKROOT = iphoneos; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-O"; @@ -408,7 +410,7 @@ repositoryURL = "https://github.com/microsoft/appcenter-sdk-apple"; requirement = { kind = upToNextMajorVersion; - minimumVersion = 3.3.0; + minimumVersion = 3.3.3; }; }; /* End XCRemoteSwiftPackageReference section */ diff --git a/Blear/AppDelegate.swift b/Blear/AppDelegate.swift index 0a3e385..20af166 100644 --- a/Blear/AppDelegate.swift +++ b/Blear/AppDelegate.swift @@ -2,7 +2,7 @@ import UIKit import AppCenter import AppCenterCrashes -@UIApplicationMain +@main final class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? diff --git a/Blear/ContentView.swift b/Blear/ContentView.swift index 5617ef9..7644f8d 100644 --- a/Blear/ContentView.swift +++ b/Blear/ContentView.swift @@ -17,19 +17,17 @@ struct ContentView: View { VStack { Spacer() HStack { - ImagePickerButton { - self.onImage($0) - } + ImagePickerButton(onImage: onImage) .shadow(radius: buttonShadowRadius) Spacer() // TODO: Use a custom slider like the iOS brightness control. - // TODO: Use `View#onChange` when targeting iOS 14. - Slider(value: $blurAmount.onChange(onSliderChange), in: 10...100) + Slider(value: $blurAmount, in: 10...100) .padding(.horizontal, DeviceInfo.isPad ? 60 : 30) .frame(maxWidth: 500) + .onChange(of: blurAmount, perform: onSliderChange) Spacer() Button(action: { - self.saveImage() + saveImage() }) { Image(systemName: "square.and.arrow.down") } @@ -49,7 +47,7 @@ struct ContentView: View { .background( EmptyView() // This is not at the top-level because of a SwiftUI bug. - // TODO: Check if it's possible to have multiple alerts on a single element in iOS 14. + // TODO: Check if it's possible to have multiple alerts on a single element in iOS 15. .alert(isPresented: $isShowingWallpaperTip) { Alert( title: Text("Changing Wallpaper"), @@ -58,7 +56,7 @@ struct ContentView: View { } ) .onAppear { - self.showShakeTipIfNeeded() + showShakeTipIfNeeded() } } @@ -86,7 +84,7 @@ struct ContentView: View { HUD.show(in: view) HUD.dismiss(afterDelay: 0.8) - self.showWallpaperTipIfNeeded() + showWallpaperTipIfNeeded() } } @@ -96,7 +94,7 @@ struct ContentView: View { } delay(seconds: 1.5) { - self.isShowingShakeTip = true + isShowingShakeTip = true } } @@ -106,7 +104,7 @@ struct ContentView: View { } delay(seconds: 1) { - self.isShowingWallpaperTip = true + isShowingWallpaperTip = true } } } diff --git a/Blear/ImagePickerButton.swift b/Blear/ImagePickerButton.swift index ff58075..2913083 100644 --- a/Blear/ImagePickerButton.swift +++ b/Blear/ImagePickerButton.swift @@ -1,56 +1,28 @@ import SwiftUI struct ImagePickerButton: View { - @State private var isShowingSheet = false @State private var isShowingImagePicker = false - @State private var pickerType = UIImagePickerController.SourceType.photoLibrary @State private var image: UIImage? - private var buttons: [ActionSheet.Button] { - var buttons: [ActionSheet.Button] = [ - .default(Text("Take Photo")) { - self.pickerType = .camera - self.isShowingImagePicker = true - }, - .default(Text("Photo Library")) { - self.pickerType = .photoLibrary - self.isShowingImagePicker = true - }, - .cancel() - ] - - if !UIImagePickerController.isSourceTypeAvailable(.camera) { - buttons.removeFirst() - } - - return buttons - } - // TODO: I can drop this and use the `image` binding when the whole app is rewritten in SwiftUI. var onImage: (UIImage) -> Void var body: some View { Button(action: { - self.isShowingSheet = true + isShowingImagePicker = true }) { - Image(systemName: "camera") + Image(systemName: "photo.on.rectangle") } - .actionSheet(isPresented: $isShowingSheet) { - ActionSheet( - title: Text("Pick an Image"), - buttons: buttons - ) - } // TODO: It should ideally use a fullscreen modal when showing the camera, but that's not currently possible in SwiftUI. .sheet(isPresented: $isShowingImagePicker) { - // TODO: Use `View#onChange` when targeting iOS 14. - ImagePicker(sourceType: self.pickerType, image: self.$image.onChange { - guard let image = $0 else { - return - } + ImagePicker(sourceType: .photoLibrary, image: $image) + } + .onChange(of: image) { + guard let image = $0 else { + return + } - self.onImage(image) - }) + onImage(image) } } } diff --git a/Blear/Utilities.swift b/Blear/Utilities.swift index 79da592..45d876e 100644 --- a/Blear/Utilities.swift +++ b/Blear/Utilities.swift @@ -65,12 +65,11 @@ extension Collection { return AnyIterator { var offset: Int repeat { - offset = Int.random(in: 0.. UIImage { @@ -127,9 +132,9 @@ extension UIEdgeInsets { extension UIScrollView { @objc override func toImage() -> UIImage { - UIGraphicsImageRenderer(size: bounds.size).image { _ in + UIGraphicsImageRenderer(size: bounds.size).image { [self] _ in let newBounds = bounds.offsetBy(dx: -contentOffset.x, dy: -contentOffset.y) - self.drawHierarchy(in: newBounds, afterScreenUpdates: true) + drawHierarchy(in: newBounds, afterScreenUpdates: true) } } } @@ -216,11 +221,11 @@ extension Binding where Value: Equatable { */ func onChange(_ action: @escaping (Value) -> Void) -> Self { .init( - get: { self.wrappedValue }, + get: { wrappedValue }, set: { - let oldValue = self.wrappedValue - self.wrappedValue = $0 - let newValue = self.wrappedValue + let oldValue = wrappedValue + wrappedValue = $0 + let newValue = wrappedValue if newValue != oldValue { action(newValue) } @@ -338,7 +343,7 @@ private struct FadeInAfterDelayModifier: ViewModifier { .delay(delay) ) .onAppear { - self.isShowingContent = true + isShowingContent = true } } } diff --git a/Blear/ViewController.swift b/Blear/ViewController.swift index f83c27e..385dda2 100644 --- a/Blear/ViewController.swift +++ b/Blear/ViewController.swift @@ -51,14 +51,13 @@ final class ViewController: UIViewController { func setUpContentView() { let contentView = ContentView( - onSliderChange: { - self.lastBlurAmount = Float($0) - self.updateImage(blurAmount: Float($0)) + onSliderChange: { [self] in + lastBlurAmount = Float($0) + updateImage(blurAmount: Float($0)) }, - onImage: { - self.changeImage($0) - } + onImage: changeImage ) + let hostingView = UIHostingView(rootView: contentView) hostingView.translatesAutoresizingMaskIntoConstraints = false hostingView.tintColor = .white @@ -86,12 +85,14 @@ final class ViewController: UIViewController { workItem.cancel() } - let workItem = DispatchWorkItem { - let temp = self.blurImage(blurAmount) - DispatchQueue.main.async { - self.imageView.image = temp + let workItem = DispatchWorkItem { [self] in + let temp = blurImage(blurAmount) + + DispatchQueue.main.async { [self] in + imageView.image = temp } } + self.workItem = workItem DispatchQueue.global(qos: .userInteractive).async(execute: workItem) @@ -130,8 +131,8 @@ final class ViewController: UIViewController { let y = scrollView.contentSize.height - scrollView.frame.size.height scrollView.setContentOffset(CGPoint(x: x, y: y), animated: true) - delay(seconds: 1) { - self.scrollView.setContentOffset(.zero, animated: true) + delay(seconds: 1) { [self] in + scrollView.setContentOffset(.zero, animated: true) } } } diff --git a/readme.md b/readme.md index 4678f18..0b50d6a 100644 --- a/readme.md +++ b/readme.md @@ -17,4 +17,4 @@ ## Info -Requires minimum iOS 13. +Requires minimum iOS 14.