Skip to content

Commit eb3a5fa

Browse files
authored
Merge pull request #11 from pawello2222/ios17-refactor
[Refactor] Update project to iOS 17
2 parents e50e31d + e7b6b1e commit eb3a5fa

File tree

197 files changed

+8184
-3691
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

197 files changed

+8184
-3691
lines changed

.github/workflows/ci.yml

+12-5
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ on:
77
branches: [ main ]
88

99
env:
10-
SCHEME: WidgetExamples
11-
IOS_SDK: iphonesimulator
12-
IOS_DESTINATION: "platform=iOS Simulator,name=iPhone 13 Pro,OS=latest"
10+
SCHEME: "Widget Examples"
11+
IOS_SDK: "iphonesimulator"
12+
IOS_DESTINATION: "platform=iOS Simulator,name=Any iOS Simulator Device,OS=latest"
1313

1414
jobs:
1515
lint:
@@ -21,13 +21,20 @@ jobs:
2121
uses: norio-nomura/action-swiftlint@3.2.1
2222

2323
build:
24-
runs-on: macos-latest
24+
runs-on: macos-13
2525
steps:
2626
- name: Checkout
2727
uses: actions/checkout@v3
28+
- name: Install Swift
29+
uses: slashmo/install-swift@v0.4.0
30+
with:
31+
version: swift-5.9-DEVELOPMENT-SNAPSHOT-2023-07-04-a
32+
- run: ls /Applications
33+
- run: sudo xcode-select -s '/Applications/Xcode_15.0.app/Contents/Developer'
2834
- name: Build
2935
run: |
3036
xcodebuild clean build \
3137
-scheme "$SCHEME" \
3238
-sdk "$IOS_SDK" \
33-
-destination "$IOS_DESTINATION"
39+
-destination "$IOS_DESTINATION" \
40+
CODE_SIGNING_ALLOWED=NO

.gitignore

+5-126
Original file line numberDiff line numberDiff line change
@@ -1,133 +1,12 @@
1-
# Created by https://www.toptal.com/developers/gitignore/api/swift,xcode,macos
2-
# Edit at https://www.toptal.com/developers/gitignore?templates=swift,xcode,macos
3-
4-
### macOS ###
5-
# General
61
.DS_Store
7-
.AppleDouble
8-
.LSOverride
9-
10-
# Icon must end with two \r
11-
Icon
12-
13-
# Thumbnails
14-
._*
15-
16-
# Files that might appear in the root of a volume
17-
.DocumentRevisions-V100
18-
.fseventsd
19-
.Spotlight-V100
20-
.TemporaryItems
21-
.Trashes
22-
.VolumeIcon.icns
23-
.com.apple.timemachine.donotpresent
24-
25-
# Directories potentially created on remote AFP share
26-
.AppleDB
27-
.AppleDesktop
28-
Network Trash Folder
29-
Temporary Items
30-
.apdisk
31-
32-
### Swift ###
33-
# Xcode
34-
#
35-
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
36-
37-
## User settings
38-
xcuserdata/
39-
40-
## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
41-
*.xcscmblueprint
42-
*.xccheckout
43-
44-
## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
45-
build/
46-
DerivedData/
47-
*.moved-aside
48-
*.pbxuser
49-
!default.pbxuser
50-
*.mode1v3
51-
!default.mode1v3
52-
*.mode2v3
53-
!default.mode2v3
54-
*.perspectivev3
55-
!default.perspectivev3
56-
57-
## Obj-C/Swift specific
58-
*.hmap
59-
60-
## App packaging
61-
*.ipa
62-
*.dSYM.zip
63-
*.dSYM
64-
65-
## Playgrounds
66-
timeline.xctimeline
67-
playground.xcworkspace
68-
69-
# Swift Package Manager
70-
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
71-
# Packages/
72-
# Package.pins
73-
# Package.resolved
74-
# *.xcodeproj
75-
# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata
76-
# hence it is not needed unless you have added a package configuration file to your project
77-
# .swiftpm
78-
79-
.build/
2+
.build
3+
.swiftpm/xcode/package.xcworkspace
4+
.swiftpm/xcode/xcuserdata
5+
Package.resolved
806

