/*
 문제
 (A+B)%C는 ((A%C) + (B%C))%C 와 같을까?

 (A×B)%C는 ((A%C) × (B%C))%C 와 같을까?

 세 수 A, B, C가 주어졌을 때, 위의 네 가지 값을 구하는 프로그램을 작성하시오.
 
 입력
 첫째 줄에 A, B, C가 순서대로 주어진다. (2 ≤ A, B, C ≤ 10000)
 
 출력
 첫째 줄에 (A+B)%C, 둘째 줄에 ((A%C) + (B%C))%C, 셋째 줄에 (A×B)%C, 넷째 줄에 ((A%C) × (B%C))%C를 출력한다.
 
 */
import Foundation
let inputArr = readLine()!.components(separatedBy: " ").map{Int($0)!}
let A = inputArr[0], B = inputArr[1], C = inputArr[2]
print((A + B)%C)
print(((A%C) + (B%C))%C)
print((A*B)%C)
print(((A%C) * (B%C))%C)

설명할 사항이 딱이 없는거 같다.

한가지만 알아두자!

 

Swift 에서 readLine() 으로 입력을 받을수 있음

components(separatedBy: " ") 로 " " 기준으로 나누어 저장함

map 함수를 이용하여 Int 형 배열로 저장!

MVC 패턴의 개요

Model - View - Controller 구조로 이루어진 디자인 패턴을 의미한다.

 

Model : 앱의 데이터 또는 비즈니스 로직을 소유 ( 데이터의 변수 및 상수 , 데이터 값의 계산 등을 수행 )

View : 사용자에게 데이터 또는 UI 를 보여주는 역할을 수행 ( Storyboard 가 View 에 포함 )

Controller : Model  View 의 중간에서 View로부터 사용자의 이벤트를 감지하고, 해당 이벤트 처리를 Model에게 지시하며, Model의 계산된 데이터를 받아 View에게 전달하는 역할을 수행 ( TableViewController , ViewController, 등등.. )

 

Model - View - Controller 는 각각 어떻게 소통을 하나?

음식점을 예로 들어보자

1. 손님은 음식을 주문하기 위해 음식점의 홀에 있는 종업원에게 음식을 주문한다.
2. 음식 주문을 받은 종업원은 주방장에게 주문 내역을 보여준다.
3. 주방장은 주문내역을 보며 음식을 조리하여 조리가 완료되면 종업원을 다시 부른다.
4. 종업원은 해당 음식을 손님에게 제공한다.
5. 만약, 음식의 맛이 이상하거나 추가적인 조리를 원한다면 손님은 종업원을 호출한다.
6. 종업원은 손님의 요구사항을 적어 주방장에게 전달한다.
7. 주방장은 손님의 요구사항대로 음식을 재 조리하여 종업원을 부른다.
8. 종업원은 손님에게 재 조리된 음식을 제공한다.

자! 이제 종업원을 Controller로, 손님을 View로, 주방장을 Model 로 생각해보자

손님(View)은 요구사항을 전달하기 위해 종업원(Controller)에게 요구사항을 알려준다.

종업원(Controller)는 해당 요구사항을 주방장(Model)에게 전달한다.

주방장(Model)은 요구사항대로 조리가 되면 종업원(Controller)에게 음식을 전달한다.

종업원(Controller)주방장(Model)로부터 받은 음식을 손님(View)에게 전달한다.

즉, View  Model 은 직접적으로 소통할수 없고, Controller를 통해서만 소통을 할수 있다.

 

아주 간단한 MVC 패턴 적용 예시

TableView 를 사용해 이름들을 나열하는 화면을 그려보자!

 

일단 나 같은 경우, 공부를 해가는 과정이지만 Udemy - 안젤라유님의 강의를 듣고 최대한 습관화 하려고 노력하고있다.

이렇게 Model - View - Controller 를 구분하여 그룹으로 묶어두면 MVC패턴에 익숙해지는데 도움이 될거같아서...


Model

Name 구조체 먼저 선언해주고


View

View는 Storyboard 파일도 포함되지만, 이렇게 일부 Cell을 떼어내어 View로 구성할수 도 있다!


Controller

해당 부분을 보면 알겠지만, Model에 선언된 구조체를 Controller가 그 내용을 담고있으며,
View의 변화 ( TableView의 DataSource ) 에 따라 해당 값을 Controller가 전달한다.

 

이를 실행해보면

이와 같이 TableView 로 각 이름 값 들을 표시하는걸 볼 수 있다!

