I am new to swift. I am trying to achieve the requirement is when the spacific view record is selected I am want to move into details view with selected record including image. But the problems is the text property is display as expected not image failed.
so far I have tried Image(people.avatar ?? "")
but actually it not working. even I can not see it into preview as well.
Here is the content view code ..
import SwiftUI
struct PeopleListView: View {
@StateObject var viewModel: PeopleListViewModel
var body: some View {
NavigationStack {
VStack {
if viewModel.customError != nil && !viewModel.refreshing {
alertView()
} else {
if viewModel.refreshing {
progressView()
}
if viewModel.peopleLists.count > 0 && !viewModel.refreshing {
List(viewModel.peopleLists, id: \.self) { people in
NavigationLink(destination: PeopleDetailsView(people: people)) {
PeopleCellView(people: people)
}
}
}
}
}
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
getToolBarView()
}
}
.navigationTitle(Text("Employees List"))
}.task{
await getDataFromAPI()
}
.refreshable {
await getDataFromAPI()
}
}
func getDataFromAPI() async {
await viewModel.getPeopleList(urlStr: NetworkURL.peopleUrl)
}
@ViewBuilder
func getToolBarView() -> some View {
Button {
Task{
await getDataFromAPI()
}
} label: {
HStack {
Image(systemName: "arrow.clockwise")
.padding(.all, 10.0)
}.fixedSize()
}
.cornerRadius(5.0)
}
@ViewBuilder
func progressView() -> some View {
VStack{
RoundedRectangle(cornerRadius: 15)
.fill(.white)
.frame(height: 180)
.overlay{
VStack{
ProgressView().padding(50)
Text("Please Wait Message").font(.headline)
}
}
}
}
@ViewBuilder
func alertView() -> some View {
Text("").alert(isPresented: $viewModel.isErrorOccured) {
Alert(title: Text("General_Error"), message: Text(viewModel.customError?.localizedDescription ?? ""),dismissButton: .default(Text("Okay")))
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
PeopleListView(viewModel: PeopleListViewModel(repository: PeopleRepositoryImplementation(networkManager: NetworkManager())))
}
}
Here is code for cashed ..
import SwiftUI
struct CacheAsyncImage<Content>: View where Content: View {
private let url: URL
private let scale: CGFloat
private let transaction: Transaction
private let content: (AsyncImagePhase) -> Content
init(url: URL,
scale: CGFloat = 1.0,
transaction: Transaction = Transaction(),
@ViewBuilder content: @escaping (AsyncImagePhase) -> Content) {
self.url = url
self.scale = scale
self.transaction = transaction
self.content = content
}
var body: some View {
if let cached = ImageCache[url] {
content(.success(cached))
} else {
AsyncImage(url: url,
scale: scale,
transaction: transaction) { phase in
cacheAndRender(phase: phase)
}
}
}
func cacheAndRender(phase: AsyncImagePhase) -> some View {
if case .success(let image) = phase {
ImageCache[url] = image
}
return content(phase)
}
}
fileprivate class ImageCache {
static private var cache: [URL: Image] = [:]
static subscript(url: URL) -> Image? {
get {
ImageCache.cache[url]
}
set {
ImageCache.cache[url] = newValue
}
}
}
Here is code for async image cashed ..
import SwiftUI
struct PeopleAsyncImageView: View {
let url: URL
private let imageWidth = 150.0
private let cellHeight = 150.0
var body: some View {
CacheAsyncImage(
url: url) { phase in
switch phase {
case .success(let image):
VStack {
image
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: imageWidth)
.padding(.trailing, 10)
Spacer()
}
case .failure:
Image("placeholder-image")
case .empty:
HStack(alignment: .center) {
ProgressView()
.progressViewStyle(CircularProgressViewStyle(tint: .red))
}
@unknown default:
Image("placeholder-image")
}
}
}
}
Here is the code for view for respective properties including the image ..
import SwiftUI
struct PeopleCellView: View {
let people: PeopleData
var body: some View {
HStack {
if let url = URL(string: people.avatar ?? ""){
PeopleAsyncImageView(url: url)
.frame(width: 150, height: 150)
.mask(RoundedRectangle(cornerRadius: 16))
}
VStack(alignment: .leading,spacing: 5){
Text("First Name: " + people.firstName)
.frame(maxWidth: .infinity, alignment: .leading)
.font(.headline)
Text("Last Name: " + (people.lastName ?? ""))
.frame(maxWidth: .infinity, alignment: .leading)
Text("Email: " + (people.email ?? ""))
.frame(maxWidth: .infinity, alignment: .leading)
.font(.subheadline)
}
}
}
}
struct PeopleCellView_Previews: PreviewProvider {
static var previews: some View {
PeopleCellView(people: Constants.previewPeopleObj)
}
}
Here is the details view code ..
import SwiftUI
struct PeopleDetailsView: View {
@State var people: PeopleData
var body: some View {
VStack(alignment: .center) {
Image(people.avatar ?? "")
Text("First Name - \(people.firstName)")
Text("Last Name: \(people.lastName ?? " ")")
Text("Email: \(people.email ?? " ")")
}
}
}
struct PeopleDetailsView_Previews: PreviewProvider {
static var previews: some View {
PeopleDetailsView(people: Constants.previewPeopleObj)
}
}
Here is the screenshot of the app ..
Here is the screenshot of the details view ..