Skip to content

INTENRZ/iOS-Internz

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๐Ÿ’› INTERNZ_iOS ๐Ÿฅ๐Ÿค

์‚ฌํšŒ์— ์ฒซ ๋ฐœ๊ฑธ์Œ์„ ๋‚ด๋”›๊ธฐ ์ „ ํ•„์ˆ˜ ์š”์†Œ๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ๋Š” ์ธํ„ด ๊ฒฝํ—˜, ์–ด๋–ป๊ฒŒ ์ค€๋น„ํ•ด์•ผํ•  ์ง€ ๋ง‰๋ง‰ํ•˜๋‹ค๋ฉด?
์ธํ„ด์„ ์ฒ˜์Œ ์ค€๋น„ํ•˜๋Š” ๋Œ€ํ•™์ƒ์—๊ฒŒ, ์ธํ„ด์„ ์ค€๋น„ํ•˜์ง€๋งŒ ์–ด๋ ค์›€์„ ๊ฒช๊ณ  ์žˆ๋Š” ๋Œ€ํ•™์ƒ์—๊ฒŒ, ์ธํ„ด์„ ๊ฒฝํ—˜ํ–ˆ๊ฑฐ๋‚˜ ํ•˜๊ณ  ์žˆ๋Š” ๋Œ€ํ•™์ƒ์—๊ฒŒ
๊ฐ€์žฅ ๋จผ์ € ์ƒ๊ฐ๋‚˜๋Š” ์„œ๋น„์Šค๊ฐ€ ๋˜๊ธธ ๋ฐ”๋ผ๋ฉฐ ์ œ์•ˆํ•˜๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.


workflow

screenshots


๐Ÿ”ฅ WITH SOPT 25th iOS Project

  • ๊ฐœ๋ฐœ ๊ธฐ๊ฐ„ : 2019๋…„ 12์›” 21์ผ ~ 2020๋…„ 1์›” 3์ผ

โšก๏ธ ํ˜‘์—… ๊ทœ์น™

  • ์ปค๋ฐ‹ ๋ฉ”์„ธ์ง€๋Š” ์˜์–ด๋กœ
  • ๋ณ€์ˆ˜ ๋ช…์€ low camel ์‚ฌ์šฉ
  • ๊ฐ•์ œ ์˜ต์…”๋„ ๊ธˆ์ง€
  • ๊ฐ์ž ๋ถ„๋‹ดํ•œ ์Šคํ† ๋ฆฌ๋ณด๋“œ ์™ธ์— ๊ฑด๋“ค๊ธฐ ๊ธˆ์ง€
  • ์ปค๋ฐ‹์‹œ ๋ฐ˜๋“œ์‹œ ์„œ๋กœ์—๊ฒŒ ์•Œ๋ฆด๊ฒƒ

๐ŸŒŸ ์‚ฌ์šฉ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

  • pod 'Alamofire', '~> 4.8.2'
  • pod 'Kingfisher', '~> 4.10.1'
  • pod 'CHIPageControl', '~> 0.1.3'
  • pod 'Tabman', '~> 2.6'
  • pod 'FSCalendar'

๐Ÿ“ฑ Xcode Version

  • 11.3



๐Ÿ’ป ย  ๊ธฐ๋Šฅ ์†Œ๊ฐœ

