Skip to content

Commit 5ebd93e

Browse files
committed
network
1 parent 2ac14b7 commit 5ebd93e

File tree

6 files changed

+147
-1
lines changed

6 files changed

+147
-1
lines changed

My App/My App.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
AB5C9B6F2ADBE02F00A358EC /* My_AppUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB5C9B6E2ADBE02F00A358EC /* My_AppUITestsLaunchTests.swift */; };
1717
AB5C9B7C2ADBE8AF00A358EC /* ButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB5C9B7B2ADBE8AF00A358EC /* ButtonView.swift */; };
1818
AB5C9B802ADBF38700A358EC /* ListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB5C9B7F2ADBF38700A358EC /* ListView.swift */; };
19+
AB5C9B822ADBF7B100A358EC /* NetworkingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB5C9B812ADBF7B100A358EC /* NetworkingView.swift */; };
1920
/* End PBXBuildFile section */
2021

2122
/* Begin PBXContainerItemProxy section */
@@ -48,6 +49,7 @@
4849
AB5C9B6E2ADBE02F00A358EC /* My_AppUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = My_AppUITestsLaunchTests.swift; sourceTree = "<group>"; };
4950
AB5C9B7B2ADBE8AF00A358EC /* ButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonView.swift; sourceTree = "<group>"; };
5051
AB5C9B7F2ADBF38700A358EC /* ListView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ListView.swift; path = "My App/ListView.swift"; sourceTree = SOURCE_ROOT; };
52+
AB5C9B812ADBF7B100A358EC /* NetworkingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkingView.swift; sourceTree = "<group>"; };
5153
/* End PBXFileReference section */
5254

5355
/* Begin PBXFrameworksBuildPhase section */
@@ -104,6 +106,7 @@
104106
AB5C9B572ADBE02F00A358EC /* Preview Content */,
105107
AB5C9B7B2ADBE8AF00A358EC /* ButtonView.swift */,
106108
AB5C9B7F2ADBF38700A358EC /* ListView.swift */,
109+
AB5C9B812ADBF7B100A358EC /* NetworkingView.swift */,
107110
);
108111
path = "My App";
109112
sourceTree = "<group>";
@@ -263,6 +266,7 @@
263266
isa = PBXSourcesBuildPhase;
264267
buildActionMask = 2147483647;
265268
files = (
269+
AB5C9B822ADBF7B100A358EC /* NetworkingView.swift in Sources */,
266270
AB5C9B802ADBF38700A358EC /* ListView.swift in Sources */,
267271
AB5C9B542ADBE02E00A358EC /* ContentView.swift in Sources */,
268272
AB5C9B522ADBE02E00A358EC /* My_AppApp.swift in Sources */,

My App/My App/ContentView.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ struct ContentView: View {
1919
NavigationLink(destination: ListView(items: ["Item 1", "Item 2", "Item 3"])) {
2020
Text("Go to list")
2121
}
22+
NavigationLink(destination: NetworkingView()) {
23+
Text("Go to networking")
24+
}
2225
}
2326
.padding()
2427
}

My App/My App/NetworkingView.swift

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//
2+
// NetworkingView.swift
3+
// My App
4+
//
5+
// Created by Irfan Nafi on 10/15/23.
6+
//
7+
8+
import SwiftUI
9+
10+
struct NetworkingView: View {
11+
@State var posts: [Post] = []
12+
13+
var body: some View {
14+
List(posts, id: \.id) { post in
15+
VStack(alignment: .leading) {
16+
Text(post.title)
17+
.font(.headline)
18+
Text(post.body)
19+
.font(.subheadline)
20+
}
21+
}
22+
.task {
23+
do {
24+
posts = try await fetchPosts()
25+
} catch {
26+
print(error)
27+
}
28+
}
29+
}
30+
31+
func fetchPosts() async throws -> [Post] {
32+
let url = URL(string: "https://jsonplaceholder.typicode.com/posts")!
33+
let (data, _) = try await URLSession.shared.data(from: url)
34+
return try JSONDecoder().decode([Post].self, from: data)
35+
}
36+
}
37+
38+
struct Post: Codable, Identifiable {
39+
let id: Int
40+
let title: String
41+
let body: String
42+
}

README.md

