Skip to content

Commit

Permalink
[Refactoring] SDWebImageSwiftUI, Combine 추가 (#91)
Browse files Browse the repository at this point in the history
* [Refactor] Network 통신 에 dataTaskPublisher 적용

* [Refactor] var -> let 으로 변경

* [Refactor] AsyncImage -> SDWebImageSwiftUI WebImage 로 변경

* [Refactor] weak self 추가

* [Refacto] weak self 추가
  • Loading branch information
insub4067 authored Oct 2, 2023
1 parent a0b5380 commit c4f20f1
Show file tree
Hide file tree
Showing 10 changed files with 146 additions and 156 deletions.
21 changes: 17 additions & 4 deletions AsyncSwift.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
C63D4450291BDD2B005D5AE6 /* String+.swift in Sources */ = {isa = PBXBuildFile; fileRef = C63D444F291BDD2B005D5AE6 /* String+.swift */; };
C66C68D328D1B00A0091F960 /* EventModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C66C68D228D1B00A0091F960 /* EventModel.swift */; };
C66C68D528D1B0130091F960 /* SessionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C66C68D428D1B0130091F960 /* SessionModel.swift */; };
C66DAD5028CF478700195DEB /* SessionView+Observed.swift in Sources */ = {isa = PBXBuildFile; fileRef = C66DAD4F28CF478700195DEB /* SessionView+Observed.swift */; };
C66E3D95290BA48500097BEA /* ProfileRegisterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C66E3D94290BA48500097BEA /* ProfileRegisterView.swift */; };
C66E3D97290BA4FC00097BEA /* ProfileRegisterViewObserved.swift in Sources */ = {isa = PBXBuildFile; fileRef = C66E3D96290BA4FC00097BEA /* ProfileRegisterViewObserved.swift */; };
C66E3D99290BB9C100097BEA /* TextEditor+.swift in Sources */ = {isa = PBXBuildFile; fileRef = C66E3D98290BB9C100097BEA /* TextEditor+.swift */; };
Expand Down Expand Up @@ -56,6 +55,7 @@
E9171F0028D15426002FAF52 /* TicketingView+Observed.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9171EFF28D15426002FAF52 /* TicketingView+Observed.swift */; };
E94F92C728D2505100D9E759 /* Ticketing.swift in Sources */ = {isa = PBXBuildFile; fileRef = E94F92C628D2505100D9E759 /* Ticketing.swift */; };
E9E2A4D828CEC5680016AEFF /* WebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9E2A4D728CEC5680016AEFF /* WebView.swift */; };
FB1FB1A72ACA7B3A00FF62AC /* SDWebImageSwiftUI in Frameworks */ = {isa = PBXBuildFile; productRef = FB1FB1A62ACA7B3A00FF62AC /* SDWebImageSwiftUI */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
Expand All @@ -71,7 +71,6 @@
C63D444F291BDD2B005D5AE6 /* String+.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+.swift"; sourceTree = "<group>"; };
C66C68D228D1B00A0091F960 /* EventModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventModel.swift; sourceTree = "<group>"; };
C66C68D428D1B0130091F960 /* SessionModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionModel.swift; sourceTree = "<group>"; };
C66DAD4F28CF478700195DEB /* SessionView+Observed.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SessionView+Observed.swift"; sourceTree = "<group>"; };
C66E3D94290BA48500097BEA /* ProfileRegisterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileRegisterView.swift; sourceTree = "<group>"; };
C66E3D96290BA4FC00097BEA /* ProfileRegisterViewObserved.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileRegisterViewObserved.swift; sourceTree = "<group>"; };
C66E3D98290BB9C100097BEA /* TextEditor+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TextEditor+.swift"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -113,6 +112,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
FB1FB1A72ACA7B3A00FF62AC /* SDWebImageSwiftUI in Frameworks */,
C69C13B32913B08F00D9B47F /* FirebaseDatabase in Frameworks */,
C69C13B52913B09500D9B47F /* FirebaseFirestore in Frameworks */,
C68DE94728C76BC500CA4CC8 /* FirebaseMessaging in Frameworks */,
Expand Down Expand Up @@ -257,7 +257,6 @@
C63D444D291BDD09005D5AE6 /* MainTabView+Observed.swift */,
C6F7798A28C9CBC60036773B /* EventView+Observed.swift */,
C63A865E28CA70ED0064C417 /* EventDetailView+Observed.swift */,
C66DAD4F28CF478700195DEB /* SessionView+Observed.swift */,
B289943228CA69FF002B9F67 /* StampView+Observed.swift */,
E9171EFF28D15426002FAF52 /* TicketingView+Observed.swift */,
C69C13BD2913EC3200D9B47F /* ProfileView */,
Expand Down Expand Up @@ -287,6 +286,7 @@
C69C13B22913B08F00D9B47F /* FirebaseDatabase */,
C69C13B42913B09500D9B47F /* FirebaseFirestore */,
C69C13C5291425F200D9B47F /* CodeScanner */,
FB1FB1A62ACA7B3A00FF62AC /* SDWebImageSwiftUI */,
);
productName = AsyncSwift;
productReference = C68DE93228C7685800CA4CC8 /* AsyncSwift.app */;
Expand Down Expand Up @@ -319,6 +319,7 @@
packageReferences = (
C68DE94328C76BC500CA4CC8 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */,
C69C13C4291425F200D9B47F /* XCRemoteSwiftPackageReference "CodeScanner" */,
FB1FB1A52ACA7B3A00FF62AC /* XCRemoteSwiftPackageReference "SDWebImageSwiftUI" */,
);
productRefGroup = C68DE93328C7685800CA4CC8 /* Products */;
projectDirPath = "";
Expand Down Expand Up @@ -354,7 +355,6 @@
C63D4450291BDD2B005D5AE6 /* String+.swift in Sources */,
C63D444C291BDCDC005D5AE6 /* KeyChainManager.swift in Sources */,
C631EBC3291537E300A54143 /* SafariView.swift in Sources */,
C66DAD5028CF478700195DEB /* SessionView+Observed.swift in Sources */,
C69C13A22912868F00D9B47F /* ProfileFriendDetailView.swift in Sources */,
C6E744A028CA557100B7B2BD /* Color+.swift in Sources */,
C68DE95128C77DDA00CA4CC8 /* TicketingView.swift in Sources */,
Expand Down Expand Up @@ -632,6 +632,14 @@
minimumVersion = 2.0.0;
};
};
FB1FB1A52ACA7B3A00FF62AC /* XCRemoteSwiftPackageReference "SDWebImageSwiftUI" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/SDWebImage/SDWebImageSwiftUI.git";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 2.0.0;
};
};
/* End XCRemoteSwiftPackageReference section */

