Skip to content

πŸƒπŸ»β€β™‚οΈπŸƒπŸ»β€β™€οΈ λŸ¬λ„ˆμŠ€ν•˜μ΄ iOS "진심" 레포 πŸƒπŸ»β€β™‚οΈπŸƒπŸ»β€β™€οΈ

Notifications You must be signed in to change notification settings

RunnersHi/RunnersHi_iOS

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

RUNNERS HI - iOS

πŸƒπŸ»β€β™‚οΈπŸƒπŸ»β€β™€οΈ λŸ¬λ„ˆμŠ€ν•˜μ΄ iOS "진심" 레포 πŸƒπŸ»β€β™‚οΈπŸƒπŸ»β€β™€οΈ

  • 진행기간 : 2020λ…„ 6μ›” 27일 ~ 7μ›” 18일 26th β€˜SOPT’ APPJAM
  • μ½”λ“œ λ¦¬νŒ©ν† λ§ κΈ°κ°„ : 2021λ…„ 3μ›” 25일 ~

λŸ¬λ‹μ„ κ²Œμž„μ²˜λŸΌ, λŸ¬λ„ˆμŠ€ν•˜μ΄

μš°λ¦¬λŠ” 'ν•¨κ»˜' λ›Έ λ•Œ 더 λ§Žμ€ μ‹œλ„ˆμ§€λ₯Ό λ§Œλ“€μ–΄λƒ…λ‹ˆλ‹€. μš”μ¦˜ μ„ΈλŒ€λ“€μ€ λŸ¬λ‹ 크루에 μ†Œμ†λ˜μ–΄ λŸ¬λ‹μ„ 즐기곀 ν•˜μ§€λ§Œ, Offline λŸ¬λ‹ν¬λ£¨λŠ” κ³ μ •λœ μ‹œκ°„κ³Ό μž₯μ†ŒλΌλŠ” ν•œκ³„μ μ„ 가지고 μžˆμŠ΅λ‹ˆλ‹€. μš°λ¦¬λŠ” 같이 달리고 μ‹Άμ§€λ§Œ, 달릴 수 μ—†λŠ” μˆœκ°„λ“€μ΄ μ‘΄μž¬ν•œλ‹€λŠ” 점에 μ§‘μ€‘ν•˜κ³ μž ν•©λ‹ˆλ‹€. 우리의 μ„œλΉ„μŠ€λ₯Ό 톡해 μ‹œκ³΅κ°„μ˜ μ œμ•½μ—†μ΄ λ‹€μ–‘ν•œ μ‚¬λžŒλ“€κ³Ό ν•¨κ»˜ λ‹¬λ¦ΌμœΌλ‘œμ¨ κ±΄κ°•ν•œ 라이프 μŠ€νƒ€μΌμ„ λ§Œλ“€μ–΄λ‚˜κ°€κΈΈ λ°”λžλ‹ˆλ‹€.

⭐️ κΈ°μ‘΄ λŸ¬λ‹ μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜κ³Όμ˜ ν™•μ‹€ν•œ 차별화 μš”μ†Œλ₯Ό μ μš©ν–ˆμŠ΅λ‹ˆλ‹€.

: κΈ°μ‘΄ λŸ¬λ‹ μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜κ³Όμ˜ ν™•μ‹€ν•œ 차별화 μš”μ†Œλ₯Ό μ μš©ν–ˆμŠ΅λ‹ˆλ‹€.

⭐️ λ”°λ‘œ, 또 같이 ν•¨κ»˜ ν•˜λŠ” κ°€μΉ˜λ₯Ό μΆ”κ΅¬ν•˜κ³ μž ν•©λ‹ˆλ‹€.

: μ–΄λ–€ 단체에 μ†Œμ†λ˜μ§€ μ•Šμ•„λ„, ꡳ이 μΉœκ΅¬μ™€ 약속을 작고 λ§Œλ‚˜μ§€ μ•Šμ•„λ„, μ‚¬μš©μžλŠ” μ–Έμ œ μ–΄λ””μ„œλ“  λ‚˜μ™€ ν•¨κ»˜ λ›Έ μƒλŒ€λ₯Ό μ°Ύμ•„ 같이 λŸ¬λ‹μ„ 즐길 수 μžˆμŠ΅λ‹ˆλ‹€.

⭐️ νŠΈλ Œλ””ν•œ λ””μžμΈμ  μš”μ†Œλ₯Ό 톡해 μ‹œκ°μ μΈ 즐거움을 얻을 수 μžˆμŠ΅λ‹ˆλ‹€.

