Skip to content

Latest commit

ย 

History

History
504 lines (317 loc) ยท 12.7 KB

README.md

File metadata and controls

504 lines (317 loc) ยท 12.7 KB

Fluff_iOS


Work Flow


Commit Message

๐Ÿ”ต [Update], [Create], [Fix] โžก๏ธ ์ปค๋ฐ‹ ๋ฉ”์„ธ์ง€ ํ˜•์‹ ํ†ต์ผ

๐Ÿ”ต ํ•œ๊ธ€๋กœ ๋ณ€๊ฒฝ๋œ ํด๋”๋ช…, ๊ธฐ๋Šฅ ๊ตฌํ˜„ ์ˆœ โžก๏ธ ์ปค๋ฐ‹ ๋ฉ”์„ธ์ง€ ํ†ต์ผ


Code Convention

๐Ÿ”ต ViewController ==> ~~VC ๋กœ ํŒŒ์ผ ํ†ต์ผ

๐Ÿ”ต ๋ณ€์ˆ˜๋ช…, ํ•จ์ˆ˜๋ช… Lower Camel ์‚ฌ์šฉ

๐Ÿ”ต Extension ์ด๋ฆ„ ==> ํ™•์žฅํด๋ž˜์Šค + Extension

๐Ÿ”ต TableView, CollectionView ์˜ Delegate, DataSource

class ViewController: UIViewController {}
extension ViewController: UITableViewDelegate {}
extension ViewController: UITableViewDataSource {}

๐Ÿ”ต Optional ๋ณ€์ˆ˜ guard let ์œผ๋กœ ๋ฐ”์ธ๋”ฉํ•˜๊ธฐ


๊ฐœ๋ฐœ ํ™˜๊ฒฝ

๐Ÿ”ต Xcode Version 11.3

๐Ÿ”ต Swift 5


๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

โœ… Alamofire

โœ… KingFisher

โœ… CHIPageControl

โœ… XLPagerTabStrip

โœ… BEMCheckBox

โœ… Hero


์‹คํ–‰ํ™”๋ฉด

์‹œ์ž‘ ํ™”๋ฉด


์‹œ์ž‘ํ™”๋ฉด ์• ๋‹ˆ๋ฉ”์ด์…˜


ํšŒ์›๊ฐ€์ž…


ํšŒ์›๊ฐ€์ž… Progress Bar


์ทจํ–ฅ ๋ถ„์„


์ทจํ–ฅ ๋ถ„์„ ์• ๋‹ˆ๋ฉ”์ด์…˜


์ทจํ–ฅ ๋ถ„์„ 2


ํ™˜์˜ ํ™”๋ฉด


๋ฉ”์ธ ํ™”๋ฉด


๋‘˜๋Ÿฌ๋ณด๊ธฐ


ํ•„ํ„ฐ ์• ๋‹ˆ๋ฉ”์ด์…˜


์ƒ์„ธ ์ •๋ณด


์ฃผ๋ฌธํ•˜๊ธฐ


์žฅ๋ฐ”๊ตฌ๋‹ˆ


๊ตฌ๋งคํ•˜๊ธฐ


๊ตฌ๋งคํ•˜๊ธฐ ์• ๋‹ˆ๋ฉ”์ด์…˜


๊ฒฝ๋งค


๊ฒฝ๋งค ์• ๋‹ˆ๋ฉ”์ด์…˜


๋งค๊ฑฐ์ง„


๋งค๊ฑฐ์ง„ ์• ๋‹ˆ๋ฉ”์ด์…˜


๋งˆ์ดํŽ˜์ด์ง€


์ฐœ ๋ชฉ๋ก



๊ธฐ๋Šฅ ์†Œ๊ฐœ

ํ™ˆํƒญ

๊ธฐ๋Šฅ ๊ฐœ๋ฐœ์—ฌ๋ถ€ ๋‹ด๋‹น
๋กœ๊ทธ์ธ/ํšŒ์›๊ฐ€์ž… O ๋™๋ฏผ
ํ™ˆํƒญ O ํƒœ์ง„
๋‘˜๋Ÿฌ๋ณด๊ธฐ O ๋™๋ฏผ
๊ฒฝ๋งค โ–ณ ๋™๋ฏผ
๋งค๊ฑฐ์ง„ O ํƒœ์ง„
๋งˆ์ดํŽ˜์ด์ง€ โ–ณ ๋™๋ฏผ
์ฐœ๋ชฉ๋ก X ๐Ÿ˜ž
ํŒ”๋กœ์šฐ X ๐Ÿ˜ž

์„ธ๋ถ€๊ธฐ๋Šฅ