Lines changed: 98 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,104 @@ NavigationView {
178178

179179
![](/hackpack-assets/navigation.gif)
180180

181-
### Uploading to the App Store
181+
### Networking
182+
183+
1. Let's create a new screen that displays a list of items from an API. Right click on the folder tree and click "New File...". Select "Swift File" and click "Next". Enter "NetworkingView.swift" as the file name and click "Create". You should see a new file called `NetworkingView.swift` in the folder tree.
184+
185+
2. In `NetworkingView.swift`, let's call the [JSON Placeholder API](https://jsonplaceholder.typicode.com/) to get a list of posts. Add the following shown below. By creating a `@State var posts: [Post]` property, we can store the list of posts in the view. You can read more about state [here](<https://developer.apple.com/documentation/swiftui/state>).
186+
187+
```swift
188+
import SwiftUI
189+
190+
struct NetworkingView: View {
191+
@State var posts: [Post] = []
192+
193+
var body: some View {
194+
List(posts, id: \.id) { post in
195+
VStack(alignment: .leading) {
196+
Text(post.title)
197+
.font(.headline)
198+
Text(post.body)
199+
.font(.subheadline)
200+
}
201+
}
202+
.task {
203+
do {
204+
posts = try await fetchPosts()
205+
} catch {
206+
print(error)
207+
}
208+
}
209+
}
210+
211+
func fetchPosts() async throws -> [Post] {
212+
let url = URL(string: "https://jsonplaceholder.typicode.com/posts")!
213+
let (data, _) = try await URLSession.shared.data(from: url)
214+
return try JSONDecoder().decode([Post].self, from: data)
215+
}
216+
}
217+
218+
struct Post: Codable, Identifiable {
219+
let id: Int
220+
let title: String
221+
let body: String
222+
}
223+
```
224+
225+
3. A task is a piece of code that runs asynchronously. You can read more about tasks [here](https://docs.swift.org/swift-book/LanguageGuide/Concurrency/ConcurrencyQuickTour.html#ID617). In the `task` modifier, we call the `fetchPosts` function to get a list of posts. We then set the `posts` property to the list of posts. You can read more about the `task` modifier [here](https://developer.apple.com/documentation/swiftui/view/task(id:priority:)).
226+
227+
4. A `Codable` type is a type that can be encoded and decoded from JSON. You can read more about it [here](https://developer.apple.com/documentation/swift/codable). We create a `Post` struct that conforms to the `Codable` protocol. We also make it conform to the `Identifiable` protocol so that we can use it in a `List`. You can read more about the `Identifiable` protocol [here](https://developer.apple.com/documentation/swiftui/identifiable).
228+
229+
5. An `Identifiable` type is a type that has a stable identity. You can read more about it [here](https://developer.apple.com/documentation/swiftui/identifiable). We make the `id` property of the `Post` struct the stable identity.
230+
231+
6. Go back to `ContentView.swift`. Add a navigation link to the `VStack`, under `NavigationLink`. You can read more about it [here](https://developer.apple.com/documentation/swiftui/navigationlink).
232+
233+
```swift
234+
NavigationView {
235+
VStack {
236+
Image(systemName: "globe")
237+
.imageScale(.large)
238+
.foregroundStyle(.tint)
239+
Text("Hello, world!")
240+
ButtonView(label: "Tap me!")
241+
NavigationLink(destination: ListView(items: ["Item 1", "Item 2", "Item 3"])) {
242+
Text("Go to list")
243+
}
244+
NavigationLink(destination: NetworkingView()) {
245+
Text("Go to networking")
246+
}
247+
}
248+
.padding()
249+
}
250+
```
251+
252+
7. Here's what the app should look like now:
253+
254+
![](/hackpack-assets/network.gif)
255+
256+
### Styling
257+
258+
1. Now that we've gotten some basic SwiftUI down, let's style the app. Go back to `ContentView.swift`. Add the following code to the `VStack`, under `NavigationLink`. You can read more about the `background` modifier [here](<https://developer.apple.com/documentation/swiftui/view/background(_:alignment:)>).
259+
260+
```swift
261+
NavigationView {
262+
VStack {
263+
Image(systemName: "globe")
264+
.imageScale(.large)
265+
.foregroundStyle(.tint)
266+
Text("Hello, world!")
267+
ButtonView(label: "Tap me!")
268+
NavigationLink(destination: ListView(items: ["Item 1", "Item 2", "Item 3"])) {
269+
Text("Go to list")
270+
}
271+
NavigationLink(destination: NetworkingView()) {
272+
Text("Go to networking")
273+
}
274+
}
275+
.padding()
276+
.background(Color(.systemBackground))
277+
}
278+
```
182279

183280
# Congratulations! 🎉
184281

hackpack-assets/network.gif

2 MB
Loading

0 commit comments

Comments
 (0)