From a233bb126926278fc795ae293c5d7bd6cb02c585 Mon Sep 17 00:00:00 2001 From: Tori Lew Date: Tue, 3 Oct 2023 22:50:54 -0700 Subject: [PATCH 1/4] Ready to go! --- .gitignore | 140 ++++++++++++++++++ .../project.pbxproj | 16 ++ DebuggingAndProfiling/ContentView.swift | 21 ++- DebuggingAndProfiling/DebugThisCode.swift | 70 +++++++++ DebuggingAndProfiling/OccassionalUpdate.swift | 51 +++++++ DebuggingAndProfiling/StressTest.swift | 43 ++++++ 6 files changed, 336 insertions(+), 5 deletions(-) create mode 100644 .gitignore create mode 100644 DebuggingAndProfiling/DebugThisCode.swift create mode 100644 DebuggingAndProfiling/OccassionalUpdate.swift create mode 100644 DebuggingAndProfiling/StressTest.swift diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1efee0e --- /dev/null +++ b/.gitignore @@ -0,0 +1,140 @@ +# Created by https://www.toptal.com/developers/gitignore/api/macos,xcode,swift,swiftpackagemanager +# Edit at https://www.toptal.com/developers/gitignore?templates=macos,xcode,swift,swiftpackagemanager + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### macOS Patch ### +# iCloud generated files +*.icloud + +### Swift ### +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## User settings +xcuserdata/ + +## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) +*.xcscmblueprint +*.xccheckout + +## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) +build/ +DerivedData/ +*.moved-aside +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 + +## Obj-C/Swift specific +*.hmap + +## App packaging +*.ipa +*.dSYM.zip +*.dSYM + +## Playgrounds +timeline.xctimeline +playground.xcworkspace + +# Swift Package Manager +# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. +# Packages/ +# Package.pins +# Package.resolved +# *.xcodeproj +# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata +# hence it is not needed unless you have added a package configuration file to your project +# .swiftpm + +.build/ + +# CocoaPods +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control +# Pods/ +# Add this line if you want to avoid checking in source code from the Xcode workspace +# *.xcworkspace + +# Carthage +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + +Carthage/Build/ + +# Accio dependency management +Dependencies/ +.accio/ + +# fastlane +# It is recommended to not store the screenshots in the git repo. +# Instead, use fastlane to re-generate the screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://docs.fastlane.tools/best-practices/source-control/#source-control + +fastlane/report.xml +fastlane/Preview.html +fastlane/screenshots/**/*.png +fastlane/test_output + +# Code Injection +# After new code Injection tools there's a generated folder /iOSInjectionProject +# https://github.com/johnno1962/injectionforxcode + +iOSInjectionProject/ + +### SwiftPackageManager ### +Packages +xcuserdata +*.xcodeproj + + +### Xcode ### + +## Xcode 8 and earlier + +### Xcode Patch ### +*.xcodeproj/* +!*.xcodeproj/project.pbxproj +!*.xcodeproj/xcshareddata/ +!*.xcodeproj/project.xcworkspace/ +!*.xcworkspace/contents.xcworkspacedata +/*.gcno +**/xcshareddata/WorkspaceSettings.xcsettings + +# End of https://www.toptal.com/developers/gitignore/api/macos,xcode,swift,swiftpackagemanager diff --git a/DebuggingAndProfiling.xcodeproj/project.pbxproj b/DebuggingAndProfiling.xcodeproj/project.pbxproj index 0d6eb38..76b915d 100644 --- a/DebuggingAndProfiling.xcodeproj/project.pbxproj +++ b/DebuggingAndProfiling.xcodeproj/project.pbxproj @@ -14,6 +14,10 @@ E427DB7C2ACCFAE1000C6F53 /* DebuggingAndProfilingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E427DB7B2ACCFAE1000C6F53 /* DebuggingAndProfilingTests.swift */; }; E427DB862ACCFAE1000C6F53 /* DebuggingAndProfilingUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E427DB852ACCFAE1000C6F53 /* DebuggingAndProfilingUITests.swift */; }; E427DB882ACCFAE1000C6F53 /* DebuggingAndProfilingUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E427DB872ACCFAE1000C6F53 /* DebuggingAndProfilingUITestsLaunchTests.swift */; }; + E427DB952ACD02BB000C6F53 /* StressTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = E427DB942ACD02BB000C6F53 /* StressTest.swift */; }; + E427DB972ACD02CE000C6F53 /* OccassionalUpdate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E427DB962ACD02CE000C6F53 /* OccassionalUpdate.swift */; }; + E427DB992ACD14F0000C6F53 /* DebugThisCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = E427DB982ACD14F0000C6F53 /* DebugThisCode.swift */; }; + E427DB9B2ACD296C000C6F53 /* .gitignore in Resources */ = {isa = PBXBuildFile; fileRef = E427DB9A2ACD296C000C6F53 /* .gitignore */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -44,6 +48,10 @@ E427DB812ACCFAE1000C6F53 /* DebuggingAndProfilingUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DebuggingAndProfilingUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; E427DB852ACCFAE1000C6F53 /* DebuggingAndProfilingUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebuggingAndProfilingUITests.swift; sourceTree = ""; }; E427DB872ACCFAE1000C6F53 /* DebuggingAndProfilingUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebuggingAndProfilingUITestsLaunchTests.swift; sourceTree = ""; }; + E427DB942ACD02BB000C6F53 /* StressTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StressTest.swift; sourceTree = ""; }; + E427DB962ACD02CE000C6F53 /* OccassionalUpdate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OccassionalUpdate.swift; sourceTree = ""; }; + E427DB982ACD14F0000C6F53 /* DebugThisCode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugThisCode.swift; sourceTree = ""; }; + E427DB9A2ACD296C000C6F53 /* .gitignore */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitignore; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -74,6 +82,7 @@ E427DB5E2ACCFADD000C6F53 = { isa = PBXGroup; children = ( + E427DB9A2ACD296C000C6F53 /* .gitignore */, E427DB692ACCFADD000C6F53 /* DebuggingAndProfiling */, E427DB7A2ACCFAE1000C6F53 /* DebuggingAndProfilingTests */, E427DB842ACCFAE1000C6F53 /* DebuggingAndProfilingUITests */, @@ -96,6 +105,9 @@ children = ( E427DB6A2ACCFADD000C6F53 /* DebuggingAndProfilingApp.swift */, E427DB6C2ACCFADD000C6F53 /* ContentView.swift */, + E427DB942ACD02BB000C6F53 /* StressTest.swift */, + E427DB962ACD02CE000C6F53 /* OccassionalUpdate.swift */, + E427DB982ACD14F0000C6F53 /* DebugThisCode.swift */, E427DB6E2ACCFAE0000C6F53 /* Assets.xcassets */, E427DB702ACCFAE0000C6F53 /* Preview Content */, ); @@ -232,6 +244,7 @@ buildActionMask = 2147483647; files = ( E427DB722ACCFAE0000C6F53 /* Preview Assets.xcassets in Resources */, + E427DB9B2ACD296C000C6F53 /* .gitignore in Resources */, E427DB6F2ACCFAE0000C6F53 /* Assets.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -257,7 +270,10 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + E427DB972ACD02CE000C6F53 /* OccassionalUpdate.swift in Sources */, E427DB6D2ACCFADD000C6F53 /* ContentView.swift in Sources */, + E427DB952ACD02BB000C6F53 /* StressTest.swift in Sources */, + E427DB992ACD14F0000C6F53 /* DebugThisCode.swift in Sources */, E427DB6B2ACCFADD000C6F53 /* DebuggingAndProfilingApp.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/DebuggingAndProfiling/ContentView.swift b/DebuggingAndProfiling/ContentView.swift index 1b44996..f931a6d 100644 --- a/DebuggingAndProfiling/ContentView.swift +++ b/DebuggingAndProfiling/ContentView.swift @@ -9,11 +9,22 @@ import SwiftUI struct ContentView: View { var body: some View { - VStack { - Image(systemName: "globe") - .imageScale(.large) - .foregroundColor(.accentColor) - Text("Hello, world!") + TabView { + OccassionalUpdate() + .tabItem { + Image(systemName: "smiley") + Text("OccassionalUpdate") + } + StressTest() + .tabItem { + Image(systemName: "exclamationmark.arrow.triangle.2.circlepath") + Text("StressTest") + } + DebugThisCode() + .tabItem { + Image(systemName: "ant") + Text("DebugThisCode") + } } .padding() } diff --git a/DebuggingAndProfiling/DebugThisCode.swift b/DebuggingAndProfiling/DebugThisCode.swift new file mode 100644 index 0000000..647fc57 --- /dev/null +++ b/DebuggingAndProfiling/DebugThisCode.swift @@ -0,0 +1,70 @@ +// +// DebugThisCode.swift +// DebuggingAndProfiling +// +// Created by Mike Panitz on 10/3/23. +// + +import SwiftUI + +struct DebugThisCode: View { + @State var fahrenheitTemp = "" + @State var celsiusTemp = "" + var body: some View { + VStack { + Text("Fahrenheit to Celsius") + .font(.largeTitle) + Spacer() + VStack { + Text("Fahrenheit:") + TextField("Temperature in Fahrenheit", text: $fahrenheitTemp) + Button(action: { + print("Fah changed to \(fahrenheitTemp)") + if let fah = Double(fahrenheitTemp) { + print("Value is \(fah)") + var cel = (fah + 32) * 5 / 9 + celsiusTemp = String(cel) + } else { + print("Not a valid number") + } + }) { + Text("Convert to Celsius") + .font(.headline) + .foregroundColor(.white) + .padding() + .background(Color.blue) + .cornerRadius(10) + } + }.padding(.bottom) + + VStack { + Text("Celsius:") + TextField("Temperature in Celsius", text: $celsiusTemp) + Button(action: { + if let cel = Double(celsiusTemp) { + var fah = (cel * 5 / 9 ) + 32 + fahrenheitTemp = String(fah) + } else { + print("Not a valid number") + } + }) { + Text("Convert to Fahrenheit") + .font(.headline) + .foregroundColor(.white) + .padding() + .background(Color.blue) + .cornerRadius(10) + } + + }.padding(.top) + Spacer() + } + .padding() + } +} + +struct DebugThisCode_Previews: PreviewProvider { + static var previews: some View { + DebugThisCode() + } +} diff --git a/DebuggingAndProfiling/OccassionalUpdate.swift b/DebuggingAndProfiling/OccassionalUpdate.swift new file mode 100644 index 0000000..0bb9347 --- /dev/null +++ b/DebuggingAndProfiling/OccassionalUpdate.swift @@ -0,0 +1,51 @@ +// +// OccassionalUpdate.swift +// DebuggingAndProfiling +// +// Created by Mike Panitz on 10/3/23. +// + +import SwiftUI + +func TheSlowFunction() { + var changeThisVar = 0 + for _ in 0 ... 100000 { + for j in 0 ... 100000 { + changeThisVar = j + print(j) + } + } +} + +func CallTheSlowFunction() { + print("About to call the slow function") + TheSlowFunction() + print("Done with the slow function") +} + +struct OccassionalUpdate: View { + var body: some View { + VStack { + Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/) + Button(action: { + // Code to be executed when the button is tapped + print("Button tapped! Message printed to debug console.") + CallTheSlowFunction() + }) { + Text("Tap Me!") + .font(.headline) + .foregroundColor(.white) + .padding() + .background(Color.blue) + .cornerRadius(10) + } + } + } +} + +struct OccassionalUpdate_Previews: PreviewProvider { + static var previews: some View { + OccassionalUpdate() + } +} + diff --git a/DebuggingAndProfiling/StressTest.swift b/DebuggingAndProfiling/StressTest.swift new file mode 100644 index 0000000..fbb73dd --- /dev/null +++ b/DebuggingAndProfiling/StressTest.swift @@ -0,0 +1,43 @@ + +// +// ContentView.swift +// DebuggingAndProfiling +// +// Created by Mike Panitz on 10/3/23. +// + +import SwiftUI + +class FrequentUpdater: ObservableObject { + var timer: Timer? + + init() { + timer = Timer.scheduledTimer( + withTimeInterval: 0.01, + repeats: true + ) { _ in + self.objectWillChange.send() + } + } +} + +struct StressTest: View { + @StateObject private var updater = FrequentUpdater() + @State private var tapCount = 0 + + var body: some View { + VStack { + Text("\(UUID().uuidString)") + + Button("Tap count: \(tapCount)") { + tapCount += 1 + } + } + } +} + +struct StressTest_Previews: PreviewProvider { + static var previews: some View { + StressTest() + } +} From 45ddc67de59cfe19476871549cdd91d699eb7a48 Mon Sep 17 00:00:00 2001 From: Tori Lew Date: Wed, 11 Oct 2023 13:49:36 -0700 Subject: [PATCH 2/4] XCode Debugger - Fahrenheit to celsius --- DebuggingAndProfiling/ContentView.swift | 7 +++++++ DebuggingAndProfiling/DebugThisCode.swift | 6 ++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/DebuggingAndProfiling/ContentView.swift b/DebuggingAndProfiling/ContentView.swift index f931a6d..5872126 100644 --- a/DebuggingAndProfiling/ContentView.swift +++ b/DebuggingAndProfiling/ContentView.swift @@ -25,6 +25,13 @@ struct ContentView: View { Image(systemName: "ant") Text("DebugThisCode") } + + // The algorithm for converting fahrenheit to celsius was incorrect, and the resulting variable declaration needed to be changed from var to let. + + //ORIGINAL - var cel = (fah + 32) * 5 / 9 + //CORRECT - let cel = (fah - 32) * 5 / 9 + //ORIGINAL - var fah = (cel * 5 / 9 ) + 32 + //CORRECT - let fah = (cel * 9 / 5) + 32 } .padding() } diff --git a/DebuggingAndProfiling/DebugThisCode.swift b/DebuggingAndProfiling/DebugThisCode.swift index 647fc57..465b49e 100644 --- a/DebuggingAndProfiling/DebugThisCode.swift +++ b/DebuggingAndProfiling/DebugThisCode.swift @@ -22,7 +22,8 @@ struct DebugThisCode: View { print("Fah changed to \(fahrenheitTemp)") if let fah = Double(fahrenheitTemp) { print("Value is \(fah)") - var cel = (fah + 32) * 5 / 9 + //var cel = (fah + 32) * 5 / 9 + let cel = (fah - 32) * 5 / 9 celsiusTemp = String(cel) } else { print("Not a valid number") @@ -42,7 +43,8 @@ struct DebugThisCode: View { TextField("Temperature in Celsius", text: $celsiusTemp) Button(action: { if let cel = Double(celsiusTemp) { - var fah = (cel * 5 / 9 ) + 32 + //var fah = (cel * 5 / 9 ) + 32 + let fah = (cel * 9 / 5) + 32 fahrenheitTemp = String(fah) } else { print("Not a valid number") From a9be239dbe7d8eece96c87fc250a79ae0e01004a Mon Sep 17 00:00:00 2001 From: Tori Lew Date: Wed, 11 Oct 2023 14:31:25 -0700 Subject: [PATCH 3/4] How many times the app will redraw it's views --- DebuggingAndProfiling/ContentView.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/DebuggingAndProfiling/ContentView.swift b/DebuggingAndProfiling/ContentView.swift index 5872126..1572575 100644 --- a/DebuggingAndProfiling/ContentView.swift +++ b/DebuggingAndProfiling/ContentView.swift @@ -10,6 +10,7 @@ import SwiftUI struct ContentView: View { var body: some View { TabView { + // 2 - The app redrew its views 7 times in the 30 sec OccassionalUpdate was in the foreground and 2,730 times while stress test was in the foreground OccassionalUpdate() .tabItem { Image(systemName: "smiley") From c4eeee46c0ffe2f0b725ddd9df903d9b105d216e Mon Sep 17 00:00:00 2001 From: Tori Lew Date: Wed, 11 Oct 2023 14:42:16 -0700 Subject: [PATCH 4/4] Time Profiler to compare and contrast StressTest and the OccassionalUpdate views --- DebuggingAndProfiling/ContentView.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/DebuggingAndProfiling/ContentView.swift b/DebuggingAndProfiling/ContentView.swift index 1572575..0d371e0 100644 --- a/DebuggingAndProfiling/ContentView.swift +++ b/DebuggingAndProfiling/ContentView.swift @@ -11,6 +11,8 @@ struct ContentView: View { var body: some View { TabView { // 2 - The app redrew its views 7 times in the 30 sec OccassionalUpdate was in the foreground and 2,730 times while stress test was in the foreground + + // 3 - In the OccationalUpdate, starting took 19.82s in the 30sec it was in the foreground. In stressTest, it took 5.96 sec. So while the views were drawn more times during the stress test, those were updating faster so it didn't use as much CPU. OccassionalUpdate() .tabItem { Image(systemName: "smiley")