From 198149c39e5a8bb48c61b021f9e3154eb8c8add0 Mon Sep 17 00:00:00 2001 From: Antoine van der Lee Date: Thu, 18 Jul 2019 14:12:21 +0200 Subject: [PATCH 1/3] Make it possible to set a max width --- Sources/UINotification.swift | 3 +++ Sources/UINotificationPresentationContext.swift | 15 +++++++++++---- .../UINotificationSystemStyle.swift | 1 + Sources/UINotificationView.swift | 2 +- 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/Sources/UINotification.swift b/Sources/UINotification.swift index a879bc6..62f0b00 100644 --- a/Sources/UINotification.swift +++ b/Sources/UINotification.swift @@ -24,6 +24,9 @@ public protocol UINotificationStyle { /// The height of the notification which applies on the notification view. var height: UINotification.Height { get } + + /// The max width of the notification which applies on the notification view. Defaults to current screen width if set to `nil`. + var maxWidth: CGFloat? { get } /// When `true`, the notification is swipeable and tappable. var interactive: Bool { get } diff --git a/Sources/UINotificationPresentationContext.swift b/Sources/UINotificationPresentationContext.swift index da04810..92e7703 100644 --- a/Sources/UINotificationPresentationContext.swift +++ b/Sources/UINotificationPresentationContext.swift @@ -73,13 +73,20 @@ public final class UINotificationPresentationContext { notificationView.topConstraint = notificationViewTopConstraint - let constraints = [ - notificationView.leftAnchor.constraint(equalTo: containerViewController.view.leftAnchor), - notificationView.rightAnchor.constraint(equalTo: containerViewController.view.rightAnchor), + var constraints = [ + notificationView.leftAnchor.constraint(equalTo: containerViewController.view.leftAnchor).usingPriority(.defaultHigh), + notificationView.rightAnchor.constraint(equalTo: containerViewController.view.rightAnchor).usingPriority(.defaultHigh), notificationView.heightAnchor.constraint(equalToConstant: notification.style.height.value), notificationViewTopConstraint ] - + + if let maxWidth = notification.style.maxWidth { + constraints.append(contentsOf: [ + notificationView.widthAnchor.constraint(lessThanOrEqualToConstant: maxWidth), + notificationView.centerXAnchor.constraint(equalTo: containerViewController.view.centerXAnchor) + ]) + } + NSLayoutConstraint.activate(constraints) containerViewController.view.layoutIfNeeded() } diff --git a/Sources/UINotificationStyles/UINotificationSystemStyle.swift b/Sources/UINotificationStyles/UINotificationSystemStyle.swift index f502627..fdf366e 100644 --- a/Sources/UINotificationStyles/UINotificationSystemStyle.swift +++ b/Sources/UINotificationStyles/UINotificationSystemStyle.swift @@ -16,6 +16,7 @@ public struct UINotificationSystemStyle: UINotificationStyle { public var titleTextColor: UIColor = UIColor.black public var subtitleTextColor: UIColor = UIColor.darkGray public var height: UINotification.Height = .navigationBar + public var maxWidth: CGFloat? public var interactive: Bool = true public var chevronImage: UIImage? diff --git a/Sources/UINotificationView.swift b/Sources/UINotificationView.swift index 8e7ce35..7764d0f 100644 --- a/Sources/UINotificationView.swift +++ b/Sources/UINotificationView.swift @@ -189,7 +189,7 @@ extension UINotificationView: UINotificationDelegate { } } -fileprivate extension NSLayoutConstraint { +extension NSLayoutConstraint { /// Returns the constraint sender with the passed priority. /// From 45678e04e58868bcd7ef63384cbfd95e274e4b30 Mon Sep 17 00:00:00 2001 From: Antoine van der Lee Date: Thu, 18 Jul 2019 14:20:12 +0200 Subject: [PATCH 2/3] - Updated the example project to Swift 5.0. - Example project builds again - Max width setting is now available Fixes #41 --- .../project.pbxproj | 17 ++++++++---- .../ViewController.swift | 11 +++++--- .../UINotificationDefaultElementsTests.swift | 26 +++++++++++++++---- .../UINotificationDefaultViewTests.swift | 1 + 4 files changed, 42 insertions(+), 13 deletions(-) diff --git a/Example/UINotifications-Example.xcodeproj/project.pbxproj b/Example/UINotifications-Example.xcodeproj/project.pbxproj index 564e53a..2108de1 100644 --- a/Example/UINotifications-Example.xcodeproj/project.pbxproj +++ b/Example/UINotifications-Example.xcodeproj/project.pbxproj @@ -35,7 +35,7 @@ isa = PBXContainerItemProxy; containerPortal = 5078C8321F18D9FC006EB23F /* UINotifications.xcodeproj */; proxyType = 1; - remoteGlobalIDString = 5078C7931F18CAF5006EB23F; + remoteGlobalIDString = 502C139F206E5F230082CE37; remoteInfo = UINotifications; }; /* End PBXContainerItemProxy section */ @@ -146,19 +146,20 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0830; - LastUpgradeCheck = 0910; + LastUpgradeCheck = 1020; ORGANIZATIONNAME = WeTransfer; TargetAttributes = { 50042BCD1F18BC85007209B7 = { CreatedOnToolsVersion = 8.3.3; DevelopmentTeam = 4QMDKC8VLJ; + LastSwiftMigration = 1020; ProvisioningStyle = Automatic; }; }; }; buildConfigurationList = 50042BC91F18BC85007209B7 /* Build configuration list for PBXProject "UINotifications-Example" */; compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, @@ -271,6 +272,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; @@ -281,6 +283,7 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; @@ -288,6 +291,7 @@ CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; @@ -328,6 +332,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; @@ -338,6 +343,7 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; @@ -345,6 +351,7 @@ CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; @@ -385,7 +392,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.wetransfer.UINotifications-Example"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; }; name = Debug; }; @@ -400,7 +407,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.wetransfer.UINotifications-Example"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; }; name = Release; }; diff --git a/Example/UINotifications-Example/ViewController.swift b/Example/UINotifications-Example/ViewController.swift index 86ff432..11514fa 100644 --- a/Example/UINotifications-Example/ViewController.swift +++ b/Example/UINotifications-Example/ViewController.swift @@ -49,14 +49,19 @@ enum NotificationStyle: UINotificationStyle { } /// The height of the notification which applies on the notification view. - var height: UINotificationHeight { + var height: UINotification.Height { switch self { case .success: - return UINotificationHeight.navigationBar + return .navigationBar case .failure: - return UINotificationHeight.statusBar + return .statusBar } } + + /// Use this to set a max width to the notification view. + var maxWidth: CGFloat? { + return nil + } /// When `true`, the notification is swipeable and tappable. var interactive: Bool { diff --git a/UINotificationsTests/UINotificationDefaultElementsTests.swift b/UINotificationsTests/UINotificationDefaultElementsTests.swift index 345e500..8218a41 100644 --- a/UINotificationsTests/UINotificationDefaultElementsTests.swift +++ b/UINotificationsTests/UINotificationDefaultElementsTests.swift @@ -18,15 +18,18 @@ final class UINotificationDefaultElementsTests: UINotificationTestCase { var subtitleTextColor: UIColor = UIColor.black var backgroundColor: UIColor = UIColor.white var height: UINotification.Height { - return UINotification.Height.custom(height: self.customHeight) + guard let customHeight = customHeight else { return .navigationBar } + return .custom(height: customHeight) } var interactive: Bool = true var chevronImage: UIImage? - let customHeight: CGFloat - - init(customHeight: CGFloat) { + let customHeight: CGFloat? + let maxWidth: CGFloat? + + init(customHeight: CGFloat? = nil, maxWidth: CGFloat? = nil) { self.customHeight = customHeight + self.maxWidth = maxWidth } } @@ -73,7 +76,20 @@ final class UINotificationDefaultElementsTests: UINotificationTestCase { waitFor(notificationCenter.currentPresenter?.presentationContext.notificationView.frame.size.height == customHeight, timeout: 5.0, description: "Custom height should be applied to the view") } - + + /// When passing a notification style with a max width, this should be applied to the presented view. + func testNotificationViewMaxWidth() { + let notificationCenter = UINotificationCenter() + notificationCenter.isDuplicateQueueingAllowed = true + notificationCenter.presenterType = MockPresenter.self + let customWidth: CGFloat = 100 + let notification = UINotification(content: UINotificationContent(title: "test"), style: CustomStyle(maxWidth: customWidth)) + + notificationCenter.show(notification: notification) + + waitFor(notificationCenter.currentPresenter?.presentationContext.notificationView.frame.size.width == customWidth, timeout: 5.0, description: "Max width should be applied to the view") + } + /// When using the manual dismiss trigger, the notification should only dismiss after manually called. func testManualDismissTrigger() { let notificationCenter = UINotificationCenter() diff --git a/UINotificationsTests/UINotificationDefaultViewTests.swift b/UINotificationsTests/UINotificationDefaultViewTests.swift index 536d22f..8bf2f59 100644 --- a/UINotificationsTests/UINotificationDefaultViewTests.swift +++ b/UINotificationsTests/UINotificationDefaultViewTests.swift @@ -86,6 +86,7 @@ private struct LargeChevronStyle: UINotificationStyle { var height: UINotification.Height { return UINotification.Height.navigationBar } + var maxWidth: CGFloat? var interactive: Bool = true var chevronImage: UIImage? { let bundle = Bundle(for: UINotificationViewTests.self) From e1280c9f494add75f8a663185e1669470fc0bb20 Mon Sep 17 00:00:00 2001 From: Antoine van der Lee Date: Thu, 18 Jul 2019 14:21:30 +0200 Subject: [PATCH 3/3] Updated the readme --- README.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 73881d6..c92f6a4 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ UINotificationCenter.current.show(notification: notification, dismissTrigger: di ```swift import UINotifications -enum CustomNotificationStyle: UINotificationStyle { +enum NotificationStyle: UINotificationStyle { case success case failure @@ -98,14 +98,19 @@ enum CustomNotificationStyle: UINotificationStyle { } /// The height of the notification which applies on the notification view. - var height: UINotificationHeight { + var height: UINotification.Height { switch self { case .success: - return UINotificationHeight.navigationBar + return .navigationBar case .failure: - return UINotificationHeight.statusBar + return .statusBar } } + + /// Use this to set a max width to the notification view. + var maxWidth: CGFloat? { + return nil + } /// When `true`, the notification is swipeable and tappable. var interactive: Bool {