81-
# CocoaPods
82-
# We recommend against adding the Pods directory to your .gitignore. However
83-
# you should judge for yourself, the pros and cons are mentioned at:
84-
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
85-
# Pods/
86-
# Add this line if you want to avoid checking in source code from the Xcode workspace
87-
# *.xcworkspace
88-
89-
# Carthage
90-
# Add this line if you want to avoid checking in source code from Carthage dependencies.
91-
# Carthage/Checkouts
92-
93-
Carthage/Build/
94-
95-
# Accio dependency management
96-
Dependencies/
97-
.accio/
98-
99-
# fastlane
100-
# It is recommended to not store the screenshots in the git repo.
101-
# Instead, use fastlane to re-generate the screenshots whenever they are needed.
102-
# For more information about the recommended setup visit:
103-
# https://docs.fastlane.tools/best-practices/source-control/#source-control
104-
105-
fastlane/report.xml
106-
fastlane/Preview.html
107-
fastlane/screenshots/**/*.png
108-
fastlane/test_output
109-
110-
# Code Injection
111-
# After new code Injection tools there's a generated folder /iOSInjectionProject
112-
# https://github.com/johnno1962/injectionforxcode
113-
114-
iOSInjectionProject/
115-
116-
### Xcode ###
117-
# Xcode
118-
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
119-
120-
121-
122-
123-
## Gcc Patch
124-
/*.gcno
125-
126-
### Xcode Patch ###
7+
xcuserdata
1278
*.xcodeproj/*
1289
!*.xcodeproj/project.pbxproj
12910
!*.xcodeproj/xcshareddata/
13011
!*.xcworkspace/contents.xcworkspacedata
13112
**/xcshareddata/WorkspaceSettings.xcsettings
132-
133-
# End of https://www.toptal.com/developers/gitignore/api/swift,xcode,macos

.resources/Assets/icon.png

9.48 KB
Loading

.resources/Assets/icon.svg

+102
Loading

.resources/Assets/logo.png

24.2 KB
Loading

.resources/Assets/logo.svg

+125
Loading

.resources/Assets/social.png

56.6 KB
Loading

.resources/Assets/social.svg

+196
Loading
424 KB
Loading
443 KB
Loading
44 KB
Loading
747 KB
Loading
52.7 KB
Loading
1.16 MB
Loading
322 KB
Loading
833 KB
Loading
161 KB
Loading
2.58 MB
Loading
258 KB
Loading
34.8 KB
Loading
178 KB
Loading
534 KB
Loading
50.8 KB
Loading
131 KB
Loading
128 KB
Loading
110 KB
Loading
108 KB
Loading
138 KB
Loading
133 KB
Loading
130 KB
Loading
126 KB
Loading
138 KB
Loading
474 KB
Loading
120 KB
Loading
113 KB
Loading
241 KB
Loading
128 KB
Loading
141 KB
Loading

App/App.swift

