TIL/Swift 내용 정리

Swift Deep Dive: What are 'Any' and 'AnyObject'?

여의도사노비 2023. 2. 20. 17:31
728x90

Any와 AnyObject는 뭘까?

🤖 In Swift, 'Any' and 'AnyObject' are used to represent values of any type or any object type, respectively.

Swift에서 'Any'와 'AnyObject'는 각각 모든 타입 또는 모든 객체 타입의 값을 나타내는 데 사용됩니다.

 

🙋🏻‍♂️ 굉장히 간결한 정의인데, 무슨 느낌인지는 알 것 같다. Swift는 값의 타입에 대한 선언이 명확히 이루어져야하는 언어인데, Any 혹은 AnyObject를 사용하면 다양한 타입을 전부 사용가능하다는 뜻으로 보인다. 애플 다큐먼트를 기반으로 좀 더 알아보면..

- Swift는 불특정한 타입을 위해 두 가지 특이한 타입을 제공하는데 그것이 Any, AnyObject이다.

- Any는 함수 타입을 포함한 모든 타입의 인스턴스를 나타낼 수 있다.

- AnyObject는 클래스 타입의 인스턴스를 나타낼 수 있다.

- 타입이 명백한 경우에는 명확한 타입을 적시하는 것이 좋지만 그렇지 못할 경우에 사용하라!

 

조금 더 디테일하게 비교해볼까? (+코드)

🤖 Any is a protocol that can be used to represent an instance of any type at all, including function types. It is similar to the void* pointer in C and Object class in Java. You can use Any to work with values of unknown type, such as when you are writing generic code.

'Any'는 함수 타입을 포함하여 모든 유형의 인스턴스를 나타내는 데 사용할 수 있는 프로토콜입니다. C의 보이드* 포인터, JAVA의 오브젝트 클래스와 비슷하다. 'Any'는 일반 코드를 작성할 때와 같이 알 수 없는 타입의 값으로 작업하는 데 사용할 수 있습니다.

 

🤖 For example, you can create an array of type [Any] to store values of any type:

예를 들어 모든 타입의 값을 저장하는 [Any]타입의 배열을 만들 수 있습니다 .

var someArray: [Any] = [1, "two", 3.0, true]

 

🙋🏻‍♂️ C나 JAVA는 잘 모르지만... 결국 예시를 보면 무슨 느낌인지 딱 알 수 있다. Int 타입인 1, String 타입인 "two", Double 타입의 3.0, Boolean 타입의 true. 이 모든 값들은 전부 타입이 다르다! Swift는 타입에 민감하기 때문에 Int 혹은 String 등으로 정해진 타입의 배열은 이 모든 원소를 받아들일 수 없다. 따라서 Any라는 타입을 설정함으로써 어떤 타입이라도 전부 받아들일 수 있도록 하는 것이 Any가 존재하는 이유이다.

 

🤖 AnyObject, on the other hand, is a protocol that represents any instance of a class type. It can be used to work with objects of unknown class type.

반면에 AnyObject는 클래스 유형의 인스턴스를 나타내는 프로토콜입니다. 알 수 없는 클래스 유형의 개체에 대해 작업하는 데 사용할 수 있습니다.

 

🤖 For example, you can use AnyObject to define a function parameter that can take any object:

예를들어 AnyObject를 사용하여 모든 객체를 취할 수 있는 함수 매개변수를 정의할 수 있습니다.

func doSomething(withObject object: AnyObject) {
    // do something with the object
}

 

🙋🏻‍♂️ Any가 말 그대로 어떤 타입이든 전부 흡수한다고 치면... AnyObject는 클래스의 객체만 사용해야한다. AnyObject를 사용해서 Int, String 등의 Struct의 타입을 사용하면 오류가 난다!

 

AnyObject가 뭔지는 알겠는데... 그럼 언제, 왜 사용할까?

🤖  AnyObject를 사용하는 예시 중 하나는 Objective-C와의 호환성 때문에 필요할 수 있습니다. Objective-C는 모든 객체를 id 타입으로 다루며, Objective-C와 상호작용해야 하는 경우 AnyObject를 사용하여 Swift 객체를 Objective-C의 id 타입으로 변환할 수 있습니다.

 

