퍼스트 클래스 함수를 지원하는 언어의 퍼스트 클래스 함수를 사용하면 다른 개체나 값과 마찬가지로 함수 및 메서드를 사용할 수 있습니다. 인수로 전달하거나 속성에 저장하거나 다른 함수에서 반환 할 수 있습니다. 순서 단어에서 언어는 기능을”일류 시민”으로 취급합니다.

스위프트는 거의 기능을 처리하는이 방법을 지원하는 최초의 언어이지만,그것은 일반적으로 당신이 자바 스크립트 나 루아 같은보다 역동적 인 언어로 볼 수있는 기능입니다. 그래서 스위프트의 강력한 정적 유형 시스템과 일류 함수를 결합하는 것은 매우 흥미로운 조합이되어 우리가 꽤 창조적 인 일을 할 수있게 해줍니다.

이번 주,스위프트에서 퍼스트 클래스 함수를 사용할 수있는 몇 가지 다른 방법을 살펴 보겠습니다!

인스타버그:인스타버그가 각 버그 리포트에 자동으로 첨부하는 상세한 스택 추적,네트워크 로그 및 사용자 인터페이스 이벤트를 사용하여 버그,충돌 및 기타 문제를 훨씬 빠르게 해결합니다. *********** 무료로 그것을 시도하고 코드의 단지 한 줄과 통합 할 수 있습니다.

인수로 함수 전달

기본부터 시작하겠습니다. 함수는 값으로 사용될 수 있기 때문에,우리가 인수로 전달할 수 있다는 것을 의미한다. 예를 들어 뷰에 하위 뷰 배열을 추가하려고 한다고 가정해 보겠습니다. 일반적으로 다음과 같이 할 수 있습니다:

let subviews = subviews.forEach { subview in view.addSubview(subview)}

위의 코드는 작동하며 아무 문제가 없습니다. 그러나 우리가 일등 함수를 활용한다면,우리는 실제로 그 자세한 내용을 꽤 많이 줄일 수 있습니다.

우리가 할 수있는 일은addSubview메소드를 유형(UIView) -> Void의 폐쇄로 취급하는 것입니다(추가 할 뷰를 허용하고 아무 것도 반환하지 않기 때문에). 이것은forEach이 허용하는 인수 유형과 완벽하게 일치합니다((Element) -> Void유형의 폐쇄,이 경우Element유형은UIView입니다). 그 결과 다음과 같이view.addSubviewforEach호출에 대한 인수로 직접 전달할 수 있습니다:

subviews.forEach(view.addSubview)

그건 꽤 멋지다! 그러나 이와 같이 인스턴스 메서드를 클로저로 사용하는 경우 클로저를 유지하는 한 인스턴스를 자동으로 유지한다는 점을 명심해야 합니다. 위와 같이 비 이스케이프 클로저 인수로 함수를 전달할 때 이것은 전혀 문제가되지 않지만 클로저를 이스케이프하기 위해서는 사이클 유지를 피하기 위해 알아야 할 것입니다.

이스케이프 처리 대 이스케이프 처리되지 않은 클로저 인수 및 캡처에 대한 자세한 내용은”스위프트 클로저에서 객체 캡처”를 확인하십시오.

이니셜라이저를 인수로 전달

멋진 점은 스위프트에서 퍼스트 클래스 함수로 사용할 수 있는 함수와 메서드뿐 아니라 이니셜라이저도 이 방법으로 사용할 수 있다는 것입니다.

예를 들어,이미지 뷰를 만들 이미지 배열이 있고 이러한 이미지 뷰를 각각 스택 뷰에 추가하려고 한다고 가정해 보겠습니다. 퍼스트 클래스 함수를 사용하여map의 간단한 체인을 사용하여 위의 모든 것을 달성 할 수 있습니다.forEach:

images.map(UIImageView.init) .forEach(stackView.addArrangedSubview)

