DADAHAE's Log
비싼 장난감 가지고 노는 중 (❁´▽`❁)*✲゚*
[TIL] 22-10-07: Objective-C, CocoaPods과 SPM 찍어먹기
22-10-07 금요일
4주차

 

 

 

 

 

 

 

 

WARNING
⚠️ 경고 ⚠️

이곳은 고대 언어 발굴 현장입니다. 
C언어 계열에 알러지가 있으신 분은 특히 주의 바랍니다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

✔️ Objective-C

 

1️⃣ Functions

objc가 말하는 함수와 swift가 말하는 함수는 다르다.

작업을 함께 수행하는 명령문 그룹
  • objc 프로그램에는 main() 함수가 있고, 추가 함수 정의 가능
  • 코드를 여러 기능으로 나누는 방법은 마음대로지만, 일반적인 각 기능이 특정 작업을 수행하도록 구분한다.
    • 기계적으로는 어떻게든 상관없지만,
    • 논리적으로는 하나의 기능을 수행하도록 해야함.
  • 함수 선언
    • 컴파일러에게 함수 이름, 반환 유형 및 매개변수에 대해 알려줌
  • 함수 정의
    • 함수의 실제 본문 제공
    • 선언, 정의 다르다.
  • objc에서 함수를 메서드라고 부름
    • C언어에서 함수를 메서드로 부르나? ㄴㄴ objc에서만
더보기

잠깐 계보 살펴보기

  • obj-c = c + smalltalk(”OOP”)
  • C++ = C + “OOP”
  • Objective-C++ = C + C++ + obj-c
  • objc foundation 프레임워크
    • 기본 메서드 제공
  • 메소드 → 함수, 서브루틴, 프로시저.. 등의 다양한 이름으로 알려짐

 

Defining a Method

- (return_type) method_name:( argumentType1 )argumentName1
joiningArgument2:( argumentType2 )argumentName2 ...
joiningArgumentn:( argumentTypen )argumentNamen {
	body of the function
}

 

swift 코드를 Objective-C로 바꿔보자.

func myMethod(myName name: String, myAge age: Int) -> Void {   // swift
	print("\\(name) \\(age)")
}
myInstance.myMethod(myName: "dadahae", myAge: 13)
- (void)myMethodWithMyName:(NSString*)name myAge: (int)age {  // Objective-C
	// name 활용
	// age 활용
}
[myInstance myMethodWithMyName:@"dadahae", myAge:13]
  • 시스템이 바라보는 메소드 이름은 “myMethodWithMyName:myAge:”
    • 매개변수는 name과 age
    • “myMethodWithMyName:myAge:”(name, age) → 함수의 이름이 되는 것이다.
    • Obj-C의 메소드는 함수 호출이라기 보다는 객체와의 메시징을 위한 수단의 성격이 강하다.

 

#import <Foundation/Foundation.h>

@interface MyNumber: NSObject
- (int)getMaxiumNumberWithFirstNumber:(int)num1 secondNumber:(int)num2;
@end

@implementation MyNumber
- (int)getMaxiumNumberWithFirstNumber:(int)num1 secondNumber:(int)num2 {
		int result = num1 > num ? num1 : num2
    return result;  // call by value
}
@end

int main (int argc, const char * argv[])
{
    MyNumber *num = [[MyNumber alloc] init];
    int maxNum = [num getMaxiumNumberWithFirstNumber:13 secondNumber:10];
    printf("%d", maxNum);
   return 0;
}

 

  • 메서드 선언
    • 컴파일러에게 함수 이름과 메서드를 호출하는 방법을 알려줌
  • 함수 실제 본문은 별도로 정의 가능(implementatation + interface)

 

Calling a method

  • 메소드를 생성하는 동안 함수가 수행해야 하는 작업에 대한 정의 제공
  • 프로그램이 함수를 호출하면 프로글매 제어가 호출된 메서드로 전달
  • 호출된 메서드는 정의된 작업을 수행

 

Function Arguments

  • 형식 매개변수
    • 함수가 인수를 사용하려면 인수 값을 혀용하는 변수를 선언해야 함
    • 함수 내부의 다른 지역 변수처럼 작동하고, 함수에 들어갈 때 생성되고 종료할 때 소멸된다.
  • 함수를 호출하는 동안 인수를 함수에 전달하는 2가지 방법
    • Call by Value
    • Call by Reference
#import <Foundation/Foundation.h>

@interface MyNumber: NSObject
- (int)getMaxiumNumberWithFirstNumber:(int)num1 secondNumber:(int)num2;
- (NSString *)getHello;
@end

@implementation MyNumber
- (int)getMaxiumNumberWithFirstNumber:(int)num1 secondNumber:(int)num2 {
    
    int result = num1 > num2 ? num1: num2;
    
    return result; // call by value
}

- (NSString *)getHello {
    NSString *hello = @"Hello World";
    return hello; // call by reference
}
@end

int main (int argc, const char * argv[])
{
    MyNumber *num = [[MyNumber alloc] init];
    int maxNum = [num getMaxiumNumberWithFirstNumber:13 secondNumber:20];
    NSLog(@"%d", maxNum);
    
    NSString *hello = [num getHello];
    NSLog(@"%@", hello);
   return 0;
}

 

더보기

Q. result 는 함수 호출이 끝나고 사라질까?

A. ㅇㅇ 사라진다. result는 call by value

더보기

Q. hello 는? 함수 호출이 끝나고 사라질까?

A. 포인터로 정의되었기 때문에 살아있답. 주소값으로 접근한다. call by reference

 

  • 값을 복사할건지, 메모리 주소값을 복사할건지~

 

 

2️⃣ Blocks

클로저의 조상
  • Obj-C 클래스
    • 관련 동작, 데이터를 결합하는 개체를 정의함
  • 블록
    • C, Obj-D, C++에 추가된 기능
    • 마치 값인 것 처럼 메서드, 함수에 전달할 수 있는 코드 세그먼트
    • NSArray, NSDictionary와 같은 컬렉션에 추가할 수 있음~
    • 엔클로징 범위에서 값을 Capture하여 다른 프로그래밍 언어 closure, lambda와 유사

 

Simple Block declaration syntax

returnType (^blockName)(argumentType);
  • 간단한 블록 구현
returnType (^blockName)(argumentType)= ^ {
};

위로 꺽쇠 있다? 아~ 블록이네~

 

void (^simpleBlock)(void) = ^ {
	NSLog(@"This is block");
}

/* 
void simpleBlock() {
	NSLog(~);
}

로 해도 같은거 아니냐?! 같다. 근데 다른 점은... 값인 것 처럼 할 수 있다 없다의 차이이다.
*/
  • 블록 호출
simpleBlock();

멀티스레드

동시성 지원하는 문제 때문에 C언어에서도 적용되었다.

 

Blocks Take Arguments and Return Values

  • 블록은 메서드 및 함수와 마찬가지로
    • 인수를 사용하고 값 반환 가능
double (^multiplyTwoValues)(double, double) =   // return type, parameter
	^(double firstValue, double secondValue) {
		return firstValue * secondValue;
	};

double result = multiplyTwoValues(2,4);
NSLog(@"The result is %f", result);

 

 

3️⃣ Numbers

  • Objective-C 프로그래밍 언어에서 int, float, bool과 같은 기본 데이터 유형을 객체 형태로 저장하기 위해, Objective-C는 NSNumber로 작업할 수 있는 다양한 방법을 제공하며 중요한 방법은 다음 표에 나열되어 있습니다.
#import <Foundation/Foundation.h>

// C언어 스타일의 함수
double multiplyTwoValuesOrgin(double firstValue, double secondValue)
{
    return firstValue * secondValue;
}

// Block으로 다시 위 함수를 써본다면
// Block의 이름은 (^multiplyTwoValues)(double, double)
// Block의 실제 작동내용은 ^{ ... }으로 구현
double (^multiplyTwoValues)(double, double) = ^(double firstValue, double secondValue){
    return firstValue * secondValue;
};

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        NSLog(@"Hello, World!");
        
        double myNum = multiplyTwoValues(2, 4);
        NSLog(@"%f", myNum);
    }
    return 0;
}

 

#import <Foundation/Foundation.h>

typedef void (^CompletionBlock)();

@interface SampleClass: NSObject
- (void)performActionWithCompletion:(CompletionBlock)completionBlock;
@end

@implementation SampleClass

- (void)performActionWithCompletion:(CompletionBlock)completionBlock {
    NSLog(@"Action performed");
    completionBlock();
}

@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSLog(@"Hello, World!");
        
        SampleClass *sampleClass = [[SampleClass alloc] init];
        [sampleClass performActionWithCompletion:^{
            NSLog(@"Completion is called to intimate action is performed.");
        }];
    }
    return 0;
}

 

🦁 11:00 ~ 11:50 잠시 외출!

 

  • 두 숫자를 곱하고 곱을 반환하는 NSNumber를 활용하는 예제
#import <Foundation/Foundation.h>

// Foundation이 제공하는 NSObject를 상속받은 SampleClass는 이러한 내용을 구현합니다.
@interface SampleClass : NSObject
- (NSNumber *)multiplyA:(NSNumber *)a withB:(NSNumber *)b;
@end

// SampleClass의 구체적인 내용은 다음과 같습니다.
@implementation SampleClass

- (NSNumber *)multiplyA:(NSNumber *)a withB:(NSNumber *)b {
    
    // NSNumber 타입으로 받은 a와 b로부터 float 값들을 꺼내서 곱셈한 후
    float number1 = [a floatValue];
    float number2 = [b floatValue];
    float product = number1 * number2;
    
    // 결과를 NSNumber로 다시 만들어 반환한다.
    NSNumber *result = [NSNumber numberWithFloat:product];
    return result;
}

@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSLog(@"Hello, World!");
        
        // swift였다면 ... var sampleClass: SampleClass = SampleClass()
        SampleClass *sampleClass = [[SampleClass alloc] init];
        
        NSNumber *a = [NSNumber numberWithFloat:10.5];
        NSNumber *b = [NSNumber numberWithFloat:10.0];
        NSNumber *result = [sampleClass multiplyA:a withB:b];
        
        // 결과의 NSNumber로부터 NSString를 만들어 활용한다.
        NSString *resultString = [result stringValue];
        NSLog(@"The product is %@", resultString);
    }
    return 0;
}

result의 NSNumber를 NSString으로 만들어 활용도 할 수 있다.

 

더보기

온라인 컴파일러로 돌리면 아래 코드를 참고하세용.

* 오토 릴리즈 코드를 빼고 작성하기!

* Xcode에서는 메모리를 자동으로 관리해주기 때문에 autolease 코드가 존재한다. 자세한건 나중에 배움! (ARC)

NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
...
[pool drain];
#import <Foundation/Foundation.h>

// Foundation이 제공하는 NSObject를 상속받은 SampleClass는 이러한 내용을 구현합니다.
@interface SampleClass : NSObject
- (NSNumber *)multiplyA:(NSNumber *)a withB:(NSNumber *)b;
@end


// SampleClass의 구체적인 내용은 다음과 같습니다.
@implementation SampleClass

- (NSNumber *)multiplyA:(NSNumber *)a withB:(NSNumber *)b {
    
    // NSNumber 타입으로 받은 a와 b로부터 float 값들을 꺼내서 곱셈한 후
    float number1 = [a floatValue];
    float number2 = [b floatValue];
    float product = number1 * number2;
    
    // 결과를 NSNumber로 다시 만들어 반환한다.
    NSNumber *result = [NSNumber numberWithFloat:product];
    return result;
}

@end


int main (int argc, const char * argv[])
{
   NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

   NSLog(@"Hello, World!");
        
    // swift였다면 ... var sampleClass: SampleClass = SampleClass()
    SampleClass *sampleClass = [[SampleClass alloc] init];
        
    NSNumber *a = [NSNumber numberWithFloat:10.5];
    NSNumber *b = [NSNumber numberWithFloat:10.0];
    NSNumber *result = [sampleClass multiplyA:a withB:b];
        
    // 결과의 NSNumber로부터 NSString를 만들어 활용한다.
    NSString *resultString = [result stringValue];
    NSLog(@"The product is %@", resultString);
    
   [pool drain];
   return 0;
}

 

 

더보기

Q. 메소드 헤드부분에는 객체 포인터 타입일때 타입에 괄호()를써주는데 main 함수 내에서 객체 포인터 선언할때에는 괄호()가 없는데 큰차이점이 있나요? 써도되고 안써도되는 부분인가요?

 

A. main은 C언어 형식의 함수이고, obj-c의 메소드는 자체적인 형식이 따로있다보니 생긴 차이라 볼 수도 있습니다.

(NSNumber *)... 이것은 반환될 타입이 NSNumber의 포인터값이 될거란 뜻이고,

NSNumber *a ... 이것은 a는 NSNumber 타입이 되는 (실제로는 포인터 값이되는) 인스턴스를 뜻한다라는 서로 다른 의미가 되겠습니다.

더보기

Q. 그럼 인스턴스 생성할때도 (NSNumber*) a 라고 하면 안되는 부분인가요? 메소드 부분에도 반환될 타입에 괄호가 있지만 a변수 타입 얘기할때에도 똑같이 괄호를 사용해서 붙여준거라 단순히 괄호 유무가 큰 차이를 만드는지 궁금합니다.

 

A. C언어 포인터 타입 활용 규칙상 NSNumber * a 이렇게 쓰는게 대세이고 국룰이지만, 간혹 Number * a 라고 *를 타입에 붙이는 분들도 계십니다.

Q. 근데 함수 쪽에는 괄호를 다 지워보니 에러가나네요.

A. 네, Obj-C 메소드 문법이 원래 그렇습니다.

더보기

Q. multiplyA, withB가 밖에서 메소드 사용할 때 쓰는 이름이고 내부에서는 a 와 b로 사용하는거 맞나요??

 

A. 네, 공식적인 메소드 이름은 multiplyA:withB: 이고, 메소드 내부에서만 a,b라는 이름을 사용해서 작동됩니다.

더보기

Q. 메소드 선언시, 반드시 외부변수명과 내부변수명 모두 작성해야하는지 궁금합니다!

 

A. 네, 형식이 원래 그렇습니다. 스위프트가 이뻐보이는 이유지요.

더보기

Q. 포인터를 왜 써야하는지 잘 모르겠어요.

 

A. C언어 계열에서는 기본 타입인 int, float 같은 게 아니면 모두 포인터로만 서로 생각해서, 실제 메모리 값은 포인터 주소 찾아가서 살펴보는 형식을 취하는 종특이 있다보니 생긴 일입니다 ㅠㅠ

더보기

Q. 그러니까 return 값이나 매개변수로 int float이 아니어서 위 예제에서는 포인터를 사용한 것이라고 이해해도 될까요?

 

A. 네, 기본 타입 아니면 특히 객체 단위에선 포인터밖에 활용 방법이 없게 되서 그렇지요.

 

 

 

4️⃣ Array

  • c
    • int a[5] → 0…4
  • obj-c
    • NSArray → 상수형, 자리 잡히면 못 바꿈
  • swift
    • struct { mutating func name() { … } }

NSMutableArray 가 mutating의 원조다…

 

  • 고정 크기
  • 순서 있음
  • 같은 유형의 변수 모음
  • 배열의 요소는 인덱스로 접근 가능
  • 연속적인 메모리 위치로 구성
    • 가장 낮은 주소 → 첫번재 요소
    • 가장 높은 주소 → 마지막 요소

 

Declaring Arrays

  • type 지정
  • maximum index 지정
type arrayName[arraySize];

이것을 1차원 배열이라고 한다.

  • arraySize : 0보다 큰 정수 상수여야 함
  • type : 유요한 Obj-C 데이터 유형이 될 수 있음

 

double balance[10];

 

Initializing Arrays

  • 배열을 하나씩 초기화하거나, 아래와 같이 단일 명령문으로 초기화 가능
double balance[5] = {100.0, 2.0, 3.4, 17.0, 50.0}

 

  • 배열의 크기를 생략하면 초기화한 크기 만큼만 큰 배열이 생성된다.
double balance[] = {100.0, 2.0, 3.4, 17.0, 50.0}

 

예제)

double balance[] = {100.0, 2.0, 3.4, 17.0, 50.0}
balance[4] = 40.0
  • 5번째 요소에 40.0 할당
  • 인덱스 4번은 배열의 5번째이다. 0-indexed

 

Accessing Array Elements

  • 배열 이름을 인덱싱하여 요소에 접근함
double salary = balance[9];

 

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        int myArray[10];    // 10개의 int값이 들어갈 배열 선언
        int i, j;           // for 반복문에 활용
        
        for (i = 0; i < 10; i++) { // i는 0..<10 구간으로 증가하며 반복
            myArray[i] = i + 100;
        }
        
        for (j = 0; j < 10; j++) {
            NSLog(@"Element[%d] = %d\\n", j, myArray[j]);
        }
        
    }
    return 0;
}

 

Arrays in Detail

  • NSArray, NSMutableArray
  • Obj-C의 배열과 관련된 몇가지 중요한 개념
    • 다차원 배열
    • 함수에 배열 전달
    • 함수에서 배열 반환
    • 배열에 대한 포인터

 

 

5️⃣ Data Type

  • 컴퓨터는 0과 1로만 생각함
  • 그래서 2진법 나옴 (이진연산)
  • 메모리에 저장할때도 2진법으로 저장, 컴퓨터 메모리에도 0과 1로만 저장된다.

 

6️⃣ Pointer

Objective-C의 포인터는 배우기 쉽고 재미있습니다.

  • 동적 메모리 할당과 같은 작업은 포인터를 사용해야 한다. (아래 코드의 주석내용들 참고)
  • 모든 변수는 메모리 위치
  • 모든 메모리 위치는 메모리 주소를 나타내는 &(앰퍼센트) 연산자 사용하여 접근.

 

포인터의 개념을 예시로 이해해보자.

  • 포인터 정보 = 해당 데이터의 메모리 주소 + 메모리를 차지하는 크기
  • 토지대장 = 주소지(경상북도 울릉군...) + 몇 평수 정보(임야 13평)

주소지 대로 찾아갔는데 정확하게 어디까지의 영역이 내 땅인지 모르면 큰일이다. 메모리 주소도 마찬가지!

코드에서는 타입별 크기대로 주소지에서 영역을 계산한다.

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {

    int age = 13;
    double height = 145.32;
    
    // 변수에 담긴 값을 출력
    NSLog(@"value of age : %d", age);
    NSLog(@"value of hegith : %f", height);
    
    // 변수가 위치한 메모리 안에서의 주소
    NSLog(@"address of age : %x", &age);
    NSLog(@"address of height : %x", &height);
    
    // 포인터 정보 = 해당 데이터의 메모리 주소 + 메모리를 차지하는 크기
    // 토지대장 = 주소지(경상북도 울릉군...) + 몇 평수 정보(임야 13평)
    
    return 0;
}

 

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    // 포인터 정보 = 해당 데이터의 메모리 주소 + 메모리를 차지하는 크기
    // 토지대장 = 주소지(경상북도 울릉군...) + 몇 평수 정보(임야 13평)

    int index = 17;
    printf("i stores its value at %x\\n", &index);
    printf("this function starts at %x\\n", &main);
    
    return 0;
}

 

더보기

근데 직-접 메모리 주소를 꺼내와서 접근하는건 위험하다. 흠냐링.

 

 

  • 포인터 변수
#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    // 포인터 정보 = 해당 데이터의 메모리 주소 + 메모리를 차지하는 크기
    // 토지대장 = 주소지(경상북도 울릉군...) + 몇 평수 정보(임야 13평)

    int age = 17;
    
    // 변수 age의 주소를 확인해서, int 타입이 담길 거라고 생각하는 포인터 변수 만들기
    int *addressOfAge = &age;
    
    NSLog(@"age는 %p 주소에 위치했습니다.", addressOfAge);
    NSLog(@"%p 주소에 가보니 %d 값이 들어있습니다.", addressOfAge, *addressOfAge);
    
    /*
     출력문:
     age는 0x16fdff3ac 주소에 위치했습니다.
     0x16fdff3ac 주소에 가보니 17 값이 들어있습니다.
     */
    
    return 0;
}

 

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    // 포인터 정보 = 해당 데이터의 메모리 주소 + 메모리를 차지하는 크기
    // 토지대장 = 주소지(경상북도 울릉군...) + 몇 평수 정보(임야 13평)

    int age = 17;
    
    // 변수 age의 주소를 확인해서, int 타입이 담길 거라고 생각하는 포인터 변수 만들기
    int *infoOfAge = &age;
    
    NSLog(@"age는 %p 주소에 위치했습니다.", infoOfAge);
    // age는 0x16fdff3ac 주소에 위치했습니다.
    
    NSLog(@"age의 메모리 크기는 %zu 바이트입니다.", sizeof(int));
    // age의 메모리 크기는 4 바이트입니다.
    NSLog(@"처음 %p 주소에 가보니 %d 값이 들어있습니다.", infoOfAge, *infoOfAge);
    // 처음 0x16fdff3ac 주소에 가보니 17 값이 들어있습니다.
    
    *infoOfAge = 32;
    NSLog(@"다시 %p 주소에 가보니 %d 값이 들어있습니다.", infoOfAge, *infoOfAge);
    // 다시 0x16fdff3ac 주소에 가보니 32 값이 들어있습니다.
    
    NSLog(@"%p를 가르키는 정보의 메모리 크기는 %zu 바이트입니다.", infoOfAge, sizeof(int *));
    // 0x16fdff3ac를 가르키는 정보의 메모리 크기는 8 바이트입니다.
    
    return 0;
}

 

#import <Foundation/Foundation.h>

@interface SampleClass : NSObject
- (void)sayHello;
@end

@implementation SampleClass
- (void)sayHello {
    NSLog(@"Hello World");
}
@end

int main(int argc, const char * argv[]) {
    // 포인터 정보 = 해당 데이터의 메모리 주소 + 메모리를 차지하는 크기
    // 토지대장 = 주소지(경상북도 울릉군...) + 몇 평수 정보(임야 13평)

    int age = 17;
    
    // 변수 age의 주소를 확인해서, int 타입이 담길 거라고 생각하는 포인터 변수 만들기
    int *infoOfAge = &age;
    
    NSLog(@"age는 %p 주소에 위치했습니다.", infoOfAge);
    // age는 0x16fdff3ac 주소에 위치했습니다.
    
    NSLog(@"age의 메모리 크기는 %zu 바이트입니다.", sizeof(int));
    // age의 메모리 크기는 4 바이트입니다.
    NSLog(@"처음 %p 주소에 가보니 %d 값이 들어있습니다.", infoOfAge, *infoOfAge);
    // 처음 0x16fdff3ac 주소에 가보니 17 값이 들어있습니다.
    
    *infoOfAge = 32;
    NSLog(@"다시 %p 주소에 가보니 %d 값이 들어있습니다.", infoOfAge, *infoOfAge);
    // 다시 0x16fdff3ac 주소에 가보니 32 값이 들어있습니다.
    
    NSLog(@"%p를 가르키는 정보의 메모리 크기는 %zu 바이트입니다.", infoOfAge, sizeof(int *));
    // 0x16fdff3ac를 가르키는 정보의 메모리 크기는 8 바이트입니다.
    
    
    // SampleClass의 인스턴스를 만들어서
    // 그 메모리의 위치 정보를 SampleClass클래스에 맞춘 포인터 변수 sampleClass에 할당한다
    // 클래스에 의해 만들어지는 인스턴스는 무조건 포인터 단위로 관리해야만 활용 가능하다.
    SampleClass *sampleClass = [[SampleClass alloc] init];
    
    // sampleClass 포인터 정보가 가르키는 인스턴스 데이터를 찾아가서
    // 데이터에 명시된 sayHello 메소드를 실행하라
    [sampleClass sayHello];
    
    
    return 0;
}

 

점점 발전하는 중…

#import <Foundation/Foundation.h>

@interface SampleClass : NSObject
- (void)sayHello;
@end

@implementation SampleClass
- (void)sayHello {
    NSLog(@"Hello World");
}
@end

int main(int argc, const char * argv[]) {
    // 포인터 정보 = 해당 데이터의 메모리 주소 + 메모리를 차지하는 크기
    // 토지대장 = 주소지(경상북도 울릉군...) + 몇 평수 정보(임야 13평)

    int age = 17;
    
    // 변수 age의 주소를 확인해서, int 타입이 담길 거라고 생각하는 포인터 변수 만들기
    int *infoOfAge = &age;
    
    NSLog(@"age는 %p 주소에 위치했습니다.", infoOfAge);
    // age는 0x16fdff3ac 주소에 위치했습니다.
    
    NSLog(@"int 타입의 메모리 크기는 %zu 바이트입니다.", sizeof(int));
    // int 타입의 메모리 크기는 4 바이트입니다.
    NSLog(@"변수 age의 메모리 크기는 %zu 바이트입니다.", sizeof(age));
    // 변수 age의 메모리 크기는 4 바이트입니다.
    NSLog(@"처음 %p 주소에 가보니 %d 값이 들어있습니다.", infoOfAge, *infoOfAge);
    // 처음 0x16fdff3ac 주소에 가보니 17 값이 들어있습니다.
    
    *infoOfAge = 32;
    NSLog(@"다시 %p 주소에 가보니 %d 값이 들어있습니다.", infoOfAge, *infoOfAge);
    // 다시 0x16fdff3ac 주소에 가보니 32 값이 들어있습니다.
    
    NSLog(@"int를 담은 데이터의 포인터정보 크기는 %zu 바이트입니다.", sizeof(int *));
    // int를 담은 데이터의 포인터정보 크기는 8 바이트입니다.
    NSLog(@"%p를 가르키는 정보의 메모리 크기는 %zu 바이트입니다.", infoOfAge, sizeof(infoOfAge));
    // 0x16fdff3ac를 가르키는 정보의 메모리 크기는 8 바이트입니다.
    
    
    // SampleClass의 인스턴스를 만들어서
    // 그 메모리의 위치 정보를 SampleClass클래스에 맞춘 포인터 변수 sampleClass에 할당한다
    // 클래스에 의해 만들어지는 인스턴스는 무조건 포인터 단위로 관리해야만 활용 가능하다.
    SampleClass *sampleClass = [[SampleClass alloc] init];
    
    // sampleClass 포인터 정보가 가르키는 인스턴스 데이터를 찾아가서
    // 데이터에 명시된 sayHello 메소드를 실행하라
    [sampleClass sayHello];
    
    
    return 0;
}

 

What Are Pointers?

그 값이 다른 변수의 주소, 즉 메모리의 위치~
int *ip // pointer to an integer
double *dp // pointer to a double
float *fp // pointer to a float
char *ch // pointer to a character
  • 정수, 부동소수점, 문자 등 모든 포인터 값의 실제 데이터 유형은 메모리 주소를 나ㅏ내는 긴 16진수로 동일합니다.
  • 다른 데이터 유형의 포인터 간의 유일한 차이점은 포ㅇ잉..(응애-)

 

How to use Pointers?

  1. 포인터 변수 정의
  2. 변수의 주소를 포인터에 할당
  3. 포인터 변수에서 사용가능한 주소의 값에 접근한다.

 

NULL Pointers

  • 할당할 정확한 주소가 없는 경우 포인터 변수에 NULL 값을 할당.
  • NULL 포인터는 여러 표준 라이브러리에서 0이라고 약속함.

 

 

7️⃣ String

  • NSString으로 문자열 표현
  • NSString의 하위 클래스 NSMutableString은 문자열 개체를 생성하는 여러 방법 제공
  • 문자열 개체를 만드는 가장 간단한 방법
    • @” … “
NSString *greeting = @"Hello"

 

예시)

#import <Foundation/Foundation.h>

int main() {
	NSSting *greeting = @"Hello";
	NSLog(@"Greeting message: %@\\n", greeting);

	return 0;
}

 

 

 

 


 

 

 

 

✔️ Xcode 둘러보기

간단하게 Xcode를 둘러보면서 프로젝트 만드는 방법을 배웠다. (와! Xcode!)

이 부분은 기록하기 보다는 완전 가볍게 보여주셔서 나도 듣고 감상하는 느낌으로 들었다. 

 

CocoaPods

  • cocoa?
    • 애플이 넥스트사를 인수하고 나서 뷰를 그리는 방법들을 소개로 할 때 기본적인 프로젝트 이름을 ‘coco’라고 했다.
    • 아이폰, 맥용 단위로 프로젝트를 만들면 기본 이름이 cocoa touch…
  • Cocoapods은 Ruby로 만들었다.
  • 주로 Objective-C코드로 되어 있는게 이곳에 많이 남아있다.

 

Swift Package Manager

애플에서 이제 직접 종속성 관리를 지원한다! 나도 코코아팟은 처음 써봤다. 거의 SPM으로 했지.. 완전 편하다.

  Comments,     Trackbacks