Skip to content

Commit

Permalink
Merge pull request #93 from APPSCHOOL3-iOS/feature/#2-RecruitFeedView
Browse files Browse the repository at this point in the history
feature: 사진 파베 연동 완료
  • Loading branch information
KaiKimiOS authored Aug 25, 2023
2 parents 0ee91a4 + 795a225 commit d6a49e8
Show file tree
Hide file tree
Showing 8 changed files with 237 additions and 70 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@
A0CE323D2A952C110019300F /* StudyCommentReportView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A0CE323C2A952C110019300F /* StudyCommentReportView.swift */; };
B0F67D5A2A948B3400B2A138 /* TestView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0F67D592A948B3300B2A138 /* TestView.swift */; };
B7610BA72A951A6E0074F78C /* FeedRecruitViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7610BA62A951A6E0074F78C /* FeedRecruitViewModel.swift */; };
B786FC162A987ADF00E3C1E9 /* FeedStorageManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = B786FC152A987ADF00E3C1E9 /* FeedStorageManager.swift */; };
B786FC192A987B0F00E3C1E9 /* FirebaseStorage in Frameworks */ = {isa = PBXBuildFile; productRef = B786FC182A987B0F00E3C1E9 /* FirebaseStorage */; };
B7C4A51C2A95C10A00CB05C8 /* FeedRecruitModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7C4A51B2A95C10A00CB05C8 /* FeedRecruitModel.swift */; };
B7C4A51E2A95C3DB00CB05C8 /* FeedRecruitStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = B7C4A51D2A95C3DB00CB05C8 /* FeedRecruitStore.swift */; };
D55D36612A95E16200A7BE14 /* AddStudyMain.swift in Sources */ = {isa = PBXBuildFile; fileRef = D55D36602A95E16200A7BE14 /* AddStudyMain.swift */; };
Expand Down Expand Up @@ -216,6 +218,7 @@
A0CE323C2A952C110019300F /* StudyCommentReportView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StudyCommentReportView.swift; sourceTree = "<group>"; };
B0F67D592A948B3300B2A138 /* TestView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestView.swift; sourceTree = "<group>"; };
B7610BA62A951A6E0074F78C /* FeedRecruitViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedRecruitViewModel.swift; sourceTree = "<group>"; };
B786FC152A987ADF00E3C1E9 /* FeedStorageManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedStorageManager.swift; sourceTree = "<group>"; };
B7C4A51B2A95C10A00CB05C8 /* FeedRecruitModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedRecruitModel.swift; sourceTree = "<group>"; };
B7C4A51D2A95C3DB00CB05C8 /* FeedRecruitStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedRecruitStore.swift; sourceTree = "<group>"; };
D55D36602A95E16200A7BE14 /* AddStudyMain.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddStudyMain.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -257,7 +260,9 @@
files = (
FAB51C5E2A9661740047A725 /* FirebaseDatabaseSwift in Frameworks */,
FAB51C602A9661740047A725 /* FirebaseFirestore in Frameworks */,
D5755B1C2A97B11F000BC8E2 /* FirebaseStorage in Frameworks */,

B786FC192A987B0F00E3C1E9 /* FirebaseStorage in Frameworks */,