: νŠΉμ • λͺ©ν‘œλ₯Ό λ‹¬μ„±ν•˜λ©΄ κ°œμ„±μžˆλŠ” μ—¬λŸ¬ 가지 뱃지λ₯Ό νšλ“ν•  수 있음과 λ™μ‹œμ— λ‹€μ–‘ν•œ λŸ¬λ„ˆ λž­ν‚Ήμ„ 톡해 μ‚¬μš©μžμ˜ 즐거움을 도λͺ¨ν•˜κ³ μž ν•©λ‹ˆλ‹€. 또, λˆ„κ΅¬λ‚˜ μ‚¬μš©ν•˜κΈ° μ‰¬μš΄ UX μš”μ†ŒλŠ” 즐거움을 배둜 ν–₯μƒμ‹œμΌœ μ€„κ±°μ—μš”.

=> λ°œν‘œμ˜μƒ 보기


A. Setting


B-1. 개발 ν™˜κ²½ 및 라이브러리

Xcode swift Alamofire Socket.IO-Client-Swift XLPagerTabStrip NMapsMape


B-2. WORKFLOW

μ΅œμ’…κ³Όμ œ  RUNNER'S HI WORKFLOW_page-0001


B-3. κΈ°λŠ₯ λͺ…μ„Έμ„œ

μš°μ„ μˆœμœ„ ν™”λ©΄ 이름 κΈ°λŠ₯ 이름 κ΅¬ν˜„ λ‹΄λ‹Ήμž
P1 νšŒμ› κ°€μž… κΈ°λ³Έ 데이터(λ‹‰λ„€μž„/아이디/λΉ„λ°€λ²ˆν˜Έ/성별/레벨) λ°›κΈ° πŸ”΅ 졜영재
P2 νŠœν† λ¦¬μ–Ό μŠ€ν”Œλž˜μ‰¬ πŸ”΅ 김민희
P1 맀칭화면 맀칭 데이터(λͺ©ν‘œμ‹œκ°„/μƒλŒ€ 성별)λ°›κΈ° πŸ”΅ 김민희
P1 맀칭화면 맀칭 κΈ°μ€€(λͺ©ν‘œμ‹œκ°„/성별/레벨)에 따라 λ§€μΉ­λŸ¬λ„ˆ μ°ΎκΈ° πŸ”΅ 김민희
P1 맀칭성곡화면 μƒλŒ€λŸ¬λ„ˆ ν”„λ‘œν•„, 레벨, 전적 보여주기 πŸ”΅ 김민희
P1 둜그인 둜그인 κΈ°λŠ₯ πŸ”΅ 졜영재
P1 λŸ¬λ‹μ€‘ν™”λ©΄ μ‹€μ‹œκ°„μœΌλ‘œ λŸ¬λ‹κ±°λ¦¬, 페이슀, 남은 μ‹œκ°„ 보여주기 πŸ”΅ 김민희
P1 λŸ¬λ‹μ€‘ν™”λ©΄ μΉ΄μš΄νŠΈλ‹€μš΄ πŸ”΅ 김민희
P1 λŸ¬λ‹μ€‘ν™”λ©΄ νœ΄λŒ€ν° μ‚¬μš©μž λ™μž‘ 및 ν”ΌνŠΈλ‹ˆμŠ€ ν™œλ™ μ ‘κ·Ό πŸ”΅ 김민희
P2 λŸ¬λ‹μ€‘ν™”λ©΄ ν˜„μž¬ μœ„μΉ˜ ν‘œμ‹œ πŸ”΅ 김민희
P2 λŸ¬λ‹λž­ν‚Ήν™”λ©΄ 1) 이동거리 λ†’μ€μˆœ 2)승이 λ§Žμ€ 순 3)νŒ¨κ°€ λ§Žμ€ 순 μ‚¬μš©μž λž­ν‚Ή πŸ”΅ 졜영재
P2 λŸ¬λ‹κΈ°λ‘ν™”λ©΄ λ‚˜μ˜ λŸ¬λ‹λ°μ΄ν„° λͺ¨μ•„μ„œ 보여주기 κΈ°λŠ₯ πŸ”΅ 졜영재
P2 λŸ¬λ‹κΈ°λ‘ν™”λ©΄ λŸ¬λ‹ 뱃지 λͺ¨μ•„μ„œ 보여주기 κΈ°λŠ₯ πŸ”΅ 졜영재
P2 λŸ¬λ‹κ²°κ³Όν™”λ©΄ 두 λŸ¬λ„ˆμ˜ 이동거리 비ꡐ κΈ°λŠ₯ πŸ”΅ 김민희
P1 λŸ¬λ‹κ²°κ³Όν™”λ©΄ λ‚˜μ˜ 기둝/μƒλŒ€λŸ¬λ„ˆ 기둝 λͺ¨μ•„μ„œ 보여주기 κΈ°λŠ₯ πŸ”΅ 김민희
P2 λ§ˆμ΄νŽ˜μ΄μ§€ λ‚˜μ˜ ν”„λ‘œν•„ 이미지/λ‹‰λ„€μž„/승패/레벨/뱃지 ν‘œμ‹œ πŸ”΅ 졜영재

