From 8ceb35169e08b9217b6536b96d170845caabf389 Mon Sep 17 00:00:00 2001 From: Matias Pequeno Date: Thu, 16 Mar 2023 14:45:27 -0300 Subject: [PATCH] Allow users to change access token from the Demo UI. --- .../contents.xcworkspacedata | 7 ++ .../iosAppSwift.xcodeproj/project.pbxproj | 14 ++- .../contents.xcworkspacedata | 4 + .../iosAppSwift/iosAppSwift/ContentView.swift | 93 ++++++++++--------- Demos/iosAppSwift/iosAppSwift/Prelude.swift | 47 ++++++++++ .../iosAppSwift/iosAppSwiftApp.swift | 3 +- 6 files changed, 121 insertions(+), 47 deletions(-) create mode 100644 .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata create mode 100644 Demos/iosAppSwift/iosAppSwift.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Demos/iosAppSwift/iosAppSwift/Prelude.swift diff --git a/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata b/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..919434a6 --- /dev/null +++ b/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Demos/iosAppSwift/iosAppSwift.xcodeproj/project.pbxproj b/Demos/iosAppSwift/iosAppSwift.xcodeproj/project.pbxproj index bf3d190c..d945201d 100644 --- a/Demos/iosAppSwift/iosAppSwift.xcodeproj/project.pbxproj +++ b/Demos/iosAppSwift/iosAppSwift.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 3B24660A29C37CEA0078C74F /* Prelude.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B24660929C37CEA0078C74F /* Prelude.swift */; }; 3BDB8240292D2DCE0093AC9D /* iosAppSwiftApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BDB823F292D2DCE0093AC9D /* iosAppSwiftApp.swift */; }; 3BDB8242292D2DCE0093AC9D /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BDB8241292D2DCE0093AC9D /* ContentView.swift */; }; 3BDB8244292D2DCF0093AC9D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3BDB8243292D2DCF0093AC9D /* Assets.xcassets */; }; @@ -16,6 +17,7 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 3B24660929C37CEA0078C74F /* Prelude.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Prelude.swift; sourceTree = ""; }; 3BDB823C292D2DCE0093AC9D /* iosAppSwift.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iosAppSwift.app; sourceTree = BUILT_PRODUCTS_DIR; }; 3BDB823F292D2DCE0093AC9D /* iosAppSwiftApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iosAppSwiftApp.swift; sourceTree = ""; }; 3BDB8241292D2DCE0093AC9D /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; @@ -60,6 +62,7 @@ 3BDB8241292D2DCE0093AC9D /* ContentView.swift */, 3BDB8243292D2DCF0093AC9D /* Assets.xcassets */, 3BDB8245292D2DCF0093AC9D /* Preview Content */, + 3B24660929C37CEA0078C74F /* Prelude.swift */, ); path = iosAppSwift; sourceTree = ""; @@ -153,6 +156,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 3B24660A29C37CEA0078C74F /* Prelude.swift in Sources */, 3BDB8242292D2DCE0093AC9D /* ContentView.swift in Sources */, 3BDB8240292D2DCE0093AC9D /* iosAppSwiftApp.swift in Sources */, ); @@ -281,7 +285,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 15; + CURRENT_PROJECT_VERSION = 35; DEVELOPMENT_ASSET_PATHS = "\"iosAppSwift/Preview Content\""; DEVELOPMENT_TEAM = 6B5NER795L; ENABLE_PREVIEWS = YES; @@ -292,11 +296,12 @@ INFOPLIST_KEY_UILaunchScreen_Generation = YES; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0; + MARKETING_VERSION = 1.1; PRODUCT_BUNDLE_IDENTIFIER = com.matux.test.rollbarAppDemo; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; @@ -311,7 +316,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 15; + CURRENT_PROJECT_VERSION = 35; DEVELOPMENT_ASSET_PATHS = "\"iosAppSwift/Preview Content\""; DEVELOPMENT_TEAM = 6B5NER795L; ENABLE_PREVIEWS = YES; @@ -322,11 +327,12 @@ INFOPLIST_KEY_UILaunchScreen_Generation = YES; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0; + MARKETING_VERSION = 1.1; PRODUCT_BUNDLE_IDENTIFIER = com.matux.test.rollbarAppDemo; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; diff --git a/Demos/iosAppSwift/iosAppSwift.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Demos/iosAppSwift/iosAppSwift.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..94b2795e --- /dev/null +++ b/Demos/iosAppSwift/iosAppSwift.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,4 @@ + + + diff --git a/Demos/iosAppSwift/iosAppSwift/ContentView.swift b/Demos/iosAppSwift/iosAppSwift/ContentView.swift index 94f09b1d..72ade803 100644 --- a/Demos/iosAppSwift/iosAppSwift/ContentView.swift +++ b/Demos/iosAppSwift/iosAppSwift/ContentView.swift @@ -11,57 +11,66 @@ enum ExampleError: Error { } struct ContentView: View { + @AppStorage("rollbar_post_client_item_access_token") var accessToken = "" + let example = Example() func button(_ title: String, action: @escaping () -> ()) -> some View { - return Button(title, action: action) + Button(title, action: action) .buttonStyle(.bordered) .tint(.blue) } + func restart() { + let config = Rollbar.configuration().mutableCopy() + config.destination.accessToken = accessToken + Rollbar.update(withConfiguration: config) + Rollbar.infoMessage("Rollbar Apple SDK access token changed.") + } + var body: some View { VStack { - Text("Rollbar Apple SDK Example") + Text("Rollbar Apple SDK Demo") .font(.title) .padding(.bottom) - VStack { - Group { - button("Manual Logging Example", action: example.manualLogging) - .padding(.bottom) - } - - Group { - button("Fatal Error", action: example.forceFatalError) - .padding(.bottom) - } - - Group { - button("Force unwrap nil") { example.forceUnwrapNil(Int?.none) } - button("Implicitly unwrapped nil arg") { example.implicitlyUnwrappedArg(String?.none) } - .padding(.bottom) - } - - Group { - button("Force as! invalid cast") { example.forceInvalidCast([""]) } - button("Unsafe bit cast") { example.unsafeBitCast(0) } - .padding(.bottom) - } - - Group { - button("Out of bounds access") { example.outOfBounds(Int.max) } - button("Increment past endIndex") { example.incrementPastEndIndex(0...3) } - button("Outside UInt range") { example.outsideRepresentableRange(-21.5) } - button("Duplicate Dictionary keys") { example.duplicateKeys("someKey") } - button("Divide by zero") { example.divide(by: 0) } - .padding(.bottom) - } - - Group { - button("Force try! and fail") { try! example.throwError() } - button("Throw an NSException") { example.throwNSException((1, 2)) } - .padding(.bottom) - } + TextField("post client item access token", text: $accessToken) + .foregroundColor(accessToken.isValid ? .accentColor : .red) + .textFieldStyle(.roundedBorder) + .multilineTextAlignment(.center) + .textCase(.lowercase) + .lineLimit(1) + .onSubmit(accessToken.isValid ? restart : {}) + .padding(.bottom) + + ScrollView { + VStack { + Group { + button("Manual Logging Example", action: example.manualLogging) + .padding(.bottom) + button("Force unwrap nil") { example.forceUnwrapNil(Int?.none) } + button("Implicitly unwrapped nil") { example.implicitlyUnwrapped(nil) } + .padding(.bottom) + } + + Group { + button("Force try! and fail") { try! example.throwError() } + button("Force as! invalid cast") { example.forceInvalidCast([""]) } + button("Unsafe bit cast") { example.unsafeBitCast(0) } + .padding(.bottom) + + button("Out of bounds access") { example.outOfBounds(Int.max) } + button("Increment past endIndex") { example.incrementPastEndIndex(0...3) } + button("Outside UInt range") { example.outsideRepresentableRange(-21.5) } + .padding(.bottom) + + button("Duplicate Dictionary keys") { example.duplicateKeys("someKey") } + button("Divide by zero") { example.divide(by: 0) } + button("Throw an NSException") { example.throwNSException((1, 2)) } + button("Fatal Error", action: example.forceFatalError) + .padding(.bottom) + } + }.padding(.horizontal) } } .padding() @@ -109,9 +118,9 @@ struct Example { func forceUnwrapNil(_ x: T?) { // implementation detail: // ---------------------- - // since these functions are basically noops, the + // since these functions are basically no-ops, the // optimizer is clever enough to crush all of them - // into a single noop, which in turn, messes up the + // into a single no-op, which in turn, messes up the // stackframe. // // we prevent this by simply producing a side-effect. @@ -124,7 +133,7 @@ struct Example { _ = x! * x! // the illegal op. } - func implicitlyUnwrappedArg(_ s: S!) { + func implicitlyUnwrapped(_ s: String!) { print("implicitlyUnwrappedArgument: \(String(describing: s))") _ = s.lowercased() } diff --git a/Demos/iosAppSwift/iosAppSwift/Prelude.swift b/Demos/iosAppSwift/iosAppSwift/Prelude.swift new file mode 100644 index 00000000..97827926 --- /dev/null +++ b/Demos/iosAppSwift/iosAppSwift/Prelude.swift @@ -0,0 +1,47 @@ +import Foundation + +extension String { + var isValid: Bool { + #"(^[a-f0-9]{32}$)"#.matches(in: self)?.count == 1 + } +} + +extension StringProtocol { + + /// Returns an array of `Substring`s by matching the given `String` using + /// this string as a regular expression pattern. + /// + /// Returns `nil` if this string isn't a valid regex pattern, if no + /// matches are found, an empty string is returned. + func matches(in str: String) -> [Substring]? { + let regex = try? NSRegularExpression(pattern: String(self)) + let range = NSRange(str.startIndex.. [Substring] { + guard self.numberOfRanges > 1 else { return [] } + + var result = ContiguousArray() + result.reserveCapacity(self.numberOfRanges) + + for index in 1.. Range? { + Range(self.range(at: index), in: string) + } +} diff --git a/Demos/iosAppSwift/iosAppSwift/iosAppSwiftApp.swift b/Demos/iosAppSwift/iosAppSwift/iosAppSwiftApp.swift index 3bb3b627..1f2d6975 100644 --- a/Demos/iosAppSwift/iosAppSwift/iosAppSwiftApp.swift +++ b/Demos/iosAppSwift/iosAppSwift/iosAppSwiftApp.swift @@ -14,13 +14,14 @@ struct iosAppSwiftApp: App { } class AppDelegate: NSObject, UIApplicationDelegate { + @AppStorage("rollbar_post_client_item_access_token") var accessToken = "" func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil ) -> Bool { // Dynamically read these settings from your config settings on application startup. - let accessToken = "YOUR-ROLLBAR-TOKEN" // Rollbar post_client_item access token + let accessToken = self.accessToken // Rollbar post_client_item access token let environment = "staging" let codeVersion = "main" // Ideally codeVersion is commit SHA https://docs.rollbar.com/docs/versions