๊ธฐ๋Šฅ ๊ฐœ๋ฐœ์—ฌ๋ถ€ ๋‹ด๋‹น
SNS๋กœ๊ทธ์ธ X ๐Ÿง
ํ™ˆํƒญ ์„ธ๋ถ€์ •๋ณด O ํƒœ์ง„
๋‘˜๋Ÿฌ๋ณด๊ธฐ ํ•„ํ„ฐ โ–ณ ๋™๋ฏผ
์žฅ๋ฐ”๊ตฌ๋‹ˆ ๋‹ด๊ธฐ O ๋™๋ฏผ
์žฅ๋ฐ”๊ตฌ๋‹ˆ ๊ตฌ๋งคํ•˜๊ธฐ O ๋™๋ฏผ
๊ฒฝ๋งค ์†Œ์ผ“ํ†ต์‹  โ–ณ ๋™๋ฏผ
๋งค๊ฑฐ์ง„ ์• ๋‹ˆ๋ฉ”์ด์…˜ O ํƒœ์ง„
์ทจํ–ฅ ์ถ”์ฒœ O ๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ง
ํ”Œ๋Ÿฝ ์ถ”์ฒœ O ๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ง


์–ด๋ ค์šด ๊ฒƒ ํ•ด๊ฒฐํ•œ ๊ฒƒ

  1. CollectionView ๋ ˆ์ด์•„์›ƒ ์žก๊ธฐ (DelegateFlowLayout ์•ˆ์žกํž˜)

๐Ÿ”ต Interface Builder AutoLayout ์˜ต์…˜์—์„œ None์œผ๋กœ ์ง€์ •ํ•˜๋ฉด ์ฝ”๋“œ๋กœ ์ง€์ •ํ•œ๋Œ€๋กœ ์„ค์ •

extension ViewController: UICollectionViewDelegateFlowLayout {
  // ์ƒ, ํ•˜, ์ขŒ, ์šฐ Inset ์ง€์ •
  func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
    return UIEdgeInsets(top: 8, left: spacingWidth, bottom: 0, right: spacingWidth)
}
  // ์„ธ๋กœ ๋ผ์ธ Spacing ์ง€์ •
	func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
    return 20
}
  // ๊ฐ€๋กœ ๋ผ์ธ Spacing ์ง€์ •
  func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
    return 0
}
  // ๊ฐ ์…€ Size ์ง€์ •
  func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    return CGSize(width: collectionView.frame.width, height: collectionView.frame.height)
  }
}

  1. Animationable Property๊ฐ€ ์กด์žฌ

1๏ธโƒฃ frame

2๏ธโƒฃ bounds

3๏ธโƒฃ center

4๏ธโƒฃ transform

5๏ธโƒฃ alpha

6๏ธโƒฃ backgroundColor

7๏ธโƒฃ contentStretch


  1. ScrollView Delegateํ™œ์šฉ PageControl ( โœ… CHIPageControl ์‚ฌ์šฉ )

ํŽ˜์ด์ง€ ๋ฒˆํ˜ธ ๊ณ„์‚ฐ

ํ˜„์žฌ x ์œ„์น˜๋กœ View์˜ Width์„ ๋‚˜๋ˆ„์–ด์„œ ํ˜„์žฌ ํŽ˜์ด์ง€ ๊ณ„์‚ฐ โžก๏ธ Int ๊ฐ’์œผ๋กœ ํ™˜์‚ฐ์„ ํ•˜๋ฉด ํŽ˜์ด์ง€ ๊ฐ’์ด ๋‚˜์˜จ๋‹ค.

func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
  let page = Int(targetContentOffset.pointee.x / self.view.frame.width)
  pageControl.set(progress: page, animated: true)
}

  1. UIView Blur ์ฒ˜๋ฆฌ
var backgroundEffectView: UIVisualEffectView!		// Visual Effect์„ ๋„ฃ์„ ์ˆ˜ ์žˆ๋Š” View

func setBlurView() {
  let blurEffect = UIBlurEffect(style: dark) 		// Blur Effect ๋„ฃ์„ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ ์ƒ์„ฑ
  backgroundEffectView.effect = blurEffect			// UIVisualEffectView์— Blurํšจ๊ณผ ์ ์šฉ
}

  1. ์ „์ฒด ๋ ˆ์ด์•„์›ƒ์ด ์ œ๋Œ€๋กœ ์ ์šฉ ์•ˆ๋˜๋Š” ๋ฌธ์ œ iPhone 11 Pro Max ์—์„œ ์ž‘์—… ํ›„ ==> iPhone 11 Pro์— ์ ์šฉํ•  ๊ฒฝ์šฐ ๋ ˆ์ด์•„์›ƒ์ด Pro Max๋กœ ์ ์šฉ๋˜์–ด Button์˜ Radius๊ฐ€ ์ ์šฉ์ด ์•ˆ๋จ