이 방법으로 코드를 구조화하는 것에 대해 내가 좋아하는 것은 그것이 매우 선언적이된다는 것입니다. 중첩 된for루프 대신 우리는 단순히 결과가 원하는 것을 선언합니다. 물론 선언적,소형 코드 및 가독성 사이에 균형을 맞출 수 있지만 위와 같은 간단한 작업을 위해 퍼스트 클래스 함수를 활용하는 것이 매우 좋을 수 있다고 생각합니다.

“함수를 사용한 간단한 신속한 종속성 주입”및”신속한 단위 테스트에서 시간 이동”에서 이니셜 라이저를 클로저로 전달하는 데 대한 더 많은 예제와 사용 사례를 찾을 수 있습니다.

인스턴스 메소드 참조 작성

퍼스트 클래스 함수의 놀라운 세계로 조금 더 깊이 들어가 보겠습니다. 가장 긴 시간 동안 나를 당혹스럽게 한 것은 정적 메소드를 호출하고 싶을 때 인스턴스 메소드 자동 완성 제안을 받았다는 사실이었습니다. 내가 무슨 뜻인지 확인하기 위해 엑스 코드에UIView.를 입력 해보십시오,당신은 제안으로 모든 인스턴스 방법을 얻을 수 있습니다.

처음에 나는 이것이 엑스 코드 버그라고 생각했지만,나는 그것을 조사하기로 결정했다. 형식에 있는 각 인스턴스 메서드에 대해 인스턴스를 인수로 전달하여 해당 인스턴스 메서드를 클로저로 검색할 수 있는 해당 정적 메서드가 있습니다.

예를 들어 다음을 사용하여 지정된UIView인스턴스에 대한removeFromSuperview메서드에 대한 참조를 검색할 수 있습니다:

let closure = UIView.removeFromSuperview(view)

위의 클로저를 호출하는 것은view.removeFromSuperview()을 호출하는 것과 정확히 동일 할 것입니다. 이 기능을 사용하면 실제로 꽤 멋진 결과로 이어질 수있는 몇 가지 시나리오를 살펴 보자.

애플의 프레임 워크 중 하나가이 기능을 사용하는 한 가지 방법은 리눅스에서 엑스씨 테스트를 사용하여 테스트를 실행하는 것입니다. 이 프로그램은 자바 바이트코드 프로그램의 갯수를 카운트하고,스크립트의 메인 형식을 합계냅니다,그리고 확인되지 않은 실행 텍스트 파일을 찾습니다.. 그래서 테스트를 실행하기 위해 약간의 상용구를 작성해야 합니다.

먼저 테스트 이름과 실행할 실제 메서드 간의 매핑을 포함하는 정적allTests사전을 선언해야 합니다.

그런 다음 위의 사전을XCTMain함수에 전달하여 테스트를 실행합니다:

XCTMain()

후드,이 여전히 실행 인스턴스 메소드를 생성하는 프레임 워크를 활성화하면서 단순히 정적 컨텍스트에서 이름으로 함수를 참조 할 수 있도록 정적 등가를 사용하여 인스턴스 메소드를 추출 할 수있는 기능을 사용하고 있습니다. 꽤 영리한!

시퀀스의 각 요소에 인스턴스 메서드 호출

이 기능을 사용하여 직접 스핀을 만들어 보겠습니다. 다른 객체의 인스턴스 메소드를forEach에 대한 인수로 전달할 수 있었던 것처럼 시퀀스의 모든 요소가 수행 할 인스턴스 메소드를 전달할 수 있다면 멋지지 않을까요?

예를 들어,수퍼 뷰에서 제거 할 하위 뷰 배열이 있다고 가정 해 봅시다. 이 작업을 수행하는 대신:

for view in views { view.removeFromSuperview()}

우리가 대신 이것을 할 수 있다면 멋지지 않을까요:

views.forEach(UIView.removeFromSuperview)

