Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEAT] #223 - QR 생성, QR스캔 서버 #228

Merged
merged 12 commits into from
Dec 26, 2021
16 changes: 12 additions & 4 deletions NADA-iOS-forRelease.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,12 @@
39F5A3D1271461EA00191F94 /* BackCardCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 39F5A3CF271461EA00191F94 /* BackCardCell.xib */; };
7705CF3E2752C7DB005195DF /* CardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7705CF3D2752C7DB005195DF /* CardView.swift */; };
7705CF402752C844005195DF /* CardView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7705CF3F2752C844005195DF /* CardView.xib */; };
770E58862778A78900498C2E /* Status.swift in Sources */ = {isa = PBXBuildFile; fileRef = 770E58852778A78900498C2E /* Status.swift */; };
7713E8482752E2A900724C8B /* SelectGroupBottomSheetViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7713E8472752E2A900724C8B /* SelectGroupBottomSheetViewController.swift */; };
7729171F2743D604001593E0 /* CardsInGroupResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7729171E2743D604001593E0 /* CardsInGroupResponse.swift */; };
7734D5AA27719520004360E4 /* CardShareBottomSheetViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7734D5A927719520004360E4 /* CardShareBottomSheetViewController.swift */; };
7734D5B627779EF0004360E4 /* QRCodeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7734D5B527779EF0004360E4 /* QRCodeView.swift */; };
7734D5B82777A8E8004360E4 /* String+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7734D5B72777A8E8004360E4 /* String+Extension.swift */; };
77607EDA274A68BE00204CD2 /* GroupCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77607ED8274A68BD00204CD2 /* GroupCollectionViewCell.swift */; };
77607EDB274A68BE00204CD2 /* GroupCollectionViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 77607ED9274A68BD00204CD2 /* GroupCollectionViewCell.xib */; };
7766A40F274FEBE200714912 /* CardInGroupCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7766A40D274FEBE200714912 /* CardInGroupCollectionViewCell.swift */; };
Expand Down Expand Up @@ -133,7 +136,6 @@
F8FC438826C01CDD0033E151 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8FC438726C01CDD0033E151 /* SceneDelegate.swift */; };
F8FC438F26C01CDE0033E151 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F8FC438E26C01CDE0033E151 /* Assets.xcassets */; };
F8FC439226C01CDE0033E151 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F8FC439026C01CDE0033E151 /* LaunchScreen.storyboard */; };
F8FC43AD26C020940033E151 /* TempClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8FC43AC26C020940033E151 /* TempClass.swift */; };
F8FC43B326C020B90033E151 /* BackCardCreationDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8FC43B226C020B90033E151 /* BackCardCreationDelegate.swift */; };
F8FC43B826C0227D0033E151 /* Const.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8FC43B726C0227D0033E151 /* Const.swift */; };
F8FC43BA26C022900033E151 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8FC43B926C022900033E151 /* ViewController.swift */; };
Expand Down Expand Up @@ -202,9 +204,12 @@
4A2183AE0E469153221624A0 /* Pods_NADA_iOS_forRelease.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_NADA_iOS_forRelease.framework; sourceTree = BUILT_PRODUCTS_DIR; };
7705CF3D2752C7DB005195DF /* CardView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardView.swift; sourceTree = "<group>"; };
7705CF3F2752C844005195DF /* CardView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CardView.xib; sourceTree = "<group>"; };
770E58852778A78900498C2E /* Status.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Status.swift; sourceTree = "<group>"; };
7713E8472752E2A900724C8B /* SelectGroupBottomSheetViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectGroupBottomSheetViewController.swift; sourceTree = "<group>"; };
7729171E2743D604001593E0 /* CardsInGroupResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardsInGroupResponse.swift; sourceTree = "<group>"; };
7734D5A927719520004360E4 /* CardShareBottomSheetViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardShareBottomSheetViewController.swift; sourceTree = "<group>"; };
7734D5B527779EF0004360E4 /* QRCodeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeView.swift; sourceTree = "<group>"; };
7734D5B72777A8E8004360E4 /* String+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Extension.swift"; sourceTree = "<group>"; };
77607ED8274A68BD00204CD2 /* GroupCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupCollectionViewCell.swift; sourceTree = "<group>"; };
77607ED9274A68BD00204CD2 /* GroupCollectionViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = GroupCollectionViewCell.xib; sourceTree = "<group>"; };
7766A40D274FEBE200714912 /* CardInGroupCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardInGroupCollectionViewCell.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -273,7 +278,6 @@
F8FC438E26C01CDE0033E151 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
F8FC439126C01CDE0033E151 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
F8FC439326C01CDE0033E151 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
F8FC43AC26C020940033E151 /* TempClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TempClass.swift; sourceTree = "<group>"; };
F8FC43B226C020B90033E151 /* BackCardCreationDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackCardCreationDelegate.swift; sourceTree = "<group>"; };
F8FC43B726C0227D0033E151 /* Const.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Const.swift; sourceTree = "<group>"; };
F8FC43B926C022900033E151 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -822,7 +826,7 @@
F8FC439C26C01EC90033E151 /* Classes */ = {
isa = PBXGroup;
children = (
F8FC43AC26C020940033E151 /* TempClass.swift */,
7734D5B527779EF0004360E4 /* QRCodeView.swift */,
);
path = Classes;
sourceTree = "<group>";
Expand Down Expand Up @@ -913,6 +917,7 @@
F8C83FC2272FA17B0009DF0D /* URL.swift */,
3927A7D6275F2A9B008BCD2A /* UserDefaults.swift */,
77F47D92276C79B600414659 /* Header.swift */,
770E58852778A78900498C2E /* Status.swift */,
);
path = Constants;
sourceTree = "<group>";
Expand All @@ -928,6 +933,7 @@
399C55DE2711949D00845A54 /* CGPoint+Distance.swift */,
F8719DDA274F92E90081AD51 /* UITextField+Extension.swift */,
F8D74DD7276C7FB60071E5FC /* UIImageView+Extension.swift */,
7734D5B72777A8E8004360E4 /* String+Extension.swift */,
);
path = Extensions;
sourceTree = "<group>";
Expand Down Expand Up @@ -1131,6 +1137,7 @@
F8C83FBF272FA0670009DF0D /* UserSevice.swift in Sources */,
39F5A3D0271461EA00191F94 /* BackCardCell.swift in Sources */,
F8268DB927730B0100BF114B /* FirstCardAlertBottomSheetViewController.swift in Sources */,
770E58862778A78900498C2E /* Status.swift in Sources */,
F851805B275D047C006BD5ED /* OnboardingViewController.swift in Sources */,
39C1E88F270EC762006D2089 /* UIColor+Extension.swift in Sources */,
F8C83FC9272FA3190009DF0D /* GroupAPI.swift in Sources */,
Expand All @@ -1157,18 +1164,19 @@
397B751A2763B5F1004AEB03 /* TeamNADAViewController.swift in Sources */,
3981148E273BEBB300E28630 /* CardListEditRequest.swift in Sources */,
39D88B6B274600B100A72164 /* CommonBottomSheetViewController.swift in Sources */,
7734D5B627779EF0004360E4 /* QRCodeView.swift in Sources */,
3918F66727719C4B00984648 /* UserTokenReissueRequset.swift in Sources */,
7705CF3E2752C7DB005195DF /* CardView.swift in Sources */,
F8FC43BA26C022900033E151 /* ViewController.swift in Sources */,
39523E5F2701AA9000536900 /* CardListDataModel.swift in Sources */,
39D13568273FDCB800B1A148 /* UserWithTokenRequest.swift in Sources */,
F8FC43AD26C020940033E151 /* TempClass.swift in Sources */,
F84BAFB126FDB552004CA335 /* BackCardCreationCollectionViewCell.swift in Sources */,
39811490273BEBCE00E28630 /* CardListRequest.swift in Sources */,
F8FC43BC26C022A20033E151 /* Storyboard.swift in Sources */,
F8C83FC1272FA06E0009DF0D /* UserAPI.swift in Sources */,
7766A40F274FEBE200714912 /* CardInGroupCollectionViewCell.swift in Sources */,
3927A7D7275F2A9B008BCD2A /* UserDefaults.swift in Sources */,
7734D5B82777A8E8004360E4 /* String+Extension.swift in Sources */,
F8C83FC3272FA17B0009DF0D /* URL.swift in Sources */,
392F7FB4274621F1008CDBF5 /* MoreListTableViewCell.swift in Sources */,
77AA68EA273E0EC4009C89B0 /* CardAddInGroupRequest.swift in Sources */,
Expand Down
14 changes: 14 additions & 0 deletions NADA-iOS-forRelease/Resouces/Constants/Status.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// Status.swift
// NADA-iOS-forRelease
//
// Created by Yi Joon Choi on 2021/12/26.
//