예를 들어, Objective-C로 작성된 라이브러리를 사용하는 경우, Swift 코드에서 Objective-C 객체를 사용해야 할 때가 있습니다. 이 경우, Swift에서는 AnyObject를 사용하여 Objective-C 객체를 다룹니다.

import UIKit

let view: AnyObject = UIView()

위의 예시에서, view는 UIView 인스턴스이며, AnyObject 타입으로 선언되어 있습니다. 이렇게 하면 Objective-C와의 호환성을 유지하면서 Swift에서 Objective-C 객체를 다룰 수 있습니다.

 

🙋🏻‍♂️ 예시만 보면 이해는 가는데... 오히려 id타입이라는 부분이 하나도 이해가 가지 않았다..! Swift로 iOS를 시작한 나에게 Obj-C란 알아보기도 전에 난해하게 느껴지는 키워드이다. 그래서 id가 무엇일까 찾아보았더니 "id는 C언어의 포인터 개념, void*의 역할을 한다."라는 글들이 많았다. 그리고 C언어에서의 포인터란, 메모리의 주소값을 저장하는 변수라고 한다. 즉 위의 예시는 Obj-C 환경에서 만들어진 클래스 객체인 UIView를 AnyObject를 활용해서 Swift와 Obj-C간에 타입을 맞추어주는 역할은 한다고 보면 될 것 같다.

 

Objective-C를 적용한 다른 예시도 보자!

import Foundation

class MyClass: NSObject {
    @objc func doSomething() {
        print("Hello, world!")
    }
}

let myObject: AnyObject = MyClass()

if let myClassObject = myObject as? MyClass {
    myClassObject.perform(#selector(MyClass.doSomething))
}

🤖 In this example, we define a class called MyClass that inherits from NSObject and has a method called doSomething(). We annotate this method with @objc to expose it to Objective-C code.

We create an instance of MyClass and assign it to a variable called myObject, which is declared to be of type AnyObject. We then use optional binding to check if myObject can be cast to MyClass. If it can, we use the perform method on myClassObject to call the doSomething() method.

위 코드에서는 NSObject에서 상속하고 doSomething()이라는 메서드가 있는 MyClass를 정의합니다. 그리고 Objective-C 코드를 사용하기 위해 이 메서드에 @objc 주석을 추가합니다.

MyClass의 인스턴스를 생성하고 myObject라는 변수에 할당합니다. 이 변수는 AnyObject유형으로 선언됩니다. 그런 다음 Optional Binding을 사용하여 myObject를 MyClass로 캐스팅할 수 있는지 확인합니다.

 

This example demonstrates how we can use AnyObject to work with Objective-C code and how we can use the perform method to invoke methods on an object at runtime.

이 예제는 AnyObject를 사용하여 Objective-C 코드로 작업하는 방법을 보여줍니다.

 

🙋🏻‍♂️ 이 예시는 결국 NSObject(objc) 타입의 클래스도 AnyObject를 활용하면 사용할 수 있다는 것을 보여준다. 아직 Foundation이라던지 UIKit이라던지 많은 프레임워크 속에 objc의 히스토리가 남아있기 때문에 개발을 하다 보면 더더욱 많이 사용하게 될 것 같다. 이 예시에 나온 perform 메서드 관련된 이야기도 있지만... perform 메서드를 찾아보니 이것 또한 하나의 블로깅 주제가 될 정도라 그건 패스하고 넘어간다.. ㅎㅎ 

 

간단하게 정리하자면

🙋🏻‍♂️ AnyObject란

  • 프로토콜로 정의되어 있습니다.
  • 클래스 타입의 인스턴스(객체)를 나타내는 타입입니다.
  • 컴파일 시간에 개체의 특정 클래스를 알지 못하거나 특정 프로토콜을 준수하는 개체로 작업하려는 경우에 사용할 수 있는 타입입니다.
  • Objective-C 코드와 상호 작용하는 데 사용할 수 있습니다.