๊ธฐ๋Šฅ ๊ฐœ๋ฐœ ์—ฌ๋ถ€ ๊ธฐํƒ€์‚ฌํ•ญ ๋‹ด๋‹น
์Šคํ”Œ๋ž˜์‰ฌ โ—‹ ์ฃผ์—ฐ
์˜จ๋ณด๋”ฉ โ—‹ ์–ดํ”Œ ์ฒซ ์‹คํ–‰ ์‹œ ๋™์ž‘ ๋‹ด
๋กœ๊ทธ์ธ โ—‹ ์ฃผ์—ฐ,๋‹ด
ํšŒ์›๊ฐ€์ž…(๊ธฐ๋ณธ์ •๋ณด) โ—‹ ์ด๋ฉ”์ผ ์ค‘๋ณต ์ฒดํฌ โ—‹ ๋‹ด
ํšŒ์›๊ฐ€์ž…(๊ด€์‹ฌ์ง๋ฌด + ํ”„๋กœํ•„ ์„ค์ •) โ–ณ ์ฒซ ๋ฒˆ์งธ ๋กœ๊ทธ์ธ ํ•œ ๊ฒฝ์šฐ์—๋งŒ ์ง€์ • ๋‹ด
ํ”„๋กœํ•„ ์„ค์ • โ–ณ ์ฒซ ๋ฒˆ์งธ ๋กœ๊ทธ์ธ ํ•œ ๊ฒฝ์šฐ์—๋งŒ ์ง€์ • ๋‹ด
ํ™ˆ(๋งž์ถค ๊ณต๊ณ ) โ–ณ ํšŒ์‚ฌ url ์—ฐ๊ฒฐ ๋‹ด
ํ™ˆ(์ถ”์ฒœ ํ”„๋กœํ•„) โ–ณ ์ƒ์„ธ ํ”„๋กœํ•„ ์—ฐ๊ฒฐ ๋‹ด
ํ™ˆ(์˜ค๋Š˜์˜ ์Šคํ† ๋ฆฌ) โ–ณ ์ƒ์„ธ ์Šคํ† ๋ฆฌ๋ทฐ ์—ฐ๊ฒฐ ๋‹ด
๊ณต๊ณ  โ—‹ ์ „์ฒด๊ณต๊ณ  / ์ง€๋‚œ ๊ณต๊ณ  ์ˆœ์œผ๋กœ ์ •๋ ฌ ๋‹ด
๊ณต๊ณ  ์ถ”๊ฐ€ โ—‹ ๊ด€์‹ฌ์žˆ๋Š” ๊ณต๊ณ ๋ฅผ ์บ˜๋ฆฐ๋” ์ผ์ •์— ์ถ”๊ฐ€ ๋‹ด
๊ณต๊ณ  ํ•„ํ„ฐ โ–ณ ๋ณด๊ณ  ์‹ถ์€ ์ง๋ฌด๋ฅผ ํ•„ํ„ฐ์— ๋”ฐ๋ผ ์„ค์ • ๋‹ด
๊ณต๊ณ  ์บ˜๋ฆฐ๋” โ—‹ ์›”๋ณ„ ๊ณต๊ณ  ์กฐํšŒ, ์ถ”๊ฐ€ํ•œ ๊ณต๊ณ  ๋ฆฌ์ŠคํŠธ๋ฅผ ์บ˜๋ฆฐ๋”์— ํ‘œ์‹œ ๋‹ด
์Šคํ† ๋ฆฌ โ—‹ ์ตœ์‹ ์ˆœ / ์กฐํšŒ์ˆœ ์ •๋ ฌ ๋‹ด
์นดํ…Œ๊ณ ๋ฆฌ ๋ณ„ ์Šคํ† ๋ฆฌ ์กฐํšŒ ์ธํ„ด / ๋Œ€์™ธํ™œ๋™ / ๊ณต๋ชจ์ „ / ๋™์•„๋ฆฌ / ์ž๊ฒฉ์ฆ / ๊ธฐํƒ€ ์— ๋”ฐ๋ผ ์กฐํšŒ ๋‹ด
์Šคํ† ๋ฆฌ ์ƒ์„ธ๊ธ€ โ—‹ ๋‹ด
์Šคํ† ๋ฆฌ ๋Œ“๊ธ€ โ—‹ ๋Œ“๊ธ€๋ณด๊ธฐ + ๋Œ“๊ธ€์“ฐ๊ธฐ ๋‹ด
๊ฐœ์ธ ํ”„๋กœํ•„ โ–ณ ์ •๋ณด: ํšŒ์›๊ฐ€์ž…์‹œ์˜ ํ•œ ์ค„ ์†Œ๊ฐœ + ํ”„๋กœํ•„ ์‚ฌ์ง„ + ๊ด€์‹ฌ ์ง๋ฌด ์ฃผ์—ฐ
๊ฐœ์ธ ํ”„๋กœํ•„ ์ชฝ์ง€ โ—‹ ๋Œ€ํ™”๋ฅผ ๋‚˜๋ˆˆ ์œ ์ € ๋ฆฌ์ŠคํŠธ ์ฃผ์—ฐ, ๋‹ด
๊ฐœ์ธ ํ”„๋กœํ•„ ์ชฝ์ง€ ์ƒ์„ธ ๋‚ด์šฉ โ–ณ ์ฃผ์—ฐ
๊ฐœ์ธ ํ”„๋กœํ•„ ํƒ€์ž„๋ผ์ธ ์กฐํšŒ โ—‹ ์ฃผ์—ฐ
๊ฐœ์ธ ํ”„๋กœํ•„ ํƒ€์ž„๋ผ์ธ ์ถ”๊ฐ€ โ–ณ ํ”Œ๋ŸฌํŒ…๋ฒ„ํŠผ์„ ํ†ตํ•ด ํƒ€์ž„๋ผ์ธ ์ถ”๊ฐ€ ์ฃผ์—ฐ
ํƒ€์ž„๋ผ์ธ ์Šคํ† ๋ฆฌ ๋ฆฌ์ŠคํŠธ ์กฐํšŒ โ—‹ ์ฃผ์—ฐ, ๋‹ด
๊ฐœ์ธ ํ”„๋กœํ•„ ์Šคํ† ๋ฆฌ ์ถ”๊ฐ€ โ–ณ ์ฃผ์—ฐ
๊ฐœ์ธ ํ”„๋กœํ•„ ์Šคํ† ๋ฆฌ ํŒ”๋กœ์šฐ ๋ฆฌ์ŠคํŠธ โ—‹ ์ฃผ์—ฐ, ๋‹ด