C-1. 개발 μ„€λͺ…

Tab Bar

: Tab Bar을 μ΄μš©ν•΄ 각 μŠ€ν† λ¦¬λ³΄λ“œλ₯Ό 이어주며 이동 κ°€λŠ₯

νšŒμ›κ°€μž…, 둜그인 ν™”λ©΄

πŸ₯³ 둜그인, νšŒμ›κ°€μž… ν™”λ©΄. μ •κ·œν‘œν˜„μ‹ 검사와 아이디, λ‹‰λ„€μž„ 쀑볡 검사 μžλ™λ‘œκ·ΈμΈ κΈ°λŠ₯을 ν¬ν•¨ν•œλ‹€.

둜그인 νšŒμ›κ°€μž…_κΈ°λ³Έ νšŒμ›κ°€μž…_쀑간 νšŒμ›κ°€μž…_μ™„λ£Œ

Running Tab(ν™ˆ ν™”λ©΄)

πŸ₯³ Main ν™”λ©΄. 일러슀트둀 ν¬ν•¨ν•˜λ©°, RUN NOW λ²„νŠΌ ν΄λ¦­μ‹œ μ£Όμš” κΈ°λŠ₯은 맀칭 μ„œλΉ„μŠ€κ°€ μ‹œμž‘λœλ‹€. μ›ν•˜λŠ” 맀칭 λŸ¬λ„ˆμ˜ 쑰건을 μ„€μ •ν•˜κ³  맀칭이 되면 μƒλŒ€λ°© ν”„λ‘œν•„μ„ ν™•μΈν•œ ν›„, λŸ¬λ‹μ΄ μ‹œμž‘λœλ‹€.
πŸ€“ μΆ”ν›„ develop으둜 혼자 달리기λ₯Ό 톡해 맀칭이 μ•ˆλ˜λŠ” μ‚¬λžŒλ“€ ν˜Ήμ€ 혼자 λŸ¬λ‹μ„ 츑정해보고 싢은 μ‚¬λžŒλ“€μ„ μœ„ν•œ μ„œλΉ„μŠ€λ₯Ό μ œκ³΅ν•˜κ³ μž ν•œλ‹€.
RunningTab RunningTab-맀칭 μŠ€ν¬λ¦°μƒ· 2020-07-17 μ˜€ν›„ 11 06 42
μŠ€ν¬λ¦°μƒ· 2020-07-17 μ˜€ν›„ 11 06 46 μŠ€ν¬λ¦°μƒ· 2020-07-17 μ˜€ν›„ 11 06 49

πŸ₯³ 맀칭이 되면 μƒλŒ€λ°© ν”„λ‘œν•„μ„ ν™•μΈν•œ ν›„, λŸ¬λ‹μ΄ μ‹œμž‘λœλ‹€. μ‹€μ‹œκ°„μœΌλ‘œ μžμ‹ μ˜ 속도(km), 페이슀(pace), 남은 μ‹œκ°„μ΄ ν‘œμ‹œλ˜κ³  ν˜„μž¬ μžμ‹ μ΄ λ›°κ³ μžˆλŠ” μœ„μΉ˜κ°€ 지도(넀이버)λ₯Ό 톡해 ν‘œμ‹œλœλ‹€.
πŸ€“ ν˜„μž¬λŠ” μžμ‹ μ΄ μžˆλŠ” μœ„μΉ˜λ§Œ ν‘œμ‹œλ˜μ§€λ§Œ, μΆ”ν›„ μžμ‹ μ΄ λŸ¬λ‹ν•œ κ²½λ‘œκ°€ 뜨게 ν•  생각이닀. (ν˜„μž¬ λ„€μ΄λ²„μΈ‘μ—μ„œ points 속성을 λ§‰μ•„λ‘”κ²ƒμœΌλ‘œ 보여 κ΅¬ν˜„ν•˜μ§€ λͺ»ν•œ 아쉬움이 μžˆλ‹€.)넀이버 지도 iOS SDK