+23-3
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,30 @@ import SwiftUI
2525
@main
2626
struct WidgetExamplesApp: App {
2727
var body: some Scene {
28-
let moc = CoreDataStack.shared.managedObjectContext
29-
return WindowGroup {
28+
WindowGroup {
29+
let persistenceController = PersistenceController.shared
3030
ContentView()
31-
.environment(\.managedObjectContext, moc)
31+
.environment(\.managedObjectContext, persistenceController.managedObjectContext)
32+
.modelContainer(for: Product.self)
3233
}
3334
}
3435
}
36+
37+
// MARK: - Screenshots
38+
39+
extension WidgetExamplesApp {
40+
@MainActor
41+
private func createScreenshot() {
42+
let view = SharedViewWidgetEntryView(entry: .placeholder)
43+
.padding(15)
44+
.frame(width: 150, height: 150)
45+
.background(.white)
46+
.clipShape(RoundedRectangle(cornerRadius: 20))
47+
.padding(15)
48+
.environment(\.locale, .init(identifier: "en_US"))
49+
let renderer = ImageRenderer(content: view)
50+
renderer.scale = 10
51+
let filename = URL.documentsDirectory.appending(path: "SharedViewWidget.png")
52+
try? renderer.uiImage?.pngData()?.write(to: filename)
53+
}
54+
}

App/ContentView.swift

+11-129
Original file line numberDiff line numberDiff line change
@@ -20,143 +20,25 @@
2020
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2121
// SOFTWARE.
2222

23-
import CoreData
2423
import SwiftUI
25-
import WidgetKit
2624

2725
struct ContentView: View {
28-
@Environment(\.managedObjectContext) private var managedObjectContext
29-
@FetchRequest(entity: Item.entity(), sortDescriptors: []) private var items: FetchedResults<Item>
30-
@AppStorage(Key.luckyNumber.rawValue, store: .appGroup) private var luckyNumber = 0
31-
@State private var contacts = Contact.getAll()
26+
@State private var selection: AppScreen?
3227

3328
var body: some View {
34-
List {
35-
appGroupWidgetSection
36-
coreDataWidgetSection
37-
deepLinkWidgetSection
38-
dynamicIntentWidgetSection
39-
previewWidgetSection
29+
NavigationSplitView(
30+
columnVisibility: .constant(.doubleColumn),
31+
preferredCompactColumn: .constant(.sidebar)
32+
) {
33+
AppSidebarList(selection: $selection)
34+
} detail: {
35+
AppDetailColumn(screen: selection)
4036
}
41-
.listStyle(InsetGroupedListStyle())
4237
}
4338
}
4439

45-
// MARK: - AppGroup Widget
40+
// MARK: - Preview
4641

47-
extension ContentView {
48-
private var appGroupWidgetSection: some View {
49-
Section(header: Text("AppGroup Widget")) {
50-
Text("Lucky number: \(luckyNumber)")
51-
Button("Generate new lucky number") {
52-
luckyNumber = Int.random(in: 1 ... 99)
53-
WidgetCenter.shared.reloadTimelines(ofKind: WidgetKind.appGroup)
54-
}
55-
.buttonStyle(PlainButtonStyle())
56-
.foregroundColor(.accentColor)
57-
}
58-
.onChange(of: luckyNumber) { _ in
59-
let url = FileManager.appGroupContainerURL.appendingPathComponent(FileManager.luckyNumberFilename)
60-
try? String(luckyNumber).write(to: url, atomically: false, encoding: .utf8)
61-
}
62-
}
63-
}
64-
65-
// MARK: - CoreData Widget
66-
67-
extension ContentView {
68-
private var coreDataWidgetSection: some View {
69-
Section(header: Text("CoreData Widget")) {
70-
Text("Items count: \(items.count)")
71-
addNewItemsButton
72-
deleteAllItemsButton
73-
}
74-
.onChange(of: luckyNumber) { _ in
75-
let url = FileManager.appGroupContainerURL.appendingPathComponent(FileManager.luckyNumberFilename)
76-
try? String(luckyNumber).write(to: url, atomically: false, encoding: .utf8)
77-
}
78-
}
79-
80-
private var addNewItemsButton: some View {
81-
Button("Add new item") {
82-
let context = CoreDataStack.shared.workingContext
83-
let item = Item(context: context)
84-
item.name = "test"
85-
item.count = 1
86-
CoreDataStack.shared.saveWorkingContext(context: context)
87-
WidgetCenter.shared.reloadTimelines(ofKind: WidgetKind.coreData)
88-
}
89-
.buttonStyle(PlainButtonStyle())
90-
.foregroundColor(.accentColor)
91-
}
92-
93-
private var deleteAllItemsButton: some View {
94-
Button("Delete all items") {
95-
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Item")
96-
let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
97-
do {
98-
try CoreDataStack.shared.managedObjectContext.executeAndMergeChanges(deleteRequest)
99-
} catch {
100-
print(error.localizedDescription)
101-
}
102-
WidgetCenter.shared.reloadTimelines(ofKind: WidgetKind.coreData)
103-
}
104-
.buttonStyle(PlainButtonStyle())
105-
.foregroundColor(.red)
106-
}
107-
}
108-
109-
// MARK: - DeepLink Widget
110-
111-
extension ContentView {
112-
private var deepLinkWidgetSection: some View {
113-
Section(header: Text("DeepLink Widget")) {
114-
Text("")
115-
.onOpenURL { url in
116-
if url.scheme == "widget-DeepLinkWidget", url.host == "widgetFamily" {
117-
let widgetFamily = url.lastPathComponent
118-
print("Opened from widget of size: \(widgetFamily)")
119-
}
120-
}
121-
}
122-
}
123-
}
124-
125-
// MARK: - Dynamic Intent Widget
126-
127-
extension ContentView {
128-
private var dynamicIntentWidgetSection: some View {
129-
Section(header: Text("Dynamic Intent Widget")) {
130-
ForEach(contacts.indices, id: \.self) { index in
131-
HStack {
132-
TextField("", text: $contacts[index].name, onCommit: saveContacts)
133-
DatePicker("", selection: $contacts[index].dateOfBirth, displayedComponents: .date)
134-
.onChange(of: contacts[index].dateOfBirth) { _ in
135-
saveContacts()
136-
}
137-
}
138-
}
139-
}
140-
}
141-
142-
private func saveContacts() {
143-
let key = UserDefaults.Keys.contacts.rawValue
144-
UserDefaults.appGroup.setArray(contacts, forKey: key)
145-
WidgetCenter.shared.reloadTimelines(ofKind: WidgetKind.dynamicIntent)
146-
}
147-
}
148-
149-
// MARK: - Preview Widget
150-
151-
extension ContentView {
152-
private var previewWidgetSection: some View {
153-
let entry = PreviewWidgetEntry(date: Date(), systemImageName: "star.fill")
154-
return Section(header: Text("Preview Widget")) {
155-
HStack {
156-
PreviewWidgetEntryView(entry: entry)
157-
.frame(width: 200, height: 200)
158-
}
159-
.frame(maxWidth: .infinity)
160-
}
161-
}
42+
#Preview {
43+
ContentView()
16244
}

0 commit comments

Comments
 (0)