Rebuild the app on iOS 26, SwiftUI and Swift 6 - #32
Open
bystritskiy wants to merge 1 commit into
Open
Conversation
The working tree had drifted into a state where the app did not actually play: the 2019 SwiftUI rewrite left every screen as a `// TODO:` stub, the real game logic sat commented out in DEPRECATED/GameViewController.swift, and the project still targeted iOS 15 with Swift 5 and a UIKit/storyboard launch path. Project - Regenerate project.pbxproj using PBXFileSystemSynchronizedRootGroup, so sources join the target by living in the folder - iOS 15 -> iOS 26, Swift 5.0 -> Swift 6 language mode - Drop Info.plist and LaunchScreen.storyboard in favour of INFOPLIST_KEY_* - Add a unit test target; delete the watch scheme, whose target never existed Code - Replace AppDelegate/SceneDelegate/storyboard with an @main App and TabView - Port the game rules from the shipped 1.1 code on master into GameEngine, built on @observable and ContinuousClock. Every method takes the current instant as a parameter, which is what lets the tests play a full round without waiting on wall-clock time - Redraw the two hand-animated CAGradientLayers as a MeshGradient that pulses on the beat, and surface the tolerance window as a ring arc - Remove the Firebase, AdMob and StoreKit leftovers, and replace SwiftEntryKit with native toasts: the app now has no dependencies - Move Game Center onto the async GKLeaderboard API, and let sign-in be something the player asks for rather than a modal thrown up at launch Tooling - Convert Localizable.strings to a String Catalog (en source, ru translated) - Add 16 Swift Testing cases covering the engine and record persistence - Fix .swiftlint.yml, whose whitelist_rules key current SwiftLint rejects - Drop the cocoapods hook from the Fastfile; CocoaPods left in 2022, and the test lane has been broken ever since UserDefaults keys userNAME, highscore_normal and bgSound are kept verbatim so an existing install keeps its nickname and record. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The app on
developdid not play. The 2019 SwiftUI rewrite left every screen as a// TODO:stub, the real game logic sat commented out inDEPRECATED/GameViewController.swift, and the project still targeted iOS 15 with Swift 5 behind a UIKit/storyboard launch path. This rebuilds it on a current stack and, in the process, makes it a working game again.The game rules were recovered from the code that actually shipped to the App Store, which lives on
master(HardcoreTap/HardcoreTap/ViewController.swift).What changed
Project
project.pbxprojregenerated withPBXFileSystemSynchronizedRootGroup(Xcode 16+) β sources join the target by living in the folder, no per-file entries to maintainInfo.plistandLaunchScreen.storyboardremoved; both are generated fromINFOPLIST_KEY_*build settingsHardcoreTap for Watchscheme, which pointed at a target that has never existed in this project fileCode β 17 files replacing the previous tree
AppDelegate+SceneDelegate+ storyboard β@main App+TabViewGameEngine, on@ObservableandContinuousClock. Every method takes the current instant as a parameter rather than reading the clock, which is what lets the tests play a full round β hits, misses, tolerance decay, restart cool-down β in 11 msCAGradientLayers become aMeshGradientthat pulses on the beat; the tolerance window is now visible as an arc on the beat ring, so the difficulty curve is legible at a glanceGKScore.reportto asyncGKLeaderboardTooling
Localizable.stringsβ String Catalog, 58 keys with Russian translations.swiftlint.yml:whitelist_rulesβonly_rules; the old key is a hard error on current SwiftLint, so linting was failing outrightFastfileno longer callscocoapodsβ CocoaPods was removed in 2022 and thetestlane has been broken sinceVerification
Built, tested (16/16 passing) and run on an iPhone 17 simulator. The full loop works end to end: start β tick β missed-beat detection β game-over screen. The nickname loads from the legacy
userNAMEkey, and the Russian locale renders correctly.Two defects found and fixed while verifying: the
sunit was not localized, and Game Center flashed a blank sheet over the app at launch.For the reviewer
UserDefaultskeysuserNAME,highscore_normalandbgSoundare kept verbatim, so an existing install keeps its nickname and record.GKLocalPlayer's handler fires during launch and may hand back a view controller; presenting it immediately throws a modal over the game before the player has asked for anything, and when Game Center is misconfigured that modal is blank. The leaderboard offers a button instead.GameMode.leaderboardIDare new. Until they are configured, submissions no-op and the leaderboard falls back to local records.Timer; against a continuous clock it is unhittable. 0.01 s matches the "accurate to hundredths" the game describes.Snapfiledeleted: it referenced a UI test target that has not been on this branch since 2019. Restore it alongside real UI tests if automated screenshots are wanted.Unrelated, but worth knowing:
master'sInfo.plistcontains a live-looking Fabric API key in git history. Fabric is long dead, but this repository is public.π€ Generated with Claude Code