๐Ÿ“Œ screenshots

  1. splash


  1. onBoarding


  1. Login & Signup


  1. FirstLogin


  1. home tab : ์ถ”์ฒœ ๊ณต๊ณ , ์ถ”์ฒœ ํ”„๋กœํ•„, ์ตœ์‹  ์Šคํ† ๋ฆฌ


  1. announcement tab
  • ์ „์ฒด ๊ณต๊ณ , ์ง€๋‚œ ๊ณต๊ณ  ์ •๋ ฌ ์„ ํƒ
  • ๊ณต๊ณ  ํ•„ํ„ฐ : ๋ณด๊ณ  ์‹ถ์€ ์ง๋ฌด 1๊ฐœ ์„ ํƒ, ํ•„ํ„ฐ์— ๋”ฐ๋ผ ์ •๋ ฌ
  • ๊ณต๊ณ  ์บ˜๋ฆฐ๋” : ๊ด€์‹ฌ ์ถ”๊ฐ€ํ•œ ๊ณต๊ณ ๋ฅผ ์บ˜๋ฆฐ๋”์— ์ถ”๊ฐ€


  1. story tab
  • ์Šคํ† ๋ฆฌ ์ตœ์‹ ์ˆœ, ์กฐํšŒ์ˆœ ์ •๋ ฌ
  • ํƒญ ๋ฐ” : ์ธํ„ด, ๋Œ€์™ธํ™œ๋™, ๊ณต๋ชจ์ „, ๋™์•„๋ฆฌ, ์ž๊ฒฉ์ฆ, ๊ธฐํƒ€์— ๋”ฐ๋ฅธ ์Šคํ† ๋ฆฌ ์กฐํšŒ
  • ์Šคํ† ๋ฆฌ ์ƒ์„ธ๊ธ€
  • ์Šคํ† ๋ฆฌ ๋Œ“๊ธ€



  1. profile tab
  • ๊ฐœ์ธ ํ”„๋กœํ•„ ์ •๋ณด ์กฐํšŒ
  • ๊ฐœ์ธ ํ™œ๋™์— ๋Œ€ํ•œ ํƒ€์ž„๋ผ์ธ ์ž‘์„ฑ ๋ฐ ์กฐํšŒ
  • ๊ฐœ์ธ ํ”„๋กœํ•„ > ํƒ€์ž„๋ผ์ธ > ๊ฐ ํƒ€์ž„๋ผ์ธ์— ๋Œ€ํ•ด ์ž‘์„ฑํ•œ ์Šคํ† ๋ฆฌ ๋ฆฌ์ŠคํŠธ ์กฐํšŒ
  • ํŒ”๋กœ์ž‰ / ํŒ”๋กœ์›Œ ์กฐํšŒ
  • ์ชฝ์ง€ ์ฃผ๊ณ  ๋ฐ›๊ธฐ