import Foundation
enum Status {
case group
case detail
case add
case addWithQR
}
14 changes: 14 additions & 0 deletions NADA-iOS-forRelease/Resouces/Extensions/String+Extension.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// UIString+Extension.swift
// NADA-iOS-forRelease
//
// Created by Yi Joon Choi on 2021/12/26.
//

import Foundation
extension String {
func deletingPrefix(_ prefix: String) -> String {
guard self.hasPrefix(prefix) else { return self }
return String(self.dropFirst(prefix.count))
}
}
77 changes: 77 additions & 0 deletions NADA-iOS-forRelease/Sources/Classes/QRCodeView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
//
// QRCodeView.swift
// NADA-iOS-forRelease
//
// Created by Yi Joon Choi on 2021/12/26.
//

import Foundation
import UIKit

class QRCodeView: UIView {

// ✅ CIQRCodeGenerator : QR code 생성 필터를 식별하기 위한 속성.
var filter = CIFilter(name: "CIQRCodeGenerator")

// ✅ QRCode CIImage 를 만들어서 추가할 UIImageView.
var imageView = UIImageView()

override init(frame: CGRect) {
super.init(frame: frame)
addSubview(imageView)
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

override func layoutSubviews() {
super.layoutSubviews()
imageView.frame = bounds
}

// ✅ QRCode 이미지를 만들 때 다양한 색으로 만들 수 있도록 parameter 를 받았다.
func generateCode(_ string: String, foregroundColor: UIColor = .black, backgroundColor: UIColor = .white) {

// ✅ 주어진 인코딩을(=using) 사용해서 NSData 개체를 반환한다.
guard let filter = filter, let data = string.data(using: .isoLatin1, allowLossyConversion: false) else {
return
}

// ✅ 두가지 파라미터 설정.
filter.setValue(data, forKey: "inputMessage")
filter.setValue("M", forKey: "inputCorrectionLevel")

// ✅ .outputImage : 필터에 구성된 작업을 캡슐화하는 CIImage 개체이다. 즉, 결과물
guard let ciImage = filter.outputImage else {
return
}

// ❗️ 이렇게 끝내면 qr code 가 선명하지 않게 나온다.
// imageView.image = UIImage(ciImage: ciImage, scale: 2.0, orientation: .up)

// ✅ 다음은 이미지 선명하게 변환하는 과정이다.
// ✅ 원래 이미지에 affine transform(by 파라미터를 의미.) 을 적용한 새 이미지를 반환. 이미지의 넓이와 높이를 10배 증가시킴.
let transformed = ciImage.transformed(by: CGAffineTransform.init(scaleX: 10, y: 10))

// ✅ 다음은 QR code 색 커스텀 설정하는 과정이다. 필터 생성하고 이미지 적용.
// ✅ CIColorInvert : 색상을 반전시키기 위한 필터이다.
let invertFilter = CIFilter(name: "CIColorInvert")
invertFilter?.setValue(transformed, forKey: kCIInputImageKey)

// ✅ CIMaskToAlpha : grayscale 로 변환된 이미지를 alpha 로 마스킹된 흰색이미지로 변환.
let alphaFilter = CIFilter(name: "CIMaskToAlpha")
alphaFilter?.setValue(invertFilter?.outputImage, forKey: kCIInputImageKey)

// ✅ 받은 파라미터로 imageView 의 속성을 설정.
if let ouputImage = alphaFilter?.outputImage {
imageView.tintColor = foregroundColor
imageView.backgroundColor = backgroundColor

// ✅ withRenderingMode(.alwaysTemplate) : 원본 이미지의 컬러정보가 사라지고 불투명한 부분을 tintColor 로 설정.
imageView.image = UIImage(ciImage: ouputImage, scale: 2.0, orientation: .up).withRenderingMode(.alwaysTemplate)
} else {
return
}
}
}
8 changes: 0 additions & 8 deletions NADA-iOS-forRelease/Sources/Classes/TempClass.swift

This file was deleted.

11 changes: 9 additions & 2 deletions NADA-iOS-forRelease/Sources/NetworkModel/Card/Card.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,23 @@

import Foundation

// MARK: - CardClass
struct CardClass: Codable {
let card: Card
}

// MARK: - Card
struct Card: Codable {
let cardID, background, title, name, birthDate, mbti: String
let cardID: String
let author: String? = ""
let background, title, name, birthDate, mbti: String
let instagram, link, cardDescription: String?
let isMincho, isSoju, isBoomuk, isSauced: Bool
let oneTmi, twoTmi, threeTmi: String?

enum CodingKeys: String, CodingKey {
case cardID = "cardId"
case background, title, name, birthDate, mbti, instagram, link
case author, background, title, name, birthDate, mbti, instagram, link
case cardDescription = "description"
case isMincho, isSoju, isBoomuk, isSauced, oneTmi, twoTmi, threeTmi
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ struct CardsInGroupResponse: Codable {

// MARK: - Cards
struct FrontCard: Codable {
let cardID, background, title, name, birthDate, age, mbti: String
let instagram, linkName, link, cardDescription: String?
let cardID, background, title, name, birthDate, mbti: String
let instagram, link, cardDescription: String?

enum CodingKeys: String, CodingKey {
case cardID = "cardId"
case background, title, name, birthDate, age, mbti, instagram, linkName, link
case background, title, name, birthDate, mbti, instagram, link
case cardDescription = "description"
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ public class CardAPI {
private func judgeCardDetailFetchStatus(by statusCode: Int, _ data: Data) -> NetworkResult<Any> {

let decoder = JSONDecoder()
guard let decodedData = try? decoder.decode(GenericResponse<Card>.self, from: data)
guard let decodedData = try? decoder.decode(GenericResponse<CardClass>.self, from: data)
else {
return .pathErr
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ class AddWithIdBottomSheetViewController: CommonBottomSheetViewController, UITex

private let explainLabel: UILabel = {
let label = UILabel()
label.text = "검색한 ID가 존재하지 않습니다."
label.textColor = .stateColorError
label.font = .textRegular05

Expand Down Expand Up @@ -107,16 +106,22 @@ extension AddWithIdBottomSheetViewController {
CardAPI.shared.cardDetailFetch(cardID: cardID) { response in
switch response {
case .success(let data):
if let card = data as? Card {
//TODO: 내가 쓴거 내가 추가 하면 예외처리 필요
let nextVC = CardResultBottomSheetViewController()
nextVC.cardDataModel = card
self.hideBottomSheetAndPresent(nextBottomSheet: nextVC, title: card.name, height: 574)
if let card = data as? CardClass {
if UserDefaults.standard.string(forKey: Const.UserDefaults.userID) == card.card.author {
self.errorImageView.isHidden = false
self.explainLabel.isHidden = false
self.explainLabel.text = "자신의 명함은 추가할 수 없습니다."
} else {
let nextVC = CardResultBottomSheetViewController()
nextVC.cardDataModel = card.card
self.hideBottomSheetAndPresent(nextBottomSheet: nextVC, title: card.card.name, height: 574)
}
}
case .requestErr(let message):
print("cardDetailFetchWithAPI - requestErr: \(message)")
self.errorImageView.isHidden = false
self.explainLabel.isHidden = false
self.explainLabel.text = "검색한 ID가 존재하지 않습니다."
case .pathErr:
print("cardDetailFetchWithAPI - pathErr")
case .serverErr:
Expand All @@ -127,4 +132,3 @@ extension AddWithIdBottomSheetViewController {
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ class CardResultBottomSheetViewController: CommonBottomSheetViewController {
// MARK: - Properties
var cardDataModel: Card?

var status: Status = .add

private let groupLabel: UILabel = {
let label = UILabel()
label.textColor = .secondary
Expand Down Expand Up @@ -108,7 +110,7 @@ extension CardResultBottomSheetViewController {
case .success(let data):
if let group = data as? Groups {
let nextVC = SelectGroupBottomSheetViewController()
nextVC.status = .add
nextVC.status = self.status
nextVC.cardDataModel = self.cardDataModel
nextVC.serverGroups = group
self.hideBottomSheetAndPresent(nextBottomSheet: nextVC, title: "그룹선택", height: 386)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,12 @@ class CardShareBottomSheetViewController: CommonBottomSheetViewController {

// MARK: - Properties

var cardID: String? = "1D856A"
var isShareable = false
var cardDataModel: Card?

private let qrImage: UIImageView = {
// 여기를 만든 QR이미지로 바꿔주시면 됩니당
let imageView = UIImageView()
imageView.image = UIImage(named: "qrCodeImg21")

imageView.frame = CGRect(x: 0, y: 0, width: 160, height: 160)
return imageView
}()

Expand Down Expand Up @@ -81,9 +78,10 @@ class CardShareBottomSheetViewController: CommonBottomSheetViewController {
view.addSubview(idStackView)
view.addSubview(saveAsImageButton)

idLabel.text = cardID
idLabel.text = cardDataModel?.cardID ?? ""

setupLayout()
setQRImage()
}

// 레이아웃 세팅
Expand All @@ -110,6 +108,16 @@ class CardShareBottomSheetViewController: CommonBottomSheetViewController {
])
}

private func setQRImage() {
let frame = CGRect(origin: .zero, size: qrImage.frame.size)
print("TeamNADA\(cardDataModel?.cardID ?? "")")
let qrcode = QRCodeView(frame: frame)
qrcode.generateCode("ThisIsTeamNADAQrCode\(cardDataModel?.cardID ?? "")",
foregroundColor: .primary,
backgroundColor: .background)
qrImage.addSubview(qrcode)
}

private func setImageWriteToSavedPhotosAlbum() {
let frontCardImage = setFrontCardImage()
let backCardImage = setBackCardImage()
Expand Down Expand Up @@ -172,7 +180,7 @@ class CardShareBottomSheetViewController: CommonBottomSheetViewController {
// MARK: - @objc Methods

@objc func copyId() {
UIPasteboard.general.string = cardID
UIPasteboard.general.string = cardDataModel?.cardID ?? ""
showToast(message: "명함 아이디가 복사되었습니다.", font: UIFont.button02, view: "copyID")
}

Expand Down
Loading