diff --git a/BasicAssignments.xcodeproj/project.pbxproj b/BasicAssignments.xcodeproj/project.pbxproj new file mode 100644 index 0000000..196cb8c --- /dev/null +++ b/BasicAssignments.xcodeproj/project.pbxproj @@ -0,0 +1,294 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 77; + objects = { + +/* Begin PBXCopyFilesBuildPhase section */ + 0A0FBAB42F0CAC0C00236387 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 0A0FBAB62F0CAC0C00236387 /* BasicAssignments */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = BasicAssignments; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFileSystemSynchronizedRootGroup section */ + 0A0FBAB82F0CAC0C00236387 /* BasicAssignments */ = { + isa = PBXFileSystemSynchronizedRootGroup; + path = BasicAssignments; + sourceTree = ""; + }; +/* End PBXFileSystemSynchronizedRootGroup section */ + +/* Begin PBXFrameworksBuildPhase section */ + 0A0FBAB32F0CAC0C00236387 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 0A0FBAAD2F0CAC0C00236387 = { + isa = PBXGroup; + children = ( + 0A0FBAB82F0CAC0C00236387 /* BasicAssignments */, + 0A0FBAB72F0CAC0C00236387 /* Products */, + ); + sourceTree = ""; + }; + 0A0FBAB72F0CAC0C00236387 /* Products */ = { + isa = PBXGroup; + children = ( + 0A0FBAB62F0CAC0C00236387 /* BasicAssignments */, + ); + name = Products; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 0A0FBAB52F0CAC0C00236387 /* BasicAssignments */ = { + isa = PBXNativeTarget; + buildConfigurationList = 0A0FBABD2F0CAC0C00236387 /* Build configuration list for PBXNativeTarget "BasicAssignments" */; + buildPhases = ( + 0A0FBAB22F0CAC0C00236387 /* Sources */, + 0A0FBAB32F0CAC0C00236387 /* Frameworks */, + 0A0FBAB42F0CAC0C00236387 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + fileSystemSynchronizedGroups = ( + 0A0FBAB82F0CAC0C00236387 /* BasicAssignments */, + ); + name = BasicAssignments; + packageProductDependencies = ( + ); + productName = BasicAssignments; + productReference = 0A0FBAB62F0CAC0C00236387 /* BasicAssignments */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 0A0FBAAE2F0CAC0C00236387 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 2620; + LastUpgradeCheck = 2620; + TargetAttributes = { + 0A0FBAB52F0CAC0C00236387 = { + CreatedOnToolsVersion = 26.2; + }; + }; + }; + buildConfigurationList = 0A0FBAB12F0CAC0C00236387 /* Build configuration list for PBXProject "BasicAssignments" */; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 0A0FBAAD2F0CAC0C00236387; + minimizedProjectReferenceProxies = 1; + preferredProjectObjectVersion = 77; + productRefGroup = 0A0FBAB72F0CAC0C00236387 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 0A0FBAB52F0CAC0C00236387 /* BasicAssignments */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 0A0FBAB22F0CAC0C00236387 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 0A0FBABB2F0CAC0C00236387 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MACOSX_DEPLOYMENT_TARGET = 26.2; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 0A0FBABC2F0CAC0C00236387 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MACOSX_DEPLOYMENT_TARGET = 26.2; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + }; + name = Release; + }; + 0A0FBABE2F0CAC0C00236387 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 0A0FBABF2F0CAC0C00236387 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 0A0FBAB12F0CAC0C00236387 /* Build configuration list for PBXProject "BasicAssignments" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0A0FBABB2F0CAC0C00236387 /* Debug */, + 0A0FBABC2F0CAC0C00236387 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 0A0FBABD2F0CAC0C00236387 /* Build configuration list for PBXNativeTarget "BasicAssignments" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0A0FBABE2F0CAC0C00236387 /* Debug */, + 0A0FBABF2F0CAC0C00236387 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 0A0FBAAE2F0CAC0C00236387 /* Project object */; +} diff --git a/BasicAssignments.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/BasicAssignments.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/BasicAssignments.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/BasicAssignments.xcodeproj/project.xcworkspace/xcuserdata/yeseuljang.xcuserdatad/UserInterfaceState.xcuserstate b/BasicAssignments.xcodeproj/project.xcworkspace/xcuserdata/yeseuljang.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..41873d7 Binary files /dev/null and b/BasicAssignments.xcodeproj/project.xcworkspace/xcuserdata/yeseuljang.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/BasicAssignments.xcodeproj/xcuserdata/yeseuljang.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/BasicAssignments.xcodeproj/xcuserdata/yeseuljang.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist new file mode 100644 index 0000000..9c68bb3 --- /dev/null +++ b/BasicAssignments.xcodeproj/xcuserdata/yeseuljang.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -0,0 +1,6 @@ + + + diff --git a/BasicAssignments.xcodeproj/xcuserdata/yeseuljang.xcuserdatad/xcschemes/xcschememanagement.plist b/BasicAssignments.xcodeproj/xcuserdata/yeseuljang.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..3bc6b86 --- /dev/null +++ b/BasicAssignments.xcodeproj/xcuserdata/yeseuljang.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + BasicAssignments.xcscheme_^#shared#^_ + + orderHint + 0 + + + + diff --git a/BasicAssignments/challengeMission1 - 2.swift b/BasicAssignments/challengeMission1 - 2.swift new file mode 100644 index 0000000..fa48077 --- /dev/null +++ b/BasicAssignments/challengeMission1 - 2.swift @@ -0,0 +1,102 @@ +// +// challengeMission1 - 2.swift +// BasicAssignments +// +// Created by Yeseul Jang on 1/9/26. +// + +//protocol과 struct 이용해보기 +protocol EngineProtocol { + var type: EngineType { get } +} + +struct ElectricEngineS: EngineProtocol { + let type: EngineType = .electric +} + +struct HydrogenEngineS: EngineProtocol { + let type: EngineType = .hydrogen +} + +protocol EngineSwitchableCar: CarProtocol { + var engine: any EngineProtocol { get set } + mutating func switchEngine(to newEngine: any EngineProtocol) +} + +extension EngineSwitchableCar { + mutating func switchEngine(to newEngine: any EngineProtocol) { + engine = newEngine + print("\(newEngine.type)엔진으로 교체") + } +} + +protocol CarProtocol { + var brand: String { get } + var model: String { get } + var year: String { get } + var engine: any EngineProtocol { get } + + func drive() + func stop() +} + +extension CarProtocol { + func drive() { + print("🚗 운전중입니다.") + } + + func stop() { + print("🛑 정지합니다.") + } +} + +struct ElectricCarS: CarProtocol { + let brand: String + let model: String + let year: String + let engine: any EngineProtocol + + init(brand: String, model: String, year: String) { + self.brand = brand + self.model = model + self.year = year + self.engine = ElectricEngineS() + } +} + +struct HybridCarS: EngineSwitchableCar { + let brand: String + let model: String + let year: String + var engine: any EngineProtocol + + init(brand: String, model: String, year: String) { + self.brand = brand + self.model = model + self.year = year + self.engine = HydrogenEngineS() + } +} + +/* + //상속을 사용하여 기능을 추가하는 것과, 프로토콜 채택을 통해서 기능을 추가하는 것의 장단점, 차이를 고민하고 주석으로 서술해주세요. + 요구사항 정리: + - Car 타입 안에는 파라미터 brand, model, year, engine와 메서드 drive, stop 존재 + - 전기차는 전기 엔진만을 가짐(못바꿈) + - 하이브리드차만 엔진 교체 가능(switchEngine(to:) + + class 상속이용 시: + 장점 - Car안에 메서드 drive, stop가 있고 상속 시 자식들이 사용가능하다는게 직관적이다. + 단점 - 엔진을 바꿀 수 없다는 제한은 접근제어와 init을 이용해야만 한다. + 한 클래스에 여러 기능을 넣기에는 상속은 복잡할거 같다. + + protocol 채택이용 시: + 장점 - 여러 기능을 붙이기 좋다. + 단점 - 지금과 같이 any EngineProtocol타입인데 특정 인스턴스만 갖도록 설정하려면 + 기능이 다르기때문에 새 protocol을 만들거나 associatedtype를 사용하게 되는데 + 그러면 해당 엔진 타입 때문에 차가 CarProtocol타입이 안되어서 나중에 활용이 어렵다. + + + 결론: class는 상태,값을 공유해야하거나 구현한 걸 재사용할 때 직관적이고 좋은거 같음 + 특정 타입이 어떤 기능만 가졌으면 좋겠다 싶으면 protocol이 좋은 거같다. + */ diff --git a/BasicAssignments/challengeMission1.swift b/BasicAssignments/challengeMission1.swift new file mode 100644 index 0000000..de52096 --- /dev/null +++ b/BasicAssignments/challengeMission1.swift @@ -0,0 +1,74 @@ +// +// challengeMission1.swift +// BasicAssignments +// +// Created by Yeseul Jang on 1/9/26. +// + +// Engine 이라는 커스텀 타입으로 정의해주세요. +enum EngineType { + case electric + case hydrogen +} + +class Engine { + let type: EngineType + + init(type: EngineType) { + self.type = type + } +} + +final class ElectricEngine: Engine { + init() { + super.init(type: .electric) + } +} + +final class HydrogenEngine: Engine { + init() { + super.init( type: .hydrogen) + } +} + +// Base Class Car 를 설계해주세요. +class Car { + let brand: String + let model: String + let year: String + fileprivate(set) var engine: Engine + //main에서 볼수는 있는데 엔진을 임의로 바꿀수 없게 + + init(brand: String, model: String, year: String, engine: Engine) { + self.brand = brand + self.model = model + self.year = year + self.engine = engine + } + + func drive() { + print("🚗 운전중입니다.") + } + + func stop() { + print("🛑 정지합니다.") + } +} + +class ElectricCar: Car { + init(brand: String, model: String, year: String) { + super.init(brand: brand, model: model, year: year, engine: ElectricEngine()) + } +} + +class HybridCar: Car { + init(brand: String, model: String, year: String) { + super.init(brand: brand, model: model, year: year, engine: HydrogenEngine()) + } + + func switchEngine(to newEngine: Engine) { + engine = newEngine + print("\(newEngine.type)엔진으로 교체") + } +} + diff --git a/BasicAssignments/challengeMission2.swift b/BasicAssignments/challengeMission2.swift new file mode 100644 index 0000000..4417d5b --- /dev/null +++ b/BasicAssignments/challengeMission2.swift @@ -0,0 +1,14 @@ +// +// challengeMission2.swift +// BasicAssignments +// +// Created by Yeseul Jang on 1/9/26. +// + +struct SortableBox { + var items: [T] + + mutating func sortItems() where T: Comparable { + items.sort() + } +} diff --git a/BasicAssignments/challengeMission4.swift b/BasicAssignments/challengeMission4.swift new file mode 100644 index 0000000..9b26128 --- /dev/null +++ b/BasicAssignments/challengeMission4.swift @@ -0,0 +1,44 @@ +// +// challengeMission4.swift +// BasicAssignments +// +// Created by Yeseul Jang on 1/9/26. +// + +final class A { + var b: B? + + deinit { + print("🅰️ A deinit") + } +} + +final class B { + weak var a: A? //약한 참조 + var closure: (() -> Void)? + + deinit { + print("🅱️ B deinit") + } +} + +func makeMemoryLeak() { + print("memory leak start") + + let a = A() + let b = B() + + //참조순환 + a.b = b + b.a = a + + //클로저 기반 순환참조 + b.closure = + { [weak a] in + guard let a else { return } + print("b 클로저 안에서 a 참조하기: \(a)") + } + b.closure?() + + print("memory leak end") +} diff --git a/BasicAssignments/main.swift b/BasicAssignments/main.swift new file mode 100644 index 0000000..069471d --- /dev/null +++ b/BasicAssignments/main.swift @@ -0,0 +1,213 @@ +// +// main.swift +// BasicAssignments +// +// Created by Yeseul Jang on 1/6/26. +// + +import Foundation +print("--------필수문제 1-------------------") +// 필수 문제 1-------------------------------------------------------------------------- + +//두 개의 Int 값을 파라미터로 받고, 하나의 String 값을 반환하는 클로저를 설계해주세요. +// {(num1: Int, num2: Int) -> String in return "두 수의 합은 \(num1 + num2) 입니다"} + + +// 이 클로저를 상수 sum에 저장하고, 정확한 타입을 명시해주세요 +let sum: (Int, Int) -> String = { "두 수의 합은 \($0 + $1) 입니다" } + + +//sum을 호출하는 코드를 작성해주세요. (파라미터로 전달하는 값은 임의로 선택) +print(sum(1,3)) + + +//위에서 정의한 sum과 동일한 타입의 클로저를 파라미터로 받고, 반환 값이 없는(void) 함수 calculate를 작성해주세요. +func calculate(num1: Int, num2: Int, _ sum: (Int, Int) -> String) { + print(sum(num1, num2)) +} + +calculate(num1: 5, num2: 25, sum) + + + + +print("--------필수문제 2-------------------") +// 필수 문제 2------------------------------------------------------------------------ + +//아래 for-in 문을 map 을 사용하는 코드로 변환해주세요. +let numbers = [1, 2, 3, 4, 5] +var result = [String]() + +result = numbers.map { "\($0)" } +print(result) + + + +//주어진 입력값을 고차함수를 체이닝하여 주어진 출력값이 나오도록 구현해주세요. +let oneToTen = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] +let resultArr = oneToTen.filter { $0 % 2 == 0 }.map { "\($0)" } + +print(resultArr) + + + +//이제 고차함수를 직접 만들어 봅니다. +func myMap(_ IntArr: [Int], _ change: (Int) -> String) -> [String] { + var result: [String] = [] + for num in IntArr { + result.append(change(num)) + } + return result +} + +let newArr = myMap([1, 2, 3, 4, 5]) { String($0) } +print(newArr) + + + +print("--------필수문제 3-------------------") +// 필수 문제 3--------------------------------------------------------------------------- +// Int 배열의 짝수번째 요소를 제거해서 반환하는 함수 a 를 작성해주세요. +func a(_ array: [Int]) -> [Int] { + var result = [Int]() + for i in 0.. [String] { + var result = [String]() + for i in 0..(_ array: [T]) -> [T] { + var result = [T]() + for i in 0..> 로 변경합니다. +func d(_ array: [T]) -> [T] { + var result = [T]() + for i in 0.. String +} + +extension Introducible { + func introduce() -> String { + return "안녕하세요, 저는 \(name)입니다." + } +} + + +//Robot, Cat, Dog 타입을 정의하고 Introducible 프로토콜을 채택해주세요. +//Introducible 프로토콜 에 정의되지 않은 각 타입 고유의 메서드들도 하나씩 추가 정의해주세요. +class Cat: Introducible { + var name: String = "고양이" + + func meow() -> String { + return "🐈야옹" + } +} + +class Dog: Introducible { + var name: String = "강아지" + + func bark() -> String { + return "🐾월월" + } +} + +//Robot 타입의 경우, name 값이 변경될 때마다 변경 이전값과 이후 값을 출력하도록 구현해주세요. +//만약 변경 이전값과 이후값이 같다면 출력하지 않아야합니다. +class Robot: Introducible { + var name: String = "로봇" { + didSet(oldName) { + guard oldName != name else { return } + print("name 변경 알림 \n변경 이전 값: \(oldName) \n변경 이후 값: \(name)") + } + } + + func introduce() -> String { + return "안녕하세요, 저는 🤖\(name)입니다." + } + + func charge() -> String { + return "🔋충전 중" + } +} diff --git a/BasicAssignments/mission5.swift b/BasicAssignments/mission5.swift new file mode 100644 index 0000000..f0451f0 --- /dev/null +++ b/BasicAssignments/mission5.swift @@ -0,0 +1,32 @@ +// +// mission5.swift +// BasicAssignments +// +// Created by Yeseul Jang on 1/8/26. +// +enum DeliveryStatus { + case notStarted + case inTransit(daysRemaining: Int) + case error +} + +enum DeliveryError: Error { + case invalidAddress + case notStarted + case systemError(reason: String) +} + +func predictDeliveryDay(for address: String, status: DeliveryStatus) throws -> String { + if address == "" { + throw DeliveryError.invalidAddress + } + switch status { + case .notStarted: + throw DeliveryError.notStarted + case .error: + throw DeliveryError.systemError(reason: "systemError") + case .inTransit(daysRemaining: let days): + return "배송까지 \(days)일이 남았습니다." + } +} + diff --git a/README.md b/README.md new file mode 100644 index 0000000..1e61d99 --- /dev/null +++ b/README.md @@ -0,0 +1,219 @@ +# CH 2. 프로그래밍 기초 주차 과제 + +## 필수문제 1) 클로저 사용하기 +클로저란 하나의 값처럼 여기저기 전달해서 쓸 수 있는 기능을 가진 코드 덩어리이다. +확장된 함수라고도 할 수 있는데, 함수가 이름이 있는 클로저고 클로저는 이름이 없을 수도 있는 함수이다. + +후행 클로저를 사용하면 이런 식으로 축약해서 표현이 가능하다. +```swift +// {(num1: Int, num2: Int) -> String in return "두 수의 합은 \(num1 + num2) 입니다"} +let sum: (Int, Int) -> String = { "두 수의 합은 \($0 + $1) 입니다" } +``` +## 필수문제 2) 고차함수 사용하기 +`.`으로 이어서 체이닝하여 사용할 수도 있다. +```swift +let oneToTen = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] +let resultArr = oneToTen.filter { $0 % 2 == 0 }.map { "\($0)" } +``` +## 필수문제 3) 제네릭 사용하기 +`Type parameter`는 `placeholder(자리표시자) type`을 지정하고 이름을 지정하며, 함수명 바로 뒤에 꺾쇠 괄호(예: ``) 사이에 작성됨 +괄호 안에 여러 개의 타입 매개변수 이름을 쉼표로 구분하여 작성하면 두 개 이상의 타입 매개변수를 제공할 수 있다. +```swift +func c(_ array: [T]) -> [T] { + var result = [T]() + for i in 0.. { + var items: [T] + + mutating func sortItems() where T: Comparable { + items.sort() + } +} +``` +## 도전문제 3) protocol과 extension 사용 +`protocol`을 사용하면 `protocol` 내부에서는 함수 안의 내용을 정의할 수 없다. +하지만 `extension` 사용 시 `protocol`을 준수하는 모든 인스턴스가 해당 함수를 사용할 수 있게 만들 수 있다. + +```swift +protocol Introducible { + var name: String { get set } + func introduce() -> String +} + +extension Introducible { + func introduce() -> String { + return "안녕하세요, 저는 \(name)입니다." + } +} +``` + +## 도전문제 4) 순환참조와 weak 사용 + +`weak`은 순환참조가 되지 않도록 참조 카운트를 `+`하지 않는다. +`weak`으로 참조하더라도 그 대상의 생명주기에 영향을 끼치지 않는다. +`weak` 키워드가 붙으면 항상 `Optional` 타입이다 (대상 해제시 `nil` 로 바뀜) +위의 특징 덕분에 안전하고 참조대상이 사라질 수도 있을 때 사용한다. + +```swift +final class A { + var b: B? + + deinit { + print("🅰️ A deinit") + } +} + +final class B { + weak var a: A? //약한 참조 + var closure: (() -> Void)? + + deinit { + print("🅱️ B deinit") + } +} + +func makeMemoryLeak() { + print("memory leak start") + + let a = A() + let b = B() + + //참조순환 + a.b = b + b.a = a + + //클로저 기반 순환참조 + b.closure = + { [weak a] in + guard let a else { return } + print("b 클로저 안에서 a 참조하기: \(a)") + } + b.closure?() + + print("memory leak end") +} +``` ++) `unowned`도 `weak`과 똑같이 참조 카운트를 하지 않는다. +하지만 다른 점이 있다면 이 참조 대상은 나보다 오래 살거나, 최소한 나랑 같은 생명주기를 가진다는 강한 확신을 코드로 표현하는 것이다. 때문에 확신이 있을 때만 사용을 권장한다.