물론 해당 예시가 완벽한 MVC 패턴을 그리고 있진 않지만 대략적으로 이렇게 사용된다고 이해하면 될 것 같다!

 

 

MVC 패턴의 장점

  • 다른 패턴들에 비해 비교적 적은 코드량을 갖고있다
  • Apple 에서 SwiftUI가 나오기 전, 기본적으로 채택하고 있던 패턴요소이다! ( 하지만,, 현재는 MVVM 패턴을 강조하고 있다... MVVM 패턴은 아직까진 숙지가 되지 않아 이해하게 되면 블로그에 올릴 생각! )

 

MVC 패턴의 단점

  • 모든 일을 Controller가 맡아서 하고있다, 즉 Cotroller가 너무 많은 업무를 담당하게 된다
  • Controller의 코드가 너무 길어질 수 밖에 없는 구조! → Controller의 내부 구조가 복잡해지기 쉽다
  • 프로젝트의 규모가 커질수록 유지보수 하기에 어려움이 있다! ( 사실 아직까지 큰 프로젝트를 한적이 없어서 이 말이 잘 이해가 가지 않는다... 나중에 하게 된다면 몸소 느껴봐야겠다! )

iOS의 ViewControlle의 생명주기는 개발함에 있어 굉장히 중요하다.

해당 View에 컨텐츠가 언제 나타나야 하는지, 컨텐츠의 내용은 무엇인지, 해당 컨텐츠의 내용이 뷰가 사라지면 어떻게 되야하는지 등등 개발함에 있어 반드시 알아야 하는 중요한 사항들이있다.

ViewController의 생명주기에 대해 알아보자!

1. ViewDidLoad()

공식문서에 의하면 뷰 컨트롤러가 메모리에 로드된후 호출되는 메소드이다.

다시말해 뷰가 메모리에 로딩이 완료되면 시스템에 의해 자동으로 호출되는 메소드로, 화면이 처음 생성될때 딱 한번 실행된다.

2. ViewWillAppear()

공식문서에 의하면 뷰가 뷰 계층에 추가될 것임을 뷰 컨트롤러 알려주는 메소드이다.

다시말해 뷰가 화면에 나타나기 직전! 해당 메서드가 호출된다!

그럼, ViewDidLoad 도 화면에 나타나기전, 수행되는데 이 둘의 차이는 무엇일까?

직접 구현해보면 차이를 파악알수 있다.

처음 View를 표시할때 ViewDidLoad() 가 호출되고, 그다음에 ViewWillApear() 가 호출된다,

그리고 다른 뷰로 넘어갈때, 마찬가지로 둘다 호출이 되지만 다시 이전화면으로 돌아갈때

ViewWillAppear() 메소드만 호출됨을 알수있다.

즉, ViewDidLoad() 는 메모리가 해제되기 전까지는 무조건 1번만 호출되며, ViewWillAppear() 메소드는 메모리와 관계없이 해당 뷰를 표시할때 무조건 호출되는 차이가 있다!

3. ViewDidAppear()

공식문서에 의하면 뷰가 뷰 계층에 추가되었음을 뷰 컨트롤러에 알려주는 메소드이다.

다시 말해 ViewWillAppear() 는 뷰가 표시되기 직전 호출되는 메소드라면,

ViewDidAppear() 는 뷰가 표시된 직후!!! 호출되는 메소드이다!

4. ViewWillDisappear()

공식문서에 의하면 뷰가 뷰 계층에서 제거될 것임을 뷰 컨트롤러에 알려주는 메소드이다.

다시말해 뷰가 사라지기 직전 호출되는 메소드 이다!

5. ViewDidDisappear()

공식문서에 의하면 뷰가 뷰 계층에서 제거되었음을 뷰 컨트롤러에 알려주는 메소드이다.

마찬가지로 ViewWillDisappear() 가 사라지기 직전 호출되는 메소드라면, ViewDidDisappear()는 사라진 직후 호출되는 메소드이다.

이와 같이 ViewController의 생명주기는 메소드의 이름만으로도 충분히 어떤일을 수행하는 메소드인지 짐작할수 있다!

이를 직접 구현하여 실제로 어떤 순서로 호출되는지 파악해 보자!

확실히 호출되는 순서를 보면 더욱더 이해하기 쉽다!

이 생명주기를 잘 기억하여 

View 에 표시되는 데이터나 저장해야하는 시점 등등을 적절한 메소드에 적절하게 사용하면 된다!

