iOS

NSString, String 비교 방법 (Objective-C, Swift)

Phililip
728x90

안녕하세요.

 

이번에는 Objective-C와 Swift에서 String 비교하는 방법에 대해 알아볼게요.

 

 


# NSString 비교 (for Objective-C)

NSString 비교 방법은 크게 2가지가 있습니다.

  • ==
  • [NSString isEqualToString:]

 

 

결론부터 말씀드리자면 문자열 자체를 비교할 때는 [NSString isEqualToString:] method를 사용해야 합니다.

 

이렇게요.

NSString *str1 = @"aaa";
NSString *str2 = @"aaa";
NSString *str3 = @"bbb";
NSLog(@"str1 and str2 are %@.", [str1 isEqualToString:str2] ? @"equal" : @"not equal");
NSLog(@"str1 and str3 are %@.", [str1 isEqualToString:str3] ? @"equal" : @"not equal");

// Result
// "str1 and str2 are equal."
// "str1 and str3 are not equal."

 

 

== 연산자는 서로의 주소값이 같은지 비교하는 연산자입니다.

 

그러니까 아래처럼 비교하면 문자열 자체는 같지만 서로 다른 값이라고 하겠...?

NSString *str1 = @"aaa";
NSString *str2 = @"aaa";
NSLog(@"str1 and str2 are %@.", str1 == str2 ? @"equal" : @"not equal");  🤔

// Result
// "str1 and str2 are equal."

 

음????? 😨

 

주소값을 출력해볼게요.

NSString *str1 = @"aaa";
NSString *str2 = @"aaa";
NSLog(@"str1 and str2 are %@.", str1 == str2 ? @"equal" : @"not equal");
NSLog(@"str1 = %@, str1의 주소값 = %p, str1에 저장된 문자열의 주소값 = %p", str1, &str1, str1);
NSLog(@"str2 = %@, str2의 주소값 = %p, str2에 저장된 문자열의 주소값 = %p", str2, &str2, str2);

// Result
// str1 and str2 are equal.
// str1 = aaa, str1의 주소값 = 0x7ff7b4d61a78, str1에 저장된 문자열의 주소값 = 0x10b620b98
// str2 = aaa, str2의 주소값 = 0x7ff7b4d61a70, str2에 저장된 문자열의 주소값 = 0x10b620b98

 

 

아하. 이렇게 설정되어 있었군요.

즉, str1, str2에 저장된 문자열의 주소값이 같으니 == 연산자를 사용했을 때 동일하다고 판단하는 것 같아요.

 

공식 문서는 못 찾겠어서 추측해보자면...

 

컴파일러에서 통일한 타입의 통일한 값을 새로운 변수에 할당하는 경우 메모리에 새롭게 할당하지 않고 이미 존재하고 있는 데이터를 활용하는 것 같아요. 그러니 주소값이 같은 것이죠ㅎㅎ

 

 

 

그럼 이렇게 생각이 들 수 있어요.

 

그럼 == 연산자 사용하면 안됨?? 결국 문자열이 같은지 비교할 때 문제없는 거 아님? 

 

 

하지만.. 이 생각은 버그가 발생할 수 있는 위험한 생각입니다.

 

아래 코드를 한번 볼까요?

NSString *str1 = @"aaa";
NSString *str2 = [NSMutableString stringWithString:@"aaa"];
NSLog(@"str1 and str2 are %@.", str1 == str2 ? @"equal" : @"not equal");  
NSLog(@"str1 = %@, str1의 주소값 = %p, str1에 저장된 문자열의 주소값 = %p", str1, &str1, str1);
NSLog(@"str2 = %@, str2의 주소값 = %p, str2에 저장된 문자열의 주소값 = %p", str2, &str2, str2);

 

str1 하고 str2에 저장된 문자열은 @"aaa"로 동일합니다.

 

== 비교를 했을 때 같다고 나오면 좋겠지만 결과는...

// str1 and str2 are not equal.
// str1 = aaa, str1의 주소값 = 0x7ff7b4a46a78, str1에 저장된 문자열의 주소값 = 0x10b93bb98
// str2 = aaa, str2의 주소값 = 0x7ff7b4a46a70, str2에 저장된 문자열의 주소값 = 0x6000022d4c30

 

 

주소값이 다르게 설정되었어요. 왜 그럴까요??

 

주소값이 같게 설정되는 경우가 어떤 상황일 때라고 했죠?

 

 

컴파일러에서 통일한 타입의 통일한 값을 새로운 변수에 할당하는 경우

 

 

맞습니다. 통일한 타입 & 통일한 값 이어야 합니다.

 

현재 str1에 저장된 문자열은 NSString이지만 str2에 저장된 문자열은 NSMutableString 이기 때문에 서로 타입이 다르고, 

 

그렇기 때문에 새로운 메모리를 할당받았고, 

 

그렇기 때문에 == 연산을 했을 때 서로 다르다고 판단하는 것이죠.

 

 

뭐... 이런저런 이유 때문에라도 NSString 비교할 때는 == 연산자 대신 [NSString isEqualToString:] method를 사용해주시는게 좋을 것 같습니다ㅎㅎ

 

 

 

 

# String 비교 (for Swift)

Swift에서 String은 구조체이고 value type 입니다.

 

 

 

그래서 단순히 == 연산자를 사용해서 문자열 비교가 가능합니다.

var str1 = "aaa"
var str2 = "aaa"

print("\(str1 == str2)")	// true

 

 

추가로.. Swift에서는 reference 비교를 위해 === 연산자가 있길래 String 타입에도 사용해보려고 했는데요.

 

=== 연산자는 reference type 끼리만 사용이 가능하기 때문에 String 타입은 === 연산자를 사용할 수 없었습니다..허헣

var str1 = "aaa"
var str2 = "aaa"

print("\(str1 === str2)")  // Argument type 'String' expected to be an instance of a class or class-constrained type

 

 

 

## 참고

- https://developer.apple.com/documentation/foundation/nsstring

- https://docs.swift.org/swift-book/LanguageGuide/StringsAndCharacters.html

- https://docs.swift.org/swift-book/LanguageGuide/BasicOperators.html#ID70

- https://docs.swift.org/swift-book/LanguageGuide/ClassesAndStructures.html#ID91

 

 

 


 

언어마다 String 비교 방식은 서로 다르고 매우 중요한 부분이기 때문에, 특정 언어를 사용할 때는 꼭 특징을 파악해서 사용하는게 좋을 것 같아요.

(물론 모두 외울 필요는 없겠지만요ㅎㅎ)

 

이번 글은 여기서 마무리.

 

 

 

반응형

'iOS' 카테고리의 다른 글

Moya async API 추가하기  (0) 2023.04.11
앱 이름 현지화(localization)하는 방법  (2) 2023.03.09
Apple Common Scheme List  (0) 2022.08.04
Private Pod 배포 방법  (0) 2022.06.01
SwiftUI <-> UIKit 이벤트 전달 방법  (0) 2022.05.21