λ§€μΉ­λœλŸ¬λ„ˆν”„λ‘œν•„ 맀칭_λŸ¬λ‹μ€‘ μ‹€μ‹œκ°„λŸ¬λ‹μ€‘
μ‘Œλ‹€μ΄κ²Όλ‹€

Record Tab

: μžμ‹ μ΄ μ§€κΈˆκΉŒμ§€ μŒ“μ•„μ˜¨ λŸ¬λ‹ 기둝과 λͺ¨μ•„μ˜¨ λŸ¬λ‹λ±ƒμ§€λ₯Ό 확인할 수 μžˆλ‹€.

RecordTab RecordTab-뱃지

Ranking Tab

: ν˜„μž¬ 이 μ–΄ν”Œμ—μ„œ 'μ΄λ‹¬μ˜ λŸ¬λ„ˆ', 'λͺ…μ˜ˆμ˜ μ „λ‹Ή', '쑌.잘.μ‹Έ' 둜 λ‚˜λˆ μ§„ 3개의 λž­ν‚Ή μˆœμœ„λ₯Ό 확인할 수 μžˆλ‹€.

RankingTab

MyPage Tab

: μžμ‹ μ˜ κΈ°λ³Έ 정보(ν”„λ‘œν•„ 사진, λ‹‰λ„€μž„, 레벨, 전적)을 확인할 수 있고 λͺ¨μ•„λ‘” 뱃지λ₯Ό κ°„λž΅νžˆ 확인할 수 μžˆλ‹€.

MypageTab


C-2. πŸŒŸμƒˆλ‘œ μ•Œκ²Œ 된 κΈ°λŠ₯🌟

1) Healthkit

πŸ’ͺπŸ»μš΄λ™ μ–΄ν”Œμ˜ κΈ°λ³Έ! '건강' μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜ μ—°λ™ν•΄μ„œ κ°’ κ°€μ Έμ˜€κΈ° ! 도전 !πŸ’ͺ🏻

  1. λ¨Όμ € 건강 μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ„ μ—°λ™ν•˜λ €λ©΄ Apple Developer Program Membership 이 ν•„μš”ν•©λ‹ˆλ‹€ (유료)
  2. Capabilityμ—μ„œ Healthkitλ₯Ό μΆ”κ°€ν•΄ ν™œμ„±ν™” μ‹œμΌœμ€λ‹ˆλ‹€.

Healthkit 연동

  1. info.plist νŒŒμΌμ—μ„œ Information Property List Key Referenceλ₯Ό μΆ”κ°€ν•΄μ€λ‹ˆλ‹€.

μŠ€ν¬λ¦°μƒ· 2020-07-08 μ˜€ν›„ 8 40 09

  1. HealthKit μ•‘μ„ΈμŠ€λ₯Ό ν—ˆμš©ν•˜λŠ” μ½”λ“œλ₯Ό μ§œμ•Όν•©λ‹ˆλ‹€.
  • 이 κΈ°κΈ°μ—μ„œ HealthKitλ₯Ό μ‚¬μš©ν•  수 μžˆλŠ”μ§€ ν™•μΈν•˜κΈ°.