아주 기본적이면서 아주 중요한 내용이다!

  • 블로그 쓰는걸 두려워하지 말라
    → 이미 블로그가 많은데 이게 필요한가?
         ⇒ 필요함, 실제로 많은 블로그들이 있지만 꾸준한 블로그는 드문게 사실임
         ⇒ 유명한 블로그들은 그만한 이유가 있다, 그런 블로그들 특별한건 없다 다만 꾸준히 오랜기간 연재했을뿐
  • 어디선가 발표를 해봐라 그럼 내가 발표하기위해 더 열심히 공부하게 될것이다
  • 세미나, 컨퍼런스의 내용을 들으러 가는것도 좋지만 여러 사람을 만날기회로 생각하고 가봐라
  • 두려워하지말고 여기저기 자문을 구해봐라! 그분들도 삐약이들이 궁금증을 갖고 질문을 하면 좋아할 것이다

질문

  • 질문을 참지마라.. 나보다 윗사람들에게 질문하는것을 두려워하지말고 질문해라
    → 질문안하고 혼자 끙끙대면 오히려 안좋은 결과를 초래한다
  • 왜? WHY?
    •  업무를 지시받았을때 왜? 질문할것
      → 왜? 를 찾고, 목적에 따라 어떻게? 가 나와야 좋은 개발자가 된다
      → 하나를 알려줘도 100을 알수있는 개발자가 되려면 WHY? 의문을 가질것
      → 어떻게? 를 먼저 생각하면 결과가 산으로 갈수가 있다! 목적을 알고, 목적에 따라 개발하는게 좋음!
      → 어떻게? 보다는 왜? 를 먼저 알아야한다
  • 단, 질문을 하되 몇가지 생각하며 질문해야한다
    1. 핑프면 안된다
      → 내가 뭘 하려고하는데 뭘 찾아봤는데 어떤식으로 된다, 하지만 나는 어떻게 하려고 하는데 잘 안된다 이렇게했는데 잘 안되는데 혹시 왜 이러는지 알려주실수 있나요?
    2. 질문 안하는거 보단, 질문을 너무많이해서 '물음표살인마' 가 되는게 좋음
    3. 같은 질문을 반복해서 하지 말것!
    4. 질문을 할때는 질문에 대한 배경을 설명해야한다!
      → A 를 만들라고 하셔서 A를 만드려는데 제가 알아본바 B 방법은 ~~~~~ 하는 방식이고, C방법은 ㅁㅁㅁㅁㅁ 하는 방식인거 같습니다, 이 두개의 방법중 어떤게 더 효율적일지 감이 잡히지 않습니다 어떻게 진행하는게 좋을까요?
  • 역지사지
    • 상대방 질문에 대한 이해와 존중!
⚠️ 당신은 어떤 사람과 일하고 싶나요?

 

Q&A

  1. iOS 공부할때, UIKit 을 해야하는지 SwiftUI를 해야하는지?
    → 2년안에 취업을 생각하고 있다면 UIKit이 우선! 2년내에 취업할 생각은 없고, 아직까진 취미의 영역이다 하면 SwiftUI 로 해도 됨!
  2. 프론트엔드, 백엔드, 모바일 등 여러 분야가 있는데 여러가지 경험을 하기엔 시간이 오래걸리는데 어떻게 경험을 해야하는지?
    → 사실 경험하는건 좋은것이긴하나, 경험하는데 너무 많은 시간을 쏟지 않는게 좋다 1달정도면 튜토리얼 정도는 경험할수 있다! 다만 찍먹을 하는건 나쁜게 아님!
  3. 주니어, 인터미디에트, 시니어 개발자는 인터넷 회사에서 어떻게 나누어지는 구분인가요? 또 언제까지 보통 주니어라고 불리게 될까요?
    → 기준은 없는데 일반적으로 3년~ 5년정도면 주니어인거같다
  4. Swiftui 공부하면서 mvvm을 적용해서 코드를 작성하려고 노력하고 있는데 아직 어떤게 모델에 들어가야하고 뷰모델에 들어가야하는 지 구분하는 게 어렵습니다. 다른 사람들 코드를 보면서 제 나름대로 기준을 찾아가려고 하는데 혹시 추천하는 학습 방식 있으신지 궁금합니다!
    → 많이 해봐야한다, 같은 결과물을 A방법, B방법으로 반복 학습하며 익혀봐라! ( 아마도.. MVC방법, MVVM방법, VIPER방법 등등..? )
  5. 야곰 멘토님의 손을 거친 교육생들 중에 기억나는 분이 계신가요~? 있다면 어느분이고 왜 기억에 남으시는지 궁금합니당 :)
    → 일단 교육생이라고 생각하지 않는다, 다 동료고 친구이며 같이 공부하는 사람들임! 근데 기억나는 친구! 블로그를 꾸준히 작성하는 친구가 기억에 남는다! 지금 iOS 검색하면 1등으로 나오는 블로그일것이다
  6. ios 프론트 개발에서 TDD 를 어떻게 적용할 수 있을까요?
    → TDD 쉽지 않음,,
  7. 모르고 짜는 것에 대해 공부하다보면 너무 깊어지는 것 같아서 도대체 어느 정도까지 아는 게 좋은지, 그 공식 문서처럼 깊게 알아야 하는지 궁금합니다
    → 내가 이분야 전문가가 되겠다! 싶으면 깊게 공부하는게 좋다 하지만 그게 아니라면 굳이..?
  8. 야곰님께서 보시는 좋은 블로깅의 예시가 궁금합니다!
    → 꾸준히 써라.. 꾸준한게 제일 좋은 블로그임, 글이 틀리는걸 두려워하지 마라 나중에 수정하면 그만임!
  9. 공유라는 측면에서 노션보다는 블로그를 이용하는게 더 도움이 될까요?
    → 노션은 혼자보기에 좋음.. 블로그를 써보도록 할것!
  10. UI와 iOS 개발은 뗄 수 없는 존재일까요? 몇개월간 찍먹을 해봤는데, UI 짜는 게 너무 안 맞는 것 같아요 ㅠㅠ
    → UI가 안맞으면 어쩔수 없다.. 백엔드 찍먹도 해보고 이것저것 해보며 맞는걸 찾아보는것도 좋다

