
XMARTLABS에 의해 ❤️로 제작되었습니다. 이것은 Swift에서 Xlform의 재창조입니다.
简体中文
![]() | ![]() | ![]() |
|---|
자세한 내용은 Eureka를 소개하는 블로그 게시물을 참조하십시오.
예제 프로젝트를 복제하고 실행하여 대부분의 유레카 기능의 예를 볼 수 있습니다.
![]() | ![]() |
|---|
FormViewController 확장하면 form 변수에 섹션과 행을 추가 할 수 있습니다.
import Eureka
class MyFormViewController : FormViewController {
override func viewDidLoad ( ) {
super . viewDidLoad ( )
form +++ Section ( " Section1 " )
<<< TextRow ( ) { row in
row . title = " Text Row "
row . placeholder = " Enter text here "
}
<<< PhoneRow ( ) {
$0 . title = " Phone Row "
$0 . placeholder = " And numbers here "
}
+++ Section ( " Section2 " )
<<< DateRow ( ) {
$0 . title = " Date Row "
$0 . value = Date ( timeIntervalSinceReferenceDate : 0 )
}
}
}예에서 표준 행이있는 두 섹션을 만듭니다. 결과는 다음과 같습니다.

FormViewController 에서 확장하지 않고도 form 속성을 직접 설정하여 양식을 만들 수 있지만이 방법은 일반적으로 더 편리합니다.
이 동작을 변경하려면 컨트롤러의 내비게이션 옵션을 설정해야합니다. FormViewController 에는 열거 인 navigationOptions 변수가 있으며 다음 값 중 하나 이상을 가질 수 있습니다.
canBecomeFirstResponder() 로 False를 반환하는 행을 건너 뛰어야하는 경우 기본값이 enabled & skipCanNotBecomeFirstResponderRow 됩니다
오프 스크린 행에 부드러운 스크롤을 가능하게하려면 animateScroll 속성을 통해 활성화하십시오. 기본적으로, FormViewController 사용자가 키보드 내비게이션 액세서리에서 다음 행이 화면에서 떨어질 때를 포함하여 다음 또는 이전 버튼을 누르면 행으로 즉시 점프합니다.
내비게이션 이벤트 후 키보드와 강조 표시된 행 사이의 공간 양을 설정하려면 rowKeyboardSpacing 속성을 설정하십시오. 기본적으로 양식 스크롤이 오프 스크린보기로 스크롤하면 키보드 상단과 행 하단 사이에 공간이 남지 않습니다.
class MyFormViewController : FormViewController {
override func viewDidLoad ( ) {
super . viewDidLoad ( )
form = ...
// Enables the navigation accessory and stops navigation when a disabled row is encountered
navigationOptions = RowNavigationOptions . Enabled . union ( . StopDisabledRow )
// Enables smooth scrolling on navigation to off-screen rows
animateScroll = true
// Leaves 20pt of space between the keyboard and the highlighted row after scrolling to an off screen row
rowKeyboardSpacing = 20
}
} 전체 내비게이션 액세서리보기를 변경하려면 FormViewController 의 서브 클래스에서 navigationAccessoryView 변수를 무시해야합니다.
Row 객체는 특정 유형의 값을 보유합니다. 예를 들어, SwitchRow Bool 값을 보유하고 TextRow String 값을 보유합니다.
// Get the value of a single row
let row : TextRow ? = form . rowBy ( tag : " MyRowTag " )
let value = row . value
// Get the value of all rows which have a Tag assigned
// The dictionary contains the 'rowTag':value pairs.
let valuesDictionary = form . values ( )Eureka에는 양식을 쉽게 만들 수있는 맞춤형 운영자가 포함되어 있습니다.
form +++ Section ( )
// Chain it to add multiple Sections
form +++ Section ( " First Section " ) +++ Section ( " Another Section " )
// Or use it with rows and get a blank section for free
form +++ TextRow ( )
+++ TextRow ( ) // Each row will be on a separate sectionform +++ Section ( )
<<< TextRow ( )
<<< DateRow ( )
// Or implicitly create the Section
form +++ TextRow ( )
<<< DateRow ( ) // Append Sections into a Form
form += [ Section ( " A " ) , Section ( " B " ) , Section ( " C " ) ]
// Append Rows into a Section
section += [ TextRow ( ) , DateRow ( ) ]Eureka에는 결과 제작자가 포함되어있어 형태를 쉽게 만들 수 있습니다.
// Section + Section
form = ( Section ( " A " ) +++ {
URLRow ( " UrlRow_f1 " ) { $0 . title = " Url " }
if something {
TwitterRow ( " TwitterRow_f2 " ) { $0 . title = " Twitter " }
} else {
TwitterRow ( " TwitterRow_f1 " ) { $0 . title = " Twitter " }
}
AccountRow ( " AccountRow_f1 " ) { $0 . title = " Account " }
} )
// Form + Section
form +++ {
if something {
PhoneRow ( " PhoneRow_f1 " ) { $0 . title = " Phone " }
} else {
PhoneRow ( " PhoneRow_f2 " ) { $0 . title = " Phone " }
}
PasswordRow ( " PasswordRow_f1 " ) { $0 . title = " Password " }
} @ FormBuilder
var form : Form {
Section ( " Section A " ) { section in
section . tag = " Section_A "
}
if true {
Section ( " Section B " ) { section in
section . tag = " Section_B "
}
}
NameRow ( " NameRow_f1 " ) { $0 . title = " Name " }
}유레카에는 콜백을 포함하여 행의 외관과 동작을 변경합니다.
Row Eureka가 사용하는 추상화이며 값을 보유하고 뷰 Cell 포함합니다. Cell 뷰를 관리하고 UITableViewCell 서브 클래스합니다.
예는 다음과 같습니다.
let row = SwitchRow ( " SwitchRow " ) { row in // initializer
row . title = " The title "
} . onChange { row in
row . title = ( row . value ?? false ) ? " The title expands when on " : " The title "
row . updateCell ( )
} . cellSetup { cell , row in
cell . backgroundColor = . lightGray
} . cellUpdate { cell , row in
cell . textLabel ? . font = . italicSystemFont ( ofSize : 18.0 )
} 
onchange ()
행 값이 변경 될 때 호출됩니다. 여기서 일부 매개 변수를 조정하거나 다른 행이 나타나거나 사라지게하는 데 관심이있을 수 있습니다.
OnCellSelection ()
사용자가 행을 탭 할 때마다 호출되어 선택됩니다. 이것은 또한 비활성화 된 행을 요구할 것이므로 guard !row.isDisabled else { return } 과 같은이 콜백 내부에서 코드를 시작해야합니다.
CellSetup ()
셀이 처음 구성 될 때만 한 번만 호출됩니다. 여기에서 영구 설정을 설정하십시오.
cellupdate ()
셀이 화면에 나타날 때마다 호출됩니다. CellSetup ()에 없을 수있는 변수를 사용하여 여기에서 모양을 변경할 수 있습니다.
OncellHighlightChanged ()
셀이나 서브 뷰가 첫 번째 응답자가되거나 사임 할 때마다 호출됩니다.
onrowvalidationChanged ()
행과 관련된 유효성 검사 오류가 변경 될 때마다 호출됩니다.
ONEXPANDINLINEROW ()
인라인 행을 확장하기 전에 호출되었습니다. InlineRowType 프로토콜을 준수하는 행에 적용됩니다.
OncollapseinLinerow ()
인라인 줄을 무너지기 전에 호출되었습니다. InlineRowType 프로토콜을 준수하는 행에 적용됩니다.
onpresent ()
다른 뷰 컨트롤러를 제시하기 직전에 행으로 호출됩니다. PresenterRowType 프로토콜을 준수하는 행에 적용됩니다. 제시된 컨트롤러를 설정하는 데 사용하십시오.
Section 의 헤더 또는 바닥 글로 제목 String 또는 사용자 정의 View 설정할 수 있습니다.
Section ( " Title " )
Section ( header : " Title " , footer : " Footer Title " )
Section ( footer : " Footer Title " ) .xib 파일에서 사용자 정의보기를 사용할 수 있습니다.
Section ( ) { section in
var header = HeaderFooterView < MyHeaderNibFile > ( . nibFile ( name : " MyHeaderNibFile " , bundle : nil ) )
// Will be called every time the header appears on screen
header . onSetupView = { view , _ in
// Commonly used to setup texts inside the view
// Don't change the view hierarchy or size here!
}
section . header = header
} 또는 프로그래밍 방식으로 만들어진 사용자 정의 UIView
Section ( ) { section in
var header = HeaderFooterView < MyCustomUIView > ( . class )
header . height = { 100 }
header . onSetupView = { view , _ in
view . backgroundColor = . red
}
section . header = header
}또는 콜백으로보기를 구축하십시오
Section ( ) { section in
section . header = {
var header = HeaderFooterView < UIView > ( . callback ( {
let view = UIView ( frame : CGRect ( x : 0 , y : 0 , width : 100 , height : 100 ) )
view . backgroundColor = . red
return view
} ) )
header . height = { 100 }
return header
} ( )
}
이 경우 전체 섹션을 숨기고 표시합니다.
이를 달성하기 위해 각 행에는 함수 또는 NSPredicate 사용하여 설정할 수있는 옵션 유형 Condition 의 hidden 변수가 있습니다.
Condition 의 function 사례 사용 :
Condition . function ( [ String ] , ( Form ) - > Bool ) 전달할 String 배열에는이 행에 의존하는 행의 태그가 포함되어야합니다. 해당 행의 값이 변경 될 때마다 함수가 재평가됩니다. 그런 다음 함수는 Form 취하고 행이 숨겨져야하는지 여부를 나타내는 Bool 반환합니다. 이것은 할 수있는 일에 대한 명시 적 제한이 없기 때문에 hidden 속성을 설정하는 가장 강력한 방법입니다.
form +++ Section ( )
<<< SwitchRow ( " switchRowTag " ) {
$0 . title = " Show message "
}
<<< LabelRow ( ) {
$0 . hidden = Condition . function ( [ " switchRowTag " ] , { form in
return ! ( ( form . rowBy ( tag : " switchRowTag " ) as? SwitchRow ) ? . value ?? false )
} )
$0 . title = " Switch is on! "
} 
public enum Condition {
case function ( [ String ] , ( Form ) -> Bool )
case predicate ( NSPredicate )
} hidden 변수는 NSpredicate로 설정할 수도 있습니다. 술어 문자열에서는 태그로 다른 행의 값을 참조하여 행을 숨겨야하는지 또는 보이는지 확인할 수 있습니다. 이것은 술어가 검사 해야하는 행의 값이 nsobjects 인 경우에만 작동합니다 (문자열과 int는 OBJC 대응 물에 연결되어 있지만 열거는 작동하지 않습니다). 그런 다음 더 제한된 경우 Predicates를 사용하는 것이 유용 할 수있는 이유는 무엇입니까? 글쎄, 그들은 기능보다 훨씬 단순하고 짧고 읽기 쉬울 수 있습니다. 이 예를보십시오 :
$0 . hidden = Condition . predicate ( NSPredicate ( format : " $switchTag == false " ) ) 그리고 우리는 Condition ExpressibleByStringLiteral 준수하기 때문에 더 짧게 쓸 수 있습니다.
$0 . hidden = " $switchTag == false "참고 : '$ switchtag'대신 태그가 '스위치 테그'인 행의 값을 대체합니다.
이 모든 것이 작동하기 위해서는 태그가 식별하므로 모든 관련 행에는 태그가 있어야합니다 .
우리는 또한 다음을 통해 행을 숨길 수 있습니다.
$0 . hidden = true Condition 으로서 ExpressibleByBooleanLiteral 준수합니다.
hidden 변수를 설정하지 않으면 행을 항상 볼 수 있습니다.
양식이 표시된 후 숨겨진 (또는 비활성화 된) 조건을 수동으로 설정하면 Eureka가 새로운 조건을 재평가하도록 강제하기 위해 row.evaluateHidden() 을 호출해야 할 수도 있습니다. 자세한 내용은이 FAQ 섹션을 참조하십시오.
섹션의 경우 이것은 동일하게 작동합니다. 즉, 우리는 그것을 동적으로 보여 주거나 숨기기 위해 hidden 속성을 설정할 수 있습니다.
행을 비활성화하기 위해 각 행에는 선택적 Condition 유형 속성 인 disabled 변수가 있습니다. 이 변수는 또한 hidden 변수와 동일하게 작동하므로 행에 태그가 필요합니다.
행을 영구적으로 비활성화하려면 disabled 변수를 true 로 설정할 수도 있습니다.
옵션 목록을 표시하기 위해 Eureka에는 SelectableSection 이라는 특수 섹션이 포함되어 있습니다. 하나를 만들 때 옵션과 selectionType 에 사용할 행 유형을 전달해야합니다. selectionType 은 enableDeselection 매개 변수가 선택된 행을 선택 해제 할 수 있는지 여부를 결정하는 multipleSelection 또는 singleSelection(enableDeselection: Bool) 일 수있는 열거입니다.
form +++ SelectableSection < ListCheckRow < String > > ( " Where do you live " , selectionType : . singleSelection ( enableDeselection : true ) )
let continents = [ " Africa " , " Antarctica " , " Asia " , " Australia " , " Europe " , " North America " , " South America " ]
for option in continents {
form . last! <<< ListCheckRow < String > ( option ) { listRow in
listRow . title = option
listRow . selectableValue = option
listRow . value = nil
}
} 이러한 섹션을 만들려면 SelectableRowType 프로토콜을 준수하는 행을 만들어야합니다.
public protocol SelectableRowType : RowType {
var selectableValue : Value ? { get set }
} 이 selectableValue 는 행 값이 영구적으로 저장되는 곳입니다. value 변수는 행이 선택되었는지 여부를 결정하는 데 사용되며, 선택한 경우 'selectableValue'입니다. Eureka에는 예를 들어 사용되는 ListCheckRow 포함되어 있습니다. 예제 프로젝트의 커스텀 행에서 ImageCheckRow 찾을 수도 있습니다.
SelectableSection 의 선택한 행/S를 쉽게 가져 오려면 selectedRow() 및 selectedRows() SingleSelection 선택된 행을 가져 오기 위해 호출 할 수있는 MultipleSelection 가지 방법이 있습니다.
또한 SelectorViewController 의 다음 속성을 사용하여 섹션별로 그룹화 할 옵션 목록을 설정할 수 있습니다.
sectionKeyForValue 특정 행 값에 대한 키를 반환 해야하는 폐쇄. 이 키는 나중에 옵션을 섹션별로 깨는 데 사용됩니다.
sectionHeaderTitleForKey 특정 키에 대한 섹션의 헤더 제목을 반환하는 클로저. 기본적으로 키 자체를 반환합니다.
sectionFooterTitleForKey 특정 키에 대한 섹션의 바닥 글을 반환하는 클로저.
Eureka는 다형 섹션을 사용하여 특정 필드 (연락처의 전화 번호 등)에 대한 여러 값을 지원합니다. 삽입 가능, 삭제 가능하며 재정렬 가능한 섹션을 쉽게 만들 수 있습니다.