๋ฌธ์ œ์ ๊ณผ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

  1. ์„œ๋ฒ„์—์„œ ๋ฐ›์•„์˜จ ๋ฐ์ดํ„ฐ๊ฐ€ decode ๋˜์ง€ ์•Š์Œ
    -> ResponseString ์ˆ˜์ • (https://app.quicktype.io ์ฐธ๊ณ  )
    enum CodingKeys: String, CodingKey {
        case timelineIdx, userIdx, title
        case start_date = "start_date"
        case end_date = "end_date"
        case category
    }
    
    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        timelineIdx = (try? values.decode(Int.self, forKey: .timelineIdx)) ?? 0
        userIdx = (try? values.decode(Int.self, forKey: .userIdx)) ?? 0
        title  = (try? values.decode(String.self, forKey: .title)) ?? ""
        start_date = (try? values.decode(String.self, forKey: .start_date)) ?? ""
        end_date = (try? values.decode(String.self, forKey: .end_date)) ?? ""
        category = (try? values.decode(String.self, forKey: .category)) ?? ""
    }


  1. UIPicker + Tool Bar ์ƒ์„ฑ -> ์ฝ”๋“œ๋กœ ์ž‘์„ฑ
        // 1. ์ „์ฒด๋ฅผ ์žก๋Š” view ์ƒ์„ฑ + constraint ๊ฑธ๊ธฐ
        self.picker.isHidden = false
        self.picker.frame = CGRect(x: 0, y: view.frame.height - 220, width: view.frame.width, height: 150)
        view.addSubview(self.picker)
        
        // 2. Tool Bar ์— ๋“ค์–ด๊ฐˆ ๋ฒ„ํŠผ ์ƒ์„ฑ
        let btnDone = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(self.testfunc))
        
        // 3. UIPicker Toolbar ์ƒ์„ฑ + ์†์„ฑ setting
        let barAccessory = UIToolbar(frame: CGRect(x: 0, y: 0, width: picker.frame.width, height: 44))
        
        barAccessory.barStyle = UIBarStyle.default
        barAccessory.isTranslucent = true
        barAccessory.items = [btnDone]
        
        picker.addSubview(barAccessory)
        
        
        // 4. UIPickerView ์ƒ์„ฑ
        self.pickerView.frame = CGRect(x: 0, y: barAccessory.frame.height, width: view.frame.width, height: picker.frame.height - barAccessory.frame.height)
        
        self.pickerView.delegate = self
        self.pickerView.dataSource = self
        self.pickerView.backgroundColor = UIColor.whiteFour
        
        picker.addSubview(self.pickerView)


  1. CalendarView ๋ฅผ ๊ธฐํš์— ๋งž๊ฒŒ ์ปค์Šคํ…€ ํ•˜๊ธฐ
  • FSCalendar Library ์„ค์น˜ ( https://rhammer.tistory.com/126 )
  • DateFormatter ๋ฅผ ์‚ฌ์šฉํ•ด ์›ํ•˜๋Š” ๋‚ ์งœ์— ์ด๋ฒคํŠธ ์ƒ์„ฑ
    let formatter = DateFormatter()
    formatter.locale = Locale(identifier: "ko_KR")
    formatter.dateFormat = "yyyy-MM-dd"
        
    let xmas = formatter.date(from: "2019-12-25")
    let sampledate = formatter.date(from: "2019-12-22")
        
    dates = [xmas!, sampledate!]
extension CalendarViewController: FSCalendarDataSource{
    func calendar(_ calendar: FSCalendar, numberOfEventsFor date: Date) -> Int {
        
        if self.dates.contains(date){
            return 1
        }
        
        return 0
    }
}


  1. UITabBar ์‚ฌ์šฉํ•˜๊ธฐ
       // Create bar
        let bar = TMBar.ButtonBar()
        bar.layout.transitionStyle = .snap
        
        // Customize button color
        bar.buttons.customize { (button) in
            button.tintColor = UIColor.brownishGreyTwo
            button.selectedTintColor = UIColor.marigold
        }
        
        bar.indicator.tintColor = UIColor.marigold
        
        addBar(bar, dataSource: self, at: .top)


  1. Navigation Bar Line Custom
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        if shadowImageView == nil {
            shadowImageView = findShadowImage(under: navigationController!.navigationBar)
        }
        shadowImageView?.isHidden = true
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        shadowImageView?.isHidden = false
    }
    
    private func findShadowImage(under view: UIView) -> UIImageView? {
        if view is UIImageView && view.bounds.size.height <= 1 {
            return (view as! UIImageView)
        }
        
        for subview in view.subviews {
            if let imageView = findShadowImage(under: subview) {
                return imageView
            }
        }
        return nil
    }




๐Ÿ‘ถ Contributor

iOS ๊ฐœ๋ฐœ ๊ฒฝํ—˜์ด ์—†์–ด ์‹œํ–‰์ฐฉ์˜ค๋ฅผ ๋งŽ์ด ๊ฒช์œผ๋ฉฐ ์„ฑ์žฅํ•˜๋Š” ์ค‘์ž…๋‹ˆ๋‹ค. ์ธํ„ด์ฆˆ ์ฒด๊ณ  ์ฃผ์—ฐ์ด ์ฒด์ฒด๊ณ โ€ผ๏ธ๐Ÿ˜˜

์•ฑ๊ฐœ๋ฐœ์€ ์ฒ˜์Œ์ด๋ผ ๋Šฅ์ˆ™์น˜ ๋ชปํ–ˆ์ง€๋งŒ ์ข‹์€ ํŒ€์› ๋•๋ถ„์— ๋งŽ์ด ์„ฑ์žฅํ•  ์ˆ˜ ์žˆ๋˜ ๋œป๊นŠ์€ ์‹œ๊ฐ„์ด์—ˆ์Šต๋‹ˆ๋‹ค! ์€์ž์ด ์ฒด์ฒด๊ณ  โฃ๏ธ


Releases

No releases published

Packages

No packages published