FAB51C5C2A9661740047A725 /* FirebaseDatabase in Frameworks */,
FAB51C692A9661800047A725 /* GoogleSignInSwift in Frameworks */,
FAB51C622A9661740047A725 /* FirebaseFirestoreCombine-Community in Frameworks */,
Expand Down Expand Up @@ -469,7 +474,8 @@
children = (
9E99CCEC2A944A5700699B6A /* project02-teamB-OUR-consumer */,
9E99CCEB2A944A5700699B6A /* Products */,
D5755B1A2A97B11F000BC8E2 /* Frameworks */,
B786FC172A987B0F00E3C1E9 /* Frameworks */,

);
sourceTree = "<group>";
};
Expand Down Expand Up @@ -526,10 +532,18 @@
B7C4A51B2A95C10A00CB05C8 /* FeedRecruitModel.swift */,
B7C4A51D2A95C3DB00CB05C8 /* FeedRecruitStore.swift */,
B7610BA62A951A6E0074F78C /* FeedRecruitViewModel.swift */,
B786FC152A987ADF00E3C1E9 /* FeedStorageManager.swift */,
);
path = "FeedRecruitModel+Extension";
sourceTree = "<group>";
};
B786FC172A987B0F00E3C1E9 /* Frameworks */ = {
isa = PBXGroup;
children = (
);
name = Frameworks;
sourceTree = "<group>";
};
D55D366E2A95E1D200A7BE14 /* RecruitStudyView */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -609,7 +623,8 @@
FAB51C632A9661740047A725 /* FirebaseFirestoreSwift */,
FAB51C662A9661800047A725 /* GoogleSignIn */,
FAB51C682A9661800047A725 /* GoogleSignInSwift */,
D5755B1B2A97B11F000BC8E2 /* FirebaseStorage */,
B786FC182A987B0F00E3C1E9 /* FirebaseStorage */,

);
productName = "project02-teamB-OUR-consumer";
productReference = 9E99CCEA2A944A5700699B6A /* project02-teamB-OUR-consumer.app */;
Expand Down Expand Up @@ -772,6 +787,7 @@
632883742A94DD31004DC84E /* PostView.swift in Sources */,
9B6B9B362A94A746004609AF /* PostData.swift in Sources */,
9B35B2762A94590F00AD72D7 /* FeedTabView.swift in Sources */,
B786FC162A987ADF00E3C1E9 /* FeedStorageManager.swift in Sources */,
9B35B27C2A94595900AD72D7 /* TitleView.swift in Sources */,
6332A6052A95D12C0047E2DD /* ShareView.swift in Sources */,
632883762A94F0ED004DC84E /* PostDetailView.swift in Sources */,
Expand Down Expand Up @@ -920,7 +936,7 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"project02-teamB-OUR-consumer/Preview Content\"";
DEVELOPMENT_TEAM = H996FSG2V2;
DEVELOPMENT_TEAM = "";
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "project02-teamB-OUR-consumer/Info.plist";
Expand Down Expand Up @@ -952,7 +968,7 @@
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"project02-teamB-OUR-consumer/Preview Content\"";
DEVELOPMENT_TEAM = H996FSG2V2;
DEVELOPMENT_TEAM = "";
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "project02-teamB-OUR-consumer/Info.plist";
Expand Down Expand Up @@ -1019,7 +1035,8 @@
/* End XCRemoteSwiftPackageReference section */