좋은 소식은 우리가 할 수있는 것은Sequence에서 이러한 정적으로 참조 된 인스턴스 메소드 중 하나를 허용하는 작은 확장을 만드는 것입니다. 그들은 함수를 생성하는 함수이기 때문에(함수 예외! 그래서 우리의 확장을 위해 우리는 그러한 유형의 폐쇄를 받아들이는forEach과부하를 만들 수 있습니다:

이제 모든 시퀀스의 각 멤버에서 인스턴스 메소드를 쉽게 호출 할 수 있습니다! 목표없이 목표/행동 구현-씨

한 가지 예를 더 살펴 보겠습니다. 버튼 클릭 관찰부터 제스처에 대한 응답에 이르기까지 모든 것에 대해 대상/동작 패턴이 매우 일반적입니다. 나는 개인적으로 우리가 이전에 논의한 유지 사이클 문제(인스턴스 메소드를 클로저로 참조 할 때)에 대해 걱정할 필요없이 인스턴스 메소드를 콜백으로 쉽게 사용할 수 있기 때문에이 패턴을 정말 좋아합니다.따라서@objc을 사용하여 개인 작업 메서드에 주석을 달아야 합니다. 사용자 지정 뷰 중 하나에 대상/동작 패턴을 추가하려고 한다고 가정해 보겠습니다. 즉,많은 일처럼 들릴 수도 있고 일을 몹시 복잡하게 만들 것입니다,하지만 최고 수준의 기능 덕분에-그것은 매우 간단합니다! 6515>형식알리아를 지정된 형식 및 입력에 대한 인스턴스 메서드를 반환하는 정적 함수로 정의하기 시작합니다.:

typealias Action<Type, Input> = (Type) -> (Input) -> Void

다음으로,우리의 견해를 만들어 봅시다. 사용자가 그리기 앱에서 색상을 선택하고 대상&작업을 추가하는 방법을 추가할 수 있는ColorPicker를 만듭니다. 우리는 모든 관찰을 클로저로 추적 할 것이고 클로저가 실행될 때마다 주어진 대상에 대한 인스턴스 메소드를 생성하고 실행합니다.

멋진 점은 우리가 실제로 퍼스트 클래스 함수를 더 많이 사용할 수 있다는 것입니다. 인스턴스 메서드를 생성하고 한 번에 호출할 수 있습니다.:

observations.append { view in target.map(action)?(view)}

마지막으로,ColorPicker를 나타내는CanvasViewController에서 새로운 목표/액션을 사용하겠습니다. UIButton또는UIGestureRecognizer에 타겟&액션을 추가하는 것처럼 뷰 컨트롤러 자체와 인스턴스 메소드를 간단히 전달할 수 있습니다.

이 스폰서를 확인하여 선델의 스위프트 지원:

인스타버그:인스타버그가 각 버그 리포트에 자동으로 첨부하는 상세한 스택 추적,네트워크 로그 및 사용자 인터페이스 이벤트를 사용하여 버그,충돌 및 기타 문제를 훨씬 빠르게 해결합니다. *********** 무료로 그것을 시도하고 코드의 단지 한 줄과 통합 할 수 있습니다.

결론

퍼스트 클래스 기능은 매우 강력한 기능입니다. 훨씬 더 역동적인 방식으로 함수와 메서드를 사용할 수 있게 됨으로써 우리는 꽤 흥미로운 결과를 얻을 수 있습니다.

그러나 벤 삼촌의 유명한 말로,큰 힘으로 큰 책임이 온다. 이러한 종류의 기능과 작동 방식에 대해 배우는 것이 매우 유용하다고 생각하지만,사용할 때 약간의 구속을하는 것도 중요합니다. 우리의 목표는 항상 멋지고 사용하기 쉬운 아피스를 만들고 읽기 쉬운 코드를 작성하는 것입니다&유지 관리. 퍼스트 클래스 함수는 확실히 우리가 그 목표를 달성하는 데 도움이 될 수 있지만 너무 멀리 가져 가면 정반대로 이어질 수 있습니다. 언제나처럼,내 추천은 실험하는 것입니다,이러한 기능을 시도하고 그들이 당신의 자신의 코드에서 사용할 수있는 경우 어떻게 자신을 참조하십시오.

답글 남기기

이메일 주소는 공개되지 않습니다.