다중 행사 섹션을 만들려면 일반 Section 유형 대신 MultivaluedSection 유형을 사용해야합니다. MultivaluedSection Section 확장하고 다중 행사 섹션 동작을 구성하기위한 몇 가지 추가 속성이 있습니다.
코드 예제로 다이빙합시다 ...
form +++
MultivaluedSection ( multivaluedOptions : [ . Reorder , . Insert , . Delete ] ,
header : " Multivalued TextField " ,
footer : " .Insert adds a 'Add Item' (Add New Tag) button row as last cell. " ) {
$0 . addButtonProvider = { section in
return ButtonRow ( ) {
$0 . title = " Add New Tag "
}
}
$0 . multivaluedRowToInsertAt = { index in
return NameRow ( ) {
$0 . placeholder = " Tag Name "
}
}
$0 <<< NameRow ( ) {
$0 . placeholder = " Tag Name "
}
}이전 코드 스 니펫은 다중 행사 섹션을 만드는 방법을 보여줍니다. 이 경우 MultivaluedOptions 인수가 나타내는대로 행을 삽입, 삭제 및 재정렬하려고합니다.
addButtonProvider 탭핑 및 multivaluedOptions 에 .Insert 값이 포함되어있을 때 새 행을 삽입하는 버튼 행을 사용자 정의 할 수 있습니다.
multivaluedRowToInsertAt Closure Property는 새 행을 삽입해야 할 때마다 Eureka에 의해 호출됩니다. 다중 섹션에 추가 할 행을 제공하려면이 속성을 설정해야합니다. 유레카는 인덱스를 클로저 매개 변수로 전달합니다. 대부분의 경우 다중 행사 섹션 행이 동일한 유형이지만 모든 종류의 행, 심지어 사용자 정의 행을 반환 할 수 있습니다.
Eureka는 삽입 가능한 다중 행사 섹션을 만들 때 버튼 행을 자동으로 추가합니다. 이전에 설명한 것처럼이 버튼 행의 모양을 사용자 정의 할 수 있습니다. showInsertIconInAddButton 속성은 플러스 버튼 (삽입 스타일)이 기본적으로 버튼 왼쪽에 나타나야하는지 나타냅니다.
삽입 가능한 섹션을 만들 때 염두에 두어야 할 몇 가지 고려 사항이 있습니다. 삽입 가능한 다중 행사 섹션에 추가 된 행은 Eureka가 자동으로 새 행을 삽입하기 위해 추가하는 행 위에 놓아야합니다. 섹션의 이니셜 리더스 클로저 내부 (섹션 이니셜 라이저의 마지막 매개 변수)에서 섹션에 이러한 추가 행을 추가하여 쉽게 달성 할 수 있으므로 Eureka는 섹션 끝에서 삽입 버튼을 추가합니다.
기본적으로 Eureka는 양식에 다중 발행이있는 경우에만 TableView의 isEditing True로 설정합니다. 이는 양식이 처음 제시 될 때 viewWillAppear 에서 수행됩니다.
다중 행사 섹션을 사용하는 방법에 대한 자세한 내용은 여러 사용법 예제가 포함 된 Eureka 예제 프로젝트를 살펴보십시오.
ButtonRow 아닌 추가 버튼을 사용하려면 GenericMultivaluedSection<AddButtonType> 사용할 수 있습니다. 여기서 AddButtonType 추가 버튼으로 사용하려는 행의 유형입니다. 사용자 정의 행을 사용하여 버튼의 UI를 변경하려는 경우 유용합니다.
예:
GenericMultivaluedSection < LabelRow > ( multivaluedOptions : [ . Reorder , . Insert , . Delete ] , {
$0 . addButtonProvider = { section in
return LabelRow ( ) {
$0 . title = " A Label row as add button "
}
}
// ...
}Eureka 2.0.0은 요청 된 내장 검증 기능을 많이 소개합니다.
행에는 Rules 모음과 검증 규칙을 평가 해야하는시기를 결정하는 특정 구성이 있습니다.
기본적으로 제공되는 몇 가지 규칙이 있지만 스스로 새로운 규칙을 만들 수도 있습니다.
제공된 규칙은 다음과 같습니다.
유효성 검사 규칙을 설정하는 방법을 살펴 보겠습니다.
override func viewDidLoad ( ) {
super . viewDidLoad ( )
form
+++ Section ( header : " Required Rule " , footer : " Options: Validates on change " )
<<< TextRow ( ) {
$0 . title = " Required Rule "
$0 . add ( rule : RuleRequired ( ) )
// This could also have been achieved using a closure that returns nil if valid, or a ValidationError otherwise.
/*
let ruleRequiredViaClosure = RuleClosure<String> { rowValue in
return (rowValue == nil || rowValue!.isEmpty) ? ValidationError(msg: "Field required!") : nil
}
$0.add(rule: ruleRequiredViaClosure)
*/
$0 . validationOptions = . validatesOnChange
}
. cellUpdate { cell , row in
if !row . isValid {
cell . titleLabel ? . textColor = . systemRed
}
}
+++ Section ( header : " Email Rule, Required Rule " , footer : " Options: Validates on change after blurred " )
<<< TextRow ( ) {
$0 . title = " Email Rule "
$0 . add ( rule : RuleRequired ( ) )
$0 . add ( rule : RuleEmail ( ) )
$0 . validationOptions = . validatesOnChangeAfterBlurred
}
. cellUpdate { cell , row in
if !row . isValid {
cell . titleLabel ? . textColor = . systemRed
}
} 이전 코드 스 니펫에서 볼 수 있듯이 Row의 add(rule:) 함수를 호출하여 연속으로 원하는만큼 규칙을 설정할 수 있습니다.
행은 또한 규칙을 제거하기 위해 func remove(ruleWithIdentifier identifier: String) 제공합니다. 이를 사용하려면 규칙을 작성한 후 ID를 규칙에 할당해야합니다.
때로는 행에 사용하려는 규칙 모음이 다른 많은 행에서 사용하려는 것과 동일합니다. 이 경우 유효성 검사 규칙 모음 인 RuleSet 사용하여 모든 유효성 검사 규칙을 설정할 수 있습니다.
var rules = RuleSet < String > ( )
rules . add ( rule : RuleRequired ( ) )
rules . add ( rule : RuleEmail ( ) )
let row = TextRow ( ) {
$0 . title = " Email Rule "
$0 . add ( ruleSet : rules )
$0 . validationOptions = . validatesOnChangeAfterBlurred
} Eureka를 사용하면 유효성 검사 규칙을 평가 해야하는시기를 지정할 수 있습니다. validationOptions Row의 속성을 설정하여 다음 값을 가질 수 있습니다.
.validatesOnChange 행 값이 변경 될 때마다 확인합니다..validatesOnBlur (기본값) 셀이 첫 번째 응답자를 사임 한 직후에 유효합니다. 모든 행에 적용 할 수는 없습니다..validatesOnChangeAfterBlurred 처음으로 첫 번째 응답자를 사임 한 후 행 값이 변경 될 때마다 확인합니다..validatesOnDemand validate() 메소드를 호출하여 행 또는 양식을 수동으로 확인해야합니다. 전체 양식 (모든 행)을 확인하려면 form validate() 메소드를 수동으로 호출 할 수 있습니다.
각 행에는 모든 유효성 검사 오류를 검색하는 데 사용할 수있는 validationErrors 속성이 있습니다. 이 속성은 최신 행 유효성 검사 실행의 유효성 검사 오류 목록을 보유하고 있습니다. 즉, 행의 유효성 검사 규칙을 평가하지 않습니다.
예상대로 규칙은 행 객체와 동일한 유형을 사용해야합니다. 사용 된 행 유형을 확인하기 위해 특별히주의하십시오. 컴파일러 오류가 표시 될 수 있습니다 ( "Call에서 잘못된 arugment 레이블 ( '규칙 :'예상 '규칙 세트 :').
스 와이프 동작을 사용하면 행 당 여러 리드 leadingSwipe 및 trailingSwipe 작업을 정의 할 수 있습니다. 스 와이프 동작은 iOS 시스템 기능에 따라 달라 지므로 IOS 11.0+에서만 leadingSwipe 사용할 수 있습니다.
스 와이프 동작을 정의하는 방법을 살펴 보겠습니다.
let row = TextRow ( ) {
let deleteAction = SwipeAction (
style : . destructive ,
title : " Delete " ,
handler : { ( action , row , completionHandler ) in
//add your code here.
//make sure you call the completionHandler once done.
completionHandler ? ( true )
} )
deleteAction . image = UIImage ( named : " icon-trash " )
$0 . trailingSwipe . actions = [ deleteAction ]
$0 . trailingSwipe . performsFirstActionWithFullSwipe = true
//please be aware: `leadingSwipe` is only available on iOS 11+ only
let infoAction = SwipeAction (
style : . normal ,
title : " Info " ,
handler : { ( action , row , completionHandler ) in
//add your code here.
//make sure you call the completionHandler once done.
completionHandler ? ( true )
} )
infoAction . actionBackgroundColor = . blue
infoAction . image = UIImage ( named : " icon-info " )
$0 . leadingSwipe . actions = [ infoAction ]
$0 . leadingSwipe . performsFirstActionWithFullSwipe = true
} 스 와이프 동작이 필요합니다. tableView.isEditing 필요 false . Eureka는 양식 ( viewWillAppear 에서)에 다중 행사가 있으면 이것을 true 로 설정합니다. 동일한 형태의 다중 발행과 스 와이프 동작이있는 경우 필요에 따라 isEditing 설정해야합니다.
유레카에 포함 된 행과 다른 행이 필요한 것은 매우 일반적입니다. 이 경우 자신의 행을 만들어야하지만 어려운 일은 아닙니다. 시작하려면 사용자 정의 행을 만드는 방법에 대한이 자습서를 읽을 수 있습니다. 유레카에 추가 할 준비가 된 여분의 행이 포함 된 유레 키카 커먼티를 살펴 보는 것도 원할 수도 있습니다.
사용자 정의 동작과 모양으로 행을 만들려면 Row 과 Cell 의 서브 클래스를 만들고 싶을 것입니다.
Row Eureka가 사용하는 추상화이며, Cell 뷰를 담당하는 실제 UITableViewCell 입니다. Row 에는 Cell 포함되어 있으므로 Row 과 Cell 모두 동일한 값 유형에 대해 정의되어야합니다.
// Custom Cell with value type: Bool
// The cell is defined using a .xib, so we can set outlets :)
public class CustomCell : Cell < Bool > , CellType {
@ IBOutlet weak var switchControl : UISwitch !
@ IBOutlet weak var label : UILabel !
public override func setup ( ) {
super . setup ( )
switchControl . addTarget ( self , action : #selector ( CustomCell . switchValueChanged ) , for : . valueChanged )
}
func switchValueChanged ( ) {
row . value = switchControl . on
row . updateCell ( ) // Re-draws the cell which calls 'update' bellow
}
public override func update ( ) {
super . update ( )
backgroundColor = ( row . value ?? false ) ? . white : . black
}
}
// The custom Row also has the cell: CustomCell and its correspond value
public final class CustomRow : Row < CustomCell > , RowType {
required public init ( tag : String ? ) {
super . init ( tag : tag )
// We set the cellProvider to load the .xib corresponding to our cell
cellProvider = CellProvider < CustomCell > ( nibName : " CustomCell " )
}
} 결과 : 
Callbacks CellSetup 및 Cellupdate와 마찬가지로 Cell 사용자 정의 할 수있는 설정 및 업데이트 메소드가 있습니다.
인라인 행은 특정 유형의 행으로 아래의 행을 동적으로 표시하는 행입니다. 일반적으로 행이 탭 될 때마다 확장 모드와 붕괴 된 모드 사이의 인라인 행이 변경됩니다.
따라서 인라인 행을 만들려면 2 개의 행, "항상"보이는 행 및 팽창/붕괴 행이 필요합니다.
또 다른 요구 사항은이 2 행의 값 유형이 동일해야한다는 것입니다. 이것은 한 행에 String 값을 보유하면 다른 행에 String 값도 있어야합니다.
이 2 행이 있으면 상단 행 유형이 InlineRowType 를 준수해야합니다. 이 프로토콜을 사용하려면 InlineRow Infealias와 setupInlineRow 함수를 정의해야합니다. InlineRow 유형은 확장/붕괴의 행의 유형입니다. 이것을 예로 들어보십시오.
class PickerInlineRow < T > : Row < PickerInlineCell < T > > where T : Equatable {
public typealias InlineRow = PickerRow < T >
open var options = [ T ] ( )
required public init ( tag : String ? ) {
super . init ( tag : tag )
}
public func setupInlineRow ( _ inlineRow : InlineRow ) {
inlineRow . options = self . options
inlineRow . displayValueFor = self . displayValueFor
inlineRow . cell . height = { UITableViewAutomaticDimension }
}
} InlineRowType 는 또한 당신의 인라인 행에 몇 가지 방법을 추가합니다.
func expandInlineRow ( )
func collapseInlineRow ( )
func toggleInlineRow ( ) 이러한 방법은 제대로 작동해야하지만 expandInlineRow 및 collapseInlineRow 호출 해야하는 toggleInlineRow 라는 것을 명심해야합니다.
마지막으로 행 customDidSelect 선택되면 toggleInlineRow() 호출해야합니다.
public override func customDidSelect ( ) {
super . customDidSelect ( )
if !isDisabled {
toggleInlineRow ( )
}
}참고 : 발표자 행은 새로운 UIViewController를 제공하는 행입니다.
사용자 정의 발표 행을 만들려면 PresenterRowType 프로토콜을 준수하는 클래스를 작성해야합니다. 해당 프로토콜을 준수하고 다른 유용한 기능을 추가하므로 SelectorRow 서브 클래스하는 것이 좋습니다.
PRESSERROWTYPE 프로토콜은 다음과 같이 정의됩니다.
public protocol PresenterRowType : TypedRowType {
associatedtype PresentedControllerType : UIViewController , TypedRowControllerType
/// Defines how the view controller will be presented, pushed, etc.
var presentationMode : PresentationMode < PresentedControllerType > ? { get set }
/// Will be called before the presentation occurs.
var onPresentCallback : ( ( FormViewController , PresentedControllerType ) -> Void ) ? { get set }
} 행이 다른 뷰 컨트롤러를 제시하려고 할 때 온 프레 센트 칼 백이 호출됩니다. 이것은 SelectorRow 에서 이루어 지므로 서브 클래스를하지 않으면 직접 호출해야합니다.
presentationMode 모드는 컨트롤러가 제시되는 방식과 어떤 컨트롤러가 제시되는지 정의하는 것입니다. 이 프레젠테이션은 SEGUE 식별자 인 SEGUE 클래스를 사용하여 컨트롤러를 모듈로 제시하거나 특정 뷰 컨트롤러로 푸시하는 것일 수 있습니다. 예를 들어 CustomPushrow는 다음과 같이 정의 할 수 있습니다.
예를 들어 보자 ..
/// Generic row type where a user must select a value among several options.
open class SelectorRow < Cell : CellType > : OptionsRow < Cell > , PresenterRowType where Cell : BaseCell {
/// Defines how the view controller will be presented, pushed, etc.
open var presentationMode : PresentationMode < SelectorViewController < SelectorRow < Cell > > > ?
/// Will be called before the presentation occurs.
open var onPresentCallback : ( ( FormViewController , SelectorViewController < SelectorRow < Cell > > ) -> Void ) ?
required public init ( tag : String ? ) {
super . init ( tag : tag )
}
/**
Extends `didSelect` method
*/
open override func customDidSelect ( ) {
super . customDidSelect ( )
guard let presentationMode = presentationMode , !isDisabled else { return }
if let controller = presentationMode . makeController ( ) {
controller . row = self
controller . title = selectorTitle ?? controller . title
onPresentCallback ? ( cell . formViewController ( ) ! , controller )
presentationMode . present ( controller , row : self , presentingController : self . cell . formViewController ( ) ! )
} else {
presentationMode . present ( nil , row : self , presentingController : self . cell . formViewController ( ) ! )
}
}
/**
Prepares the pushed row setting its title and completion callback.
*/
open override func prepare ( for segue : UIStoryboardSegue ) {
super . prepare ( for : segue )
guard let rowVC = segue . destination as Any as? SelectorViewController < SelectorRow < Cell > > else { return }
rowVC . title = selectorTitle ?? rowVC . title
rowVC . onDismissCallback = presentationMode ? . onDismissCallback ?? rowVC . onDismissCallback
onPresentCallback ? ( cell . formViewController ( ) ! , rowVC )
rowVC . row = self
}
}
// SelectorRow conforms to PresenterRowType
public final class CustomPushRow < T : Equatable > : SelectorRow < PushSelectorCell < T > > , RowType {
public required init ( tag : String ? ) {
super . init ( tag : tag )
presentationMode = . show ( controllerProvider : ControllerProvider . callback {
return SelectorViewController < T > ( ) { _ in }
} , onDismiss : { vc in
_ = vc . navigationController ? . popViewController ( animated : true )
} )
}
}때때로 우리는 행 중 하나의 UI 모양을 변경하고 싶지만 행 유형과 한 행과 관련된 모든 논리를 변경하지 않고는 없습니다. NIB 파일에서 인스턴스화 된 셀을 사용하는 경우 현재이 작업을 수행하는 한 가지 방법이 있습니다. 현재 Eureka의 핵심 행 중 어느 것도 NIB 파일에서 인스턴스화되지 않았지만 EureKacommunity의 사용자 정의 행 중 일부는 특히 Postaladdressrow입니다.
당신이해야 할 일은 다음과 같습니다.
cellProvider 피더 변수를 설정 하여이 NIB를 사용하여 수행됩니다. 각 콘크리트 인스턴스화 또는 defaultRowInitializer 사용하여 초기이기에서이를 수행해야합니다. 예를 들어: <<< PostalAddressRow ( ) {
$0 . cellProvider = CellProvider < PostalAddressCell > ( nibName : " CustomNib " , bundle : Bundle . main )
}이를 위해 새 행을 만들 수도 있습니다. 이 경우 논리를 상속하기 위해 변경하려는 행과 동일한 슈퍼 클래스에서 상속을 시도하십시오.
이것을 할 때 고려해야 할 사항이 있습니다.
Unknown class <YOUR_CLASS_NAME> in Interface Builder file 이라는 오류가 발생하면 런타임에로드하려면 코드 어딘가에 해당 새 유형을 인스턴스화해야 할 수도 있습니다. 전화를 let t = YourClass.self 내 경우에 도움이되었습니다. 레이블 행![]() | 버튼 행![]() | 행을 확인하십시오 ![]() |
스위치 행![]() | 슬라이더 행![]() | 스테퍼 행 ![]() |
텍스트 영역 행 ![]() |
이 행에는 셀 오른쪽에 텍스트 필드가 있습니다. 각각의 차이는 다른 대문자, 자동 정복 및 키보드 유형 구성으로 구성됩니다.
![]() | Textrow 이름 지정 urlrow introw 음운 암호로 이메일 십진수 트위터로 회계 zipcoderow |
위의 모든 FieldRow 하위 유형은 유형 NSFormatter 의 formatter 특성을 가지며,이 행은 해당 행의 값이 어떻게 표시되어야하는지 결정할 수 있습니다. 소수점 마크 후 두 자리 숫자가있는 숫자에 대한 맞춤형 포맷터는 Eureka ( DecimalFormatter )에 포함되어 있습니다. 예제 프로젝트에는 사용자의 로케일에 따라 숫자를 통화로 표시하는 CurrencyFormatter 도 포함되어 있습니다.
기본적으로 행의 formatter 설정하면 값이 편집되지 않을 때 값이 표시되는 방식에만 영향을줍니다. 행을 편집하는 동안 값을 형식화하려면 행을 초기화 할 때 useFormatterDuringInput true 로 설정하십시오. 편집 할 때 값을 서식하려면 커서 위치를 업데이트해야 할 수 있으며 Eureka는 커서 위치를 처리하기 위해 Formatter가 준수 해야하는 다음 프로토콜을 제공합니다.
public protocol FormatterProtocol {
func getNewPosition ( forPosition forPosition : UITextPosition , inTextInput textInput : UITextInput , oldValue : String ? , newValue : String ? ) -> UITextPosition
} 또한 FieldRow 하위 유형에는 useFormatterOnDidBeginEditing 속성이 있습니다. 소수점 값을 허용하고 사용자의 로케일 (예 : DecimalFormatter )을 준수하는 형태로 DecimalRow 사용하는 경우, useFormatterDuringInput 이 false 인 경우, useFormatterOnDidBeginEditing 편집 된 값의 소수점 마크가 키보드의 소수점 마크와 일치 true 설정해야합니다.
날짜 행 날짜를 유지하고 UidatePicker 컨트롤을 통해 새로운 값을 설정할 수 있습니다. uidatepicker의 모드와 날짜 선택기보기가 표시되는 방식은 그들 사이의 변화입니다.
날짜 행 ![]() 키보드에 표시된 피커. | 날짜 행 (인라인) ![]() 행이 확장됩니다. | 날짜 행 (피커) ![]() 피커는 항상 보입니다. |
Eureka는 3 가지 스타일 (정상, 인라인 및 피커)을 사용하여 다음을 포함합니다.
이들은 사용자가 선택 해야하는 옵션 목록이있는 행입니다.
<<< ActionSheetRow < String > ( ) {
$0 . title = " ActionSheetRow "
$0 . selectorTitle = " Pick a number "
$0 . options = [ " One " , " Two " , " Three " ]
$0 . value = " Two " // initially selected
} 경고 행![]() 선택할 수있는 옵션에 대한 경고가 표시됩니다. | 액션 시트 행![]() 선택할 수있는 옵션이 포함 된 액션 시트가 표시됩니다. | 푸시 행![]() 확인 행을 사용하여 나열된 옵션을 선택할 곳에서 새 컨트롤러로 푸시됩니다. | 다중 선택기 행![]() Pushrow와 마찬가지로 여러 옵션을 선택할 수 있습니다. |
세그먼트로드![]() | 세그먼트 행 (제목 w/제목)![]() | 피커 로우![]() 피커보기를 통해 일반 유형의 옵션을 제공합니다. (피커 인라인 줄도 있습니다) |
그것에 대해 알려주십시오. 여기서 언급하게되어 기쁩니다. :)

Cocoapods는 코코아 프로젝트의 종속성 관리자입니다.
프로젝트의 Podfile 에 Eureka를 지정하십시오.
source 'https://github.com/CocoaPods/Specs.git'
platform :ios , '9.0'
use_frameworks!
pod 'Eureka'그런 다음 다음 명령을 실행합니다.
$ pod installSwift Package Manager는 Swift 코드 배포를 관리하는 도구입니다.
Package.swift 설정 한 후에는 Swift Manifest 파일을 설정 한 후에는 Package.swift 의 종속성 값에 추가하여 Eureka를 종속성으로 추가 할 수 있습니다.
종속성 : [.package (url : "https://github.com/xmartlabs/eureka.git", From : "5.5.0")]
Carthage는 Cocoa의 간단하고 분산 된 종속성 관리자입니다.
Eureka를 프로젝트의 Cartfile 로 지정하십시오.
github "xmartlabs/Eureka" ~> 5.5
$ git submodule add https://github.com/xmartlabs/Eureka.git이전 GIT 하위 모드 명령에 의해 작성된 Eureka 폴더를 열고 Eureka.xcodeproj를 응용 프로그램의 Xcode 프로젝트의 프로젝트 네비게이터로 드래그하십시오.
프로젝트 네비게이터에서 Eureka.xcodeproj를 선택하고 응용 프로그램 배포 대상과 배포 대상 일치를 확인하십시오.
Xcode Navigation에서 프로젝트를 선택한 다음 사이드 바에서 응용 프로그램 대상을 선택하십시오. 다음으로 "일반"탭을 선택하고 "임베디드 바이너리"섹션에서 + 버튼을 클릭하십시오.
Eureka.framework 선택하면 완료됩니다!
eureka-forms ).기여하기 전에 추가 정보는 기여 파일을 확인하십시오.
앱에서 Eureka를 사용한다면 우리는 그것에 대해 듣고 싶습니다! 트위터에 우리에게 줄을 두십시오.
모든 행에는 다음 속성이 있습니다.
/// Block variable used to get the String that should be displayed for the value of this row.
public var displayValueFor : ( ( T ? ) -> String ? ) ? = {
return $0 . map { String ( describing : $0 ) }
} 표시하려는 문자열 값에 따라 displayValueFor 설정할 수 있습니다.
Form 클래스에 노출 된 다음 기능 중 하나를 호출하여 특정 행을 얻을 수 있습니다.
public func rowBy < T : Equatable > ( tag : String ) -> RowOf < T > ?
public func rowBy < Row : RowType > ( tag : String ) -> Row ?
public func rowBy ( tag : String ) -> BaseRow ?예를 들어:
let dateRow : DateRow ? = form . rowBy ( tag : " dateRowTag " )
let labelRow : LabelRow ? = form . rowBy ( tag : " labelRowTag " )
let dateRow2 : Row < DateCell > ? = form . rowBy ( tag : " dateRowTag " )
let labelRow2 : BaseRow ? = form . rowBy ( tag : " labelRowTag " ) let section : Section ? = form . sectionBy ( tag : " sectionTag " ) Form 클래스에 의해 노출되는 setValues(values: [String: Any?]) 호출.
예를 들어:
form . setValues ( [ " IntRowTag " : 8 , " TextRowTag " : " Hello world! " , " PushRowTag " : Company ( name : " Xmartlabs " ) ] ) "IntRowTag" , "TextRowTag" , "PushRowTag" 는 행 태그 (각각은 고유하게 행을 식별 함) 8 "Hello world!" 입니다. , Company(name:"Xmartlabs") 는 할당 할 해당 행 값입니다.
행의 값 유형은 해당 사전 값의 값 유형과 일치해야합니다.
양식이 이미 표시된 경우 테이블보기 tableView.reloadData() 각각의 가시 행으로 updateCell() 호출하여 표시된 행을 다시로드해야합니다.
조건을 설정 한 후이 조건은 자동으로 평가되지 않습니다. 즉시 그렇게하려면 .evaluateHidden() 또는 .evaluateDisabled() 를 호출 할 수 있습니다.
이 함수는 행이 양식에 추가 될 때 방금 호출되며 행은 변경에 따라 다릅니다. 행이 표시되면 조건이 변경되면 수동으로 재평가해야합니다.
이 문제를보십시오.
section . header = HeaderFooterView ( title : " Header title ( variable ) " ) // use String interpolation
//or
var header = HeaderFooterView < UIView > ( . class ) // most flexible way to set up a header using any view type
header . height = { 60 } // height can be calculated
header . onSetupView = { view , section in // each time the view is about to be displayed onSetupView is invoked.
view . backgroundColor = . orange
}
section . header = headersection . reload ( ) selectableRowSetup 및 selectableRowCellUpdate 및 selectableRowCellSetup 및 SelectAbleWcellUpDate 및 SelectAblerOwCellUpDate 및 SelectAblerViewCellErtup 속성이 제공됩니다.
let row = PushRow < Emoji > ( ) {
$0 . title = " PushRow "
$0 . options = [ ?? , ? , ?? , ? , ? , ? ]
$0 . value = ??
$0 . selectorTitle = " Choose an Emoji! "
} . onPresent { from , to in
to . dismissOnSelection = false
to . dismissOnChange = false
to . selectableRowSetup = { row in
row . cellProvider = CellProvider < ListCheckCell < Emoji > > ( nibName : " EmojiCell " , bundle : Bundle . main )
}
to . selectableRowCellUpdate = { cell , row in
cell . textLabel ? . text = " Text " + row . selectableValue! // customization
cell . detailTextLabel ? . text = " Detail " + row . selectableValue!
}
} 우리가 말했듯 Form 와 Section 유형은 MutableCollection 및 RangeReplaceableCollection 준수합니다. 양식은 섹션 모음이며 섹션은 행 모음입니다.
RangeReplaceableCollection 프로토콜 확장은 수집을 수정하는 많은 유용한 방법을 제공합니다.
extension RangeReplaceableCollection {
public mutating func append ( _ newElement : Self . Element )
public mutating func append < S > ( contentsOf newElements : S ) where S : Sequence , Self . Element == S . Element
public mutating func insert ( _ newElement : Self . Element , at i : Self . Index )
public mutating func insert < S > ( contentsOf newElements : S , at i : Self . Index ) where S : Collection , Self . Element == S . Element
public mutating func remove ( at i : Self . Index ) -> Self . Element
public mutating func removeSubrange ( _ bounds : Range < Self . Index > )
public mutating func removeFirst ( _ n : Int )
public mutating func removeFirst ( ) -> Self . Element
public mutating func removeAll ( keepingCapacity keepCapacity : Bool )
public mutating func reserveCapacity ( _ n : Self . IndexDistance )
}이 방법은 내부적으로 사용하여 벨로우즈에 표시된대로 사용자 정의 연산자를 구현합니다.
public func +++ ( left : Form , right : Section ) -> Form {
left . append ( right )
return left
}
public func += < C : Collection > ( inout lhs : Form , rhs : C ) where C . Element == Section {
lhs . append ( contentsOf : rhs )
}
public func << < ( left : Section , right : BaseRow ) -> Section {
left . append ( right )
return left
}
public func += < C : Collection > ( inout lhs : Section , rhs : C ) where C . Element == BaseRow {
lhs . append ( contentsOf : rhs )
}나머지 사용자 정의 연산자가 여기에서 어떻게 구현되는지 알 수 있습니다.
Eureka Custom Operator를 사용하고 싶은지 여부를 결정하는 것은 귀하에게 달려 있습니다.
양식은 항상 UITableView 에 표시됩니다. 스토리 보드에서 View 컨트롤러를 설정하고 원하는 위치에 UitableView를 추가 한 다음 Outlet을 FormViewController의 tableView 변수에 연결할 수 있습니다. 이를 통해 양식에 대한 사용자 정의 프레임 (제약 조건)을 정의 할 수 있습니다.
이 모든 것은 ProgramviewController의 tableView 의 프로그래밍 방식으로 변화하는 프레임, 여백 등으로 수행 할 수 있습니다.
그래서 우리는 유레카를 더 좋게 만들 수 있습니다! 
Changelog.md 파일에서 찾을 수 있습니다.