/* Begin XCSwiftPackageProductDependency section */
D5755B1B2A97B11F000BC8E2 /* FirebaseStorage */ = {
B786FC182A987B0F00E3C1E9 /* FirebaseStorage */ = {

isa = XCSwiftPackageProductDependency;
package = FAB51C582A9661740047A725 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
productName = FirebaseStorage;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ struct FeedRecruitModel {
var id: String = UUID().uuidString
var creator: String
var content: String
var imageURL: [String]
var location: String
var privateSetting: Bool
var reportCount: Int
var createdAt: Double = Date().timeIntervalSince1970
var feedImagePath: String

var createdDate: String {
let dateCreatedAt: Date = Date(timeIntervalSince1970: createdAt)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import PhotosUI

struct FeedRecruitPHPickerViewControllerWrapper: UIViewControllerRepresentable {
@Binding var selectedImages: [UIImage]
// @Binding var selectedItem: PhotosPickerItem?

func makeUIViewController(context: Context) -> PHPickerViewController {
var configuration = PHPickerConfiguration()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import Foundation
import FirebaseFirestore
import FirebaseFirestoreSwift
import PhotosUI
import _PhotosUI_SwiftUI

class FeedRecruitStore: ObservableObject {

Expand All @@ -30,13 +32,13 @@ class FeedRecruitStore: ObservableObject {
let docData: [String: Any] = document.data()
let creator: String = docData["creator"] as? String ?? ""
let content: String = docData["content"] as? String ?? ""
let imageURL: [String] = docData["imageURL"] as? [String] ?? []
let location: String = docData["location"] as? String ?? ""
let privateSetting: Bool = docData["privateSetting"] as? Bool ?? false
let createdAt: Double = docData["createdDate"] as? Double ?? 0.0
let reportCount: Int = docData["reportCount"] as? Int ?? 0
let studyImagePath: String = docData["studyImagePath"] as? String ?? ""

let feeds = FeedRecruitModel(id: id, creator: creator, content: content, imageURL: imageURL, location: location, privateSetting: privateSetting, reportCount: reportCount , createdAt: createdAt)
let feeds = FeedRecruitModel(id: id, creator: creator, content: content, location: location, privateSetting: privateSetting, reportCount: reportCount , createdAt: createdAt, feedImagePath: studyImagePath)

tempFeeds.append(feeds)
}
Expand All @@ -52,11 +54,11 @@ class FeedRecruitStore: ObservableObject {
dbRef.document(feed.id)
.setData(["creator": feed.creator,
"content": feed.content,
"imageURL": feed.imageURL,
"location": feed.location,
"privateSetting": feed.privateSetting,
"createdAt": feed.createdDate,
"reportCount": feed.reportCount])
"reportCount": feed.reportCount,
"studyImagePath": feed.feedImagePath])

fetchFeeds()
}
Expand All @@ -69,5 +71,40 @@ class FeedRecruitStore: ObservableObject {
fetchFeeds()
}

//이미지 FireBase Storage에 Save.



func returnImagePath(item: PhotosPickerItem, completion: @escaping (String?) -> Void) {
Task {
guard let data = try await item.loadTransferable(type: Data.self) else {
completion(nil)
return
}
let (_, _, url) = try await FeedStorageManager.shared.saveImage(data: data, id: dbRef.document().documentID)
completion(url.absoluteString)
}
}


func saveStudyImage(item: PhotosPickerItem) {
Task {
guard let data = try await item.loadTransferable(type: Data.self) else { return }
let (path, name, url) = try await FeedStorageManager.shared.saveImage(data: data, id: dbRef.document().documentID)
print("SUCCESS!!!!")
print("path : \(path)")
print("name : \(name)")
print("url : \(url)")
}
}










}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import Foundation
import FirebaseStorage
import FirebaseAuth
import Firebase

final class FeedStorageManager {

static let shared = FeedStorageManager()
private init() { }

private let storage = Storage.storage().reference()

private var imagesReference: StorageReference {
storage.child("images")
}

private func userReference(id: String) -> StorageReference {
storage.child("FeedPosts").child(id)
}

func getSavedImage(id: String, path: String) async throws -> Data {
try await userReference(id: id).child(path).data(maxSize: 3 * 1024 * 1024)
}

func saveImage(data: Data, id: String) async throws -> (path: String, name: String, url: URL) {
let meta = StorageMetadata()
meta.contentType = "image/jpeg"

let path = "\(UUID().uuidString).jpeg"
let returnedMetaData = try await userReference(id: id).child(path).putDataAsync(data, metadata: meta)

guard let returnedPath = returnedMetaData.path, let returnedName = returnedMetaData.name else {
throw URLError(.badURL)
}

let test = try await userReference(id: id).child(path).downloadURL()
return (returnedPath, returnedName, test)
}



}
Original file line number Diff line number Diff line change
Expand Up @@ -6,60 +6,86 @@
//

import SwiftUI
import PhotosUI

struct FeedRecruitPhotoAddView: View {

@Binding var selectedItem: PhotosPickerItem?

@Binding var selectedImages: [UIImage]
@State private var isImagePickerPresented: Bool = false
@State var imageData : Data? = nil

var body: some View {
VStack {
HStack {

Button("사진 추가") {
isImagePickerPresented = true
}
Spacer()
}
.padding()

if selectedImages.isEmpty {
ScrollView(.horizontal) {
HStack {
ForEach(1..<4) { _ in
ZStack {
Rectangle()
.stroke(lineWidth: 2)
.foregroundColor(.black)
.frame(width: 100, height: 100)
.border(.black)
Image(systemName: "plus")
.font(.system(size: 80, weight: .thin))
.padding(.horizontal)
}
}
}.padding(.horizontal)
if imageData == nil {
HStack {

Text("사진추가")
Spacer()
}
.padding()


PhotosPicker(selection: $selectedItem, matching: .images, photoLibrary: .shared()) {
Image(systemName: "plus")
.foregroundColor(.gray)
.font(.system(size: 40, weight: .thin))
.padding(40)
.frame(maxWidth: .infinity, maxHeight: 100)
.overlay(RoundedRectangle(cornerRadius: 10).stroke(Color.gray, lineWidth: 1))

}
} else {
ScrollView(.horizontal) {
HStack {
ForEach(selectedImages, id: \.self) { image in
Image(uiImage: image)
.resizable()
.frame(width: 100, height: 100)
.aspectRatio(contentMode: .fit)
.overlay {
Rectangle().stroke(.black, lineWidth: 2)
}

}
HStack {

Text("사진추가")
Spacer()
}
.padding()

ZStack{
PhotosPicker(selection: $selectedItem, matching: .images, photoLibrary: .shared()) {
Image(systemName: "plus")
.foregroundColor(.gray)
.font(.system(size: 40, weight: .thin))
.padding(40)
.frame(maxWidth: .infinity, maxHeight: 150)
.overlay(RoundedRectangle(cornerRadius: 10).stroke(Color.gray, lineWidth: 1))

}


if let imageData,
let image = UIImage(data: imageData) {

Image(uiImage: image)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 150, height: 150, alignment: .center)

}

}


}

}



.onChange(of: selectedItem) { newItem in
Task {
if let data = try? await newItem?.loadTransferable(type: Data.self) {
self.imageData = data
}
}
}
.sheet(isPresented: $isImagePickerPresented) {
FeedRecruitPHPickerViewControllerWrapper(selectedImages: $selectedImages)
}
// .sheet(isPresented: $isImagePickerPresented) {
// FeedRecruitPHPickerViewControllerWrapper(selectedImages: $selectedImages)
// }
}
}

Expand All @@ -69,3 +95,13 @@ struct FeedRecruitPhotoAddView: View {
// }
//}

//
//
// .onChange(of: selectedItem) { newItem in
// Task {
// if let data = try? await newItem?.loadTransferable(type: Data.self) {
// self.imageData = data
// }
// }
// }

Loading

0 comments on commit d6a49e8

Please sign in to comment.