๐Ÿ“ฑ iOS

    [Swift] ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ NetworkManager๋งŒ๋“ค๊ธฐ (feat. Generic)

    ์ง€๋‚œ๋ฒˆ์— ์ด๋Ÿฐ ๊ธ€์„ ์ผ์—ˆ๋Š”๋ฐ, https://990427.tistory.com/112 [Swift] json value type์ด ๋‹ฌ๋ผ์ง€๋Š” response์— ๋Œ€์‘ํ•˜์—ฌ API Responder๋งŒ๋“ค๊ธฐ ์š”์ฆ˜ Set์ด ๋œ ๋‚˜์˜ ๊ฐœ๋ฐœ ์Šคํƒ€์ผ,, ์ค‘๋ณต์„ ๋‹ค ์ œ๊ฑฐํ•ด๋ฒ„๋ฆฌ์ž ์ง€๊ธˆ ํ•˜๊ณ  ์žˆ๋Š” ํ”„๋กœ์ ํŠธ์—์„œ API๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ช…์„ธํ–ˆ์Šต๋‹ˆ๋‹ค ๊ทธ๋ž˜์„œ ์–ด๋–ค api๋ฅผ ํ˜ธ์ถœํ•˜๋ƒ์— ๋”ฐ๋ผ form์˜ ๋ณ€ํ™”๋Š” ์—†์ง€๋งŒ data์˜ ๊ฐ’์€ ํ•ญ์ƒ 990427.tistory.com ์ƒํƒœ ์ฝ”๋“œ๋ฅผ ๋ฐ›์„ ์ˆ˜ ์—†๋‹ค๋Š” ๋ฌธ์ œ์ ๋„ ์žˆ์—ˆ๊ณ , ๋ชจ๋“ˆ๋งˆ๋‹ค ๋‹ค ๋‹ค๋ฅธ MoyaProvider๋ฅผ ์‚ฌ์šฉํ•˜๋‹ค๋ณด๋‹ˆ๊นŒ ์ €๋ฒˆ์— ๋งŒ๋“  ํ•จ์ˆ˜์˜ ์“ฐ์ž„์ด ์ข€.. ๋ณ„๋กœ๋ž„๊นŒ? ๊ทธ๋ž˜์„œ ๊ฐœ์„ ํ•ด๋ณด์ž!๊ณ  ์ƒ๊ฐํ–ˆ๊ณ  ์กฐ๊ธˆ๋” ์œ ์—ฐํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก BaseNetworkManager๋ฅผ ๋งŒ๋“ค๊ธฐ๋กœ ํ–ˆ์Šต๋‹ˆ๋‹ค. Ba..

    [UIKit] CustomDatePicker ๋งŒ๋“ค๊ธฐ (3/3)

    [UIKit] CustomDatePicker ๋งŒ๋“ค๊ธฐ (3/3)

    Rx๋ฅผ ๋ชจ๋ฅด์‹ ๋‹ค๋ฉด ์ดํ•ดํ•˜๊ธฐ ์–ด๋ ค์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค ๐Ÿฅน ๋“œ๋””์–ด ๋งˆ์ง€๋ง‰ ๊ด€๋ฌธ.. ๋…„,์›”์„ ๊ด€์ฐฐํ•˜์—ฌ ์ผ ์ˆ˜๋ฅผ ์ •ํ•˜์ž! ์ผ๋‹จ ๋‚˜๋Š” ์ง€๊ธˆ ์ด๊ฑธ ๋งŒ๋“œ๋Š” ์ค‘์ด๋‹ค ๋…„,์›”์€ ์˜์กด์„ฑ์ด ์—†์ง€๋งŒ, '์ผ'์€ ๋…„,์›”์— ์˜์กด์„ฑ์„ ๊ฐ€์ง€๊ฒŒ ๋œ๋‹ค. 1์›”์€ 31์ผ๊นŒ์ง€, 2์›”์€ 28์ผ๊นŒ์ง€ ๋ญ์ด๋Ÿฐ๊ฑฐ ~.. ๊ทธ๋ž˜์„œ '์ผ'์€ ๋…„,์›”์ด ๋ฐ”๋€Œ๋ฉด reset์„ ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค. ์˜ˆ๋ฅผ๋“ค์–ด 2023๋…„1์›”31์ผ์„ ๋งŒ๋“ค์–ด์ค€ ์ƒํƒœ์—์„œ '์›”'์„ 2์›”๋กœ ๋ฐ”๊พธ๋ฉด 31์ผ์€ ์—†๊ธฐ ๋•Œ๋ฌธ์—!! ๊ทธ๋ž˜์„œ customPicker์—์„œ ๋ญ”๊ฐ€๋ฅผ ์„ ํƒํ–ˆ์„ ๋•Œ ๊ด€์ฐฐํ•˜๋Š” ๋Œ€์ƒ์—๊ฒŒ ์•Œ๋ ค์ค„ ์ˆ˜ ์žˆ๋„๋ก Rx๋ฅผ ์ถ”๊ฐ€์ ์œผ๋กœ ์ ์šฉํ–ˆ๋‹ค. (1/3)์—์„œ ๋งŒ๋“ค์—ˆ๋˜ CustomPickerButton์— ์ถ”๊ฐ€ํ•œ ๋ถ€๋ถ„! public class CustomPickerButton: UIButton { var change..

    [Swift] ์„œ๋ฒ„์— iOS ์ด๋ฏธ์ง€ ๋ณด๋‚ผ ๋•Œ ์šฉ๋Ÿ‰ ์ด์Šˆ & ํ•ด๊ฒฐ

    [Swift] ์„œ๋ฒ„์— iOS ์ด๋ฏธ์ง€ ๋ณด๋‚ผ ๋•Œ ์šฉ๋Ÿ‰ ์ด์Šˆ & ํ•ด๊ฒฐ

    ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ ๊ตฌํ˜„์ค‘์— ์ƒ๊ธด ์ด์Šˆ form-data๋กœ ์•„์ดํฐ ์‚ฌ์ง„์ฒฉ์— ์žˆ๋Š” ์ด๋ฏธ์ง€๋ฅผ ์„œ๋ฒ„๋กœ ๋ณด๋‚ด๋ ค๋ฉด JPEG๋กœ ๋ณ€ํ™˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค ์•„์ดํฐ์—์„œ ๊ธฐ๋ณธ์ ์œผ๋กœ HEIF ํ™•์žฅ์ž๋กœ ์‚ฌ์ง„์„ ์ €์žฅํ•˜๋Š”๋ฐ, ์ด๋Š” ํ˜ธํ™˜์„ฑ์ด ๋–จ์–ด์ง€๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค ์–ด์จŒ๋“  ์šฐ๋ฆฌ๋Š” PHPicker๋ฅผ ํ†ตํ•ด์„œ ์‚ฌ์ง„์ฒฉ์— ์žˆ๋Š” ์‚ฌ์ง„์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๊ณ , ์ด๋ฅผ jpeg๋กœ ๋ณ€ํ™˜ํ•˜๊ธฐ ์œ„ํ•ด jpegData๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค image.jpegData(compressionQuality: 1.0) ์‚ฌ์‹ค ๋’ค์— 1.0์€ ๊ธฐ๋ณธ๊ฐ’์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜๊ณ  ์•„๋ฌด ์ƒ๊ฐ์—†์ด ์ผ๋Š”๋ฐ ์–˜๋•Œ๋งค ์ด์Šˆ๊ฐ€ ์ƒ๊ธธ์ค„์ด์•ผ... Moya๋ฅผ ํ†ตํ•ด API ํ†ต์‹ ์„ ํ•˜๋Š”๋ฐ, ๊ณ„์† ์ด๋Ÿฐ ์—๋Ÿฌ๊ฐ€ ๋œจ๋Š” ๊ฒƒ.. Failed to map data to a Decodable object. postman์œผ๋กœ ์•„์ดํฐ ์‚ฌ์ง„์ฒฉ์— ์žˆ๋Š” ์‚ฌ์ง„ ..

    [UIKit] toast message ๋งŒ๋“ค๊ธฐ

    [UIKit] toast message ๋งŒ๋“ค๊ธฐ

    ์•ฑ์„ ๋งŒ๋“ค๋‹ค๋ณด๋ฉด toast msg๋ฅผ ๋„์›Œ์„œ ์ •๋ณด๋ฅผ ์ฃผ๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์€๋ฐ ์•„์‰ฝ๊ฒŒ๋„ iOS์—๋Š” ๊ทธ๋Ÿฐ ๊ธฐ๋Šฅ์ด ์—†๋‹ค.. ์ง์ ‘ ๋งŒ๋“ค์ž! ์šฐ์„  UIView๋ฅผ ์ƒ์†ํ•˜๋Š” class๋ฅผ ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค public class ToastMessage: UIView {} ์ €๋Š” ์š”๋ก  ์ข…๋ฅ˜์˜ ํ† ์ŠคํŠธ ๋ฉ”์„ธ์ง€๋ฅผ ๋งŒ๋“ค๊ฑฐ์—์š” (x๋Š” ์ œ์™ธ) ๊ทธ๋ž˜์„œ ์ด๋Ÿฐ ํ”„๋กœํผํ‹ฐ์™€ enum์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค public enum ToastType { case common, alert, info } var text = UILabel() var icon = UIImageView() var type : ToastType UI๋Š” ๊ฐ์ž ์ทจํ–ฅ๊ป ๋งŒ๋“œ์‹œ๊ณ  (์ƒ๋žต) ํ† ์ŠคํŠธ ๋ฉ”์„ธ์ง€์˜ ํŠน์ง•์€ ์ž ๊น ๋–ด๋‹ค ์‚ฌ๋ผ์ง€๋Š”๊ฑฐ ์ž–์•„์š” ? ๊ทธ ๋ถ€๋ถ„์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด animate๋ฅผ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค an..

    [Swift] json value type์ด ๋‹ฌ๋ผ์ง€๋Š” response์— ๋Œ€์‘ํ•˜์—ฌ API Responder๋งŒ๋“ค๊ธฐ

    [Swift] json value type์ด ๋‹ฌ๋ผ์ง€๋Š” response์— ๋Œ€์‘ํ•˜์—ฌ API Responder๋งŒ๋“ค๊ธฐ

    ์š”์ฆ˜ Set์ด ๋œ ๋‚˜์˜ ๊ฐœ๋ฐœ ์Šคํƒ€์ผ,, ์ค‘๋ณต์„ ๋‹ค ์ œ๊ฑฐํ•ด๋ฒ„๋ฆฌ์ž ์ง€๊ธˆ ํ•˜๊ณ  ์žˆ๋Š” ํ”„๋กœ์ ํŠธ์—์„œ API๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ช…์„ธํ–ˆ์Šต๋‹ˆ๋‹ค ๊ทธ๋ž˜์„œ ์–ด๋–ค api๋ฅผ ํ˜ธ์ถœํ•˜๋ƒ์— ๋”ฐ๋ผ form์˜ ๋ณ€ํ™”๋Š” ์—†์ง€๋งŒ data์˜ ๊ฐ’์€ ํ•ญ์ƒ ๋‹ฌ๋ผ์ง„๋‹ค ์ผ๋‹จ json์„ ํŒŒ์‹ฑํ•  struct๋ฅผ ๋งŒ๋“ค์–ด์ฃผ์–ด์•ผ ํ•˜๋Š”๋ฐ, ๋ชจ๋“  api๋งˆ๋‹ค struct๋ฅผ ๋งŒ๋“ค๊ฒŒ ๋˜๋ฉด ์ด๋Ÿฐ์‹์œผ๋กœ ๊ณ„์†ํ•ด์„œ DTO struct์˜ ์ค‘๋ณต์ด ์ผ์–ด๋‚˜๊ฒŒ ๋œ๋‹ค ์ค‘๋ณต์ด ๋„ˆ๋ฌด ์‹ซ์€ ๋‚˜.. ์ œ๋„ค๋ฆญ์œผ๋กœ ๋ฌถ์ž! struct ResponseDTO : Decodable { var success : Bool var data : CommonDataDTO var error : ErrorDTO? } struct ErrorDTO : Decodable, Error { let code : Int let mes..

    [RxSwift] ๊ฐœ๋…์žก๊ธฐ (Subscribe, Observable, Subject)

    [RxSwift] ๊ฐœ๋…์žก๊ธฐ (Subscribe, Observable, Subject)

    ์ตœ๋Œ€ํ•œ ๊ฐ„๋‹จํ•˜๊ฒŒ ์„ค๋ช…ํ•ด๋ณด๋Š” RxSwift iOS ๊ณต๋ถ€ํ•˜๋Š” ์‚ฌ๋žŒ์€ ๋ฌด์กฐ๊ฑด ๋“ค์–ด๋ดค์„ RxSwift RxSwift๋Š” ReactiveX Swift์ธ๋ฐ์š”, reactiveX ? ๋Œ€์ถฉ ํ•ด์„ํ•˜๋ฉด ์˜ต์ €๋ฒ„๋ธ”์„ ์‚ฌ์šฉํ•ด์„œ ๋น„๋™๊ธฐ๋‚˜ event-based๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ๊ฒƒ์ด๋‹ค ์˜ต์ €๋ฒ„๋ธ”์ด ๋ญ”๋ฐ ????? Observable ? ๋Œ€์ถฉ ํ•ด์„ํ•˜๋ฉด - ์˜ต์ €๋ฒ„๋Š” ์˜ต์ €๋ฒ„๋ธ”์„ ๊ตฌ๋…ํ•œ๋‹ค - ์˜ต์ €๋ฒ„๋Š” ์˜ต์ €๋ฒ„๋ธ”์ด ๋ฐฉ์ถœํ•˜๋Š” items์— ๋Œ€ํ•ด ๋ฐ˜์‘ํ•œ๋‹ค - ์˜ต์ €๋ฒ„๋Š” ๋Œ€๊ธฐํ•˜์ง€ ์•Š๊ณ , ๋ฐ˜์‘ํ•  ์ค€๋น„๋ฅผ ํ•œ ์–ด๋– ํ•œ ํ˜•ํƒœ๋กœ ๊ธฐ๋‹ค๋ฆฐ๋‹ค items์ด ์–ด๋–ค๊ฑด์ง€๋Š” ๋ชฐ๋ผ๋„ ์ผ๋‹จ ์˜ต์ €๋ฒ„๋Š” ์˜ต์ €๋ฒ„๋ธ”์ด ๋ญ”๊ฐ€๋ฅผ ํ•˜๋ฉด ๋ฐ˜์‘ํ•œ๋Œ€!! ์˜ต์ €๋ฒ„๊ฐ€ ๋ฌด์Šจ ํ˜•ํƒœ์ธ์ง€๋Š” ๋ชฐ๋ผ๋„ ์ผ๋‹จ ๋Œ€๊ธฐ ใ„ดใ„ด ์ฆ‰, sync ใ„ดใ„ด ๋งŽ์€ ์šฉ์–ด๋“ค์ด ๋‚˜์˜ค๋Š”๋ฐ Observer, Observable, Subscribe ๊ทผ๋ฐ ์ด..

    [Swift] Custom Calendar ๋‹ฌ์˜ ๋งˆ์ง€๋ง‰ ๋‚  ๊ตฌํ•˜๊ธฐ

    [Swift] Custom Calendar ๋‹ฌ์˜ ๋งˆ์ง€๋ง‰ ๋‚  ๊ตฌํ•˜๊ธฐ

    ์ด ๊ธ€์€ UI๋ฅผ ์ œ์™ธํ•˜๊ณ  ๋‚ ์งœ ๊ณ„์‚ฐ์„ ํ•˜๋Š” ๋กœ์ง๋งŒ ๋‹ด๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค Custom Calendar๋ฅผ ๋งŒ๋“ค๋‹ค๋ณด๋‹ˆ ํ•ด๋‹นํ•˜๋Š” ๋‹ฌ์˜ ๋งˆ์ง€๋ง‰ ๋‚ ์ด ์–ธ์ œ์ธ์ง€ ๊ณ„์‚ฐํ•ด์•ผ ํ–ˆ๋‹ค. ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ฒ˜๋Ÿผ ์ ‘๊ทผํ•˜๋ฉด ์œค ๋‹ฌ๋„ ๊ณ„์‚ฐํ•ด์ค˜์•ผ ํ•˜๊ณ  ์†๋„ ์ธก๋ฉด์—์„œ๋„ ๋น„ํšจ์œจ์ ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ด์„œ foundation์ƒ์— ์žˆ๋Š” calendar๋ผ๋Š” ๊ตฌ์กฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋งŒ๋“ค์—ˆ๋‹ค! ๋จผ์ € ๋‚ ์งœ ๊ณ„์‚ฐ์— ํ•„์š”ํ•œ Calendar์™€ DateFormatter๋ฅผ ๋งŒ๋“ค์–ด์ฃผ์ž let calendar = Calendar(identifier: .gregorian) let dateFormatter = DateFormatter() dateFormatter.dateFormat = "yyyy-MM-dd" ์ฒซ ๋‚ ์€ ๋ฌด์กฐ๊ฑด 1์ผ์ด๋‹ˆ๊นŒ ์ง์ ‘ ์ž…๋ ฅํ•ด์ค€๋‹ค let st = dateFormatter.da..

    [UIKit] CustomDatePicker ๋งŒ๋“ค๊ธฐ (2/3)

    [UIKit] CustomDatePicker ๋งŒ๋“ค๊ธฐ (2/3)

    CustomPickerButton์„ ๋งŒ๋“ค์—ˆ์œผ๋‹ˆ DatePicker๋กœ ์ง„ํ™”ํ•ด๋ณด์ž ์•Œ๋‹ค์‹œํ”ผ ๋‚˜๋Š” ์ด๊ฑธ ๋งŒ๋“ค๊ธฐ๋กœ ํ–ˆ๋‹ค ๐Ÿ“Œ UI setting ๋ณ„๊ฑฐ ์—†๋‹ค.. ๊ทธ๋ƒฅ ใ„นใ…‡ UI setting code open class CustomDatePicker: UIView{ private var Titlelabel = UILabel() private var years = [String]() private var months = [String]() private var days = [String]() private let yearWidth : CGFloat = 126 private let monthWidth : CGFloat = 103 private let dayWidth : CGFloat = 103 private lazy ..

    [UIKit] CustomDatePicker ๋งŒ๋“ค๊ธฐ (1/3)

    [UIKit] CustomDatePicker ๋งŒ๋“ค๊ธฐ (1/3)

    UIKit ๊ณต๋ถ€๊ฒธ ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋Š” ๋„์ค‘์— DatePicker๋ฅผ ์ปค์Šคํ…€ํ•ด์•ผ ํ•˜๋Š” ์ƒํ™ฉ๊ณผ ๋งˆ์ฃผํ–ˆ๋‹ค. ๐Ÿ“Œ ๊ตฌํ˜„๋‚ด์šฉ ์ผ๋‹จ ๊ธฐ๋ณธ ์ œ๊ณต๋˜๋Š” DatePicker๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋Š” ์—†์—ˆ๋‹ค ๊ทธ๋ž˜์„œ UIButton์˜ inputView์— pickerView๋ฅผ ๋„ฃ์–ด์„œ ๋งŒ๋“ค๊ฒƒ์ด๋‹ค ์ผ๋ฐ˜์ ์œผ๋กœ TextField์˜ inputView์— pickerView๋ฅผ ์‚ฌ์šฉํ•˜๋˜๋ฐ ๋‚˜๋Š” TextField๊ฐ€ ํ•„์š”์—†์–ด์„œ ๋Œ€์žฅ์ •์„ ๊ฑธ์–ด๋ณด๊ธฐ๋กœ ํ–ˆ๋‹ค.. ๐Ÿ“Œ UI setting ์œ„์— ์–ธ๊ธ‰ํ–ˆ๋˜ CustomDatePicker์—์„œ box ํ•˜๋‚˜์”ฉ์„ CustomPickerButton์ด๋ผ๊ณ  ํ•˜๊ฒ ๋‹ค. // CustomPickerButton.swift public class CustomPickerButton: UIButton { private var uiView = UIV..

    [SwiftUI] @State๋ฅผ ๊ฐ€์ง€๋Š” View์˜ ์—…๋ฐ์ดํŠธ

    [SwiftUI] @State๋ฅผ ๊ฐ€์ง€๋Š” View์˜ ์—…๋ฐ์ดํŠธ

    ์˜ค๋Š˜์€ @State์— ๋Œ€ํ•ด์„œ ์กฐ๊ธˆ ๋” ๊นŠ์ด ์žˆ๊ฒŒ ์•Œ์•„๋ณด๋ ค๊ณ  ํ•ด์š”! ์ผ๋‹จ @State๊ฐ€ ์–ด๋–ค ์—ญํ• ์„ ํ•˜๋Š”์ง€ ์•„๋Š” ๊ฒƒ์œผ๋กœ ๊ฐ„์ฃผํ•˜๊ณ  ์•„์ฃผ ๊ฐ„๋‹จํ•œ ์˜ˆ์ œ๋ฅผ ๋ณผ๊ฒŒ์š”, ๋ชจ๋ฅด๋ฉด ์ด๊ฑฐ ๋ณด๊ณ ์˜ค๊ธฐ https://990427.tistory.com/64 [SwiftUI] ๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ (1/5) @State ๋ฐ์ดํ„ฐ๋ฐ”์ธ๋”ฉ ๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ(data binding)์€ ์ œ๊ณต์ž์™€ ์†Œ๋น„์ž๋กœ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ ์›๋ณธ์„ ๊ฒฐํ•ฉ์‹œ์ผœ ์ด๊ฒƒ๋“ค์„ ๋™๊ธฐํ™”ํ•˜๋Š” ๊ธฐ๋ฒ•์ด๋‹ค. ๋ผ๊ณ  ์œ„ํ‚ค๋ฐฑ๊ณผ๊ฐ€ ๋งํ•˜๋Š”๋ฐ, ์‰ฝ๊ฒŒ๋งํ•ด SwiftUI์—์„œ ๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ์€ view 990427.tistory.com ์•„๋ž˜ ์ฝ”๋“œ๋Š” changeItem ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ text ๊ฐ’์„ ๋ณ€๊ฒฝ์‹œํ‚ค๋Š” ์˜ˆ์ œ์ž…๋‹ˆ๋‹ค struct ContentView : View { @State var text = "default" va..