가변인자란?

int main(int abc, ...) { }

위 코드의 main 함수의 인자중,  ...  가변 인자 혹은 가변 파라미터

매개변수로 아무것도 넘겨주지 않거나 여러 개를 넘겨줄 수도 있음

함수가 고정된 수의 필수 인수에 가변 수의 선택적 인수가 붙은 형식을 사용할때 적용

 

va_list, va_start, va_end, va_copy, va_arg 함수

1) va_list

가변 인자의 시작 주소를 의미하는 포인터

2) va_start

// va_start 함수 원형
void va_start(va_list ap, variable_name);

va_list로 만들어진 포인터에게 가변인자 중 첫 번째 선택적 인수(variable_name)의 주소를 가르쳐주는중요한 매크로이다.

va_arg(), va_copy(), va_end()에 대한 후속 호출에 대해 ap 포인터를 초기화한다.

  • ap: va_list 로 만든 포인터가 담긴다.
  • variable_name: 인수 목록의 첫 번째 인자 바로 앞에 오는 필수 매개 변수의 이름. 즉, 마지막 고정된 필수 인수가 담긴다.

3) va_copy

void va_copy(va_list dest, va_list src);

va_start()를 dest에 적용한 후 src의 현재 상태에 도달하는 데 이전에 사용된 것과 동일한 순서로 va_arg()를 사용한 경우와 같이 dest를 src의 사본으로 초기화한다. va_copy() 또는 va_start()는 동일한 dest에 대한 va_end()의 중간 호출 없이 dest를 다시 초기화하도록 호출해야 한다.

4) va_arg

var_type va_arg(va_list ap, var_type);

ap로 지정된 위치에서 지정된 var_type 값을 검색하고 리스트에서 다음 인수를 가리키도록 ap 를 증가 시켜 다음 인수가 시작 되는 위치를 결정한다. 즉, 특정 가변인자를 가리키고 있는 va_list의 포인터를 다음 가변인자로 이동시켜 주는 매크로이다. 

  • ap: va_list로 만든 포인터가 담긴다.
  • var_type: int나 long, double과 같은 타입 이름이 담긴다.

var_type을 설정할 때 char, short 의 경우에는 int로 대신 쓰고, flaot의 경우에는 double로 대신 쓴 이후 형 변환을 해주어야 한다.
ex) char ch = (char) va_arg(ap, int);

va_end

void va_end(va_list arg_ptr);

모든 인수가 검색 된 후 va_end 는 포인터를 NULL로 다시 설정 한다. 즉, 사용한 가변인자 변수를 끝낼때 사용.

4. 반환값

va_arg() 함수는 현재 인수를 리턴한다. va_copy(), va_end(), va_start() 함수는 값을 리턴하지 않는다.

+ Recent posts