함수는 작업을 함께 수행하는 명령문의 그룹입니다.
모든 Objective-C 프로그램에는 main() 이라는 하나의 C 함수 가 있으며 가장 사소한 프로그램은 모두 추가 함수를 정의할 수 있습니다.
코드를 별도의 기능으로 나눌 수 있습니다.
코드를 여러 기능으로 나누는 방법은 사용자에게 달려 있지만 논리적으로 구분은 일반적으로 각 기능이 특정 작업을 수행하도록 합니다.
함수 선언 은 컴파일러에게 함수의 이름, 반환 유형 및 매개변수에 대해 알려줍니다.
함수 정의는 함수의 실제 본문을 제공합니다.
기본적으로 Objective-C에서는 함수를 메서드라고 부릅니다.
Objective-C 기반 프레임워크는 프로그램에서 호출할 수 있는 수많은 기본 제공 메서드를 제공합니다.
예를 들어, 다른 문자열에 문자열을 추가하려면 appendString( ) 메서드를 사용합니다.
메소드는 함수, 서브루틴, 프로시저 등과 같이 다양한 이름으로 알려져 있습니다.
Objective-C 프로그래밍 언어에서 메소드 정의의 일반적인 형식은 다음과 같습니다.
- (return_type) method_name:( argumentType1 )argumentName1
joiningArgument2:( argumentType2 )argumentName2 ...
joiningArgumentn:( argumentTypen )argumentNamen {
body of the function
}
Objective-C 프로그래밍 언어의 메서드 정의는 메서드 헤더 와 메서드 본문 으로 구성 됩니다.
방법의 모든 부분은 다음과 같습니다.
반환 유형 - 메서드는 값을 반환할 수 있습니다. return_type 은 함수가 반환하는 값의 데이터 유형입니다. 일부 메서드는 값을 반환하지 않고 원하는 작업을 수행합니다. 이 경우 return_type 은 키워드 void 입니다.
메서드 이름 - 메서드의 실제 이름입니다. 메서드 이름과 매개 변수 목록은 함께 메서드 서명을 구성합니다.
인수(Argument) - 인수는 자리 표시자와 같습니다. 함수가 호출되면 인수에 값을 전달합니다. 이 값을 실제 매개변수 또는 인수라고 합니다. 매개변수 목록은 메소드의 인수 유형, 순서 및 수를 나타냅니다. 인수는 선택 사항입니다. 즉, 메서드에 인수가 없을 수 있습니다.
결합 인수(Joining Argument) - 결합 인수는 호출하는 동안 읽기 쉽고 명확하게 하기 위한 것입니다.
메서드 본문 - 메서드 본문에는 메서드가 수행하는 작업을 정의하는 명령문의 모음이 포함되어 있습니다.
다음은 max() 라는 메서드의 소스 코드입니다.
이 메서드는 두 개의 매개변수 num1과 num2를 사용하고 두 매개변수 사이의 최대값을 반환합니다.
/* function returning the max between two numbers */
- (int) max:(int) num1 secondNumber:(int) num2 {
/* local variable declaration */
int result;
if (num1 > num2) {
result = num1;
} else {
result = num2;
}
return result;
}
메서드 선언은 컴파일러에게 함수 이름과 메서드를 호출하는 방법을 알려줍니다.
함수의 실제 본문은 별도로 정의할 수 있습니다.
메소드 선언은 다음과 같은 부분으로 구성됩니다.
- (return_type) function_name:( argumentType1 )argumentName1
joiningArgument2:( argumentType2 )argumentName2 ...
joiningArgumentn:( argumentTypen )argumentNamen;
앞서 정의한 함수 max()의 경우 다음은 메서드 선언입니다.
한 소스 파일에서 메서드를 정의하고 다른 파일에서 해당 메서드를 호출할 때 메서드 선언이 필요합니다.
이 경우 함수를 호출하는 파일의 맨 위에 함수를 선언해야 합니다.
-(int) max:(int)num1 andNum2:(int)num2;
Objective-C 메소드를 생성하는 동안 함수가 수행해야 하는 작업에 대한 정의를 제공합니다. 메서드를 사용하려면 정의된 작업을 수행하기 위해 해당 함수를 호출해야 합니다.
프로그램이 함수를 호출하면 프로그램 제어가 호출된 메서드로 전달됩니다. 호출된 메서드는 정의된 작업을 수행하고 반환문이 실행되거나 함수 종료 중괄호에 도달하면 프로그램 제어를 다시 주 프로그램으로 반환합니다.
메서드를 호출하려면 메서드 이름과 함께 필요한 매개 변수를 전달하기만 하면 되고 메서드가 값을 반환하면 반환된 값을 저장할 수 있습니다.
#import <Foundation/Foundation.h>
@interface SampleClass:NSObject
/* method declaration */
- (int)max:(int)num1 andNum2:(int)num2;
@end
@implementation SampleClass
/* method returning the max between two numbers */
- (int)max:(int)num1 andNum2:(int)num2 {
/* local variable declaration */
int result;
if (num1 > num2) {
result = num1;
} else {
result = num2;
}
return result;
}
@end
int main () {
/* local variable definition */
int a = 100;
int b = 200;
int ret;
SampleClass *sampleClass = [[SampleClass alloc]init];
/* calling a method to get max value */
ret = [sampleClass max:a andNum2:b];
NSLog(@"Max value is : %d\n", ret );
return 0;
}
// Max value is : 200
함수가 인수를 사용하려면 인수 값을 허용하는 변수를 선언해야 합니다. 이러한 변수를 함수의 형식 매개변수 라고 합니다.
형식 매개변수는 함수 내부의 다른 지역 변수처럼 작동하며 함수에 들어갈 때 생성되고 종료할 때 소멸됩니다.
함수를 호출하는 동안 인수를 함수에 전달할 수 있는 두 가지 방법이 있습니다.
기본적으로 Objective-C는 값에 의한 호출을 사용 하여 인수를 전달합니다.
일반적으로 이것은 함수 내의 코드가 함수를 호출하는 데 사용되는 인수를 변경할 수 없음을 의미하며, 앞서 언급한 max()함수를 호출하는 동안 동일한 메서드를 사용했습니다.
Objective-C 클래스는 관련 동작과 데이터를 결합하는 개체를 정의합니다.
때로는 메서드 모음이 아니라 단일 작업이나 동작 단위를 나타내는 것이 합리적입니다.
블록은 C, Objective-C 및 C++에 추가된 언어 수준 기능으로, 이를 통해 마치 값인 것처럼 메서드나 함수에 전달할 수 있는 고유한 코드 세그먼트를 만들 수 있습니다.
블록은 NSArray 또는 NSDictionary와 같은 컬렉션에 추가할 수 있음을 의미하는 Objective-C 개체입니다.
또한 엔클로징 범위에서 값을 캡처하여 다른 프로그래밍 언어의 클로저 또는 람다와 유사하게 만드는 기능이 있습니다.
returntype (^blockName)(argumentType);
간단한 블록 구현
returntype (^blockName)(argumentType)= ^{
};
void (^simpleBlock)(void) = ^{
NSLog(@"This is a block”);
}
다음을 사용하여 블록을 호출할 수 있습니다.
simpleBlock();
블록은 메서드 및 함수와 마찬가지로 인수를 사용하고 값을 반환할 수도 있습니다.
다음은 인수와 반환 값이 있는 블록을 구현하고 호출하는 간단한 예입니다.
double (^multiplyTwoValues)(double, double) =
^(double firstValue, double secondValue) {
return firstValue * secondValue;
};
double result = multiplyTwoValues(2,4);
NSLog(@"The result is %f", result);
예제
#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;
}
다음은 블록에서 typedef를 사용하는 간단한 예입니다.
이 예제는 온라인 컴파일러에서 작동하지 않습니다. Xcode를 사용하여 실행하십시오.
#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() {
/* my first program in Objective-C */
SampleClass *sampleClass = [[SampleClass alloc]init];
[sampleClass performActionWithCompletion:^{
NSLog(@"Completion is called to intimate action is performed.");
}];
return 0;
}
// Action Performed
// Completion is called to intimate action is performed.
Objective-C 프로그래밍 언어에서 int, float, bool과 같은 기본 데이터 유형을 객체 형태로 저장하기 위해, Objective-C는 NSNumber로 작업할 수 있는 다양한 방법을 제공하며 중요한 방법은 다음 표에 나열되어 있습니다.
다음은 두 숫자를 곱하고 곱을 반환하는 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;
}
// performed.The product is 105
Objective-C 프로그래밍 언어는 같은 유형의 요소에 대한 고정 크기의 순차적 컬렉션을 저장할 수 있는 배열 이라는 데이터 구조를 제공합니다. 배열은 데이터 모음을 저장하는 데 사용되지만 종종 배열을 같은 유형의 변수 모음으로 생각하는 것이 더 유용합니다.
number0, number1, ..., number99와 같은 개별 변수를 선언하는 대신 숫자와 같은 하나의 배열 변수를 선언하고 숫자[0], 숫자[1], ..., 숫자[99]를 사용하여 표현합니다. 개별 변수. 배열의 특정 요소는 인덱스에 의해 액세스됩니다.
모든 배열은 연속적인 메모리 위치로 구성됩니다. 가장 낮은 주소는 첫 번째 요소에 해당하고 가장 높은 주소는 마지막 요소에 해당합니다.
Objective-C에서 배열을 선언하기 위해 프로그래머는 다음과 같이 배열에 필요한 요소 유형과 요소 수를 지정합니다.
type arrayName [ arraySize ];
이것을 1차원 배열이라고 합니다.
arraySize 는 0보다 큰 정수 상수여야 하고 type 은 유효한 Objective-C 데이터 유형이 될 수 있습니다.
예를 들어, double 유형의 balance 라는 10개 요소 배열을 선언 하려면 다음 명령문을 사용하십시오.
double balance[10];
이제, balance는 최대 10개의 이중 숫자를 보유하기에 충분한 가변 배열입니다.
Objective-C에서 배열을 하나씩 초기화하거나 다음과 같이 단일 명령문을 사용하여 초기화할 수 있습니다.
double balance[5] = {1000.0, 2.0, 3.4, 17.0, 50.0};
이것을 1차원 배열이라고 합니다. 중괄호 { } 사이의 값 수는 대괄호 [ ] 사이의 배열에 대해 선언한 요소 수보다 클 수 없습니다.
다음은 배열의 단일 요소를 할당하는 예입니다.
배열의 크기를 생략하면 초기화를 담을 수 있을 만큼만 큰 배열이 생성됩니다. 따라서 다음과 같이 쓰면 -
double balance[] = {1000.0, 2.0, 3.4, 17.0, 50.0}
이전 예제에서 했던 것과 똑같은 배열을 만들 것입니다.
double balance[] = {1000.0, 2.0, 3.4, 17.0, 50.0};
balance[4] = 50.0;
위의 명령문은 배열의 5번째 요소에 50.0 값을 할당합니다.
4번째 인덱스가 있는 배열은 5번째, 즉 모든 배열이 기본 인덱스라고도 하는 첫 번째 요소의 인덱스로 0을 갖기 때문에 마지막 요소가 됩니다.
다음은 위에서 논의한 동일한 배열의 그림 표현입니다.
배열 이름을 인덱싱하여 요소에 액세스합니다. 이것은 배열 이름 뒤의 대괄호 안에 요소의 인덱스를 배치하여 수행됩니다. 예를 들어 -
double salary = balance[9];
위의 명령문은 배열에서 10번째 요소를 가져와서 값을 급여 변수에 할당합니다. 다음은 위에서 언급한 세 가지 개념(선언, 할당 및 배열 액세스)을 모두 사용하는 예입니다.
#import <Foundation/Foundation.h>
int main () {
int n[ 10 ]; /* n is an array of 10 integers */
int i,j;
/* initialize elements of array n to 0 */
for ( i = 0; i < 10; i++ ) {
n[ i ] = i + 100; /* set element at location i to i + 100 */
}
/* output each array element's value */
for (j = 0; j < 10; j++ ) {
NSLog(@"Element[%d] = %d\n", j, n[j] );
}
return 0;
}
/*
Element[0] = 100
Element[1] = 101
Element[2] = 102
Element[3] = 103
Element[4] = 104
Element[5] = 105
Element[6] = 106
Element[7] = 107
Element[8] = 108
Element[9] = 109
*/
배열은 Objective-C에 중요하며 더 많은 세부 정보가 필요합니다.
Objective-C 프로그래머에게 명확해야 하는 배열과 관련된 몇 가지 중요한 개념은 다음과 같습니다.
일부 Objective-C 프로그래밍 작업은 포인터를 사용하여 더 쉽게 수행되며 동적 메모리 할당과 같은 다른 작업은 포인터를 사용하지 않고 수행할 수 없습니다.
따라서 완벽한 Objective-C 프로그래머가 되기 위해서는 포인터를 배워야 합니다. 간단하고 쉬운 단계로 학습을 시작해 보겠습니다.
아시다시피 모든 변수는 메모리 위치이며 모든 메모리 위치에는 메모리의 주소를 나타내는 앰퍼샌드(&) 연산자를 사용하여 액세스할 수 있는 주소가 정의되어 있습니다.
정의된 변수의 주소를 인쇄하는 다음 예를 고려하십시오.
#import <Foundation/Foundation.h>
int main () {
int var1;
char var2[10];
NSLog(@"Address of var1 variable: %x\n", &var1 );
NSLog(@"Address of var2 variable: %x\n", &var2 );
return 0;
}
// Address of var1 variable: 1c0843fc
// Address of var2 variable: 1c0843f0
포인터는 그 값이 다른 변수의 주소, 즉 메모리 위치의 직접 주소인 변수입니다.
다른 변수나 상수와 마찬가지로 포인터를 사용하여 변수 주소를 저장하려면 먼저 포인터를 선언해야 합니다.
포인터 변수 선언의 일반적인 형식은 다음과 같습니다.
type *var-name;
여기서 type 은 포인터의 기본 유형입니다.
유효한 Objective-C 데이터 유형이어야 하며 var-name 은 포인터 변수의 이름입니다.
포인터를 선언하는 데 사용한 별표 *는 곱셈에 사용하는 것과 동일한 별표입니다.
그러나 이 문에서 별표는 변수를 포인터로 지정하는 데 사용됩니다.
다음은 유효한 포인터 선언입니다.
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진수로 동일합니다.
다른 데이터 유형의 포인터 간의 유일한 차이점은 포인터가 가리키는 변수 또는 상수의 데이터 유형입니다.
포인터를 사용하여 매우 자주 수행할 중요한 작업이 거의 없습니다.
(a) 포인터 변수를 정의하고,
(b) 변수의 주소를 포인터에 할당하고,
(c) 마지막으로 포인터 변수에서 사용 가능한 주소의 값에 액세스합니다.
이것은 피연산자가 지정한 주소에 있는 변수의 값을 반환하는 단항 연산자 * 를 사용하여 수행됩니다.
다음 예제에서는 이러한 작업을 사용합니다.
#import <Foundation/Foundation.h>
int main () {
int var = 20; /* actual variable declaration */
int *ip; /* pointer variable declaration */
ip = &var; /* store address of var in pointer variable*/
NSLog(@"Address of var variable: %x\n", &var );
/* address stored in pointer variable */
NSLog(@"Address stored in ip variable: %x\n", ip );
/* access the value using the pointer */
NSLog(@"Value of *ip variable: %d\n", *ip )
return 0;
}
// Address of var variable: 337ed41c
// Address stored in ip variable: 337ed41c
// Value of *ip variable: 20
할당할 정확한 주소가 없는 경우 포인터 변수에 NULL 값을 할당하는 것이 항상 좋은 방법입니다.
이는 변수 선언 시 수행됩니다. NULL이 할당된 포인터를 널 포인터라고 합니다.
NULL 포인터는 여러 표준 라이브러리에서 정의된 값이 0인 상수입니다. 다음 프로그램을 고려하십시오 -
#import <Foundation/Foundation.h>
int main () {
int *ptr = NULL;
NSLog(@"The value of ptr is : %x\n", ptr );
return 0;
}
// The value of ptr is : 0
대부분의 운영 체제에서 프로그램은 운영 체제에 의해 예약된 메모리이므로 주소 0의 메모리에 액세스할 수 없습니다.
그러나 메모리 주소 0은 특별한 의미가 있습니다.
포인터가 액세스 가능한 메모리 위치를 가리키도록 의도되지 않았음을 나타냅니다.
그러나 관례에 따라 포인터에 null(영) 값이 포함되어 있으면 아무 것도 가리키지 않는 것으로 간주됩니다.
널 포인터를 확인하려면 다음과 같이 if 문을 사용할 수 있습니다.
if(ptr) /* succeeds if p is not null */
if(!ptr) /* succeeds if p is null */
포인터는 쉽지만 많은 개념을 가지고 있으며 Objective-C 프로그래밍에 매우 중요합니다.
Objective-C 프로그래머에게 명확해야 하는 몇 가지 중요한 포인터 개념이 다음과 같습니다.
Objective-C 프로그래밍 언어의 문자열은 NSString을 사용하여 표현되며 하위 클래스 NSMutableString은 문자열 개체를 생성하는 여러 방법을 제공합니다.
문자열 개체를 만드는 가장 간단한 방법은 Objective-C @"..." 구문을 사용하는 것입니다.
NSString *greeting = @"Hello";
#import <Foundation/Foundation.h>
int main () {
NSString *greeting = @"Hello";
NSLog(@"Greeting message: %@\n", greeting );
return 0;
}
// Greeting message: Hello
Objective-C는 문자열 조작을 위한 광범위한 방법을 지원합니다.
#import <Foundation/Foundation.h>
int main () {
NSString *str1 = @"Hello";
NSString *str2 = @"World";
NSString *str3;
int len ;
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
/* uppercase string */
str3 = [str2 uppercaseString];
NSLog(@"Uppercase String : %@\n", str3 );
/* concatenates str1 and str2 */
str3 = [str1 stringByAppendingFormat:@"World"];
NSLog(@"Concatenated string: %@\n", str3 );
/* total length of str3 after concatenation */
len = [str3 length];
NSLog(@"Length of Str3 : %d\n", len );
/* InitWithFormat */
str3 = [[NSString alloc] initWithFormat:@"%@ %@",str1,str2];
NSLog(@"Using initWithFormat: %@\n", str3 );
[pool drain];
return 0;
}
// Uppercase String : WORLD
// Concatenated string: HelloWorld
// Length of Str3 : 10
// Using initWithFormat: Hello World