guard HKHealthStore.isHealthDataAvailable() else {
    completion(false, HealthkitSetupError.notAvailableOnDevice)
    return
  }
  • HealthKitκ³Ό μƒν˜Έ μž‘μš©ν•  데이터 μœ ν˜• μ€€λΉ„ν•˜κΈ°.
    guard   let walkAddRun = HKObjectType.quantityType(forIdentifier: .distanceWalkingRunning),
    //κ±·κΈ°+달리기 거리(walkAddRun)
          let step = HKObjectType.quantityType(forIdentifier: .stepCount),
          // μ‹¬λ°•μˆ˜
          let activeEnergy = HKObjectType.quantityType(forIdentifier: .activeEnergyBurned)
          //ν™œλ™μ—λ„ˆμ§€
          else {
          let activeEnergy = HKObjectType.quantityType(forIdentifier: .activeEnergyBurned) else {
          completion(false, HealthkitSetupError.dataTypeNotAvailable)
          return
  }

(데이터 μœ ν˜•μ€ https://developer.apple.com/documentation/healthkit/hkquantitytypeidentifier μ—μ„œ μ°Έκ³ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.)

  • HealthKit이 읽고 μ“Έ μœ ν˜• λͺ©λ‘ μž‘μ„±ν•˜κΈ°
let healthKitTypesToWrite: Set<HKSampleType> = [walkAddRun,
                                                 activeEnergy,
                                                 step,
                                                 HKObjectType.workoutType()
                                                 ]
 
 let healthKitTypesToRead: Set<HKObjectType> = [walkAddRun,
                                                activeEnergy,
                                                HKObjectType.workoutType()
                                                 ]

healthKitTypesToWriteλŠ” μ–΄ν”Œμ΄ λ‹€μŒ 데이터λ₯Ό μ“°κΈ° ν—ˆμš©ν•˜λŠ” λͺ©λ‘, healthKitTypesToReadλŠ” μ–΄ν”Œμ΄ λ‹€μŒ 데이터λ₯Ό 읽기 ν—ˆμš©ν•˜λŠ” λͺ©λ‘μž…λ‹ˆλ‹€.

  • μš”μ²­ 승인 λ°›κΈ°
HKHealthStore().requestAuthorization(toShare: healthKitTypesToWrite,
                                      read: healthKitTypesToRead) { (success, error) in
   completion(success, error)
 }

2) μ‹€μ‹œκ°„ 톡신 인생 첫 μ†ŒμΌ“ 톡신 도전 !πŸ’ͺ🏻

-> μ„œλ²„ 자료 ν™•μΈν•˜κΈ°

import SocketIO
   static let shared = SocketIOManager()
   var manager = SocketManager(socketURL: URL(string: "μ†ŒμΌ“μ£Όμ†Œ")!, config: [.log(true), .compress])
   var socket: SocketIOClient!
   
   FindRunnerVC.socket = FindRunnerVC.self.manager.socket(forNamespace: "/matching")

: μ–΄ν”Œμ—μ„œ μ†ŒμΌ“ 톡신을 μ“°λŠ” λ²”μœ„λŠ” 맀칭 λŸ¬λ„ˆλŠ” 찾을 λ•ŒλΆ€ν„° κ²Œμž„μ΄ λλ‚˜κ³  κ²°κ³Ό 비ꡐ μ „κΉŒμ§€ μ†ŒμΌ“ 톡신을 μ‚¬μš©ν–ˆμŠ΅λ‹ˆλ‹€.
ν•œ λ·°μ—μ„œλ§Œ μ†ŒμΌ“ 톡신이 μ“°μ΄λŠ” 것이 μ•„λ‹ˆλΌ μ†ŒμΌ“μ΄ μ—°κ²°λΌμ„œ μ—¬λŸ¬ λ·°λ₯Ό ν†΅κ³Όν•˜κΈ° λ•Œλ¬Έμ— 싱글톀을 μ‚¬μš©ν•΄μ„œ 톡신을 μ΄μ–΄κ°”μŠ΅λ‹ˆλ‹€.

   FindRunnerVC.socket.on("start", callback: { (data, ack) in
     FindRunnerVC.self.socket.emit("joinRoom",myToken,myGoal,myWantGender,self.leftTime)
        })

: μ„œλ²„λŠ” μ‹œμž‘ν•΄λ„ μ’‹λ‹€λŠ” 응닡 -> ν΄λΌλŠ” λ‚΄ 정보와 λ‚΄κ°€ μ›ν•˜λŠ” μƒλŒ€μ˜ 쑰건을 λ³΄λ‚΄μ€λ‹ˆλ‹€.

        FindRunnerVC.socket.on("roomCreated", callback: { (data, ack) in
            FindRunnerVC.self.socket.emit("startCount",data[0] as! SocketData)
        })

: λ‚΄κ°€ μ›ν•˜λŠ” 쑰건의 μƒλŒ€λ₯Ό 찾지 λͺ»ν•œλ‹€λ©΄ μ„œλ²„λŠ” μƒˆλ‘œμš΄ 받을 λ§Œλ“€μ–΄μ„œ λ‚˜λ₯Ό λ„£μ–΄μ£Όκ³  -> ν΄λΌλŠ” μ‹œκ°„ 카운트λ₯Ό ν•˜λΌκ³  μ•Œλ €μ€λ‹ˆλ‹€. roomCreated λ•Œ λ°›λŠ” 정보인 data[0]은 λ‚΄κ°€ μ†ν•΄μžˆλŠ” 방의 λ²ˆν˜Έκ°€ λ©λ‹ˆλ‹€.

        FindRunnerVC.socket.on("matched", callback: { (data, ack) in
            FindRunnerVC.self.socket.emit("endCount",data[0] as! SocketData)
        })

: λŒ€κΈ°μ€‘μ— μƒλŒ€λ₯Ό μ°Ύμ•˜μ„λ•ŒλŠ” μ„œλ²„λŠ” matched와 data[0]으둜 λ‚΄κ°€ μ†ν•œ λ°© 이름을 보내주고, ν΄λΌμ—μ„œλŠ” μ‚¬μš©μžκ°€ μ†ν•œ 방의 이름과 endCountλ₯Ό λ³΄λ‚΄μ€λ‹ˆλ‹€.

        FindRunnerVC.socket.emit("compareResult",UserDefaults.standard.object(forKey: "opponentRoom") as? String ?? " ",UserDefaults.standard.object(forKey: "opponetDistance") as? Int ?? 2,UserDefaults.standard.object(forKey: "myGoalTime") as? Int ?? 0,array2,UserDefaults.standard.object(forKey: "createdTime") as? String ?? " ",UserDefaults.standard.object(forKey: "endTime") as? String ?? " ")

: λŸ¬λ‹ κ²Œμž„μ΄ λλ‚˜λ©΄ λ‚˜μ˜ λ°© 번호, 달린 거리, 달린 μ‹œκ°„, λ°© 번호, 지도 μœ„μΉ˜, μ‹œμž‘ν•œ μ‹œκ°„, λλ‚œ μ‹œκ°„μ„ ν•¨κ»˜ λ³΄λ‚΄μ€λ‹ˆλ‹€.

3) νšŒμ›κ°€μž… κΈ°λŠ₯

  • μ •κ·œν‘œν˜„μ‹κ³Ό μ‹€μ‹œκ°„ μž…λ ₯ 체크
   private func loginCheck() {
        idTextField.addTarget(self, action: #selector(idTextChecked(_:)), for: .editingChanged)
        nickTextField.addTarget(self, action: #selector(nickTextChecked(_:)), for: .editingChanged)
        pwTextField.addTarget(self, action: #selector(pwTextChecked(_:)), for: .editingChanged)
        pwReTextField.addTarget(self, action: #selector(pwReTextChecked(_:)), for: .editingChanged)
    }

editingChangedλ₯Ό ν™œμš©ν•œ ν•¨μˆ˜λ₯Ό μ„ μ–Έν•΄μ£Όμ–΄ μ‹€μ‹œκ°„μœΌλ‘œ 쑰건에 λ§žλŠ” μž…λ ₯이 λ“€μ–΄μ˜€λŠ”μ§€ μ²΄ν¬ν•˜κ³ , 그에 λ”°λ₯Έ ν…μŠ€νŠΈλ₯Ό λ„μš°κ±°λ‚˜, 쑰건에 λ§žμ•„μ•Ό λ‹€λ₯Έ λ™μž‘λ“€μ„ μ‹€ν–‰ν•  수 μžˆλ„λ‘ ν–ˆλ‹€.

    func isValidNick(nick: String?) -> Bool {
        guard nick != nil else { return false }
        let regEx = "[γ„±-γ…Žγ…-γ…£κ°€-힣A-Za-z0-9]{2,6}"
        let pred = NSPredicate(format:"SELF MATCHES %@", regEx)
        return pred.evaluate(with: nick)
    }

λ‹‰λ„€μž„ μ •κ·œν‘œν˜„ 쑰건

ν…μŠ€νŠΈ ν•„λ“œκ°€ 쑰건에 λ§žμ§€ μ•ŠλŠ”λ‹€λ©΄, 였λ₯˜ 메세지와 ν•¨κ²Œ ν…μŠ€νŠΈ ν•„λ“œμ˜ λ””μžμΈμ„ λ³€κ²½ν•΄μ£Όκ³  λ‹€μŒμœΌλ‘œ λ„˜μ–΄κ°ˆ 수 μžˆλŠ” λ²„νŠΌμ„ λΉ„ν™œμ„±ν™” μ‹œν‚€λŠ” λ“±μ˜ κ΅¬ν˜„μ„ ν–ˆλ‹€. μ •κ·œν‘œν˜„μ‹ μžμ²΄λ³΄λ‹€λŠ” μ‹€μ‹œκ°„μœΌλ‘œ μ‚¬μš©μžμ˜ μž…λ ₯을 ν™•μΈν•˜μ—¬ 쑰건을 κ²€μ‚¬ν•΄μ£ΌλŠ” 뢀뢄이 μ–΄λ €μ› λŠ”λ°, 우리 νŒ€μ˜ κ²½μš°μ—λŠ” νšŒμ›κ°€μž…μ‹œμ— μ²΄ν¬ν•΄μ•Όν•˜λŠ” 쑰건이 λ‹€μ–‘ν–ˆκΈ° λ•Œλ¬Έμ— λ·°λ₯Ό μ§œλŠ” 과정이 κΉŒλ‹€λ‘­κ³  μ‹œκ°„μ΄ μ˜€λž˜κ±Έλ Έλ‹€.

  • μ»¬λ ‰μ…˜ 뷰와 IsSelectedλ₯Ό ν™œμš©ν•œ 선택지 κ΅¬ν˜„

      override var isSelected: Bool {
          willSet {
              self.genderActionLabel.backgroundColor = newValue ? UIColor.lightishBlue : UIColor.brownishGrey
              print(genderActionLabel.text ?? nil!)           

νšŒμ›κ°€μž…μ‹œμ— μ‚¬μš©μžμ˜ μΆ”κ°€ 정보λ₯Ό μž…λ ₯ν•΄μ•Όν•˜λŠ” 뢀뢄을 μ²˜μŒμ—λŠ” λ‹¨μˆœν•˜κ²Œ λ²„νŠΌμœΌλ‘œ κ΅¬ν˜„ν•˜λ €κ³  ν•˜μ˜€λ‹€. κ·ΈλŸ¬λ‚˜ μ‚¬μš©μžκ°€ ν•˜λ‚˜μ˜ μ„ νƒμ§€λ§Œμ„ μ„ νƒν•΄μ•Όν•˜κ³ , κ·Έ κ°’λ§Œμ„ μ„œλ²„μ— μ „λ‹¬ν•΄μ•Όν•˜λŠ” 쑰건 탓에 일반 λ²„νŠΌμœΌλ‘œλŠ” κΈ°νšμ„ κ΅¬ν˜„ν•  μˆ˜κ°€ μ—†μ—ˆλ‹€. 그렇기에 μ»¬λ ‰μ…˜ λ·°μ—μ„œ IsSelectedλ₯Ό ν™œμš©ν•˜μ—¬ μ‚¬μš©μžκ°€ ν•˜λ‚˜λ§Œμ˜ 선택지λ₯Ό κ³ λ₯Ό 수 있게 κ΅¬ν˜„ν•˜μ˜€λ‹€. μ•ˆλ“œλ‘œμ΄λ“œμ—μ„œλŠ” 기본적으둜 μ œκ³΅λ˜λŠ” κΈ°λŠ₯μ΄μ§€λ§Œ, iOSμ—μ„œλŠ” 일일이 κ΅¬ν˜„ν•΄μ£Όμ–΄μ•Όν•˜λŠ” κΈ°λŠ₯μ΄μ—ˆλ‹€. μ „ν˜€ μ•Œμ§€ λͺ»ν•˜λ˜ κΈ°λŠ₯μ΄μ—ˆκΈ°μ— λ§Žμ€ μ‚¬λžŒλ“€μ˜ 도움을 λ°›μ•˜κ³ , ꡬ글링과 μž‘μ—…μ„ ν•˜λŠ”λ°μ— λ§Žμ€ μ‹œκ°„μ΄ λ“€μ—ˆλ‹€.

4) CoreMotion

  • CoreMotion은 νœ΄λŒ€ν°μ˜ μ„Όμ„œλ₯Ό μ‚¬μš©ν•˜λŠ” 방법이닀. μ›λž˜ Healthkitλ₯Ό μ‚¬μš©ν–ˆμ§€λ§Œ, HealthkitλŠ” λ§Žμ€ 정보λ₯Ό μ œκ³΅ν•΄μ£Όμ§€λ§Œ μ—…λ°μ΄νŠΈκ°€ μ‹€μ‹œκ°„(λͺ‡ 초 λ‹¨μœ„)둜 λ˜μ§€μ•ŠλŠ” λ¬Έμ œκ°€ λ°œμƒν•΄μ„œ CoreMotion으둜 μˆ˜μ •ν•˜μ˜€λ‹€.coremotion을 μ΄μš©ν•΄μ„œ μ‹€μ‹œκ°„ 거리λ₯Ό λ°›μ•„μ™”λ‹€. λ¬Όλ‘  μ—¬κΈ°μ„œλ„ 페이슀λ₯Ό κ³„μ‚°ν•΄μ£Όμ§€λ§Œ μš°λ¦¬κ°€ μ›ν•˜λŠ” λ‹¨μœ„μ™€λŠ” λ‹¬λžκΈ°λ•Œλ¬Έμ— νŽ˜μ΄μŠ€λŠ” 직접 κ³„μ‚°ν•˜λŠ” 방법을 μ‚¬μš©ν–ˆλ‹€.
    CoreMotion
pedometer = CMPedometer()

: CMPedometerλŠ” μ‹€μ‹œκ°„ κ±·κΈ°λ₯Ό κ°€μ Έμ˜€κΈ° μœ„ν•œ κ°œμ²΄μ΄λ‹€. 즉 만보기의 역할을 ν•œλ‹€. 만보기λ₯Ό 톡해 걸음 수 및 이동 ν•œ 거리와 μƒμŠΉ λ˜λŠ” ν•˜κ°• ν•œ μΈ΅ μˆ˜μ— λŒ€ν•œ 기타 정보λ₯Ό 검색할 수 μžˆλ‹€.

        pedometer.startUpdates(from: Date(), withHandler: { 
          (pedometerData, error) in
            if let pedData = pedometerData{
                self.numberOfSteps = Int(pedData.numberOfSteps)
                if let distance = pedData.distance{
                    self.distance = Double(distance)
                }
                if let averageActivePace = pedData.averageActivePace {
                    self.averagePace = Double(averageActivePace)
                }
                if let currentPace = pedData.currentPace {
                    self.pace = Double(currentPace)
                }
            } else {
                self.numberOfSteps = nil
            }
        })

: startUpdates ν•¨μˆ˜λ₯Ό 톡해 λ³΄ν–‰μž κ΄€λ ¨ 데이터λ₯Ό 앱에 λŒκ³ μ˜¨λ‹€. distanceλŠ” μ‚¬μš©μžκ°€ κ±·κ±°λ‚˜ λ›°λŠ” λ™μ•ˆ μ΄λ™ν•œ 거리λ₯Ό 가져와쀀닀. averageActivePaceλŠ” λ―Έν„°λ‹Ή 초 λ‹¨μœ„λ‘œ ν™˜μ‚°ν•œ 평균 νŽ˜μ΄μŠ€μ΄λ‹€. currentPaceλŠ” λ―Έν„°λ‹Ή 초 λ‹¨μœ„λ‘œ μΈ‘μ •ν•œ ν˜„μž¬ 속도이닀. μ΄λ ‡κ²Œ CoreDataμ—μ„œλŠ” λ‹¬λ¦¬κΈ°μ—μ„œ ν•„μš”ν•œ λ§Žμ€ 정보듀을 μ œκ³΅ν•œλ‹€.


D. νŒ€μ› μ—­ν•  및 μ†Œκ°œ

  • 김민희 Repo : λŸ¬λ„ˆμŠ€ν•˜μ΄ iOS λ¦¬λ“œκ°œλ°œμž, MainTab κ΅¬ν˜„ 및 μ†ŒμΌ“ 톡신 λ‹΄λ‹Ή
  • 졜영재 Repo : λŸ¬λ„ˆμŠ€ν•˜μ΄ iOS μ„œλΈŒκ°œλ°œμž, RankTab / RecordTab / MyPabeTab / SignTab λ‹΄λ‹Ή 및 http 톡신 λ‹΄λ‹Ή

F. κ²°κ³Ό / μ„±κ³Ό

: IT μ°½μ—… 동아리 26th β€˜SOPT’ APPJAM λŒ€μƒ μˆ˜μƒ, ν˜„μž¬ μ•±μŠ€ν† μ–΄ μΆœμ‹œ μ€€λΉ„ 쀑.

About

πŸƒπŸ»β€β™‚οΈπŸƒπŸ»β€β™€οΈ λŸ¬λ„ˆμŠ€ν•˜μ΄ iOS "진심" 레포 πŸƒπŸ»β€β™‚οΈπŸƒπŸ»β€β™€οΈ

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published