Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
39b0b0e
[Feat] Add function for universal links
E-know Sep 9, 2022
5496c0f
[Feat] URL Parsing
E-know Sep 14, 2022
dbbc9bd
[Feat] Add KeyChain for StampHistory
E-know Sep 14, 2022
c647808
Merge branch 'develop' into dev/universalLink
E-know Sep 14, 2022
e7a227f
[Feat] Keychain exception handling
E-know Sep 14, 2022
f0b5762
[Modify] Change variable to higher order function
E-know Sep 14, 2022
4d93dd5
Update AsyncSwift/Observed/KeyChain.swift
E-know Sep 14, 2022
6fe33bf
[Modify] KeyChain 값 AppData에 저장
E-know Sep 14, 2022
69bf93f
Merge remote-tracking branch 'E-know/dev/universalLink' into dev/univ…
E-know Sep 14, 2022
5b8340a
Merge pull request #2 from Async-Swift/develop
E-know Sep 15, 2022
7125ad7
[Feat] seminar002 -> fetch Json File
E-know Sep 15, 2022
beb398b
[Fix] Change when Json files are called
E-know Sep 15, 2022
e9c0886
[Modify] Project Settings
E-know Sep 15, 2022
4df1fba
[Modify] Stamp Model
E-know Sep 15, 2022
f478e6d
[Modify] Variable Description and Rename
E-know Sep 15, 2022
170ea25
Update AsyncSwift/Observed/AppData.swift
E-know Sep 15, 2022
b3be393
[Modify] Change If -> switch
E-know Sep 15, 2022
cc3b0b7
[Modify] Rename Variable
E-know Sep 15, 2022
ac161f9
[Modify] Change Keychain return value
E-know Sep 15, 2022
9495614
Merge remote-tracking branch 'E-know/dev/universalLink' into dev/univ…
E-know Sep 15, 2022
2a0956f
Update AsyncSwift/Observed/KeyChain.swift
E-know Sep 15, 2022
573dabf
Update AsyncSwift/Observed/KeyChain.swift
E-know Sep 15, 2022
ef2c321
[Modify] Weak reference guard handling
E-know Sep 15, 2022
4f205c0
[Fix] Fix code error
E-know Sep 15, 2022
23ecdb9
[Modify] Change to If statement return
E-know Sep 15, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions AsyncSwift.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
objects = {

/* Begin PBXBuildFile section */
B25E600C28D2400500E96C78 /* KeyChain.swift in Sources */ = {isa = PBXBuildFile; fileRef = B25E600B28D2400500E96C78 /* KeyChain.swift */; };
B289943328CA69FF002B9F67 /* StampView+Observed.swift in Sources */ = {isa = PBXBuildFile; fileRef = B289943228CA69FF002B9F67 /* StampView+Observed.swift */; };
B2E1083128C9CD6900C3DD59 /* AppData.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2E1083028C9CD6900C3DD59 /* AppData.swift */; };
B2FC6F6328D309FF00D2ACBF /* Stamp.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2FC6F6228D309FF00D2ACBF /* Stamp.swift */; };
C63A865F28CA70ED0064C417 /* EventDetailView+Observed.swift in Sources */ = {isa = PBXBuildFile; fileRef = C63A865E28CA70ED0064C417 /* EventDetailView+Observed.swift */; };
C63A866328CB3D490064C417 /* View+.swift in Sources */ = {isa = PBXBuildFile; fileRef = C63A866228CB3D490064C417 /* View+.swift */; };
C63A866528CB3F6D0064C417 /* DateFormatter+.swift in Sources */ = {isa = PBXBuildFile; fileRef = C63A866428CB3F6D0064C417 /* DateFormatter+.swift */; };
Expand Down Expand Up @@ -36,8 +38,10 @@
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
B25E600B28D2400500E96C78 /* KeyChain.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyChain.swift; sourceTree = "<group>"; };
B289943228CA69FF002B9F67 /* StampView+Observed.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "StampView+Observed.swift"; sourceTree = "<group>"; };
B2E1083028C9CD6900C3DD59 /* AppData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppData.swift; sourceTree = "<group>"; };
B2FC6F6228D309FF00D2ACBF /* Stamp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Stamp.swift; sourceTree = "<group>"; };
C63A865E28CA70ED0064C417 /* EventDetailView+Observed.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "EventDetailView+Observed.swift"; sourceTree = "<group>"; };
C63A866228CB3D490064C417 /* View+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+.swift"; sourceTree = "<group>"; };
C63A866428CB3F6D0064C417 /* DateFormatter+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DateFormatter+.swift"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -150,6 +154,7 @@
C66C68D228D1B00A0091F960 /* EventModel.swift */,
C66C68D428D1B0130091F960 /* SessionModel.swift */,
E94F92C628D2505100D9E759 /* Ticketing.swift */,
B2FC6F6228D309FF00D2ACBF /* Stamp.swift */,
);
path = Models;
sourceTree = "<group>";
Expand All @@ -160,6 +165,7 @@
C6F7798A28C9CBC60036773B /* EventView+Observed.swift */,
C63A865E28CA70ED0064C417 /* EventDetailView+Observed.swift */,
C66DAD4F28CF478700195DEB /* SessionView+Observed.swift */,
B25E600B28D2400500E96C78 /* KeyChain.swift */,
B2E1083028C9CD6900C3DD59 /* AppData.swift */,
B289943228CA69FF002B9F67 /* StampView+Observed.swift */,
E9171EFF28D15426002FAF52 /* TicketingView+Observed.swift */,
Expand Down Expand Up @@ -250,6 +256,7 @@
C66DAD5028CF478700195DEB /* SessionView+Observed.swift in Sources */,
C6E744A028CA557100B7B2BD /* Color+.swift in Sources */,
C68DE95128C77DDA00CA4CC8 /* TicketingView.swift in Sources */,
B25E600C28D2400500E96C78 /* KeyChain.swift in Sources */,
C6F7798B28C9CBC60036773B /* EventView+Observed.swift in Sources */,
C66C68D528D1B0130091F960 /* SessionModel.swift in Sources */,
E9171F0028D15426002FAF52 /* TicketingView+Observed.swift in Sources */,
Expand All @@ -265,6 +272,7 @@
C63A866528CB3F6D0064C417 /* DateFormatter+.swift in Sources */,
C6F7798F28C9D1BF0036773B /* SessionView.swift in Sources */,
C66C68D328D1B00A0091F960 /* EventModel.swift in Sources */,
B2FC6F6328D309FF00D2ACBF /* Stamp.swift in Sources */,
B2E1083128C9CD6900C3DD59 /* AppData.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -392,7 +400,8 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = AsyncSwift/AsyncSwift.entitlements;
CODE_SIGN_STYLE = Automatic;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"AsyncSwift/Preview Content\"";
DEVELOPMENT_TEAM = 76AJ433CP5;
Expand All @@ -415,6 +424,7 @@
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.kim.AsyncSwift;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = AsyncSwiftProvisioningProfile;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;
Expand All @@ -427,7 +437,8 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = AsyncSwift/AsyncSwift.entitlements;
CODE_SIGN_STYLE = Automatic;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"AsyncSwift/Preview Content\"";
DEVELOPMENT_TEAM = 76AJ433CP5;
Expand All @@ -450,6 +461,7 @@
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.kim.AsyncSwift;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = AsyncSwiftProvisioningProfile;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;
Expand Down
6 changes: 5 additions & 1 deletion AsyncSwift/AsyncSwiftApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ struct AsyncSwiftApp: App {
MainTabView()
.environmentObject(appData)
.onOpenURL { url in
print(url)
if appData.checkLink(url: url) {
print("Success Link URL: \(url)")
} else {
print("Fail Link URL: \(url)")
}
}
}
}
Expand Down
12 changes: 12 additions & 0 deletions AsyncSwift/Models/Stamp.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//
// Stamp.swift
// AsyncSwift
//
// Created by Inho Choi on 2022/09/15.
//

import Foundation

struct Stamp: Decodable {
let title: String
}
68 changes: 65 additions & 3 deletions AsyncSwift/Observed/AppData.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,70 @@ import SwiftUI
import UIKit

final class AppData: ObservableObject {
@Published var currentTab: Tab = .event // Universal Link로 앱진입시 StampView 전환을 위한 변수
var scannedSeminarQR = true // Universal Link로 진입시 QR코드 스캔 여부
/// Universal Link로 앱진입시 StampView 전환을 위한 변수
@Published var currentTab: Tab = .event

private var currentStamp: Stamp?
lazy var isStampExist: Bool = {
KeyChain.shared.getItem(key: currentStamp?.title) != nil
}()

init(){
fetchCurrentStamp()
}

func checkLink(url: URL) -> Bool {
// URL Example = https://www.asyncswift.info?tab=ticketing
// URL Example = https://www.asyncswift.info?tab=event
guard URLComponents(url: url, resolvingAgainstBaseURL: true)?.host != nil else { return false }

var queries = [String: String]()
for item in URLComponents(url: url, resolvingAgainstBaseURL: true)?.queryItems ?? [] {
queries[item.name] = item.value
}

guard let currentStampName = currentStamp?.title else { return false }

switch queries["tab"] {
case Tab.stamp.rawValue:
KeyChain.shared.addItem(key: currentStampName, pwd: "true") ? print("Adding Stamp History KeyChain is Success") : print("Adding Stamp History is Fail")
self.isStampExist = true
currentTab = .stamp
case Tab.event.rawValue:
currentTab = .event
default:
return false
}

return true
}

private func fetchCurrentStamp() {
guard
let url = URL(string: "https://raw.githubusercontent.com/Async-Swift/jsonstorage/main/stamp.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 stamp = try JSONDecoder().decode(Stamp.self, from: data)
self.currentStamp = stamp
} catch {
self.currentStamp = nil
}
}
}
dataTask.resume()
}
}


Expand Down Expand Up @@ -39,4 +101,4 @@ enum Tab: String, CaseIterable {
case .stamp: StampView()
}
}
}
}
76 changes: 76 additions & 0 deletions AsyncSwift/Observed/KeyChain.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
//
// KeyChain.swift
// AsyncSwift
//
// Created by Inho Choi on 2022/09/15.
//

import Foundation
import UIKit

final class KeyChain {
static let shared = KeyChain()

private init() { }

func addItem(key: Any, pwd: Any) -> Bool {
let addQuery: [CFString: Any] = [kSecClass: kSecClassGenericPassword,
kSecAttrAccount: key,
kSecValueData: (pwd as AnyObject).data(using: String.Encoding.utf8.rawValue) as Any]

let status = SecItemAdd(addQuery as CFDictionary, nil)

switch status {
case errSecSuccess:
return true
case errSecDuplicateItem:
return updateItem(value: pwd, key: key)
default:
print("addItem Error : \(status.description))")
return false
}
}

func getItem(key: Any) -> Any? {
let getQuery: [CFString: Any] = [kSecClass: kSecClassGenericPassword,
kSecAttrAccount: key,
kSecReturnAttributes: true,
kSecReturnData: true]
var item: CFTypeRef?
let result = SecItemCopyMatching(getQuery as CFDictionary, &item)

if result == errSecSuccess,
let existingItem = item as? [String: Any],
let data = existingItem[kSecValueData as String] as? Data,
let password = String(data: data, encoding: .utf8) {
return password
}
print("getItem Error : \(result.description)")
return nil
}

func updateItem(value: Any, key: Any) -> Bool {
let prevQuery: [CFString: Any] = [kSecClass: kSecClassGenericPassword,
kSecAttrAccount: key]
let updateQuery: [CFString: Any] = [kSecValueData: (value as AnyObject).data(using: String.Encoding.utf8.rawValue) as Any]

let result: Bool = {
let status = SecItemUpdate(prevQuery as CFDictionary, updateQuery as CFDictionary)
return status == errSecSuccess
}()

return result
}

func deleteItem(key: String) -> Bool {
let deleteQuery: [CFString: Any] = [kSecClass: kSecClassGenericPassword,
kSecAttrAccount: key]
let status = SecItemDelete(deleteQuery as CFDictionary)
if status == errSecSuccess {
return true
} else {
print("deleteItem Error : \(status.description)")
return false
}
}
}
2 changes: 1 addition & 1 deletion AsyncSwift/Views/StampView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ struct StampView: View {
var body: some View {
NavigationView {
Group {
if appData.scannedSeminarQR {
if appData.isStampExist {
ZStack {
stampBack
stampFront
Expand Down