iOS / Swift
8 min read
•
Updated Aug 2026
Building a Native iOS 4K Wallpaper App in Swift & SwiftUI with AsyncImage
Step-by-step iOS native guide using Swift 5.9, SwiftUI, URLSession, and AsyncImage to build a liquid-smooth wallpaper app with dark mode support.
1. Swift Codable Model for Wallpapers
Create a Swift model to decode the NexWall 4K JSON payload with type safety:
import Foundation
struct WallpaperItem: Identifiable, Codable {
let id: Int
let categoryId: Int
let imageUrl: String
let thumbnailUrl: String
let isPremium: Bool
let resolution: String
enum CodingKeys: String, CodingKey {
case id
case categoryId = "category_id"
case imageUrl = "image_url"
case thumbnailUrl = "thumbnail_url"
case isPremium = "is_premium"
case resolution
}
}
struct WallpaperResponse: Codable {
let success: Bool
let data: [WallpaperItem]
}
2. URLSession Network Service
import Foundation
class WallpaperAPIService: ObservableObject {
@Published var wallpapers: [WallpaperItem] = []
@Published var isLoading = false
private let apiKey = "YOUR_NEXWALL_API_KEY"
func fetchWallpapers(page: Int = 1) async {
guard let url = URL(string: "https://nexwall.kodnextech.com/api/developer/v1/wallpapers?page=\(page)&per_page=30") else { return }
var request = URLRequest(url: url)
request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Accept")
do {
let (data, _) = try await URLSession.shared.data(for: request)
let decoded = try JSONDecoder().decode(WallpaperResponse.self, from: data)
DispatchQueue.main.async {
self.wallpapers = decoded.data
self.isLoading = false
}
} catch {
print("Fetch error: \(error)")
}
}
}
3. SwiftUI Staggered Grid with AsyncImage
import SwiftUI
struct WallpaperGridView: View {
@StateObject var api = WallpaperAPIService()
let columns = [GridItem(.flexible(), spacing: 12), GridItem(.flexible(), spacing: 12)]
var body: some View {
NavigationView {
ScrollView {
LazyVGrid(columns: columns, spacing: 12) {
ForEach(api.wallpapers) { item in
AsyncImage(url: URL(string: item.thumbnailUrl)) { image in
image.resizable()
.aspectRatio(9/16, contentMode: .fill)
.clipped()
.cornerRadius(14)
} placeholder: {
Color(white: 0.15).aspectRatio(9/16, contentMode: .fit)
}
}
}
.padding()
}
.background(Color.black.edgesIgnoringSafeArea(.all))
.navigationTitle("4K Wallpapers")
.task {
await api.fetchWallpapers()
}
}
}
}
Want to test this endpoint right now?
Use the interactive Live Sandbox Console to test queries without writing code.