A reusable Swift Package for showing an app's "My Apps" section.
MyAppsCore: data models, iTunes API service, and view model.MyAppsUI: ready-to-use SwiftUI section view.
This package shows other apps from the same App Store publisher account (same artistId) as your seed app.
Selection logic:
- Use
developerSeedAppIDto look up a seed app and resolve itsartistId. - Fetch apps for that developer and keep only items with the same
artistId. - Exclude
currentAppIDso the current app is not shown in the list. - Apply storefront filtering by
countryCode(results can vary by country).
en,zh-Hans,zh-Hant,ja,ko,de,fr,es,it,pt-BR,pt-PT,ru,tr,pl,ar
In Xcode:
File->Add Packages...- input
https://github.com/roMummy/MyAppsKit.git - Add product to your target:
MyAppsUIfor ready-to-use SwiftUI section UI.MyAppsCorefor non-UI/business-layer usage only.
import MyAppsCore
import MyAppsUI
import SwiftUI
struct SettingsView: View {
@StateObject private var myAppsViewModel = DeveloperAppsViewModel(
configuration: .init(
currentAppID: "0000",
developerSeedAppID: "000",
countryCode: "us"
)
)
var body: some View {
MyAppsSectionView(
state: myAppsViewModel.state,
onRetry: {
Task { await myAppsViewModel.retry() }
},
onTapApp: { app in
guard let url = app.trackViewURL else { return }
UIApplication.shared.open(url)
},
onSectionAppear: {
// optional analytics
}
)
.task {
await myAppsViewModel.loadIfNeeded()
}
}
}Use only MyAppsCore and build your own UI.
Example below renders a simple list item with icon + title + description.
import MyAppsCore
import SwiftUI
struct SimpleMyAppsListView: View {
@Environment(\.openURL) private var openURL
@StateObject private var viewModel = DeveloperAppsViewModel(
configuration: .init(
currentAppID: "0000",
developerSeedAppID: "000",
countryCode: "us"
)
)
var body: some View {
Group {
switch viewModel.state {
case .idle, .loading:
ProgressView()
case .failed(let message):
VStack(spacing: 12) {
Text(message)
.font(.footnote)
.foregroundStyle(.secondary)
Button("Retry") {
Task { await viewModel.retry() }
}
}
case .loaded(let apps):
List(apps) { app in
HStack(alignment: .top, spacing: 12) {
AsyncImage(url: URL(string: app.artworkUrl100 ?? "")) { image in
image.resizable().scaledToFill()
} placeholder: {
Color(.systemGray5)
}
.frame(width: 44, height: 44)
.clipShape(RoundedRectangle(cornerRadius: 10))
VStack(alignment: .leading, spacing: 4) {
Text(app.trackName)
.font(.headline)
.lineLimit(1)
Text(summaryText(for: app.description))
.font(.subheadline)
.foregroundStyle(.secondary)
.lineLimit(2)
}
}
.contentShape(Rectangle())
.onTapGesture {
guard let url = app.trackViewURL else { return }
openURL(url)
}
}
.listStyle(.plain)
}
}
.task {
await viewModel.loadIfNeeded()
}
}
private func summaryText(for text: String?) -> String {
guard let text else { return "No description" }
let trimmed = text.trimmingCharacters(in: .whitespacesAndNewlines)
guard trimmed.isEmpty == false else { return "No description" }
return String(trimmed.split(separator: "\n").first ?? Substring(trimmed))
}
}If you only need raw data (no ViewModel), you can call DeveloperAppsService directly:
import MyAppsCore
let service = DeveloperAppsService(
configuration: .init(
currentAppID: "0000",
developerSeedAppID: "000",
countryCode: "us"
)
)
let apps = try await service.fetchApps()