✔︎ 오늘의 정리
- Cell 꾹 눌러서 수정 / 삭제 창 띄우기
- fileManager를 통한 이미지 저장
- datePicker와 dateFormatter
- clipsToBounds와 masksToBounds
Cell 꾹 눌러서 수정 / 삭제 창 띄우기
요 method를 사용해서 한다!
셀을 꾹 눌렀을 때 대리자를 실행할 경우를 설정해 준다구 한다.
return값으로 들어가는 UIContextMenuConfiguration이 대리자로 되는듯?!
func tableView(_ tableView: UITableView, contextMenuConfigurationForRowAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? {
let modify = UIAction(title: "수정하기") { _ in
// 수정 ViewController
print("수정하깅")
}
let delete = UIAction(title: "삭제하기") { _ in
// 삭제 Alert 띄움
print("삭제하깅")
}
let menuConfiguration = UIContextMenuConfiguration(actionProvider: { _ in
UIMenu(title: "", children: [modify, delete])
})
return menuConfiguration
}
요런 식으루 구성했다.
자세한 기능은 추후에 추가하고 일단 보이는 거부터 맹글어 줬다!!
참고 블로그
https://nsscreencast.com/episodes/484-context-menus-table-views
collectionView는 이쪽 ^_^
https://medium.com/doyeona/context-menus-in-ios13-collectionview-1d292d4fe8e0
fileManager를 통한 이미지 저장
- info.plist 권한 설정
- 저장한 파일의 경로 설정(URL / appendingPathComponent)
- 폴더 생성
- 파일 경로 설정 & 확장자 설정
- 파일 삭제
//
// ImageManager.swift
// Orang
//
// Created by yeoni on 2023/10/02.
//
import UIKit
class ImageManager {
static let shared = ImageManager()
private init() { }
enum DirectoryName: String {
case profile
}
let fileManager = FileManager.default
func makeDirectory(directoryName: DirectoryName) {
let documentURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first!
// 실제 파일 이름
let directoryURL = documentURL.appendingPathComponent(directoryName.rawValue)
do {
try fileManager.createDirectory(at: directoryURL, withIntermediateDirectories: false, attributes: nil)
} catch let error {
print("directory Error: \(error.localizedDescription)")
}
}
func saveImageToDirectory(directoryName: DirectoryName, identifier: String, image: UIImage?) {
let documentURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first!
// 저장할 directoryURL 설정
let directoryURL = documentURL.appendingPathComponent(directoryName.rawValue)
var imageName = directoryName.rawValue
if directoryName != .profile {
imageName += identifier
}
// 이미지 이름 & 최종 경로 설정
let fileURL = directoryURL.appendingPathComponent(imageName, conformingTo: .jpeg)
print(fileURL)
do {
if let imageData = image?.jpegData(compressionQuality: 0.3) {
try imageData.write(to: fileURL)
print("Image saved at: \(fileURL)")
}
} catch let error {
print("Failed to save image: \(error.localizedDescription)")
}
}
func loadImageFromDirectory(directoryName: DirectoryName, with identifier: String) -> UIImage? {
let documentURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first!
let directoryURL = documentURL.appendingPathComponent(directoryName.rawValue)
let fileURL = directoryURL.appendingPathComponent(identifier, conformingTo: .jpeg)
guard fileManager.fileExists(atPath: fileURL.path) else { return nil }
/*
여러 개를 읽고 싶다면...
do {
let fileURLs = try fileManager.contentsOfDirectory(at: documentURL, includingPropertiesForKeys: nil)
let imageURLs = fileURLs.filter { $0.pathExtension.lowercased() == "jpeg" }
let images = imageURLs.compactMap { UIImage(contentsOfFile: $0.path) }
} catch let error {
print("Error to read directory: \(error)")
}
*/
return UIImage(contentsOfFile: fileURL.path)
}
func removeImageFromDirectory(directoryName: DirectoryName, identifier: String) {
let documentURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first!
let directoryURL = documentURL.appendingPathComponent(directoryName.rawValue)
let fileURL = directoryURL.appendingPathComponent(identifier, conformingTo: .jpeg)
do {
if fileManager.fileExists(atPath: fileURL.path) {
try fileManager.removeItem(at: fileURL)
}
} catch let error {
print("Failed to delete file: \(error.localizedDescription)")
}
}
}
datePicker와 dateFormatter
func configureView() {
birthTextField.tag = 1
meetDateTextField.tag = 2
[birthTextField, meetDateTextField].forEach {
setupDatePicker(textField: $0)
}
profileImageButton.addTarget(self, action: #selector(profileImageButtonClicked), for: .touchUpInside)
}
private func setupDatePicker(textField: UITextField) {
let datePicker = UIDatePicker()
datePicker.tag = textField.tag
datePicker.datePickerMode = .date
datePicker.preferredDatePickerStyle = .inline
// 원하는 언어로 지역 설정
datePicker.locale = Locale(identifier: "ko-KR")
datePicker.addTarget(self, action: #selector(dateChange), for: .valueChanged)
textField.inputView = datePicker
textField.text = datePicker.dateFormat()
}
// 값이 변할 때 마다 동작
@objc func dateChange(_ sender: UIDatePicker) {
if sender.tag == 1 {
birthTextField.text = sender.dateFormat()
} else {
meetDateTextField.text = sender.dateFormat()
}
^___^
clipToBounds와 masksToBounds
둘 다 자기 자신의 영역 이외에 영역을 그릴지말지를 정하는 것은 같으나 다른 점은 clipToBounds는 View 속한 프로퍼티이지만, masksToBounds는 CALayer에 속한 것이 다르다 ,, ^_^
예리님이 질문하시길래 막찾아보고 알려드려서 우와여기글좋다~~!! 하고 예리님께 여기링크드릴까요?? 햇는데
예리님이 단칼에 "아뇨,," 하셧음..
그래서대신그냥적기라도해요..
'TIL' 카테고리의 다른 글
[SeSAC] October 12, 2023 (1) | 2023.10.13 |
---|---|
[SeSAC] October 7, 2023 (0) | 2023.10.07 |
[SeSAC] September 17, 2023 (0) | 2023.09.20 |
[SeSAC] September 7, 2023 (0) | 2023.09.07 |
[SeSAC] September 4, 2023 (2) | 2023.09.07 |