// Layout ๊ด€๋ จ ๋ฉ”์†Œ๋“œ ๊ณต๋ถ€๋“ค ๋” ํ•„์š”
// View์˜ SubView๋“ค์˜ ๋ ˆ์ด์•„์›ƒ ๊ด€๋ จํ•ด์„œ ๋‹ค์‹œ ์žก์•„์ค„ ํ•„์š”๊ฐ€ ์žˆ์„ ๊ฒฝ์šฐ
// ์ด ํ•จ์ˆ˜์—์„œ View๋“ค์˜ Layout์„ ๋‹ค์‹œ ๋ฆฌ์…‹์‹œ์ผœ์ฃผ๋ฉด์„œ ์žก์•„์ค€๋‹ค.
// iPhone11 Pro Max๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์žกํ˜€์žˆ๋˜ ๊ฒƒ์„ iPhone 11 Pro์„ ๊ธฐ์ค€์œผ๋กœ ๋‹ค์‹œ ์žก์„ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค.
override func viewDidLayoutSubviews() {
  super.viewDidLayoutSubviews()
  initColorButtons()
}

  1. StackView ์ด์šฉ Animation ์ ์šฉ AutoLayout ์žก์•„์ฃผ๊ธฐ

๐Ÿ”ต ํ•„ํ„ฐ๋ฅผ ์ ์šฉํ–ˆ์„ ๋•Œ๋งŒ ์„ ํƒํ•˜๋Š” ๋ฉ”๋‰ด์—์„œ StackView์„ ํ™œ์šฉ ์˜คํ† ๋ ˆ์ด์•„์›ƒ์„ ์žก์•„์ฃผ์—ˆ๋‹ค. isHidden ์˜ต์…˜ ํ™œ์šฉ

detailFilterView.isHidden = false
// setNeedsLayout ํ•„์š” isHidden ํ›„ ==> ์ด ๋ถ€๋ถ„๋„ ๊ณต๋ถ€ ํ•„์š”
self.view.setNeedsLayout()
UIView.animate(withDuration: 1, delay: 0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0, options: .curveEaseInOut, animations: {
                    self.view.layoutIfNeeded()
// ๋ณดํ†ต isHidden ํ›„ ๋‚˜ํƒ€๋‚ ๋•Œ, ํ™”๋ฉด ๋ฒ„๋ฒ…๊ฑฐ๋ฆฌ๋Š” ๋ฌธ์ œ๋กœ layoutIfNeeded() ํ•„์š”
// ์—ฌ๊ธฐ๋„ ๊ณต๋ถ€ ํ•„์š”
                }, completion: nil)

  1. ๊ฐ€์žฅ ์ƒ์œ„ View๋กœ ๋„์šฐ๊ธฐ (Navigation Bar, Tab Bar ์œ„๋กœ View๊ฐ€ ์˜ฌ๋ผ์˜ด)
guard let window = UIApplication.shared.keyWindow else { return }
window.addSubView(UIView())

  1. Tabbar isHidden ์„ Bottom์— Spacing์ด ์ƒ๊ธฐ๋Š” ๋ฌธ์ œ
// hideBottomBarWhenPushed์„ ๋„˜์–ด๊ฐ€๋Š” View์— ์„ค์ •
private func setTabbar() {
  self.hidesBottomBarWhenPushed = true
}

  1. ์„œ๋ฒ„ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•  ๋•Œ, ์„œ๋ฒ„์—์„œ Key๊ฐ’ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒฝ์šฐ

๐Ÿ”ต JSON ์—์„œ ํ•ญ์ƒ Key๊ฐ’์€ String์ด๋‹ˆ๊น CodingKeys๋ผ๋Š” enum์€ CodingKey๋ผ๋Š” ํ”„๋กœํ† ์ฝœ์„ ์ฑ„ํƒํ•˜๊ฒŒ ํ•œ๋‹ค.

๐Ÿ”ต JSON ํƒ€์ž…์—์„œ name์˜ ํ‚ค๊ฐ€ ์žˆ์„ ๊ฒฝ์šฐ โžก๏ธ myName์œผ๋กœ ๋Œ€์ž…

๐Ÿ”ต JSON ํƒ€์ž…์—์„œ age์˜ ํ‚ค๊ฐ€ ์žˆ์„ ๊ฒฝ์šฐ โžก๏ธ myAge์œผ๋กœ ๋Œ€์ž…