/* Begin XCSwiftPackageProductDependency section */
Expand Down Expand Up @@ -660,6 +668,11 @@
package = C69C13C4291425F200D9B47F /* XCRemoteSwiftPackageReference "CodeScanner" */;
productName = CodeScanner;
};
FB1FB1A62ACA7B3A00FF62AC /* SDWebImageSwiftUI */ = {
isa = XCSwiftPackageProductDependency;
package = FB1FB1A52ACA7B3A00FF62AC /* XCRemoteSwiftPackageReference "SDWebImageSwiftUI" */;
productName = SDWebImageSwiftUI;
};
/* End XCSwiftPackageProductDependency section */
};
rootObject = C68DE92A28C7685800CA4CC8 /* Project object */;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,24 @@
"version" : "2.1.1"
}
},
{
"identity" : "sdwebimage",
"kind" : "remoteSourceControl",
"location" : "https://github.com/SDWebImage/SDWebImage.git",
"state" : {
"revision" : "936f1c7067728d16c362ba4fb93c17df78b5fd79",
"version" : "5.18.2"
}
},
{
"identity" : "sdwebimageswiftui",
"kind" : "remoteSourceControl",
"location" : "https://github.com/SDWebImage/SDWebImageSwiftUI.git",
"state" : {
"revision" : "e837c37d45449fbd3b4745c10c5b5274e73edead",
"version" : "2.2.3"
}
},
{
"identity" : "swift-protobuf",
"kind" : "remoteSourceControl",
Expand Down
26 changes: 11 additions & 15 deletions AsyncSwift/Observed/EventDetailView+Observed.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,27 @@ import EventKit
import SwiftUI

extension EventDetailView {

final class Observed: ObservableObject {

init(event: Event) {
self.event = event
}

@Published var event: Event
let event: Event
@Published var isShowingSheet = false
@Published var isShowingAddEventConfirmationAlert = false
@Published var isShowingAddEventSuccessAlert = false
@Published var isShowingAddEventFailureAlert = false

func additionConfirmed() {
addEventOnCalendar { isSuccess in
DispatchQueue.main.async { [weak self] in
if let self = self {
switch isSuccess {
case true:
self.isShowingAddEventSuccessAlert = true
case false:
self.isShowingAddEventFailureAlert = true
}
addEventOnCalendar { [weak self] isSuccess in
DispatchQueue.main.async {
switch isSuccess {
case true:
self?.isShowingAddEventSuccessAlert = true
case false:
self?.isShowingAddEventFailureAlert = true
}
}
}
Expand All @@ -39,11 +38,8 @@ extension EventDetailView {
func addEventOnCalendar(completion: @escaping ((Bool) -> Void) ) {
let eventStore = EKEventStore()

eventStore.requestAccess(to: .event) { (granted, error) in
if let error = error {
print("failed to save event with error : \(error) or access not granted")
return
}
eventStore.requestAccess(to: .event) { [weak self] (granted, error) in
guard let self, error == nil else { return }
let event = EKEvent(eventStore: eventStore)
let formatter = DateFormatter.calendarFormatter
event.title = self.event.title
Expand Down
52 changes: 23 additions & 29 deletions AsyncSwift/Observed/EventView+Observed.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,42 +6,36 @@
//

import SwiftUI
import Combine

final class EventViewObserved: ObservableObject {

@Published var event = Event()
@Published var eventStatus: EventStatus = .upcoming
@Published var isLoading = true
let onLoadingCells = Array(repeating: [0], count: 6)

init() {
self.fetchJson {
self.calculateEventStatus()
self.isLoading = false
}
}

func fetchJson(completion: @escaping () -> Void) {
guard let url = URL(string: "https://async-swift.github.io/jsonstorage/asyncswift.json") else { return }
let request = URLRequest(url: url)
let dataTask = URLSession.shared.dataTask(with: request) { data, response, _ in
guard
let response = response as? HTTPURLResponse,
response.statusCode == 200,
let data = data
else { return }
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
do {
let decodedData = try JSONDecoder().decode(Event.self, from: data)
self.event = decodedData
completion()
} catch let error {
print("\(error.localizedDescription)")
}
}
}
dataTask.resume()
var cancellable = Set<AnyCancellable>()

func getEventData() {
let urlString = "https://async-swift.github.io/jsonstorage/asyncswift.json"
let url = URL(string: urlString)!
URLSession.shared.dataTaskPublisher(for: url)
.tryMap() { element -> Data in
guard let httpResponse = element.response as? HTTPURLResponse,
httpResponse.statusCode == 200
else { throw URLError(.badServerResponse) }
return element.data
}
.decode(type: Event.self, decoder: JSONDecoder())
.receive(on: RunLoop.main)
.sink { _ in

} receiveValue: { [weak self] event in
self?.event = event
self?.calculateEventStatus()
self?.isLoading = false
}
.store(in: &cancellable)
}

func calculateEventStatus() {
Expand Down
20 changes: 0 additions & 20 deletions AsyncSwift/Observed/SessionView+Observed.swift

This file was deleted.

53 changes: 29 additions & 24 deletions AsyncSwift/Observed/StampView+Observed.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,18 @@
//

import SwiftUI
import Combine

extension StampView {
@MainActor final class Observed: ObservableObject {
final class Observed: ObservableObject {
@Published var cards: [Card] = []
@Published var events = [String]()
@Published var currentIndex = 0
@Published var isLoading = true
private let keyChainManager = KeyChainManager()
private let cardInterval: CGFloat = (UIScreen.main.bounds.width - 32) * 56 / 358
private let cardSize: CGFloat = UIScreen.main.bounds.width - 32
private var cancenllable = Set<AnyCancellable>()

init() {
fetchStampsImages()
Expand All @@ -33,35 +35,38 @@ extension StampView {
private func fetchStampsImages(){
let events = getEvents()

guard !events.isEmpty else {
isLoading = false
return
}
guard !events.isEmpty else { return isLoading = false }

events.enumerated().forEach { [weak self] in
guard let self else { return }
let event = $0.element
let index = $0.offset
Task { @MainActor () -> Void in
guard let cardImageURL = URL(string: "https://raw.githubusercontent.com/Async-Swift/jsonstorage/main/Images/Stamp/" + event + "/stamp.png")
else { return }

let cardImageRequest = URLRequest(url: cardImageURL)
let (cardImageData, cardImageResponse) = try await URLSession.shared.data(for: cardImageRequest)
guard let httpsResponse = cardImageResponse as? HTTPURLResponse, httpsResponse.statusCode == 200 else { return }

guard let cardUIImage = UIImage(data: cardImageData) else { return }

let card = Card(
originalPosition: self.cardInterval * CGFloat(index),
image: Image(uiImage: cardUIImage),
event: event
)
self.cards.append(card)
if index == events.count - 1 {
self.isLoading = false

let urlString = "https://raw.githubusercontent.com/Async-Swift/jsonstorage/main/Images/Stamp/" + event + "/stamp.png"
let url = URL(string: urlString)!

URLSession.shared.dataTaskPublisher(for: url)
.map(\.data)
.tryMap {
guard let image = UIImage(data: $0) else {
throw URLError(.badURL)
}
return Card(
originalPosition: self.cardInterval * CGFloat(index),
image: Image(uiImage: image),
event: event
)
}
}
.receive(on: RunLoop.main)
.sink(receiveCompletion: { _ in

}, receiveValue: { [weak self] card in
self?.cards.append(card)
if index == events.count - 1 {
self?.isLoading = false
}
})
.store(in: &cancenllable)
}
}

Expand Down
47 changes: 20 additions & 27 deletions AsyncSwift/Observed/TicketingView+Observed.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import Foundation
extension TicketingView {
final class Observed: ObservableObject {
@Published var ticketing: Ticketing?

@Published var isActivatedWebViewNavigationLink = false
var cancellable = Set<AnyCancellable>()

var hasAvailableTicket: Bool {
let currentDate = Date()
Expand All @@ -22,32 +22,25 @@ extension TicketingView {
var isTicketingLinkDisabled: Bool {
ticketing?.currentTicket?.ticketingURL == nil && !hasAvailableTicket
}

func onAppear() {
guard
let url = URL(string: "https://raw.githubusercontent.com/Async-Swift/jsonstorage/main/ticketing.json")
else { return }


let request = URLRequest(url: url)
let dataTask = URLSession.shared.dataTask(with: request) { data, response, _ in
guard
let response = response as? HTTPURLResponse,
response.statusCode == 200,
let data = data
else { return }

DispatchQueue.main.async { [weak self] in
do {
let ticketing = try JSONDecoder().decode(Ticketing.self, from: data)
self?.ticketing = ticketing
} catch {
self?.ticketing = nil
}
}
}

dataTask.resume()

func getTicketingData() {
let urlString = "https://raw.githubusercontent.com/Async-Swift/jsonstorage/main/ticketing.json"
let url = URL(string: urlString)!
URLSession.shared.dataTaskPublisher(for: url)
.tryMap() { element -> Data in
guard let httpResponse = element.response as? HTTPURLResponse,
httpResponse.statusCode == 200
else { throw URLError(.badServerResponse) }
return element.data
}
.decode(type: Ticketing.self, decoder: JSONDecoder())
.receive(on: RunLoop.main)
.sink { _ in

} receiveValue: { [weak self] event in
self?.ticketing = event
}
.store(in: &cancellable)
}

func didTappedTicketingButton() {
Expand Down
Loading

0 comments on commit c4f20f1

Please sign in to comment.