이제 메인 화면의 UILabel보기는 질렸을테니 그 화면을 사라지게 하기 위해 게시물 작성 뷰컨트롤러를 만들겁니다.
UITabBar와 연결된 UIViewController하나를 swift파일을 만들어 연결해주세요
맨 위에는 표시용 UILabel로 따로 연결은 하지 않습니다.
포스팅할 사진을 골랐을 때 화면에 크게 띄우는 UIImageView
포스팅할 내용을 입력할 UITextView
작성이 끝나고 완료할 작성하기 버튼 사진을 여러개 고르는 모드로 전환해주는 select버튼
고른 사진갯수를 표시할 Label
사진 라이브러리에 접근하여 촤르륵 놓아줄 UICollectionView/UICollectioncell 그리고 그 안의 UIImageView
포스팅을 서버에 보낼 동안 동작될 UIActivityIndicator까지
연결해주세요
연결은 이렇게 import도 입력해줍시다.
그 다음 코드를 입력하기 전에 info.plist에 가서 사진 라이브러리 접근 권한 설정을 해주어야 합니다
새 항목을 만든 다음 Pri..이렇게만 입력하면 좌르륵 자동 완성문이 뜰텐데 사진의 선택된Privacy항목 4개를 만들어주세요
그냥 Library라고 쓰여져 있는 것만 해도 충분합니다. 하는김에 다햇어요 저는
그 다음 새로운 swift 파일을 만들어서
이런 파일을 만들어 주세요
이 코드는 사진 다중 선택을 제어해줄 모델입니다.
AlbumViewController: UIViewController, UICollectionViewDataSource,
UICollectionViewDelegate,
UICollectionViewDelegateFlowLayout {
.
.
.
override func viewDidLoad() {
super.viewDidLoad()
commentInputText.delegate = self
MyAlbumView.delegate = self
MyAlbumView.dataSource = self
}
override func viewWillAppear(_ animated: Bool) {
}
override func viewDidDisappear(_ animated: Bool) {
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
return UICollectionCell()
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
guard let asset = fetchResult?.object(at: indexPath.item) else { return }
}
func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let size = CGSize(width: self.view.frame.width / 3 - 1, height: 100)
return size
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 1
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 1
}
}
일단 UICollectionView와 UITextView의 delegate를 상속해주고 viewdidload에 self 처리를 해줍시다.
그 다음 에러가 발생하지 않도록 필수 함수들과 쓰일 delegate함수들을 선언해주세요
이제 사진라이브러리 접근 코드를 짤건데 개인적으로 이거 공부하다가 1주일간 펑펑 울면서 공부했을 정도로 아무것도 이해가 안돼 포기할뻔한 소재였어요. 좀 이해하니까 나아졌지만 후유증이 남아서 아직도 보면 띠용합니다...저만 그럴지도 모르지만 암튼 그렇다구요
var fetchOptions: PHFetchOptions = {
let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
fetchOptions.predicate = NSPredicate(format: "mediaType = %d", PHAssetMediaType.image.rawValue)
return fetchOptions
}()
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let TcgSize: CGSize = CGSize(width: 1024, height: 1024)
let scale = UIScreen.main.scale
var selectAsset: PHAsset?
var dictionarySelectedIndecPath: [IndexPath: Bool] = [:]
var selectedAssetIndex: [Int] = []
var count = 0
var urlString: [String] = []
var follows: [String] = []
var images: [Data] = []
var selectedImages : [UIImage] = []
var fetchResult: PHFetchResult<PHAsset>?
let imageManager = PHCachingImageManager()
외부 변수상수로 이것들을 초기화해주세요 위치는 viewdidload위가 적당합니다.
이 다음엔 코드가 길어져서 extension으로 확장해서 따로 작성하겠습니다.일
extension AlbumViewController: PHPhotoLibraryChangeObserver {
func photoLibraryDidChange(_ changeInstance: PHChange) {
OperationQueue.main.addOperation {
guard let fetchResult = self.fetchResult else { return }
if let changes = changeInstance.changeDetails(for: fetchResult) {
self.fetchResult = changes.fetchResultAfterChanges
}
}
}
func phothAurhorizationStatus() {
let phothAurhorizationStatus = PHPhotoLibrary.authorizationStatus()
switch phothAurhorizationStatus {
case .authorized:
print("ok")
self.requestImageCollection()
DispatchQueue.main.async {
self.MyAlbumView.reloadData()
}
case .denied:
print("denied")
case .notDetermined:
print("notDetermined")
PHPhotoLibrary.requestAuthorization { status in
switch status {
case .authorized:
print("사용자 허용")
self.requestImageCollection()
DispatchQueue.main.async {
self.MyAlbumView.reloadData()
}
case .denied:
print("허용되지 않음")
default: break
}
}
case .restricted:
let alert = UIAlertController(title: "안내",
message: "동의 진행 중입니다.",
preferredStyle: .alert)
let cancelAction = UIAlertAction(title: "확인",
style: .default)
alert.addAction(cancelAction)
present(alert, animated: true)
@unknown default:
print("fatal error")
}
MyAlbumView.reloadData()
}
func requestImageCollection() {
let fetchOption = PHFetchOptions()
let cameraRoll = PHAssetCollection.fetchAssetCollections(with: .smartAlbum, subtype: .smartAlbumUserLibrary, options: nil)
fetchOption.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
for integer in 0 ..< cameraRoll.count {
let collection = cameraRoll.object(at: integer)
self.fetchResult = PHAsset.fetchAssets(in: collection, options: fetchOption)
}
DispatchQueue.main.async {
self.MyAlbumView.reloadData()
}
guard let fetchResult = fetchResult else { return }
OperationQueue.main.addOperation {
self.imageManager.requestImage(for: fetchResult.object(at: 0),
targetSize: self.TcgSize,
contentMode: .aspectFit,
options: nil) { image, _ in
self.selectedImg.image = image
}
}
}
}
일단 첫번째 함수는 제치고 두번째 phothAurhorizationStatus()부터 보면 이 함수는 접근 권한을 요청하는 이벤트 발생 메소드입니다.
동의화면을 띄우고 동의했을 때 동의하지 않았을 때 동의가 이미 되있을 때를 나누어 각각의 경우에 따라 이벤트 처리를 하는 함수입니다.
이 코드는 부스트코스에서 배운걸 그대로 가져왔어요 헤헤..
그리고 동의하거나 동의가 되어있는 상태에서 실행되는 requestImageCollection() 를 보면 이 함수는
접근이 동의됬을 때 fetchResult라는 외부변수로 선언된 PHFetchResult<PHAsset>타입에 라이브러리 사진들을 담고
PHCachingImageManager() 타입으로 초기화된 let 상수가 UIImage으로 변환시켜 UICollectionView의 UIImageView에
담을 수 있게 해주는 기능을 합니다
기똥차게 어려워서 온갖 구글링과 개발문서들을 보고 겨우 살짝 이해해서 구현에 성공한 함수이기도 하지요...
다시 첫번째 함수로 들어오면 이 함수는 변화를 감지하여 반영하는 함수로 사진 라이브러리에 사진이 추가되거나 삭제되거나 할때 반응하여 갱신을 해주는 역할을 합니다. 이 자료가 정말 없어서 되면서도 왜 될까?이건 정말 이해 못했는데 말그대로 눈물 쏟으면서 구글링하다 알게된 함수지요
이 함수를 사용할려면
PHPhotoLibrary.shared().register(self) <- 이뷰에서 감지를 하게 만드는 메소드를 선언해줘야 합니다
또한 다른 화면으로 이동할 땐 쓸일이 없으니
삭제하는 것도 만들어주어야겠죠
이제 마지막으로 UICollectionCell을 만들어서 UIcollectionView가 제대로 동작하게 해봅시다.
import UIKit
class MyAlbumCollectionCell : UICollectionViewCell {
@IBOutlet weak var albumImageView: UIImageView!
@IBOutlet weak var selectedImageView: UIImageView!
@IBOutlet weak var selectedView: UIView!
var representAssetIdentifier: String?
var thumbnailSize: CGSize {
let scale = UIScreen.main.scale
return CGSize(width: (UIScreen.main.bounds.width / 3) * scale, height: 100 * scale)
}
override func awakeFromNib() {
super.awakeFromNib()
albumImageView.contentMode = .scaleAspectFill
}
override func prepareForReuse() {
super.prepareForReuse()
}
override var isHighlighted: Bool {
didSet {
selectedView.isHidden = !isHighlighted
}
}
override var isSelected: Bool {
didSet {
selectedView.isHidden = !isSelected
selectedImageView.isHidden = !isSelected
}
}
func configure(with image:UIImage?) {
self.albumImageView.image = image
}
}
새로은 swift파일을 만들어 UICollectioncell을 상속하는 클래스를 만들고 코드를 체워주세요
isSelected,isHighlihted는 다음 포스팅에 다룰테니 무시하셔도 됩니다.
그 다음 에러발생 방지로 대충 체워둔 collcetionview 프로토콜 함수들을 체워주겠습니다.
이렇게 cell 클래스에 만든 함수와 imageManagaer를 연결해서 메소드를 만들면 사진을 불러와 볼 수 있는 기능은 완성되었습니다.
이렇게 해서 실행을 한후 이 뷰컨트롤러로 이동을 하면!
권한 부여 안내가 뜨고 ok를 눌러주면
시뮬레이터에 있는 샘플용 사진들이 바로 UICollectionView에 갱신되는 것을 볼 수 있습니다.
이 다음 포스팅에서는 사진을 선택하는 custom collection didSelected함수와 할 수 있으면 게시물 송신까지 해보겠습니다.
'IOS Swift > Festagram' 카테고리의 다른 글
Swift 프로젝트 : FestaGram 04 게시물 작성 화면 03 (0) | 2020.04.16 |
---|---|
Swift 프로젝트 : FestaGram 04 게시물 작성 화면 02 (0) | 2020.04.15 |
Swift 프로젝트 : FestaGram 03 메인(피드)화면 03 (0) | 2020.03.31 |
Swift 프로젝트 : FestaGram 03 메인(피드)화면 02 (0) | 2020.03.27 |
Swift 프로젝트 FestaGram 03/ 메인(피드)화면 01 (0) | 2020.03.26 |