struct Person: Codable {
  var myName: String
  var myAge: Int?
  
  enum CodingKeys: String, CodingKey {
    case myName = "name"
    case myAge = "age"
  }
  
  init(from decoder: Decoder) throws {
    let values = try decoder.container(keyedBy: CodingKeys.self)
    myName = (try? values.decode(String.self, forkey: .myName)) ?? ""
    myAge = (try? values.decode(String.self, forkey: .myAge)) ?? nil
  }
}

  1. Dictionary ํƒ€์ž… Value๊ฐ’์œผ๋กœ Sortingํ•˜๊ธฐ
// key, value ์ˆœ์œผ๋กœ Sorting ==> value์˜ ๊ฐ’์„ ๊ธฐ์ค€์œผ๋กœ ํฐ ๊ฐ’์ด ์™ผ์ชฝ์— ์˜ค๊ฒŒ ๋ฐ”๊พธ๊ธฐ
let sortedParameter = surveyResult.sorted { $0.1 > $1.1 }
            let sortingKey = [sortedParameter[0].key, sortedParameter[1].key, sortedParameter[2].key]

  1. ํ‚ค๋ณด๋“œ๊ฐ€ View ํ„ฐ์น˜ Keyboard Down Event ๋ฐœ์ƒ
self.view.endEditting(true)

  1. NavigationBar์— BarButtonItem ์ฝ”๋“œ๋กœ ์ถ”๊ฐ€ํ•˜๊ธฐ
private func setNaviBackButton() {
  self.navigationItem.leftBarButtonItem = UIBarButtonItem(image: UIImage(named: "10"), style: .done, target: self, action: #selector(popView))
  self.navigationController?.navigationBar.topItem?.title = ""
}

@objc func popView() {
  self.navigationController?.popViewController(animated: true)
}

  1. TableView ์„ ํƒ ํ›„, ๋‹ค์Œ๋ทฐ๋กœ ๋„˜์–ด๊ฐ”๋‹ค ์˜ฌ ๋•Œ ์„ ํƒ๋œ ์˜์—ญ ํ•ด์ œํ•˜๊ธฐ
override func viewDidDisappear(_ animated: Bool) {
  super.viewDidDisappear(animated)
	if let index = myPageButtonTableView.indexPathForSelectedRow {
    myPageButtonTableView.deselectRow(at: index, animated: true)
  }
}

  1. TableView ๋ฐ‘์ค„ ๋ผ์ธ์ด ๋น„๋Š” ํ˜„์ƒ ํ•ด๊ฒฐ โžก๏ธ ๋น„๋Š” ๊ณต๊ฐ„ ์—†๊ฒŒ
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  guard let cartCell = tableView.dequeueReusableCell(withIdentifier: "cartCell") as? CartTableViewCell else { return UITableViewCell() }
  // zero๋กœ ์ฃผ๋ฉด ๋ฌธ์ œ ํ•ด๊ฒฐ ์ขŒ๊ณต๊ฐ„ Inset์ด 0์œผ๋กœ ์„ค์ •๋œ๋‹ค.
  cartCell.separatorInset = UIEdgeInsets.zero
}

  1. ์นด๋ฉ”๋ผ ์‚ฌ์šฉํ•˜๊ธฐ UIImagePicker ์‚ฌ์šฉ

โœ… Info.plist Camera, Galary ์ ‘๊ทผ ๊ถŒํ•œ ์„ค์ • ํ•„์ˆ˜, UIImagePickeroControllerDelegate ์„ค์ • ํ•„์ˆ˜

extension FluvApplyVC: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
    func openLibrary() {
        imagePicker.sourceType = .photoLibrary
        present(imagePicker, animated: false, completion: nil)
    }
    
    func openCamera() {
        if UIImagePickerController.isSourceTypeAvailable(.camera) {
            imagePicker.sourceType = .camera
        } else {
        }
        present(imagePicker, animated: false, completion: nil)
    }
    
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
            profileImage = image
            profileButton.setBackgroundImage(profileImage, for: .normal)
            dismiss(animated: true, completion: nil)
        }
    }
}

  1. NumberFormatter ์‚ฌ์šฉ ์ˆซ์ž ๊ตฌ๋ถ„
// 3์ž๋ฆฌ๋ถ€ํ„ฐ ๋‹จ์œ„ ์‚ฌ์šฉํ•˜๊ฒŒ ๊ตฌ๋ถ„
let numberFormatter = NumberFormatter()
numberFormatter.style = .decimal

let text = numberFormatter.string(from: NSNumber(value: styleData[indexPath.row].price))! + "์›"

์ฐธ๊ฐ€์ž