diff --git a/.travis.yml b/.travis.yml index 044f65c..8af5afd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,14 +2,16 @@ # * http://www.objc.io/issue-6/travis-ci.html # * https://github.com/supermarin/xcpretty#usage -osx_image: xcode10.2 +osx_image: xcode12 language: objective-c env: - - DESTINATION='platform=iOS Simulator,name=iPhone 6S,OS=9.3' - DESTINATION='platform=iOS Simulator,name=iPhone 7,OS=10.3.1' - DESTINATION='platform=iOS Simulator,name=iPhone 8,OS=11.4' - - DESTINATION='platform=iOS Simulator,name=iPhone XS,OS=12.2' + - DESTINATION='platform=iOS Simulator,name=iPhone XS,OS=12.4' + - DESTINATION='platform=iOS Simulator,name=iPhone 11,OS=13.5' + - DESTINATION='platform=iOS Simulator,name=iPhone 11,OS=14.0' + script: - set -o pipefail && xcodebuild test -enableCodeCoverage YES -workspace Example/TableViewLiaison.xcworkspace -scheme TableViewLiaison-Example -destination "$DESTINATION" | xcpretty diff --git a/Example/Podfile.lock b/Example/Podfile.lock index ae3ae34..abf071c 100644 --- a/Example/Podfile.lock +++ b/Example/Podfile.lock @@ -1,5 +1,5 @@ PODS: - - TableViewLiaison (1.0.3) + - TableViewLiaison (2.0.0) DEPENDENCIES: - TableViewLiaison (from `../`) @@ -9,8 +9,8 @@ EXTERNAL SOURCES: :path: "../" SPEC CHECKSUMS: - TableViewLiaison: c48125074fa532bd852f1f4cd1bafd1c9325f184 + TableViewLiaison: abfd253eb471298f90b277f9ec2df6a3af2004e9 PODFILE CHECKSUM: f818d085ecc094e9577389f3dd62126b0c67c6c6 -COCOAPODS: 1.6.1 +COCOAPODS: 1.7.4 diff --git a/Example/Pods/Local Podspecs/TableViewLiaison.podspec.json b/Example/Pods/Local Podspecs/TableViewLiaison.podspec.json index 000d277..7eb6270 100644 --- a/Example/Pods/Local Podspecs/TableViewLiaison.podspec.json +++ b/Example/Pods/Local Podspecs/TableViewLiaison.podspec.json @@ -1,6 +1,6 @@ { "name": "TableViewLiaison", - "version": "1.0.3", + "version": "2.0.0", "summary": "Framework to help you better manage UITableViews.", "description": "TableViewLiaison abstracts and simplifies UITableView construction and management.", "homepage": "https://github.com/dylanshine/TableViewLiaison", @@ -13,11 +13,12 @@ }, "source": { "git": "https://github.com/dylanshine/TableViewLiaison.git", - "tag": "1.0.3" + "tag": "2.0.0" }, "platforms": { "ios": "9.0" }, "source_files": "TableViewLiaison/Classes/**/*", + "swift_versions": "5.0", "swift_version": "5.0" } diff --git a/Example/Pods/Manifest.lock b/Example/Pods/Manifest.lock index ae3ae34..abf071c 100644 --- a/Example/Pods/Manifest.lock +++ b/Example/Pods/Manifest.lock @@ -1,5 +1,5 @@ PODS: - - TableViewLiaison (1.0.3) + - TableViewLiaison (2.0.0) DEPENDENCIES: - TableViewLiaison (from `../`) @@ -9,8 +9,8 @@ EXTERNAL SOURCES: :path: "../" SPEC CHECKSUMS: - TableViewLiaison: c48125074fa532bd852f1f4cd1bafd1c9325f184 + TableViewLiaison: abfd253eb471298f90b277f9ec2df6a3af2004e9 PODFILE CHECKSUM: f818d085ecc094e9577389f3dd62126b0c67c6c6 -COCOAPODS: 1.6.1 +COCOAPODS: 1.7.4 diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj index 6dd135c..f43ad07 100644 --- a/Example/Pods/Pods.xcodeproj/project.pbxproj +++ b/Example/Pods/Pods.xcodeproj/project.pbxproj @@ -7,300 +7,290 @@ objects = { /* Begin PBXBuildFile section */ - 01D6785D207D424DB9FD0ADD076DAE4A /* TableViewLiaison+Row.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB5177E80F74242EA432B65270A94930 /* TableViewLiaison+Row.swift */; }; - 12E833A65C2B594267122A8528689760 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CB4607EFCA7C5F75397649E792E2AFCB /* Foundation.framework */; }; - 1D1BF19060D11E76D7CBF60241E89120 /* AnyTableViewRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49EC22D2241750534696D27E5F590755 /* AnyTableViewRow.swift */; }; - 27957164FF471D0625E99B58A52DBCCE /* Pods-TableViewLiaison_Tests-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 4749D85964F054ADE0C01F72DBF05189 /* Pods-TableViewLiaison_Tests-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 2FB6A8BAA26C5329944B90DD2DD0C57E /* TableViewSectionComponentCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5EFA079AFA1336963EC67F3EA16DA717 /* TableViewSectionComponentCommand.swift */; }; - 302239045403240F0D0E7EB16374389F /* AnyTableViewSectionComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B7DF44F73E4D3388DBC196CBB9C4106 /* AnyTableViewSectionComponent.swift */; }; - 40ECC4BF15F3A6A1A3B242AF322C0803 /* TableViewLiaison+UITableViewDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9ADD5E1F3BDEA73A16ABAA84AB23AF6 /* TableViewLiaison+UITableViewDelegate.swift */; }; - 48AFAD2CEA1D62D424137004F26E177A /* TableViewSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F3F499C23DA4ABFDACEB4A56F433639 /* TableViewSection.swift */; }; - 53AB22CC330BE270771764EB297BA1B4 /* TableViewSectionComponentDisplayOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6DDE93447EE72DEBF8441C36FBB777C /* TableViewSectionComponentDisplayOption.swift */; }; - 575FE4D543A8670CF07A45490783F5E4 /* TableViewRegistrationType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 23551DE62EE3635B18432362E4DD6D07 /* TableViewRegistrationType.swift */; }; - 5E0B4CEE1FE23DEF6664679D7D5EEF7E /* TableViewLiaison.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC88125E071EDBB08FE4B0EA8AAF6775 /* TableViewLiaison.swift */; }; - 617CFD248B9E44DAA3C0EF1A59ADD5B3 /* TableViewPrefetchCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E09BC0F0696D11A9668D449E0896DDA /* TableViewPrefetchCommand.swift */; }; - 65EB91BF6CCC07DA37789690977FF8A5 /* TableViewLiaison+Section.swift in Sources */ = {isa = PBXBuildFile; fileRef = 72469840B78E9E0B47EDE9E9C2A1A9C1 /* TableViewLiaison+Section.swift */; }; - 678D9E865042E9FE8D05668B0489FB62 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CB4607EFCA7C5F75397649E792E2AFCB /* Foundation.framework */; }; - 6DAA495DAE623FA6765069DC6895F5D4 /* TableViewSectionComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78BAF03D3CD5A713EC848578283F6EE2 /* TableViewSectionComponent.swift */; }; - 72D15770E876499B60D61454B7518A4A /* TableViewSectionComponentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17E9F3BCCE82122EDF269A82E851D002 /* TableViewSectionComponentView.swift */; }; - 739ACA8474D43D680EFB588A8D366D9F /* PaginationTableViewRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCF73F4CCBF347860D5B41206FE137C9 /* PaginationTableViewRow.swift */; }; - 7742026217FA882BEA5F1B151918142C /* Pods-TableViewLiaison_Example-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = BCA9FB0B4D7EEE0029C12E606D3F3D87 /* Pods-TableViewLiaison_Example-dummy.m */; }; - 7946E39A15AE394CDEE7A222307F0AEE /* Array+IndexPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = 68A9000AEE92A7E271ACA6CD8788659C /* Array+IndexPath.swift */; }; - 79507A7E4978BF6916F03699B0B64A39 /* TableViewLiaison-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 74A918CD6CE6E84B57C9AB5664CDD398 /* TableViewLiaison-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 7A3FD46128BC5521A04C615707ADB94D /* TableViewLiaison+Pagination.swift in Sources */ = {isa = PBXBuildFile; fileRef = 10B1C53A2CADE23378380A08817D1664 /* TableViewLiaison+Pagination.swift */; }; - 7A7E475325A7684FA97B3AB6138D3E38 /* TableViewHeightType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20E1E39E9F37384BC7AD34EB2DFB1040 /* TableViewHeightType.swift */; }; - 819CB967684EB9F08ED5B0F110CAE62E /* TableViewLiaisonPaginationDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2B5C767CAA2610C6AE259EC646027B4 /* TableViewLiaisonPaginationDelegate.swift */; }; - 9EA5C92B8B3FD454C4262F6CDC71D2A2 /* PaginationTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92256764226915400D09832635489CBE /* PaginationTableViewCell.swift */; }; - ACB480EC8F2D0BF0E5CB7B1C4041F454 /* Pods-TableViewLiaison_Tests-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 79CA9937219F290FAD2548BA508CEA29 /* Pods-TableViewLiaison_Tests-dummy.m */; }; - AFAED8E47A2E9AEC5121976A8907A877 /* TableViewRowCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19A10E2085A6F35D84D00183AA3B665E /* TableViewRowCommand.swift */; }; - B6A89549DDDEA62250AE421D621401BC /* TableViewLiaison-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = CC3240813F9B0633E678F3653B641464 /* TableViewLiaison-dummy.m */; }; - B90578DC814690029E762C516910B4A1 /* Array+SafeAccess.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3627E6270141F3D94BF5A8AFCB3A380 /* Array+SafeAccess.swift */; }; - C5FB9C295871F5844FB2515D510D2081 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CB4607EFCA7C5F75397649E792E2AFCB /* Foundation.framework */; }; - CFB42637BC3629D8A570EE6236E1FE0D /* TableViewLiaison+UITableViewDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA6BB5B3E5B4C06E1D0BE8C060C9EBE4 /* TableViewLiaison+UITableViewDataSource.swift */; }; - D180CD203CA3AAE30402692DA5B51A81 /* Pods-TableViewLiaison_Example-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = DF0A59383169AF6CB2AB8EE20E530695 /* Pods-TableViewLiaison_Example-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - DE6A02FE586821E7A6ED1D4AB47F2419 /* TableViewContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98DD38E44B1CF1C417D87C8E497699CE /* TableViewContent.swift */; }; - EA60C2E0610D3CDDB2CD66283E2401ED /* UITableView+Generic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80BC76774F151BB4C777DD65B6AB1B5D /* UITableView+Generic.swift */; }; - EFA3088B21B8381A686F95F44DB77A9C /* TableViewRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = F25DD676FC9A44B47F95A7996596BCB1 /* TableViewRow.swift */; }; - F1F7E965462578DEC4FB02B4FAD87F38 /* TableViewLiaison+UITableViewDataSourcePrefetching.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E167870D969CCB057AECCFC8A66704B /* TableViewLiaison+UITableViewDataSourcePrefetching.swift */; }; - FCA83AD26A019F4F5D77494C43143BA6 /* TableViewLiaison+Registration.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED21D359F88D72B583354E2BFDE4A28F /* TableViewLiaison+Registration.swift */; }; + 05CED4F61B58E01A10BE62785140E744 /* TableViewRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2C77C9761945EBFF60FAFFC4ED1EBBB /* TableViewRow.swift */; }; + 09BCB9800E121B031FEC743F8C2DE758 /* TableViewSectionComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = DADE7C5188D309EF91133D8DF4C3FC1E /* TableViewSectionComponent.swift */; }; + 0AFBC88AA2A93D44CE4477AA73045418 /* Array+SafeAccess.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56DB21A24ED5601EACDFA056D8F264DE /* Array+SafeAccess.swift */; }; + 1869189F25238662005A4F8A /* TableViewRow+Void.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1869189E25238662005A4F8A /* TableViewRow+Void.swift */; }; + 22BAB1493CABE7277E9372CF341CEE0F /* TableViewLiaison+Row.swift in Sources */ = {isa = PBXBuildFile; fileRef = B048904DA3507C0F9CECE45BB214FEA2 /* TableViewLiaison+Row.swift */; }; + 2526A72D2B1AB00A3261B74F3F244072 /* TableViewLiaison+UITableViewDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5447DDE7EFBDCF1E929ECA11F09C9BC /* TableViewLiaison+UITableViewDelegate.swift */; }; + 474E72CE7ECE34BA46A113FF5B5DF671 /* TableViewLiaison+Registration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7160A210AE2A16F6ACA0188A78317B0E /* TableViewLiaison+Registration.swift */; }; + 53AF190579CF80675A8E9E534875077F /* TableViewLiaison+Section.swift in Sources */ = {isa = PBXBuildFile; fileRef = E5A8FE652B4FABB89E82AC4A2CA80A52 /* TableViewLiaison+Section.swift */; }; + 56F39AC14D927E65AD0965CA22023A66 /* TableViewSectionComponentCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7573F233D5F6CEF38AA3F9231D5C2E4F /* TableViewSectionComponentCommand.swift */; }; + 6A61F2EBFFEF9FF3C43CD51EF9BB9138 /* Pods-TableViewLiaison_Tests-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 9BC9E03F36CCD9A13BE770E9AD2744C8 /* Pods-TableViewLiaison_Tests-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6B05DE2E308CB9341E2894DBEC2C777B /* Pods-TableViewLiaison_Example-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = D18F1EAA4C2F1E1907299E3CFC9782EF /* Pods-TableViewLiaison_Example-dummy.m */; }; + 6D2835CA2B2CC12C8A76BD61DD69A950 /* TableViewSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDE1FE52D4B47816AAA4A0465A6F39B8 /* TableViewSection.swift */; }; + 7152DE2CBB0ADEBF21909A9E214133C8 /* AnyTableViewSectionComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4183C3768BE5AAA2E09006A3051EDEE /* AnyTableViewSectionComponent.swift */; }; + 734C1DC03811FDA6A90F446AC9BB9CF1 /* TableViewContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C53ADA2E81C660135544475007B3110 /* TableViewContent.swift */; }; + 77DE9C0F2002AEBB2C6068E51A7CDB78 /* Array+IndexPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = 542204BFED3D8E21F6FD6406D0571869 /* Array+IndexPath.swift */; }; + 83BAD8974888922A3D7D7216FDE5B650 /* TableViewLiaisonPaginationDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DE88C4BEED868F99874D3078C017043 /* TableViewLiaisonPaginationDelegate.swift */; }; + 8771AC5C4136326AAE4F71D6378F2EE7 /* TableViewSectionComponentViewType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98BE1F2019F8B7AE965DFA4E4D69261F /* TableViewSectionComponentViewType.swift */; }; + 8C379B5744813E16E5EF156AE06E4DF6 /* TableViewLiaison+Pagination.swift in Sources */ = {isa = PBXBuildFile; fileRef = 566418E542D0DC1C0EA485D3E76EC55F /* TableViewLiaison+Pagination.swift */; }; + 8DBB48B683CB9670857410796C73A1CC /* Pods-TableViewLiaison_Example-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 2BE2BADE3A60E93388A127D7EC125284 /* Pods-TableViewLiaison_Example-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 963C742AB8687C3A2B2A67D702F15A7B /* TableViewLiaison.swift in Sources */ = {isa = PBXBuildFile; fileRef = C837D66ACA1FC950C8D81A1B3BBCC96E /* TableViewLiaison.swift */; }; + 98264FABC694A549EF590BA0E7E8DEF3 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3212113385A8FBBDB272BD23C409FF61 /* Foundation.framework */; }; + A379FB3BD3AE01952472819680B0DBAA /* TableViewRowCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47DAD4920F28E38D1731BD867D72A348 /* TableViewRowCommand.swift */; }; + A4D0F27AAF3918BBE9544F2520009A84 /* TableViewRegistrationType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 623E6BC5FCBAF959938A78B97326E006 /* TableViewRegistrationType.swift */; }; + A9B7F1C917186C40DC2F3B1ED75AD92E /* Pods-TableViewLiaison_Tests-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = B251F4F82FD3F601D1773D783E80901B /* Pods-TableViewLiaison_Tests-dummy.m */; }; + B5E226F4E5F3FA7B08222406F096245A /* PaginationTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B037171A919F84B9BF52071333B0C76F /* PaginationTableViewCell.swift */; }; + BFA895EEC31D6CF791D69F645A99E291 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3212113385A8FBBDB272BD23C409FF61 /* Foundation.framework */; }; + C3816FA78293ECC5E9F185AE245F2DEC /* TableViewPrefetchCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4A00D88F476EF759F5A341B73FF1B1F /* TableViewPrefetchCommand.swift */; }; + C3C8CF1EECAD6DAEE5FEE0900BB0C259 /* TableViewLiaison+UITableViewDataSourcePrefetching.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC7E37B92952AF0BD7F825F21CA6414D /* TableViewLiaison+UITableViewDataSourcePrefetching.swift */; }; + C733118E5E5BF27403AECB7315CDFF14 /* AnyTableViewRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39440B047BD31AD77D32EED7B722F3F3 /* AnyTableViewRow.swift */; }; + CD1086469F10317979EDCE4C7B5EA3DB /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3212113385A8FBBDB272BD23C409FF61 /* Foundation.framework */; }; + E7263CE313D2C143C18C59F6EAB7C5E2 /* TableViewLiaison+UITableViewDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A0C12FF8D4A6EEAB2AB5195BB399B3A /* TableViewLiaison+UITableViewDataSource.swift */; }; + EC9E6A8C09B6AE625B86E379A3FF3059 /* TableViewSectionComponentDisplayOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BF18FE979A9DF0D96BF5215159AF5FA /* TableViewSectionComponentDisplayOption.swift */; }; + EDC021A4E9CEACF9ACB2FDEAC9535684 /* TableViewHeightType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4ABB758F3C9934C164D319B31E07AF77 /* TableViewHeightType.swift */; }; + EE42C92DD0F4F600F6B35CF6B4EE9453 /* TableViewLiaison-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = E482BB4C586F2457DCA0BCEC25B83792 /* TableViewLiaison-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + F0A077BEAD50D3F0F2125D25F0F3DDB6 /* TableViewLiaison-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 677FCC813D731AC451857AC9F85F5B40 /* TableViewLiaison-dummy.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 830C67D0D8AAF7A81CD6D390AF2775AF /* PBXContainerItemProxy */ = { + 1E95DEC5D006CA26A293210E37470815 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = 1F1AF93A27DC48078E725239389B6149; - remoteInfo = TableViewLiaison; + remoteGlobalIDString = 2DDC787062DD756D0DC8CC0F79AAAD29; + remoteInfo = "Pods-TableViewLiaison_Example"; }; - 8BD23F9124D6A4856CA2E57824CC81E3 /* PBXContainerItemProxy */ = { + C03B3C4C4E0FE0E0FD3EBACCCD7978CC /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = 5999CAFA1A66431EF00DAB4EA6DC5B3D; - remoteInfo = "Pods-TableViewLiaison_Example"; + remoteGlobalIDString = 63B68EDA16878E71CC0225339FF9F10D; + remoteInfo = TableViewLiaison; }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 10B1C53A2CADE23378380A08817D1664 /* TableViewLiaison+Pagination.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "TableViewLiaison+Pagination.swift"; sourceTree = ""; }; - 11C27AD3F52DB9591677D3D254A9D9A6 /* Pods-TableViewLiaison_Example-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-TableViewLiaison_Example-Info.plist"; sourceTree = ""; }; - 13B1994D7FF207834903042899E781D2 /* Pods-TableViewLiaison_Example.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-TableViewLiaison_Example.modulemap"; sourceTree = ""; }; - 17E9F3BCCE82122EDF269A82E851D002 /* TableViewSectionComponentView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TableViewSectionComponentView.swift; sourceTree = ""; }; - 19A10E2085A6F35D84D00183AA3B665E /* TableViewRowCommand.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TableViewRowCommand.swift; sourceTree = ""; }; - 1E167870D969CCB057AECCFC8A66704B /* TableViewLiaison+UITableViewDataSourcePrefetching.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "TableViewLiaison+UITableViewDataSourcePrefetching.swift"; sourceTree = ""; }; - 1EFF66B2DD39937B320B901771C92BE6 /* Pods_TableViewLiaison_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_TableViewLiaison_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 20E1E39E9F37384BC7AD34EB2DFB1040 /* TableViewHeightType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TableViewHeightType.swift; sourceTree = ""; }; - 23551DE62EE3635B18432362E4DD6D07 /* TableViewRegistrationType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TableViewRegistrationType.swift; sourceTree = ""; }; - 27AECBBED6EF8093E1BCC647C10A38F8 /* Pods-TableViewLiaison_Tests-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-TableViewLiaison_Tests-acknowledgements.plist"; sourceTree = ""; }; - 36FECD0F53AAE0EACF9D67120F68CC59 /* TableViewLiaison.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; path = TableViewLiaison.podspec; sourceTree = ""; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; - 3D8199053CC0D4A7938F7E76A8AD0007 /* TableViewLiaison.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = TableViewLiaison.modulemap; sourceTree = ""; }; - 4749D85964F054ADE0C01F72DBF05189 /* Pods-TableViewLiaison_Tests-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-TableViewLiaison_Tests-umbrella.h"; sourceTree = ""; }; - 49EC22D2241750534696D27E5F590755 /* AnyTableViewRow.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AnyTableViewRow.swift; sourceTree = ""; }; - 4B7DF44F73E4D3388DBC196CBB9C4106 /* AnyTableViewSectionComponent.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AnyTableViewSectionComponent.swift; sourceTree = ""; }; - 4F0A07C296C81D2816212A08901F66D8 /* TableViewLiaison.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = TableViewLiaison.xcconfig; sourceTree = ""; }; - 5C9B9CEC5C3DAC1C8133A42E29B2DF6C /* Pods-TableViewLiaison_Tests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-TableViewLiaison_Tests.modulemap"; sourceTree = ""; }; - 5E09BC0F0696D11A9668D449E0896DDA /* TableViewPrefetchCommand.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TableViewPrefetchCommand.swift; sourceTree = ""; }; - 5EFA079AFA1336963EC67F3EA16DA717 /* TableViewSectionComponentCommand.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TableViewSectionComponentCommand.swift; sourceTree = ""; }; - 5F3F499C23DA4ABFDACEB4A56F433639 /* TableViewSection.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TableViewSection.swift; sourceTree = ""; }; - 6102744377C5128F8AD0C091CA4A065D /* TableViewLiaison-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "TableViewLiaison-prefix.pch"; sourceTree = ""; }; - 68A9000AEE92A7E271ACA6CD8788659C /* Array+IndexPath.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Array+IndexPath.swift"; sourceTree = ""; }; - 72469840B78E9E0B47EDE9E9C2A1A9C1 /* TableViewLiaison+Section.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "TableViewLiaison+Section.swift"; sourceTree = ""; }; - 74A918CD6CE6E84B57C9AB5664CDD398 /* TableViewLiaison-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "TableViewLiaison-umbrella.h"; sourceTree = ""; }; - 78BAF03D3CD5A713EC848578283F6EE2 /* TableViewSectionComponent.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TableViewSectionComponent.swift; sourceTree = ""; }; - 79CA9937219F290FAD2548BA508CEA29 /* Pods-TableViewLiaison_Tests-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-TableViewLiaison_Tests-dummy.m"; sourceTree = ""; }; - 7F4A12D83D7136FD5886654139EB4C55 /* Pods-TableViewLiaison_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-TableViewLiaison_Example.debug.xcconfig"; sourceTree = ""; }; - 80BC76774F151BB4C777DD65B6AB1B5D /* UITableView+Generic.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "UITableView+Generic.swift"; sourceTree = ""; }; - 860F10DDB6EA369A90623B927FB55ABA /* Pods-TableViewLiaison_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-TableViewLiaison_Tests.debug.xcconfig"; sourceTree = ""; }; - 8CF6F0B0DEB0789991029ED313993C26 /* Pods-TableViewLiaison_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-TableViewLiaison_Example.release.xcconfig"; sourceTree = ""; }; - 8FD69900CC19612796691F222342A420 /* Pods-TableViewLiaison_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-TableViewLiaison_Tests.release.xcconfig"; sourceTree = ""; }; - 92256764226915400D09832635489CBE /* PaginationTableViewCell.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PaginationTableViewCell.swift; sourceTree = ""; }; - 98DD38E44B1CF1C417D87C8E497699CE /* TableViewContent.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TableViewContent.swift; sourceTree = ""; }; - 99EF0B21EAF329BF515D828AA517206D /* TableViewLiaison.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = TableViewLiaison.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 00182C5E30993E14829AF81F528AF094 /* Pods-TableViewLiaison_Example-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-TableViewLiaison_Example-frameworks.sh"; sourceTree = ""; }; + 06F9FB00A0C7F55098FC9E02A4DC972D /* TableViewLiaison-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "TableViewLiaison-Info.plist"; sourceTree = ""; }; + 16E022ED31B9CA9ABBBF2DF6D4AA8C38 /* Pods-TableViewLiaison_Tests-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-TableViewLiaison_Tests-acknowledgements.markdown"; sourceTree = ""; }; + 1869189E25238662005A4F8A /* TableViewRow+Void.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TableViewRow+Void.swift"; sourceTree = ""; }; + 2BE2BADE3A60E93388A127D7EC125284 /* Pods-TableViewLiaison_Example-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-TableViewLiaison_Example-umbrella.h"; sourceTree = ""; }; + 2CC134A50075CFADAB209CE9701B6826 /* Pods-TableViewLiaison_Tests-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-TableViewLiaison_Tests-Info.plist"; sourceTree = ""; }; + 3212113385A8FBBDB272BD23C409FF61 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + 39440B047BD31AD77D32EED7B722F3F3 /* AnyTableViewRow.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AnyTableViewRow.swift; sourceTree = ""; }; + 47DAD4920F28E38D1731BD867D72A348 /* TableViewRowCommand.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TableViewRowCommand.swift; sourceTree = ""; }; + 4A0C12FF8D4A6EEAB2AB5195BB399B3A /* TableViewLiaison+UITableViewDataSource.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "TableViewLiaison+UITableViewDataSource.swift"; sourceTree = ""; }; + 4ABB758F3C9934C164D319B31E07AF77 /* TableViewHeightType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TableViewHeightType.swift; sourceTree = ""; }; + 4BF18FE979A9DF0D96BF5215159AF5FA /* TableViewSectionComponentDisplayOption.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TableViewSectionComponentDisplayOption.swift; sourceTree = ""; }; + 4DD9D6D89CA3897008D52D231E2896A2 /* Pods-TableViewLiaison_Example-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-TableViewLiaison_Example-Info.plist"; sourceTree = ""; }; + 542204BFED3D8E21F6FD6406D0571869 /* Array+IndexPath.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Array+IndexPath.swift"; sourceTree = ""; }; + 566418E542D0DC1C0EA485D3E76EC55F /* TableViewLiaison+Pagination.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "TableViewLiaison+Pagination.swift"; sourceTree = ""; }; + 56DB21A24ED5601EACDFA056D8F264DE /* Array+SafeAccess.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Array+SafeAccess.swift"; sourceTree = ""; }; + 594DB591A638D8A14C62A0E34CC2E33A /* TableViewLiaison.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; path = TableViewLiaison.podspec; sourceTree = ""; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 623E6BC5FCBAF959938A78B97326E006 /* TableViewRegistrationType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TableViewRegistrationType.swift; sourceTree = ""; }; + 677FCC813D731AC451857AC9F85F5B40 /* TableViewLiaison-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "TableViewLiaison-dummy.m"; sourceTree = ""; }; + 6B9C5722A589B317E4242AE322BD1E5C /* Pods-TableViewLiaison_Tests-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-TableViewLiaison_Tests-acknowledgements.plist"; sourceTree = ""; }; + 6CBB732BC779EF1CC0FC2527613FDA1A /* Pods-TableViewLiaison_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-TableViewLiaison_Example.debug.xcconfig"; sourceTree = ""; }; + 6DE88C4BEED868F99874D3078C017043 /* TableViewLiaisonPaginationDelegate.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TableViewLiaisonPaginationDelegate.swift; sourceTree = ""; }; + 6FEFACE66A9477B446A4629D16700DA6 /* Pods_TableViewLiaison_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_TableViewLiaison_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 7160A210AE2A16F6ACA0188A78317B0E /* TableViewLiaison+Registration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "TableViewLiaison+Registration.swift"; sourceTree = ""; }; + 7573F233D5F6CEF38AA3F9231D5C2E4F /* TableViewSectionComponentCommand.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TableViewSectionComponentCommand.swift; sourceTree = ""; }; + 82C47FDE4CDDB7EB7897588CA54A4DF2 /* Pods-TableViewLiaison_Example-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-TableViewLiaison_Example-acknowledgements.markdown"; sourceTree = ""; }; + 87B09734EAFA49F4EC4715E364864E5E /* Pods-TableViewLiaison_Tests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-TableViewLiaison_Tests.modulemap"; sourceTree = ""; }; + 8D1BBF13016C32E4C948B01547F19111 /* TableViewLiaison-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "TableViewLiaison-prefix.pch"; sourceTree = ""; }; + 8EC28BB46E837AD11ECB38653E396AB0 /* Pods-TableViewLiaison_Example-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-TableViewLiaison_Example-acknowledgements.plist"; sourceTree = ""; }; + 98BE1F2019F8B7AE965DFA4E4D69261F /* TableViewSectionComponentViewType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TableViewSectionComponentViewType.swift; sourceTree = ""; }; + 9BC9E03F36CCD9A13BE770E9AD2744C8 /* Pods-TableViewLiaison_Tests-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-TableViewLiaison_Tests-umbrella.h"; sourceTree = ""; }; + 9C53ADA2E81C660135544475007B3110 /* TableViewContent.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TableViewContent.swift; sourceTree = ""; }; 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; - 9E6B02863445488371DF0F30DE4946E8 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; - A2B5C767CAA2610C6AE259EC646027B4 /* TableViewLiaisonPaginationDelegate.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TableViewLiaisonPaginationDelegate.swift; sourceTree = ""; }; - A8576C6DD35D33E86359341CEDBF4C26 /* Pods-TableViewLiaison_Example-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-TableViewLiaison_Example-acknowledgements.markdown"; sourceTree = ""; }; - AD161E5C8A976FBCE7C64B9B957FDF6B /* Pods-TableViewLiaison_Example-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-TableViewLiaison_Example-acknowledgements.plist"; sourceTree = ""; }; - B6DDE93447EE72DEBF8441C36FBB777C /* TableViewSectionComponentDisplayOption.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TableViewSectionComponentDisplayOption.swift; sourceTree = ""; }; - B8143A0084B93A33F3575B711D164C3B /* Pods-TableViewLiaison_Tests-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-TableViewLiaison_Tests-acknowledgements.markdown"; sourceTree = ""; }; - BCA9FB0B4D7EEE0029C12E606D3F3D87 /* Pods-TableViewLiaison_Example-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-TableViewLiaison_Example-dummy.m"; sourceTree = ""; }; - C198A71F0B43BB6BE9ED2E689C842DBA /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; - C3627E6270141F3D94BF5A8AFCB3A380 /* Array+SafeAccess.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "Array+SafeAccess.swift"; sourceTree = ""; }; - CB4607EFCA7C5F75397649E792E2AFCB /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; - CB5177E80F74242EA432B65270A94930 /* TableViewLiaison+Row.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "TableViewLiaison+Row.swift"; sourceTree = ""; }; - CC3240813F9B0633E678F3653B641464 /* TableViewLiaison-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "TableViewLiaison-dummy.m"; sourceTree = ""; }; - CC88125E071EDBB08FE4B0EA8AAF6775 /* TableViewLiaison.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TableViewLiaison.swift; sourceTree = ""; }; - CCF73F4CCBF347860D5B41206FE137C9 /* PaginationTableViewRow.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PaginationTableViewRow.swift; sourceTree = ""; }; - CF86EA38B17778B70CB98F5AE75D3DD6 /* Pods-TableViewLiaison_Tests-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-TableViewLiaison_Tests-Info.plist"; sourceTree = ""; }; - DF0A59383169AF6CB2AB8EE20E530695 /* Pods-TableViewLiaison_Example-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-TableViewLiaison_Example-umbrella.h"; sourceTree = ""; }; - E9ADD5E1F3BDEA73A16ABAA84AB23AF6 /* TableViewLiaison+UITableViewDelegate.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "TableViewLiaison+UITableViewDelegate.swift"; sourceTree = ""; }; - ED21D359F88D72B583354E2BFDE4A28F /* TableViewLiaison+Registration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "TableViewLiaison+Registration.swift"; sourceTree = ""; }; - F25DD676FC9A44B47F95A7996596BCB1 /* TableViewRow.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TableViewRow.swift; sourceTree = ""; }; - F633119E7AFA9576D7B246F4AF36B81A /* Pods_TableViewLiaison_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_TableViewLiaison_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - FA6BB5B3E5B4C06E1D0BE8C060C9EBE4 /* TableViewLiaison+UITableViewDataSource.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "TableViewLiaison+UITableViewDataSource.swift"; sourceTree = ""; }; - FB9194D388694759FF829A406C2F5221 /* Pods-TableViewLiaison_Example-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-TableViewLiaison_Example-frameworks.sh"; sourceTree = ""; }; - FD108E6301C89D867C3212278347DC08 /* TableViewLiaison-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "TableViewLiaison-Info.plist"; sourceTree = ""; }; + 9DAFADB5BFCF07724523E3507AF4EF39 /* Pods_TableViewLiaison_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_TableViewLiaison_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + A5447DDE7EFBDCF1E929ECA11F09C9BC /* TableViewLiaison+UITableViewDelegate.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "TableViewLiaison+UITableViewDelegate.swift"; sourceTree = ""; }; + A6C8BFB4AD6F7EB7674F79C3CECFFED1 /* TableViewLiaison.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = TableViewLiaison.modulemap; sourceTree = ""; }; + A8193F9DB022E11C068F17689E400330 /* Pods-TableViewLiaison_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-TableViewLiaison_Tests.debug.xcconfig"; sourceTree = ""; }; + ABB0596AEFAA0A39C6D20AC06034569C /* Pods-TableViewLiaison_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-TableViewLiaison_Example.release.xcconfig"; sourceTree = ""; }; + B037171A919F84B9BF52071333B0C76F /* PaginationTableViewCell.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = PaginationTableViewCell.swift; sourceTree = ""; }; + B048904DA3507C0F9CECE45BB214FEA2 /* TableViewLiaison+Row.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "TableViewLiaison+Row.swift"; sourceTree = ""; }; + B251F4F82FD3F601D1773D783E80901B /* Pods-TableViewLiaison_Tests-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-TableViewLiaison_Tests-dummy.m"; sourceTree = ""; }; + BB9E88433CF98F9ACF0C3829E0916090 /* Pods-TableViewLiaison_Example.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-TableViewLiaison_Example.modulemap"; sourceTree = ""; }; + C7449AA9408C515E5B866C6F3F0F6B73 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; + C837D66ACA1FC950C8D81A1B3BBCC96E /* TableViewLiaison.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TableViewLiaison.swift; sourceTree = ""; }; + CE06A532BDFC74C3DF86B17BBCAC24AA /* TableViewLiaison.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = TableViewLiaison.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D18F1EAA4C2F1E1907299E3CFC9782EF /* Pods-TableViewLiaison_Example-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-TableViewLiaison_Example-dummy.m"; sourceTree = ""; }; + D2C77C9761945EBFF60FAFFC4ED1EBBB /* TableViewRow.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TableViewRow.swift; sourceTree = ""; }; + D4183C3768BE5AAA2E09006A3051EDEE /* AnyTableViewSectionComponent.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AnyTableViewSectionComponent.swift; sourceTree = ""; }; + DADE7C5188D309EF91133D8DF4C3FC1E /* TableViewSectionComponent.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TableViewSectionComponent.swift; sourceTree = ""; }; + DC7E37B92952AF0BD7F825F21CA6414D /* TableViewLiaison+UITableViewDataSourcePrefetching.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "TableViewLiaison+UITableViewDataSourcePrefetching.swift"; sourceTree = ""; }; + E482BB4C586F2457DCA0BCEC25B83792 /* TableViewLiaison-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "TableViewLiaison-umbrella.h"; sourceTree = ""; }; + E4A00D88F476EF759F5A341B73FF1B1F /* TableViewPrefetchCommand.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TableViewPrefetchCommand.swift; sourceTree = ""; }; + E5A8FE652B4FABB89E82AC4A2CA80A52 /* TableViewLiaison+Section.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "TableViewLiaison+Section.swift"; sourceTree = ""; }; + E83DA9FE3D4BAAF2B3E4A55E3E3BB16B /* TableViewLiaison.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = TableViewLiaison.xcconfig; sourceTree = ""; }; + EDE1FE52D4B47816AAA4A0465A6F39B8 /* TableViewSection.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TableViewSection.swift; sourceTree = ""; }; + EE66BF70151AEACF266B7B4E3FA7D103 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; + F414CE15008469ED83BD5B05EEE0885B /* Pods-TableViewLiaison_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-TableViewLiaison_Tests.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - 29E8744EDA8896D1DD1E4CBC343B4E62 /* Frameworks */ = { + 24CE9E31E2EEE839A9DC020C4EA03059 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - C5FB9C295871F5844FB2515D510D2081 /* Foundation.framework in Frameworks */, + BFA895EEC31D6CF791D69F645A99E291 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 48FAC3BE92E60547CF627E02DBEBE5AA /* Frameworks */ = { + 6EA74DF5EA800BCC87424BAC9EC2E68C /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 678D9E865042E9FE8D05668B0489FB62 /* Foundation.framework in Frameworks */, + 98264FABC694A549EF590BA0E7E8DEF3 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - E1FE8BC3B01B9F24CA40FD4523905D3F /* Frameworks */ = { + 7ADA5F4F36DD16C4F1BE672BD19F8CB2 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 12E833A65C2B594267122A8528689760 /* Foundation.framework in Frameworks */, + CD1086469F10317979EDCE4C7B5EA3DB /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 087C31486007F01EA50AF7D3DB9EEC0F /* Pod */ = { + 22DF65871D0F4F211523301209831221 /* Products */ = { isa = PBXGroup; children = ( - C198A71F0B43BB6BE9ED2E689C842DBA /* LICENSE */, - 9E6B02863445488371DF0F30DE4946E8 /* README.md */, - 36FECD0F53AAE0EACF9D67120F68CC59 /* TableViewLiaison.podspec */, + 9DAFADB5BFCF07724523E3507AF4EF39 /* Pods_TableViewLiaison_Example.framework */, + 6FEFACE66A9477B446A4629D16700DA6 /* Pods_TableViewLiaison_Tests.framework */, + CE06A532BDFC74C3DF86B17BBCAC24AA /* TableViewLiaison.framework */, ); - name = Pod; + name = Products; sourceTree = ""; }; - 202C21A0F52B7D410EE81659E8C86C81 /* Liaison */ = { + 23F6A333B2A0AFD19815F58424A7BF28 /* Liaison */ = { isa = PBXGroup; children = ( - CC88125E071EDBB08FE4B0EA8AAF6775 /* TableViewLiaison.swift */, - 10B1C53A2CADE23378380A08817D1664 /* TableViewLiaison+Pagination.swift */, - ED21D359F88D72B583354E2BFDE4A28F /* TableViewLiaison+Registration.swift */, - CB5177E80F74242EA432B65270A94930 /* TableViewLiaison+Row.swift */, - 72469840B78E9E0B47EDE9E9C2A1A9C1 /* TableViewLiaison+Section.swift */, - FA6BB5B3E5B4C06E1D0BE8C060C9EBE4 /* TableViewLiaison+UITableViewDataSource.swift */, - 1E167870D969CCB057AECCFC8A66704B /* TableViewLiaison+UITableViewDataSourcePrefetching.swift */, - E9ADD5E1F3BDEA73A16ABAA84AB23AF6 /* TableViewLiaison+UITableViewDelegate.swift */, + C837D66ACA1FC950C8D81A1B3BBCC96E /* TableViewLiaison.swift */, + 566418E542D0DC1C0EA485D3E76EC55F /* TableViewLiaison+Pagination.swift */, + 7160A210AE2A16F6ACA0188A78317B0E /* TableViewLiaison+Registration.swift */, + B048904DA3507C0F9CECE45BB214FEA2 /* TableViewLiaison+Row.swift */, + E5A8FE652B4FABB89E82AC4A2CA80A52 /* TableViewLiaison+Section.swift */, + 4A0C12FF8D4A6EEAB2AB5195BB399B3A /* TableViewLiaison+UITableViewDataSource.swift */, + DC7E37B92952AF0BD7F825F21CA6414D /* TableViewLiaison+UITableViewDataSourcePrefetching.swift */, + A5447DDE7EFBDCF1E929ECA11F09C9BC /* TableViewLiaison+UITableViewDelegate.swift */, ); name = Liaison; path = TableViewLiaison/Classes/Liaison; sourceTree = ""; }; - 41AE14DA9FD1443600138B133F854E9D /* Extensions */ = { + 2A5EFEB26D84A97140088954A4DF41B4 /* Pods-TableViewLiaison_Example */ = { isa = PBXGroup; children = ( - 68A9000AEE92A7E271ACA6CD8788659C /* Array+IndexPath.swift */, - C3627E6270141F3D94BF5A8AFCB3A380 /* Array+SafeAccess.swift */, - 80BC76774F151BB4C777DD65B6AB1B5D /* UITableView+Generic.swift */, + BB9E88433CF98F9ACF0C3829E0916090 /* Pods-TableViewLiaison_Example.modulemap */, + 82C47FDE4CDDB7EB7897588CA54A4DF2 /* Pods-TableViewLiaison_Example-acknowledgements.markdown */, + 8EC28BB46E837AD11ECB38653E396AB0 /* Pods-TableViewLiaison_Example-acknowledgements.plist */, + D18F1EAA4C2F1E1907299E3CFC9782EF /* Pods-TableViewLiaison_Example-dummy.m */, + 00182C5E30993E14829AF81F528AF094 /* Pods-TableViewLiaison_Example-frameworks.sh */, + 4DD9D6D89CA3897008D52D231E2896A2 /* Pods-TableViewLiaison_Example-Info.plist */, + 2BE2BADE3A60E93388A127D7EC125284 /* Pods-TableViewLiaison_Example-umbrella.h */, + 6CBB732BC779EF1CC0FC2527613FDA1A /* Pods-TableViewLiaison_Example.debug.xcconfig */, + ABB0596AEFAA0A39C6D20AC06034569C /* Pods-TableViewLiaison_Example.release.xcconfig */, ); - name = Extensions; - path = TableViewLiaison/Classes/Extensions; + name = "Pods-TableViewLiaison_Example"; + path = "Target Support Files/Pods-TableViewLiaison_Example"; sourceTree = ""; }; - 4916041BBC84B2BA79DC7E85A0DB593A /* Views */ = { + 55B44B9279A2B06DBB504A73B6440D9B /* Extensions */ = { isa = PBXGroup; children = ( - 92256764226915400D09832635489CBE /* PaginationTableViewCell.swift */, + 542204BFED3D8E21F6FD6406D0571869 /* Array+IndexPath.swift */, + 56DB21A24ED5601EACDFA056D8F264DE /* Array+SafeAccess.swift */, ); - name = Views; - path = TableViewLiaison/Classes/Views; + name = Extensions; + path = TableViewLiaison/Classes/Extensions; sourceTree = ""; }; - 6FF1D66B971C02AF78A7DC4A888A459A /* TableViewLiaison */ = { + 5EE765E26B193715D4EE5B82784FE57D /* Pods-TableViewLiaison_Tests */ = { isa = PBXGroup; children = ( - FAFD0C2BB15083FB7D5CDAC9582FB290 /* Enums */, - 41AE14DA9FD1443600138B133F854E9D /* Extensions */, - 202C21A0F52B7D410EE81659E8C86C81 /* Liaison */, - 087C31486007F01EA50AF7D3DB9EEC0F /* Pod */, - 763C60136305E7AEC6B2E509753BEBE4 /* Protocols */, - 9DDB0AF7BC17B07A14A59032B2889C52 /* Rows */, - 9B1B43A0EEC91F8A100BFBA29E63232D /* Sections */, - A741306D7B042B84EA2C546ECFC1BE5A /* Support Files */, - 4916041BBC84B2BA79DC7E85A0DB593A /* Views */, + 87B09734EAFA49F4EC4715E364864E5E /* Pods-TableViewLiaison_Tests.modulemap */, + 16E022ED31B9CA9ABBBF2DF6D4AA8C38 /* Pods-TableViewLiaison_Tests-acknowledgements.markdown */, + 6B9C5722A589B317E4242AE322BD1E5C /* Pods-TableViewLiaison_Tests-acknowledgements.plist */, + B251F4F82FD3F601D1773D783E80901B /* Pods-TableViewLiaison_Tests-dummy.m */, + 2CC134A50075CFADAB209CE9701B6826 /* Pods-TableViewLiaison_Tests-Info.plist */, + 9BC9E03F36CCD9A13BE770E9AD2744C8 /* Pods-TableViewLiaison_Tests-umbrella.h */, + A8193F9DB022E11C068F17689E400330 /* Pods-TableViewLiaison_Tests.debug.xcconfig */, + F414CE15008469ED83BD5B05EEE0885B /* Pods-TableViewLiaison_Tests.release.xcconfig */, ); - name = TableViewLiaison; - path = ../..; + name = "Pods-TableViewLiaison_Tests"; + path = "Target Support Files/Pods-TableViewLiaison_Tests"; sourceTree = ""; }; - 763C60136305E7AEC6B2E509753BEBE4 /* Protocols */ = { + 62A02EE1EA984CB00B6581F1975A2D07 /* Sections */ = { isa = PBXGroup; children = ( - 49EC22D2241750534696D27E5F590755 /* AnyTableViewRow.swift */, - 4B7DF44F73E4D3388DBC196CBB9C4106 /* AnyTableViewSectionComponent.swift */, - 98DD38E44B1CF1C417D87C8E497699CE /* TableViewContent.swift */, - A2B5C767CAA2610C6AE259EC646027B4 /* TableViewLiaisonPaginationDelegate.swift */, + EDE1FE52D4B47816AAA4A0465A6F39B8 /* TableViewSection.swift */, + DADE7C5188D309EF91133D8DF4C3FC1E /* TableViewSectionComponent.swift */, ); - name = Protocols; - path = TableViewLiaison/Classes/Protocols; + name = Sections; + path = TableViewLiaison/Classes/Sections; sourceTree = ""; }; - 8363E33122017345CD0E72766143EB0E /* Products */ = { + 7B40FBB1BC4B77C6F01368EFC43D2A04 /* Support Files */ = { isa = PBXGroup; children = ( - 1EFF66B2DD39937B320B901771C92BE6 /* Pods_TableViewLiaison_Example.framework */, - F633119E7AFA9576D7B246F4AF36B81A /* Pods_TableViewLiaison_Tests.framework */, - 99EF0B21EAF329BF515D828AA517206D /* TableViewLiaison.framework */, + A6C8BFB4AD6F7EB7674F79C3CECFFED1 /* TableViewLiaison.modulemap */, + E83DA9FE3D4BAAF2B3E4A55E3E3BB16B /* TableViewLiaison.xcconfig */, + 677FCC813D731AC451857AC9F85F5B40 /* TableViewLiaison-dummy.m */, + 06F9FB00A0C7F55098FC9E02A4DC972D /* TableViewLiaison-Info.plist */, + 8D1BBF13016C32E4C948B01547F19111 /* TableViewLiaison-prefix.pch */, + E482BB4C586F2457DCA0BCEC25B83792 /* TableViewLiaison-umbrella.h */, ); - name = Products; + name = "Support Files"; + path = "Example/Pods/Target Support Files/TableViewLiaison"; sourceTree = ""; }; 86963B8563104ADB13C6432F2198815D /* Targets Support Files */ = { isa = PBXGroup; children = ( - CFF5527C93C36C9DE5D13F2BF59B3A80 /* Pods-TableViewLiaison_Example */, - B9DDEF5A075E30539905DE22325F2876 /* Pods-TableViewLiaison_Tests */, + 2A5EFEB26D84A97140088954A4DF41B4 /* Pods-TableViewLiaison_Example */, + 5EE765E26B193715D4EE5B82784FE57D /* Pods-TableViewLiaison_Tests */, ); name = "Targets Support Files"; sourceTree = ""; }; - 9B055D0CFEA43187E72B03DED11F5662 /* iOS */ = { - isa = PBXGroup; - children = ( - CB4607EFCA7C5F75397649E792E2AFCB /* Foundation.framework */, - ); - name = iOS; - sourceTree = ""; - }; - 9B1B43A0EEC91F8A100BFBA29E63232D /* Sections */ = { + B2729DE1560CFD1222CA131E7719D989 /* Views */ = { isa = PBXGroup; children = ( - 5F3F499C23DA4ABFDACEB4A56F433639 /* TableViewSection.swift */, - 78BAF03D3CD5A713EC848578283F6EE2 /* TableViewSectionComponent.swift */, + B037171A919F84B9BF52071333B0C76F /* PaginationTableViewCell.swift */, ); - name = Sections; - path = TableViewLiaison/Classes/Sections; + name = Views; + path = TableViewLiaison/Classes/Views; sourceTree = ""; }; - 9DDB0AF7BC17B07A14A59032B2889C52 /* Rows */ = { + BAB66372414C794CBA39D059C42666CD /* Enums */ = { isa = PBXGroup; children = ( - CCF73F4CCBF347860D5B41206FE137C9 /* PaginationTableViewRow.swift */, - F25DD676FC9A44B47F95A7996596BCB1 /* TableViewRow.swift */, + 4ABB758F3C9934C164D319B31E07AF77 /* TableViewHeightType.swift */, + E4A00D88F476EF759F5A341B73FF1B1F /* TableViewPrefetchCommand.swift */, + 623E6BC5FCBAF959938A78B97326E006 /* TableViewRegistrationType.swift */, + 47DAD4920F28E38D1731BD867D72A348 /* TableViewRowCommand.swift */, + 7573F233D5F6CEF38AA3F9231D5C2E4F /* TableViewSectionComponentCommand.swift */, + 4BF18FE979A9DF0D96BF5215159AF5FA /* TableViewSectionComponentDisplayOption.swift */, + 98BE1F2019F8B7AE965DFA4E4D69261F /* TableViewSectionComponentViewType.swift */, ); - name = Rows; - path = TableViewLiaison/Classes/Rows; + name = Enums; + path = TableViewLiaison/Classes/Enums; sourceTree = ""; }; - A741306D7B042B84EA2C546ECFC1BE5A /* Support Files */ = { + C0834CEBB1379A84116EF29F93051C60 /* iOS */ = { isa = PBXGroup; children = ( - 3D8199053CC0D4A7938F7E76A8AD0007 /* TableViewLiaison.modulemap */, - 4F0A07C296C81D2816212A08901F66D8 /* TableViewLiaison.xcconfig */, - CC3240813F9B0633E678F3653B641464 /* TableViewLiaison-dummy.m */, - FD108E6301C89D867C3212278347DC08 /* TableViewLiaison-Info.plist */, - 6102744377C5128F8AD0C091CA4A065D /* TableViewLiaison-prefix.pch */, - 74A918CD6CE6E84B57C9AB5664CDD398 /* TableViewLiaison-umbrella.h */, + 3212113385A8FBBDB272BD23C409FF61 /* Foundation.framework */, ); - name = "Support Files"; - path = "Example/Pods/Target Support Files/TableViewLiaison"; + name = iOS; sourceTree = ""; }; - B9DDEF5A075E30539905DE22325F2876 /* Pods-TableViewLiaison_Tests */ = { + C68E3452623F10551821501FE00CD0FC /* Pod */ = { isa = PBXGroup; children = ( - 5C9B9CEC5C3DAC1C8133A42E29B2DF6C /* Pods-TableViewLiaison_Tests.modulemap */, - B8143A0084B93A33F3575B711D164C3B /* Pods-TableViewLiaison_Tests-acknowledgements.markdown */, - 27AECBBED6EF8093E1BCC647C10A38F8 /* Pods-TableViewLiaison_Tests-acknowledgements.plist */, - 79CA9937219F290FAD2548BA508CEA29 /* Pods-TableViewLiaison_Tests-dummy.m */, - CF86EA38B17778B70CB98F5AE75D3DD6 /* Pods-TableViewLiaison_Tests-Info.plist */, - 4749D85964F054ADE0C01F72DBF05189 /* Pods-TableViewLiaison_Tests-umbrella.h */, - 860F10DDB6EA369A90623B927FB55ABA /* Pods-TableViewLiaison_Tests.debug.xcconfig */, - 8FD69900CC19612796691F222342A420 /* Pods-TableViewLiaison_Tests.release.xcconfig */, + C7449AA9408C515E5B866C6F3F0F6B73 /* LICENSE */, + EE66BF70151AEACF266B7B4E3FA7D103 /* README.md */, + 594DB591A638D8A14C62A0E34CC2E33A /* TableViewLiaison.podspec */, ); - name = "Pods-TableViewLiaison_Tests"; - path = "Target Support Files/Pods-TableViewLiaison_Tests"; + name = Pod; sourceTree = ""; }; CF1408CF629C7361332E53B88F7BD30C = { @@ -309,143 +299,150 @@ 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */, E30A3EA77AA375F77AAFCA2450896A66 /* Development Pods */, D210D550F4EA176C3123ED886F8F87F5 /* Frameworks */, - 8363E33122017345CD0E72766143EB0E /* Products */, + 22DF65871D0F4F211523301209831221 /* Products */, 86963B8563104ADB13C6432F2198815D /* Targets Support Files */, ); sourceTree = ""; }; - CFF5527C93C36C9DE5D13F2BF59B3A80 /* Pods-TableViewLiaison_Example */ = { + D210D550F4EA176C3123ED886F8F87F5 /* Frameworks */ = { isa = PBXGroup; children = ( - 13B1994D7FF207834903042899E781D2 /* Pods-TableViewLiaison_Example.modulemap */, - A8576C6DD35D33E86359341CEDBF4C26 /* Pods-TableViewLiaison_Example-acknowledgements.markdown */, - AD161E5C8A976FBCE7C64B9B957FDF6B /* Pods-TableViewLiaison_Example-acknowledgements.plist */, - BCA9FB0B4D7EEE0029C12E606D3F3D87 /* Pods-TableViewLiaison_Example-dummy.m */, - FB9194D388694759FF829A406C2F5221 /* Pods-TableViewLiaison_Example-frameworks.sh */, - 11C27AD3F52DB9591677D3D254A9D9A6 /* Pods-TableViewLiaison_Example-Info.plist */, - DF0A59383169AF6CB2AB8EE20E530695 /* Pods-TableViewLiaison_Example-umbrella.h */, - 7F4A12D83D7136FD5886654139EB4C55 /* Pods-TableViewLiaison_Example.debug.xcconfig */, - 8CF6F0B0DEB0789991029ED313993C26 /* Pods-TableViewLiaison_Example.release.xcconfig */, + C0834CEBB1379A84116EF29F93051C60 /* iOS */, ); - name = "Pods-TableViewLiaison_Example"; - path = "Target Support Files/Pods-TableViewLiaison_Example"; + name = Frameworks; sourceTree = ""; }; - D210D550F4EA176C3123ED886F8F87F5 /* Frameworks */ = { + D716F9FFCAC7EDE50F6920D6836DD756 /* Protocols */ = { isa = PBXGroup; children = ( - 9B055D0CFEA43187E72B03DED11F5662 /* iOS */, + 39440B047BD31AD77D32EED7B722F3F3 /* AnyTableViewRow.swift */, + D4183C3768BE5AAA2E09006A3051EDEE /* AnyTableViewSectionComponent.swift */, + 9C53ADA2E81C660135544475007B3110 /* TableViewContent.swift */, + 6DE88C4BEED868F99874D3078C017043 /* TableViewLiaisonPaginationDelegate.swift */, ); - name = Frameworks; + name = Protocols; + path = TableViewLiaison/Classes/Protocols; + sourceTree = ""; + }; + D8ACBFF6598EB77A0A8D083C94AC6D68 /* TableViewLiaison */ = { + isa = PBXGroup; + children = ( + BAB66372414C794CBA39D059C42666CD /* Enums */, + 55B44B9279A2B06DBB504A73B6440D9B /* Extensions */, + 23F6A333B2A0AFD19815F58424A7BF28 /* Liaison */, + C68E3452623F10551821501FE00CD0FC /* Pod */, + D716F9FFCAC7EDE50F6920D6836DD756 /* Protocols */, + F89E7D3BA79145527857B394DF18C31E /* Rows */, + 62A02EE1EA984CB00B6581F1975A2D07 /* Sections */, + 7B40FBB1BC4B77C6F01368EFC43D2A04 /* Support Files */, + B2729DE1560CFD1222CA131E7719D989 /* Views */, + ); + name = TableViewLiaison; + path = ../..; sourceTree = ""; }; E30A3EA77AA375F77AAFCA2450896A66 /* Development Pods */ = { isa = PBXGroup; children = ( - 6FF1D66B971C02AF78A7DC4A888A459A /* TableViewLiaison */, + D8ACBFF6598EB77A0A8D083C94AC6D68 /* TableViewLiaison */, ); name = "Development Pods"; sourceTree = ""; }; - FAFD0C2BB15083FB7D5CDAC9582FB290 /* Enums */ = { + F89E7D3BA79145527857B394DF18C31E /* Rows */ = { isa = PBXGroup; children = ( - 20E1E39E9F37384BC7AD34EB2DFB1040 /* TableViewHeightType.swift */, - 5E09BC0F0696D11A9668D449E0896DDA /* TableViewPrefetchCommand.swift */, - 23551DE62EE3635B18432362E4DD6D07 /* TableViewRegistrationType.swift */, - 19A10E2085A6F35D84D00183AA3B665E /* TableViewRowCommand.swift */, - 5EFA079AFA1336963EC67F3EA16DA717 /* TableViewSectionComponentCommand.swift */, - B6DDE93447EE72DEBF8441C36FBB777C /* TableViewSectionComponentDisplayOption.swift */, - 17E9F3BCCE82122EDF269A82E851D002 /* TableViewSectionComponentView.swift */, + D2C77C9761945EBFF60FAFFC4ED1EBBB /* TableViewRow.swift */, + 1869189E25238662005A4F8A /* TableViewRow+Void.swift */, ); - name = Enums; - path = TableViewLiaison/Classes/Enums; + name = Rows; + path = TableViewLiaison/Classes/Rows; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ - 762EBB4B90C42401F1EB34013D14C53E /* Headers */ = { + 8898C118C6345D02F07CC449F7507E3E /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - D180CD203CA3AAE30402692DA5B51A81 /* Pods-TableViewLiaison_Example-umbrella.h in Headers */, + EE42C92DD0F4F600F6B35CF6B4EE9453 /* TableViewLiaison-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; - 91A655F05B1E35824E5C878DEA8A6498 /* Headers */ = { + CB2DEA7A20612C91E091F7164037F578 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 79507A7E4978BF6916F03699B0B64A39 /* TableViewLiaison-umbrella.h in Headers */, + 6A61F2EBFFEF9FF3C43CD51EF9BB9138 /* Pods-TableViewLiaison_Tests-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; - A7EEBC0EDD99EF9928532D89807D6526 /* Headers */ = { + E8DB16A1A6979B45D55F09455FA89018 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 27957164FF471D0625E99B58A52DBCCE /* Pods-TableViewLiaison_Tests-umbrella.h in Headers */, + 8DBB48B683CB9670857410796C73A1CC /* Pods-TableViewLiaison_Example-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ - 1F1AF93A27DC48078E725239389B6149 /* TableViewLiaison */ = { + 2DDC787062DD756D0DC8CC0F79AAAD29 /* Pods-TableViewLiaison_Example */ = { isa = PBXNativeTarget; - buildConfigurationList = 93072F49F88DAB825BB6E94B24448E30 /* Build configuration list for PBXNativeTarget "TableViewLiaison" */; + buildConfigurationList = E601FF309FB648DBAE4DD6608F5A3912 /* Build configuration list for PBXNativeTarget "Pods-TableViewLiaison_Example" */; buildPhases = ( - 91A655F05B1E35824E5C878DEA8A6498 /* Headers */, - 2D1489F94B861128F81EAB314BE7A69C /* Sources */, - 48FAC3BE92E60547CF627E02DBEBE5AA /* Frameworks */, - 33F1B8FB97FBE1DCB86A91D93DAE221E /* Resources */, + E8DB16A1A6979B45D55F09455FA89018 /* Headers */, + 6F5F4899CA26BF2992790C01CA917DC5 /* Sources */, + 7ADA5F4F36DD16C4F1BE672BD19F8CB2 /* Frameworks */, + 77BACC1C95C7A607D8290B2B246D53BD /* Resources */, ); buildRules = ( ); dependencies = ( + 2F08631040717BAF0B68043030E4DC49 /* PBXTargetDependency */, ); - name = TableViewLiaison; - productName = TableViewLiaison; - productReference = 99EF0B21EAF329BF515D828AA517206D /* TableViewLiaison.framework */; + name = "Pods-TableViewLiaison_Example"; + productName = "Pods-TableViewLiaison_Example"; + productReference = 9DAFADB5BFCF07724523E3507AF4EF39 /* Pods_TableViewLiaison_Example.framework */; productType = "com.apple.product-type.framework"; }; - 5999CAFA1A66431EF00DAB4EA6DC5B3D /* Pods-TableViewLiaison_Example */ = { + 583EB31DDD1C8B06BBA505828232B351 /* Pods-TableViewLiaison_Tests */ = { isa = PBXNativeTarget; - buildConfigurationList = F9CDC2FC5E84DA51E71CB92393A9F17C /* Build configuration list for PBXNativeTarget "Pods-TableViewLiaison_Example" */; + buildConfigurationList = 7868C8CAD0F2BFEABB32F26AD49E96E0 /* Build configuration list for PBXNativeTarget "Pods-TableViewLiaison_Tests" */; buildPhases = ( - 762EBB4B90C42401F1EB34013D14C53E /* Headers */, - DCCD75D8F83E203CDCD7024EDD1010B4 /* Sources */, - 29E8744EDA8896D1DD1E4CBC343B4E62 /* Frameworks */, - C805834819FAE4C143A8BA90BE5DDE48 /* Resources */, + CB2DEA7A20612C91E091F7164037F578 /* Headers */, + F4571E1A41E04A71EAA4532636AC622B /* Sources */, + 6EA74DF5EA800BCC87424BAC9EC2E68C /* Frameworks */, + 5ED7E012EC7BBDC05C48510385AFF6FF /* Resources */, ); buildRules = ( ); dependencies = ( - 5D81E15383FB728B4223A9EEAB88C389 /* PBXTargetDependency */, + 1F31D8A87518FE98D58BA7F7BCDB730D /* PBXTargetDependency */, ); - name = "Pods-TableViewLiaison_Example"; - productName = "Pods-TableViewLiaison_Example"; - productReference = 1EFF66B2DD39937B320B901771C92BE6 /* Pods_TableViewLiaison_Example.framework */; + name = "Pods-TableViewLiaison_Tests"; + productName = "Pods-TableViewLiaison_Tests"; + productReference = 6FEFACE66A9477B446A4629D16700DA6 /* Pods_TableViewLiaison_Tests.framework */; productType = "com.apple.product-type.framework"; }; - 87FBBA76EA9B51C025C1362733B43E22 /* Pods-TableViewLiaison_Tests */ = { + 63B68EDA16878E71CC0225339FF9F10D /* TableViewLiaison */ = { isa = PBXNativeTarget; - buildConfigurationList = B068AEA2594636EC40D608B58A462EE5 /* Build configuration list for PBXNativeTarget "Pods-TableViewLiaison_Tests" */; + buildConfigurationList = 29556B3FD8756FDCC1697C1A8FB43B3D /* Build configuration list for PBXNativeTarget "TableViewLiaison" */; buildPhases = ( - A7EEBC0EDD99EF9928532D89807D6526 /* Headers */, - 8FB7C1ADEAD823E1FE6895AE53D2D600 /* Sources */, - E1FE8BC3B01B9F24CA40FD4523905D3F /* Frameworks */, - AB0BF6ADC86D20CEF3A830D97DD59590 /* Resources */, + 8898C118C6345D02F07CC449F7507E3E /* Headers */, + D988F32ECE09FD060E42F636EC47AEA1 /* Sources */, + 24CE9E31E2EEE839A9DC020C4EA03059 /* Frameworks */, + EEBD0714D6E959BE33F05ADAB6A0F199 /* Resources */, ); buildRules = ( ); dependencies = ( - 2B3857C92BB3A484866BA905AA5CCE33 /* PBXTargetDependency */, ); - name = "Pods-TableViewLiaison_Tests"; - productName = "Pods-TableViewLiaison_Tests"; - productReference = F633119E7AFA9576D7B246F4AF36B81A /* Pods_TableViewLiaison_Tests.framework */; + name = TableViewLiaison; + productName = TableViewLiaison; + productReference = CE06A532BDFC74C3DF86B17BBCAC24AA /* TableViewLiaison.framework */; productType = "com.apple.product-type.framework"; }; /* End PBXNativeTarget section */ @@ -454,45 +451,50 @@ BFDFE7DC352907FC980B868725387E98 /* Project object */ = { isa = PBXProject; attributes = { - LastSwiftUpdateCheck = 0930; - LastUpgradeCheck = 1020; + LastSwiftUpdateCheck = 1100; + LastUpgradeCheck = 1200; + TargetAttributes = { + 2DDC787062DD756D0DC8CC0F79AAAD29 = { + LastSwiftMigration = 1020; + }; + }; }; buildConfigurationList = 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */; compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( - English, en, + Base, ); mainGroup = CF1408CF629C7361332E53B88F7BD30C; - productRefGroup = 8363E33122017345CD0E72766143EB0E /* Products */; + productRefGroup = 22DF65871D0F4F211523301209831221 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( - 5999CAFA1A66431EF00DAB4EA6DC5B3D /* Pods-TableViewLiaison_Example */, - 87FBBA76EA9B51C025C1362733B43E22 /* Pods-TableViewLiaison_Tests */, - 1F1AF93A27DC48078E725239389B6149 /* TableViewLiaison */, + 2DDC787062DD756D0DC8CC0F79AAAD29 /* Pods-TableViewLiaison_Example */, + 583EB31DDD1C8B06BBA505828232B351 /* Pods-TableViewLiaison_Tests */, + 63B68EDA16878E71CC0225339FF9F10D /* TableViewLiaison */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - 33F1B8FB97FBE1DCB86A91D93DAE221E /* Resources */ = { + 5ED7E012EC7BBDC05C48510385AFF6FF /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - AB0BF6ADC86D20CEF3A830D97DD59590 /* Resources */ = { + 77BACC1C95C7A607D8290B2B246D53BD /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - C805834819FAE4C143A8BA90BE5DDE48 /* Resources */ = { + EEBD0714D6E959BE33F05ADAB6A0F199 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( @@ -502,76 +504,138 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - 2D1489F94B861128F81EAB314BE7A69C /* Sources */ = { + 6F5F4899CA26BF2992790C01CA917DC5 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 1D1BF19060D11E76D7CBF60241E89120 /* AnyTableViewRow.swift in Sources */, - 302239045403240F0D0E7EB16374389F /* AnyTableViewSectionComponent.swift in Sources */, - 7946E39A15AE394CDEE7A222307F0AEE /* Array+IndexPath.swift in Sources */, - B90578DC814690029E762C516910B4A1 /* Array+SafeAccess.swift in Sources */, - 9EA5C92B8B3FD454C4262F6CDC71D2A2 /* PaginationTableViewCell.swift in Sources */, - 739ACA8474D43D680EFB588A8D366D9F /* PaginationTableViewRow.swift in Sources */, - DE6A02FE586821E7A6ED1D4AB47F2419 /* TableViewContent.swift in Sources */, - 7A7E475325A7684FA97B3AB6138D3E38 /* TableViewHeightType.swift in Sources */, - 7A3FD46128BC5521A04C615707ADB94D /* TableViewLiaison+Pagination.swift in Sources */, - FCA83AD26A019F4F5D77494C43143BA6 /* TableViewLiaison+Registration.swift in Sources */, - 01D6785D207D424DB9FD0ADD076DAE4A /* TableViewLiaison+Row.swift in Sources */, - 65EB91BF6CCC07DA37789690977FF8A5 /* TableViewLiaison+Section.swift in Sources */, - CFB42637BC3629D8A570EE6236E1FE0D /* TableViewLiaison+UITableViewDataSource.swift in Sources */, - F1F7E965462578DEC4FB02B4FAD87F38 /* TableViewLiaison+UITableViewDataSourcePrefetching.swift in Sources */, - 40ECC4BF15F3A6A1A3B242AF322C0803 /* TableViewLiaison+UITableViewDelegate.swift in Sources */, - B6A89549DDDEA62250AE421D621401BC /* TableViewLiaison-dummy.m in Sources */, - 5E0B4CEE1FE23DEF6664679D7D5EEF7E /* TableViewLiaison.swift in Sources */, - 819CB967684EB9F08ED5B0F110CAE62E /* TableViewLiaisonPaginationDelegate.swift in Sources */, - 617CFD248B9E44DAA3C0EF1A59ADD5B3 /* TableViewPrefetchCommand.swift in Sources */, - 575FE4D543A8670CF07A45490783F5E4 /* TableViewRegistrationType.swift in Sources */, - EFA3088B21B8381A686F95F44DB77A9C /* TableViewRow.swift in Sources */, - AFAED8E47A2E9AEC5121976A8907A877 /* TableViewRowCommand.swift in Sources */, - 48AFAD2CEA1D62D424137004F26E177A /* TableViewSection.swift in Sources */, - 6DAA495DAE623FA6765069DC6895F5D4 /* TableViewSectionComponent.swift in Sources */, - 2FB6A8BAA26C5329944B90DD2DD0C57E /* TableViewSectionComponentCommand.swift in Sources */, - 53AB22CC330BE270771764EB297BA1B4 /* TableViewSectionComponentDisplayOption.swift in Sources */, - 72D15770E876499B60D61454B7518A4A /* TableViewSectionComponentView.swift in Sources */, - EA60C2E0610D3CDDB2CD66283E2401ED /* UITableView+Generic.swift in Sources */, + 6B05DE2E308CB9341E2894DBEC2C777B /* Pods-TableViewLiaison_Example-dummy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 8FB7C1ADEAD823E1FE6895AE53D2D600 /* Sources */ = { + D988F32ECE09FD060E42F636EC47AEA1 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - ACB480EC8F2D0BF0E5CB7B1C4041F454 /* Pods-TableViewLiaison_Tests-dummy.m in Sources */, + C733118E5E5BF27403AECB7315CDFF14 /* AnyTableViewRow.swift in Sources */, + 7152DE2CBB0ADEBF21909A9E214133C8 /* AnyTableViewSectionComponent.swift in Sources */, + 77DE9C0F2002AEBB2C6068E51A7CDB78 /* Array+IndexPath.swift in Sources */, + 0AFBC88AA2A93D44CE4477AA73045418 /* Array+SafeAccess.swift in Sources */, + B5E226F4E5F3FA7B08222406F096245A /* PaginationTableViewCell.swift in Sources */, + 734C1DC03811FDA6A90F446AC9BB9CF1 /* TableViewContent.swift in Sources */, + EDC021A4E9CEACF9ACB2FDEAC9535684 /* TableViewHeightType.swift in Sources */, + 1869189F25238662005A4F8A /* TableViewRow+Void.swift in Sources */, + 8C379B5744813E16E5EF156AE06E4DF6 /* TableViewLiaison+Pagination.swift in Sources */, + 474E72CE7ECE34BA46A113FF5B5DF671 /* TableViewLiaison+Registration.swift in Sources */, + 22BAB1493CABE7277E9372CF341CEE0F /* TableViewLiaison+Row.swift in Sources */, + 53AF190579CF80675A8E9E534875077F /* TableViewLiaison+Section.swift in Sources */, + E7263CE313D2C143C18C59F6EAB7C5E2 /* TableViewLiaison+UITableViewDataSource.swift in Sources */, + C3C8CF1EECAD6DAEE5FEE0900BB0C259 /* TableViewLiaison+UITableViewDataSourcePrefetching.swift in Sources */, + 2526A72D2B1AB00A3261B74F3F244072 /* TableViewLiaison+UITableViewDelegate.swift in Sources */, + F0A077BEAD50D3F0F2125D25F0F3DDB6 /* TableViewLiaison-dummy.m in Sources */, + 963C742AB8687C3A2B2A67D702F15A7B /* TableViewLiaison.swift in Sources */, + 83BAD8974888922A3D7D7216FDE5B650 /* TableViewLiaisonPaginationDelegate.swift in Sources */, + C3816FA78293ECC5E9F185AE245F2DEC /* TableViewPrefetchCommand.swift in Sources */, + A4D0F27AAF3918BBE9544F2520009A84 /* TableViewRegistrationType.swift in Sources */, + 05CED4F61B58E01A10BE62785140E744 /* TableViewRow.swift in Sources */, + A379FB3BD3AE01952472819680B0DBAA /* TableViewRowCommand.swift in Sources */, + 6D2835CA2B2CC12C8A76BD61DD69A950 /* TableViewSection.swift in Sources */, + 09BCB9800E121B031FEC743F8C2DE758 /* TableViewSectionComponent.swift in Sources */, + 56F39AC14D927E65AD0965CA22023A66 /* TableViewSectionComponentCommand.swift in Sources */, + EC9E6A8C09B6AE625B86E379A3FF3059 /* TableViewSectionComponentDisplayOption.swift in Sources */, + 8771AC5C4136326AAE4F71D6378F2EE7 /* TableViewSectionComponentViewType.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - DCCD75D8F83E203CDCD7024EDD1010B4 /* Sources */ = { + F4571E1A41E04A71EAA4532636AC622B /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 7742026217FA882BEA5F1B151918142C /* Pods-TableViewLiaison_Example-dummy.m in Sources */, + A9B7F1C917186C40DC2F3B1ED75AD92E /* Pods-TableViewLiaison_Tests-dummy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 2B3857C92BB3A484866BA905AA5CCE33 /* PBXTargetDependency */ = { + 1F31D8A87518FE98D58BA7F7BCDB730D /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = "Pods-TableViewLiaison_Example"; - target = 5999CAFA1A66431EF00DAB4EA6DC5B3D /* Pods-TableViewLiaison_Example */; - targetProxy = 8BD23F9124D6A4856CA2E57824CC81E3 /* PBXContainerItemProxy */; + target = 2DDC787062DD756D0DC8CC0F79AAAD29 /* Pods-TableViewLiaison_Example */; + targetProxy = 1E95DEC5D006CA26A293210E37470815 /* PBXContainerItemProxy */; }; - 5D81E15383FB728B4223A9EEAB88C389 /* PBXTargetDependency */ = { + 2F08631040717BAF0B68043030E4DC49 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = TableViewLiaison; - target = 1F1AF93A27DC48078E725239389B6149 /* TableViewLiaison */; - targetProxy = 830C67D0D8AAF7A81CD6D390AF2775AF /* PBXContainerItemProxy */; + target = 63B68EDA16878E71CC0225339FF9F10D /* TableViewLiaison */; + targetProxy = C03B3C4C4E0FE0E0FD3EBACCCD7978CC /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ - 07488D4657FB0A78086563621D425F8A /* Debug */ = { + 087B9A8A55957E8F6C7994B1851D8069 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E83DA9FE3D4BAAF2B3E4A55E3E3BB16B /* TableViewLiaison.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/TableViewLiaison/TableViewLiaison-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/TableViewLiaison/TableViewLiaison-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/TableViewLiaison/TableViewLiaison.modulemap"; + PRODUCT_MODULE_NAME = TableViewLiaison; + PRODUCT_NAME = TableViewLiaison; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 4C212179AB1C8A13EF0768FBFEB8889C /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E83DA9FE3D4BAAF2B3E4A55E3E3BB16B /* TableViewLiaison.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/TableViewLiaison/TableViewLiaison-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/TableViewLiaison/TableViewLiaison-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/TableViewLiaison/TableViewLiaison.modulemap"; + PRODUCT_MODULE_NAME = TableViewLiaison; + PRODUCT_NAME = TableViewLiaison; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 8F17DC3A99F99FBAD606CE6963886315 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -597,6 +661,67 @@ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_RELEASE=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_INSTALLED_PRODUCT = NO; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 5.0; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Release; + }; + 916E0404255105F480DC4950B7625F7A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -622,7 +747,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -630,45 +755,14 @@ STRIP_INSTALLED_PRODUCT = NO; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 4.2; - SYMROOT = "${SRCROOT}/../build"; - }; - name = Debug; - }; - 0A297DE99A06D5CD255C0DB4013F0911 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 4F0A07C296C81D2816212A08901F66D8 /* TableViewLiaison.xcconfig */; - buildSettings = { - CODE_SIGN_IDENTITY = ""; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/TableViewLiaison/TableViewLiaison-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/TableViewLiaison/TableViewLiaison-Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/TableViewLiaison/TableViewLiaison.modulemap"; - PRODUCT_MODULE_NAME = TableViewLiaison; - PRODUCT_NAME = TableViewLiaison; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; + SYMROOT = "${SRCROOT}/../build"; }; name = Debug; }; - 1C02ED271A6FF93F3833AB3E960E6273 /* Release */ = { + C7993E014DAF10D1345222DB25AF150C /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 8CF6F0B0DEB0789991029ED313993C26 /* Pods-TableViewLiaison_Example.release.xcconfig */; + baseConfigurationReference = A8193F9DB022E11C068F17689E400330 /* Pods-TableViewLiaison_Tests.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; CODE_SIGN_IDENTITY = ""; @@ -680,12 +774,12 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Target Support Files/Pods-TableViewLiaison_Example/Pods-TableViewLiaison_Example-Info.plist"; + INFOPLIST_FILE = "Target Support Files/Pods-TableViewLiaison_Tests/Pods-TableViewLiaison_Tests-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-TableViewLiaison_Example/Pods-TableViewLiaison_Example.modulemap"; + MODULEMAP_FILE = "Target Support Files/Pods-TableViewLiaison_Tests/Pods-TableViewLiaison_Tests.modulemap"; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PODS_ROOT = "$(SRCROOT)"; @@ -694,17 +788,17 @@ SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Release; + name = Debug; }; - 27E2DA000A89D92CCC6462F354C1AE6B /* Debug */ = { + D2C0314B18A773CE4B1005ECC05D4B10 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 860F10DDB6EA369A90623B927FB55ABA /* Pods-TableViewLiaison_Tests.debug.xcconfig */; + baseConfigurationReference = 6CBB732BC779EF1CC0FC2527613FDA1A /* Pods-TableViewLiaison_Example.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -714,12 +808,12 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Target Support Files/Pods-TableViewLiaison_Tests/Pods-TableViewLiaison_Tests-Info.plist"; + INFOPLIST_FILE = "Target Support Files/Pods-TableViewLiaison_Example/Pods-TableViewLiaison_Example-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-TableViewLiaison_Tests/Pods-TableViewLiaison_Tests.modulemap"; + MODULEMAP_FILE = "Target Support Files/Pods-TableViewLiaison_Example/Pods-TableViewLiaison_Example.modulemap"; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PODS_ROOT = "$(SRCROOT)"; @@ -727,15 +821,17 @@ PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Debug; }; - 3AE4905CC229422231DF6FEA137C9C3C /* Release */ = { + D30B2D4FEF30C191D009C98774E96A72 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 8FD69900CC19612796691F222342A420 /* Pods-TableViewLiaison_Tests.release.xcconfig */; + baseConfigurationReference = F414CE15008469ED83BD5B05EEE0885B /* Pods-TableViewLiaison_Tests.release.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; CODE_SIGN_IDENTITY = ""; @@ -749,7 +845,7 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = "Target Support Files/Pods-TableViewLiaison_Tests/Pods-TableViewLiaison_Tests-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACH_O_TYPE = staticlib; MODULEMAP_FILE = "Target Support Files/Pods-TableViewLiaison_Tests/Pods-TableViewLiaison_Tests.modulemap"; @@ -767,70 +863,12 @@ }; name = Release; }; - A1962E6FF39BBAC201A2E5DDF99557DF /* Release */ = { + E8CCE609F5B50E633F69F18239B4F625 /* Release */ = { isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREPROCESSOR_DEFINITIONS = ( - "POD_CONFIGURATION_RELEASE=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; - MTL_ENABLE_DEBUG_INFO = NO; - MTL_FAST_MATH = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; - STRIP_INSTALLED_PRODUCT = NO; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_VERSION = 4.2; - SYMROOT = "${SRCROOT}/../build"; - }; - name = Release; - }; - EC281403C35DA17F2AC100BAD28E6F9F /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7F4A12D83D7136FD5886654139EB4C55 /* Pods-TableViewLiaison_Example.debug.xcconfig */; + baseConfigurationReference = ABB0596AEFAA0A39C6D20AC06034569C /* Pods-TableViewLiaison_Example.release.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -842,7 +880,7 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = "Target Support Files/Pods-TableViewLiaison_Example/Pods-TableViewLiaison_Example-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACH_O_TYPE = staticlib; MODULEMAP_FILE = "Target Support Files/Pods-TableViewLiaison_Example/Pods-TableViewLiaison_Example.modulemap"; @@ -853,36 +891,6 @@ PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SDKROOT = iphoneos; SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - FB89A371B6699E55CC07E31C81907012 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 4F0A07C296C81D2816212A08901F66D8 /* TableViewLiaison.xcconfig */; - buildSettings = { - CODE_SIGN_IDENTITY = ""; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/TableViewLiaison/TableViewLiaison-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/TableViewLiaison/TableViewLiaison-Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/TableViewLiaison/TableViewLiaison.modulemap"; - PRODUCT_MODULE_NAME = TableViewLiaison; - PRODUCT_NAME = TableViewLiaison; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; @@ -894,38 +902,38 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */ = { + 29556B3FD8756FDCC1697C1A8FB43B3D /* Build configuration list for PBXNativeTarget "TableViewLiaison" */ = { isa = XCConfigurationList; buildConfigurations = ( - 07488D4657FB0A78086563621D425F8A /* Debug */, - A1962E6FF39BBAC201A2E5DDF99557DF /* Release */, + 4C212179AB1C8A13EF0768FBFEB8889C /* Debug */, + 087B9A8A55957E8F6C7994B1851D8069 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 93072F49F88DAB825BB6E94B24448E30 /* Build configuration list for PBXNativeTarget "TableViewLiaison" */ = { + 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */ = { isa = XCConfigurationList; buildConfigurations = ( - 0A297DE99A06D5CD255C0DB4013F0911 /* Debug */, - FB89A371B6699E55CC07E31C81907012 /* Release */, + 916E0404255105F480DC4950B7625F7A /* Debug */, + 8F17DC3A99F99FBAD606CE6963886315 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - B068AEA2594636EC40D608B58A462EE5 /* Build configuration list for PBXNativeTarget "Pods-TableViewLiaison_Tests" */ = { + 7868C8CAD0F2BFEABB32F26AD49E96E0 /* Build configuration list for PBXNativeTarget "Pods-TableViewLiaison_Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( - 27E2DA000A89D92CCC6462F354C1AE6B /* Debug */, - 3AE4905CC229422231DF6FEA137C9C3C /* Release */, + C7993E014DAF10D1345222DB25AF150C /* Debug */, + D30B2D4FEF30C191D009C98774E96A72 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - F9CDC2FC5E84DA51E71CB92393A9F17C /* Build configuration list for PBXNativeTarget "Pods-TableViewLiaison_Example" */ = { + E601FF309FB648DBAE4DD6608F5A3912 /* Build configuration list for PBXNativeTarget "Pods-TableViewLiaison_Example" */ = { isa = XCConfigurationList; buildConfigurations = ( - EC281403C35DA17F2AC100BAD28E6F9F /* Debug */, - 1C02ED271A6FF93F3833AB3E960E6273 /* Release */, + D2C0314B18A773CE4B1005ECC05D4B10 /* Debug */, + E8CCE609F5B50E633F69F18239B4F625 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/Example/Pods/Target Support Files/Pods-TableViewLiaison_Example/Pods-TableViewLiaison_Example-frameworks.sh b/Example/Pods/Target Support Files/Pods-TableViewLiaison_Example/Pods-TableViewLiaison_Example-frameworks.sh index b959b96..d51f877 100755 --- a/Example/Pods/Target Support Files/Pods-TableViewLiaison_Example/Pods-TableViewLiaison_Example-frameworks.sh +++ b/Example/Pods/Target Support Files/Pods-TableViewLiaison_Example/Pods-TableViewLiaison_Example-frameworks.sh @@ -94,7 +94,7 @@ install_dsym() { binary="${DERIVED_FILES_DIR}/${basename}.framework.dSYM/Contents/Resources/DWARF/${basename}" # Strip invalid architectures so "fat" simulator / device frameworks work on device - if [[ "$(file "$binary")" == *"Mach-O dSYM companion"* ]]; then + if [[ "$(file "$binary")" == *"Mach-O "*"dSYM companion"* ]]; then strip_invalid_archs "$binary" fi @@ -109,6 +109,14 @@ install_dsym() { fi } +# Copies the bcsymbolmap files of a vendored framework +install_bcsymbolmap() { + local bcsymbolmap_path="$1" + local destination="${BUILT_PRODUCTS_DIR}" + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}" +} + # Signs a framework with the provided identity code_sign_if_enabled() { if [ -n "${EXPANDED_CODE_SIGN_IDENTITY:-}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then diff --git a/Example/Pods/Target Support Files/Pods-TableViewLiaison_Tests/Pods-TableViewLiaison_Tests.debug.xcconfig b/Example/Pods/Target Support Files/Pods-TableViewLiaison_Tests/Pods-TableViewLiaison_Tests.debug.xcconfig index 3bd98a0..c85f108 100644 --- a/Example/Pods/Target Support Files/Pods-TableViewLiaison_Tests/Pods-TableViewLiaison_Tests.debug.xcconfig +++ b/Example/Pods/Target Support Files/Pods-TableViewLiaison_Tests/Pods-TableViewLiaison_Tests.debug.xcconfig @@ -1,7 +1,6 @@ FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/TableViewLiaison" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/TableViewLiaison/TableViewLiaison.framework/Headers" -LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' OTHER_LDFLAGS = $(inherited) -framework "TableViewLiaison" PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) diff --git a/Example/Pods/Target Support Files/Pods-TableViewLiaison_Tests/Pods-TableViewLiaison_Tests.release.xcconfig b/Example/Pods/Target Support Files/Pods-TableViewLiaison_Tests/Pods-TableViewLiaison_Tests.release.xcconfig index 3bd98a0..c85f108 100644 --- a/Example/Pods/Target Support Files/Pods-TableViewLiaison_Tests/Pods-TableViewLiaison_Tests.release.xcconfig +++ b/Example/Pods/Target Support Files/Pods-TableViewLiaison_Tests/Pods-TableViewLiaison_Tests.release.xcconfig @@ -1,7 +1,6 @@ FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/TableViewLiaison" GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/TableViewLiaison/TableViewLiaison.framework/Headers" -LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' OTHER_LDFLAGS = $(inherited) -framework "TableViewLiaison" PODS_BUILD_DIR = ${BUILD_DIR} PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) diff --git a/Example/Pods/Target Support Files/TableViewLiaison/TableViewLiaison-Info.plist b/Example/Pods/Target Support Files/TableViewLiaison/TableViewLiaison-Info.plist index 10ad18b..0a12077 100644 --- a/Example/Pods/Target Support Files/TableViewLiaison/TableViewLiaison-Info.plist +++ b/Example/Pods/Target Support Files/TableViewLiaison/TableViewLiaison-Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.0.3 + 2.0.0 CFBundleSignature ???? CFBundleVersion diff --git a/Example/TableViewLiaison.xcodeproj/project.pbxproj b/Example/TableViewLiaison.xcodeproj/project.pbxproj index a1672b6..05c4c1a 100644 --- a/Example/TableViewLiaison.xcodeproj/project.pbxproj +++ b/Example/TableViewLiaison.xcodeproj/project.pbxproj @@ -7,6 +7,9 @@ objects = { /* Begin PBXBuildFile section */ + 181EB67522D91A1D0081A691 /* NetworkManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 181EB67422D91A1D0081A691 /* NetworkManager.swift */; }; + 187D09CD22D8DF8A00464294 /* TableViewContentFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 187D09CC22D8DF8A00464294 /* TableViewContentFactory.swift */; }; + 18F35FF522E2C94B005C1FEC /* UIColor+Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18F35FF422E2C94B005C1FEC /* UIColor+Constants.swift */; }; 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD51AFB9204008FA782 /* AppDelegate.swift */; }; 607FACD81AFB9204008FA782 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD71AFB9204008FA782 /* ViewController.swift */; }; 607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 607FACD91AFB9204008FA782 /* Main.storyboard */; }; @@ -22,20 +25,14 @@ FC7980C42203546B006DA65D /* ImageTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC7980BC2203546A006DA65D /* ImageTableViewCell.swift */; }; FC7980C52203546B006DA65D /* ActionButtonsTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = FC7980BD2203546B006DA65D /* ActionButtonsTableViewCell.xib */; }; FC7980C62203546B006DA65D /* TextTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC7980BE2203546B006DA65D /* TextTableViewCell.swift */; }; - FC7980C922035487006DA65D /* PostTableViewSectionHeaderViewComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC7980C822035487006DA65D /* PostTableViewSectionHeaderViewComponent.swift */; }; FC7980CD220354A4006DA65D /* User.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC7980CB220354A4006DA65D /* User.swift */; }; FC7980CE220354A4006DA65D /* Post.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC7980CC220354A4006DA65D /* Post.swift */; }; - FC7980D3220354BD006DA65D /* ActionButtonsTableViewRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC7980D0220354BD006DA65D /* ActionButtonsTableViewRow.swift */; }; - FC7980D4220354BD006DA65D /* ImageTableViewRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC7980D1220354BD006DA65D /* ImageTableViewRow.swift */; }; - FC7980D5220354BD006DA65D /* TextTableViewRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC7980D2220354BD006DA65D /* TextTableViewRow.swift */; }; - FC7980D922035618006DA65D /* TextTableViewRowFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC7980D722035618006DA65D /* TextTableViewRowFactory.swift */; }; FC7980DA22035618006DA65D /* PostTableViewSectionFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC7980D822035618006DA65D /* PostTableViewSectionFactory.swift */; }; FC7980DC22035839006DA65D /* PostTableViewSectionHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC7980DB22035839006DA65D /* PostTableViewSectionHeaderView.swift */; }; FC7980EA22035AD3006DA65D /* TestTableHeaderFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC7980DE22035ACB006DA65D /* TestTableHeaderFooterView.swift */; }; FC7980EB22035AD3006DA65D /* TestTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC7980E322035ACC006DA65D /* TestTableViewCell.swift */; }; FC7980EC22035AD3006DA65D /* TestTableViewLiaisonPaginationDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC7980E222035ACB006DA65D /* TestTableViewLiaisonPaginationDelegate.swift */; }; - FC7980ED22035AD3006DA65D /* TestTableViewRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC7980DF22035ACB006DA65D /* TestTableViewRow.swift */; }; - FC7980EE22035AD3006DA65D /* TestTableViewSectionComponent.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC7980E022035ACB006DA65D /* TestTableViewSectionComponent.swift */; }; + FC7980ED22035AD3006DA65D /* TestTableViewComponents.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC7980DF22035ACB006DA65D /* TestTableViewComponents.swift */; }; FC7980EF22035AD3006DA65D /* UITableView+SwizzleTesting.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC7980E122035ACB006DA65D /* UITableView+SwizzleTesting.swift */; }; FC7980F422035AE9006DA65D /* TableViewLiaison+UnitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC7980F022035AE9006DA65D /* TableViewLiaison+UnitTests.swift */; }; FC7980F522035AE9006DA65D /* TableViewRow+UnitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC7980F122035AE9006DA65D /* TableViewRow+UnitTests.swift */; }; @@ -55,7 +52,10 @@ /* Begin PBXFileReference section */ 0F31E225D3F00A591E6B37D6 /* Pods_TableViewLiaison_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_TableViewLiaison_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 181EB67422D91A1D0081A691 /* NetworkManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkManager.swift; sourceTree = ""; }; + 187D09CC22D8DF8A00464294 /* TableViewContentFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TableViewContentFactory.swift; sourceTree = ""; }; 18B62CA01D5E027EA1CC96A7 /* Pods_TableViewLiaison_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_TableViewLiaison_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 18F35FF422E2C94B005C1FEC /* UIColor+Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+Constants.swift"; sourceTree = ""; }; 3E176AE50B84F086C4D7E1A1 /* Pods-TableViewLiaison_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TableViewLiaison_Example.debug.xcconfig"; path = "Target Support Files/Pods-TableViewLiaison_Example/Pods-TableViewLiaison_Example.debug.xcconfig"; sourceTree = ""; }; 607FACD01AFB9204008FA782 /* TableViewLiaison_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TableViewLiaison_Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; 607FACD41AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -80,18 +80,12 @@ FC7980BC2203546A006DA65D /* ImageTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageTableViewCell.swift; sourceTree = ""; }; FC7980BD2203546B006DA65D /* ActionButtonsTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ActionButtonsTableViewCell.xib; sourceTree = ""; }; FC7980BE2203546B006DA65D /* TextTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextTableViewCell.swift; sourceTree = ""; }; - FC7980C822035487006DA65D /* PostTableViewSectionHeaderViewComponent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PostTableViewSectionHeaderViewComponent.swift; sourceTree = ""; }; FC7980CB220354A4006DA65D /* User.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = User.swift; sourceTree = ""; }; FC7980CC220354A4006DA65D /* Post.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Post.swift; sourceTree = ""; }; - FC7980D0220354BD006DA65D /* ActionButtonsTableViewRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActionButtonsTableViewRow.swift; sourceTree = ""; }; - FC7980D1220354BD006DA65D /* ImageTableViewRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageTableViewRow.swift; sourceTree = ""; }; - FC7980D2220354BD006DA65D /* TextTableViewRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextTableViewRow.swift; sourceTree = ""; }; - FC7980D722035618006DA65D /* TextTableViewRowFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextTableViewRowFactory.swift; sourceTree = ""; }; FC7980D822035618006DA65D /* PostTableViewSectionFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PostTableViewSectionFactory.swift; sourceTree = ""; }; FC7980DB22035839006DA65D /* PostTableViewSectionHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostTableViewSectionHeaderView.swift; sourceTree = ""; }; FC7980DE22035ACB006DA65D /* TestTableHeaderFooterView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestTableHeaderFooterView.swift; sourceTree = ""; }; - FC7980DF22035ACB006DA65D /* TestTableViewRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestTableViewRow.swift; sourceTree = ""; }; - FC7980E022035ACB006DA65D /* TestTableViewSectionComponent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestTableViewSectionComponent.swift; sourceTree = ""; }; + FC7980DF22035ACB006DA65D /* TestTableViewComponents.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestTableViewComponents.swift; sourceTree = ""; }; FC7980E122035ACB006DA65D /* UITableView+SwizzleTesting.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UITableView+SwizzleTesting.swift"; sourceTree = ""; }; FC7980E222035ACB006DA65D /* TestTableViewLiaisonPaginationDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestTableViewLiaisonPaginationDelegate.swift; sourceTree = ""; }; FC7980E322035ACC006DA65D /* TestTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestTableViewCell.swift; sourceTree = ""; }; @@ -130,6 +124,14 @@ name = Frameworks; sourceTree = ""; }; + 181EB67322D91A0C0081A691 /* Networking */ = { + isa = PBXGroup; + children = ( + 181EB67422D91A1D0081A691 /* NetworkManager.swift */, + ); + name = Networking; + sourceTree = ""; + }; 607FACC71AFB9204008FA782 = { isa = PBXGroup; children = ( @@ -155,12 +157,11 @@ isa = PBXGroup; children = ( 607FACD71AFB9204008FA782 /* ViewController.swift */, - FC7980CF220354AD006DA65D /* Rows */, FC7980D622035609006DA65D /* Factories */, FC7980CA22035499006DA65D /* Models */, - FC7980C722035475006DA65D /* Sections */, FC7980B622035452006DA65D /* Views */, FC7980B322035439006DA65D /* Extensions */, + 181EB67322D91A0C0081A691 /* Networking */, 607FACD31AFB9204008FA782 /* Supporting Files */, ); name = "Example for TableViewLiaison"; @@ -225,6 +226,7 @@ isa = PBXGroup; children = ( FC7980B42203544C006DA65D /* TimeInterval+SecondConversion.swift */, + 18F35FF422E2C94B005C1FEC /* UIColor+Constants.swift */, ); name = Extensions; sourceTree = ""; @@ -244,14 +246,6 @@ name = Views; sourceTree = ""; }; - FC7980C722035475006DA65D /* Sections */ = { - isa = PBXGroup; - children = ( - FC7980C822035487006DA65D /* PostTableViewSectionHeaderViewComponent.swift */, - ); - name = Sections; - sourceTree = ""; - }; FC7980CA22035499006DA65D /* Models */ = { isa = PBXGroup; children = ( @@ -261,21 +255,11 @@ name = Models; sourceTree = ""; }; - FC7980CF220354AD006DA65D /* Rows */ = { - isa = PBXGroup; - children = ( - FC7980D0220354BD006DA65D /* ActionButtonsTableViewRow.swift */, - FC7980D1220354BD006DA65D /* ImageTableViewRow.swift */, - FC7980D2220354BD006DA65D /* TextTableViewRow.swift */, - ); - name = Rows; - sourceTree = ""; - }; FC7980D622035609006DA65D /* Factories */ = { isa = PBXGroup; children = ( + 187D09CC22D8DF8A00464294 /* TableViewContentFactory.swift */, FC7980D822035618006DA65D /* PostTableViewSectionFactory.swift */, - FC7980D722035618006DA65D /* TextTableViewRowFactory.swift */, ); name = Factories; sourceTree = ""; @@ -286,8 +270,7 @@ FC7980DE22035ACB006DA65D /* TestTableHeaderFooterView.swift */, FC7980E322035ACC006DA65D /* TestTableViewCell.swift */, FC7980E222035ACB006DA65D /* TestTableViewLiaisonPaginationDelegate.swift */, - FC7980DF22035ACB006DA65D /* TestTableViewRow.swift */, - FC7980E022035ACB006DA65D /* TestTableViewSectionComponent.swift */, + FC7980DF22035ACB006DA65D /* TestTableViewComponents.swift */, FC7980E122035ACB006DA65D /* UITableView+SwizzleTesting.swift */, ); name = Fixtures; @@ -341,7 +324,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0830; - LastUpgradeCheck = 1020; + LastUpgradeCheck = 1200; ORGANIZATIONNAME = CocoaPods; TargetAttributes = { 607FACCF1AFB9204008FA782 = { @@ -428,15 +411,11 @@ buildActionMask = 2147483647; files = ( ); - inputFileListPaths = ( - ); inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-TableViewLiaison_Example/Pods-TableViewLiaison_Example-frameworks.sh", "${BUILT_PRODUCTS_DIR}/TableViewLiaison/TableViewLiaison.framework", ); name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - ); outputPaths = ( "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/TableViewLiaison.framework", ); @@ -474,20 +453,18 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 181EB67522D91A1D0081A691 /* NetworkManager.swift in Sources */, FC7980C62203546B006DA65D /* TextTableViewCell.swift in Sources */, FC7980B52203544C006DA65D /* TimeInterval+SecondConversion.swift in Sources */, 607FACD81AFB9204008FA782 /* ViewController.swift in Sources */, FC7980DC22035839006DA65D /* PostTableViewSectionHeaderView.swift in Sources */, - FC7980D4220354BD006DA65D /* ImageTableViewRow.swift in Sources */, FC7980C42203546B006DA65D /* ImageTableViewCell.swift in Sources */, FC7980CD220354A4006DA65D /* User.swift in Sources */, + 187D09CD22D8DF8A00464294 /* TableViewContentFactory.swift in Sources */, FC7980DA22035618006DA65D /* PostTableViewSectionFactory.swift in Sources */, - FC7980C922035487006DA65D /* PostTableViewSectionHeaderViewComponent.swift in Sources */, - FC7980D5220354BD006DA65D /* TextTableViewRow.swift in Sources */, - FC7980D3220354BD006DA65D /* ActionButtonsTableViewRow.swift in Sources */, FC7980C12203546B006DA65D /* ActionButtonsTableViewCell.swift in Sources */, 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */, - FC7980D922035618006DA65D /* TextTableViewRowFactory.swift in Sources */, + 18F35FF522E2C94B005C1FEC /* UIColor+Constants.swift in Sources */, FC7980CE220354A4006DA65D /* Post.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -502,9 +479,8 @@ FC7980F422035AE9006DA65D /* TableViewLiaison+UnitTests.swift in Sources */, FC7980EC22035AD3006DA65D /* TestTableViewLiaisonPaginationDelegate.swift in Sources */, FC7980F522035AE9006DA65D /* TableViewRow+UnitTests.swift in Sources */, - FC7980EE22035AD3006DA65D /* TestTableViewSectionComponent.swift in Sources */, FC7980EB22035AD3006DA65D /* TestTableViewCell.swift in Sources */, - FC7980ED22035AD3006DA65D /* TestTableViewRow.swift in Sources */, + FC7980ED22035AD3006DA65D /* TestTableViewComponents.swift in Sources */, FC7980F722035AE9006DA65D /* TableViewSectionComponent+UnitTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -561,6 +537,7 @@ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -586,11 +563,12 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; }; name = Debug; }; @@ -616,6 +594,7 @@ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -634,10 +613,11 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 5.0; VALIDATE_PRODUCT = YES; }; name = Release; @@ -649,11 +629,13 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; DEVELOPMENT_TEAM = Z3Y4VUCM48; INFOPLIST_FILE = TableViewLiaison/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; MODULE_NAME = ExampleApp; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 1; }; name = Debug; }; @@ -664,11 +646,13 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; DEVELOPMENT_TEAM = Z3Y4VUCM48; INFOPLIST_FILE = TableViewLiaison/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; MODULE_NAME = ExampleApp; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = 1; }; name = Release; }; diff --git a/Example/TableViewLiaison.xcodeproj/xcshareddata/xcschemes/TableViewLiaison-Example.xcscheme b/Example/TableViewLiaison.xcodeproj/xcshareddata/xcschemes/TableViewLiaison-Example.xcscheme index b4b36d4..0f84b30 100644 --- a/Example/TableViewLiaison.xcodeproj/xcshareddata/xcschemes/TableViewLiaison-Example.xcscheme +++ b/Example/TableViewLiaison.xcodeproj/xcshareddata/xcschemes/TableViewLiaison-Example.xcscheme @@ -1,6 +1,6 @@ + shouldUseLaunchSchemeArgsEnv = "YES" + codeCoverageEnabled = "YES"> + + + + @@ -53,17 +63,6 @@ - - - - - - - - - + - + - - + + - + + + - + @@ -54,7 +60,13 @@ - + + + + + + + diff --git a/Example/TableViewLiaison/ActionButtonsTableViewRow.swift b/Example/TableViewLiaison/ActionButtonsTableViewRow.swift deleted file mode 100644 index 9976367..0000000 --- a/Example/TableViewLiaison/ActionButtonsTableViewRow.swift +++ /dev/null @@ -1,27 +0,0 @@ -// -// ActionButtonsTableViewRow.swift -// OKTableViewLiaison_Example -// -// Created by Dylan Shine on 5/15/18. -// Copyright © 2018 CocoaPods. All rights reserved. -// - -import Foundation -import TableViewLiaison - -final class ActionButtonsTableViewRow: TableViewRow { - - init() { - super.init((), registrationType: .defaultNibType) - - set(height: .height, 30) - set(command: .configuration) { cell, _, _ in - cell.likeButton.setTitle("❤️", for: .normal) - cell.commentButton.setTitle("💬", for: .normal) - cell.messageButton.setTitle("📮", for: .normal) - cell.bookmarkButton.setTitle("📚", for: .normal) - cell.selectionStyle = .none - } - } - -} diff --git a/Example/TableViewLiaison/Base.lproj/LaunchScreen.xib b/Example/TableViewLiaison/Base.lproj/LaunchScreen.xib index db36720..762f8eb 100644 --- a/Example/TableViewLiaison/Base.lproj/LaunchScreen.xib +++ b/Example/TableViewLiaison/Base.lproj/LaunchScreen.xib @@ -1,35 +1,32 @@ - - - - + + - - + - + - - + @@ -40,7 +37,7 @@ - + diff --git a/Example/TableViewLiaison/Base.lproj/Main.storyboard b/Example/TableViewLiaison/Base.lproj/Main.storyboard index cc6e0cc..72e56d4 100644 --- a/Example/TableViewLiaison/Base.lproj/Main.storyboard +++ b/Example/TableViewLiaison/Base.lproj/Main.storyboard @@ -1,11 +1,11 @@ - + - + @@ -21,12 +21,15 @@ - + - + + + - + + diff --git a/Example/TableViewLiaison/ImageTableViewCell.swift b/Example/TableViewLiaison/ImageTableViewCell.swift index 71d7c06..6df02c9 100644 --- a/Example/TableViewLiaison/ImageTableViewCell.swift +++ b/Example/TableViewLiaison/ImageTableViewCell.swift @@ -3,13 +3,33 @@ // TableViewLiaison_Example // // Created by Dylan Shine on 3/29/18. -// Copyright © 2018 OkCupid. All rights reserved. +// Copyright © 2018 Shine Labs. All rights reserved. // import UIKit final class ImageTableViewCell: UITableViewCell { - @IBOutlet weak var contentImageView: UIImageView! + @IBOutlet private weak var spinner: UIActivityIndicatorView! + @IBOutlet private weak var contentImageView: UIImageView! + + var contentImage: UIImage? { + get { return contentImageView.image } + set { + if let image = newValue{ + contentImageView.image = image + spinner.stopAnimating() + } else { + contentImageView.image = nil + spinner.isHidden = false + spinner.startAnimating() + } + } + } + + override func prepareForReuse() { + super.prepareForReuse() + contentImage = nil + } } diff --git a/Example/TableViewLiaison/ImageTableViewCell.xib b/Example/TableViewLiaison/ImageTableViewCell.xib index 438277d..0dfb866 100644 --- a/Example/TableViewLiaison/ImageTableViewCell.xib +++ b/Example/TableViewLiaison/ImageTableViewCell.xib @@ -1,38 +1,47 @@ - + - + - + - + + + + + + + + + + diff --git a/Example/TableViewLiaison/ImageTableViewRow.swift b/Example/TableViewLiaison/ImageTableViewRow.swift deleted file mode 100644 index 09feb85..0000000 --- a/Example/TableViewLiaison/ImageTableViewRow.swift +++ /dev/null @@ -1,35 +0,0 @@ -// -// ImageTableViewRow.swift -// OKTableViewLiaison_Example -// -// Created by Dylan Shine on 5/15/18. -// Copyright © 2018 CocoaPods. All rights reserved. -// - -import Foundation -import TableViewLiaison - -final class ImageTableViewRow: TableViewRow { - - init(image: UIImage, tableView: UITableView) { - - super.init(image, registrationType: .defaultNibType) - - set(height: .height) { [weak tableView] image -> CGFloat in - - guard let tableView = tableView else { - return 0 - } - - let ratio = image.size.width / image.size.height - - return tableView.frame.width / ratio - } - - set(command: .configuration) { cell, image, indexPath in - cell.contentImageView.image = image - cell.contentImageView.contentMode = .scaleAspectFill - } - } -} - diff --git a/Example/TableViewLiaison/Images.xcassets/AppIcon.appiconset/Contents.json b/Example/TableViewLiaison/Images.xcassets/AppIcon.appiconset/Contents.json index 7006c9e..ddbd406 100644 --- a/Example/TableViewLiaison/Images.xcassets/AppIcon.appiconset/Contents.json +++ b/Example/TableViewLiaison/Images.xcassets/AppIcon.appiconset/Contents.json @@ -1,53 +1,68 @@ { "images" : [ { + "filename" : "Icon-App-20x20@2x.png", "idiom" : "iphone", - "size" : "20x20", - "scale" : "2x" + "scale" : "2x", + "size" : "20x20" }, { + "filename" : "Icon-App-20x20@3x.png", "idiom" : "iphone", - "size" : "20x20", - "scale" : "3x" + "scale" : "3x", + "size" : "20x20" }, { + "filename" : "Icon-App-29x29@1x.png", "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" + "scale" : "1x", + "size" : "29x29" }, { + "filename" : "Icon-App-29x29@2x.png", "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" + "scale" : "2x", + "size" : "29x29" }, { + "filename" : "Icon-App-29x29@3x.png", "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" + "scale" : "3x", + "size" : "29x29" }, { + "filename" : "Icon-App-40x40@2x.png", "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" + "scale" : "2x", + "size" : "40x40" }, { + "filename" : "Icon-App-40x40@3x.png", "idiom" : "iphone", - "size" : "60x60", - "scale" : "2x" + "scale" : "3x", + "size" : "40x40" }, { + "filename" : "Icon-App-60x60@2x.png", "idiom" : "iphone", - "size" : "60x60", - "scale" : "3x" + "scale" : "2x", + "size" : "60x60" }, { + "filename" : "Icon-App-60x60@3x.png", + "idiom" : "iphone", + "scale" : "3x", + "size" : "60x60" + }, + { + "filename" : "ItunesArtwork@2x.png", "idiom" : "ios-marketing", - "size" : "1024x1024", - "scale" : "1x" + "scale" : "1x", + "size" : "1024x1024" } ], "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 } } diff --git a/Example/TableViewLiaison/Images.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/Example/TableViewLiaison/Images.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 0000000..12e9934 Binary files /dev/null and b/Example/TableViewLiaison/Images.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/Example/TableViewLiaison/Images.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/Example/TableViewLiaison/Images.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000..1d2f4dd Binary files /dev/null and b/Example/TableViewLiaison/Images.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/Example/TableViewLiaison/Images.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/Example/TableViewLiaison/Images.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 0000000..9f896d1 Binary files /dev/null and b/Example/TableViewLiaison/Images.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/Example/TableViewLiaison/Images.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/Example/TableViewLiaison/Images.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 0000000..558bbc0 Binary files /dev/null and b/Example/TableViewLiaison/Images.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/Example/TableViewLiaison/Images.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/Example/TableViewLiaison/Images.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png new file mode 100644 index 0000000..d864945 Binary files /dev/null and b/Example/TableViewLiaison/Images.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/Example/TableViewLiaison/Images.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/Example/TableViewLiaison/Images.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000..78061d6 Binary files /dev/null and b/Example/TableViewLiaison/Images.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/Example/TableViewLiaison/Images.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/Example/TableViewLiaison/Images.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 0000000..1b47654 Binary files /dev/null and b/Example/TableViewLiaison/Images.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/Example/TableViewLiaison/Images.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/Example/TableViewLiaison/Images.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000..1b47654 Binary files /dev/null and b/Example/TableViewLiaison/Images.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/Example/TableViewLiaison/Images.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/Example/TableViewLiaison/Images.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000..6b6f691 Binary files /dev/null and b/Example/TableViewLiaison/Images.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/Example/TableViewLiaison/Images.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png b/Example/TableViewLiaison/Images.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png new file mode 100644 index 0000000..60c1080 Binary files /dev/null and b/Example/TableViewLiaison/Images.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png differ diff --git a/Example/TableViewLiaison/Images.xcassets/Contents.json b/Example/TableViewLiaison/Images.xcassets/Contents.json index da4a164..73c0059 100644 --- a/Example/TableViewLiaison/Images.xcassets/Contents.json +++ b/Example/TableViewLiaison/Images.xcassets/Contents.json @@ -1,6 +1,6 @@ { "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 } -} \ No newline at end of file +} diff --git a/Example/TableViewLiaison/Images.xcassets/bear.imageset/bear.jpg b/Example/TableViewLiaison/Images.xcassets/bear.imageset/bear.jpg deleted file mode 100644 index adce327..0000000 Binary files a/Example/TableViewLiaison/Images.xcassets/bear.imageset/bear.jpg and /dev/null differ diff --git a/Example/TableViewLiaison/Images.xcassets/bookmark.imageset/Contents.json b/Example/TableViewLiaison/Images.xcassets/bookmark.imageset/Contents.json new file mode 100644 index 0000000..eb049e3 --- /dev/null +++ b/Example/TableViewLiaison/Images.xcassets/bookmark.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "bookmark@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "bookmark@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "bookmark@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Example/TableViewLiaison/Images.xcassets/bookmark.imageset/bookmark@1x.png b/Example/TableViewLiaison/Images.xcassets/bookmark.imageset/bookmark@1x.png new file mode 100644 index 0000000..bf6bd98 Binary files /dev/null and b/Example/TableViewLiaison/Images.xcassets/bookmark.imageset/bookmark@1x.png differ diff --git a/Example/TableViewLiaison/Images.xcassets/bookmark.imageset/bookmark@2x.png b/Example/TableViewLiaison/Images.xcassets/bookmark.imageset/bookmark@2x.png new file mode 100644 index 0000000..f720d98 Binary files /dev/null and b/Example/TableViewLiaison/Images.xcassets/bookmark.imageset/bookmark@2x.png differ diff --git a/Example/TableViewLiaison/Images.xcassets/bookmark.imageset/bookmark@3x.png b/Example/TableViewLiaison/Images.xcassets/bookmark.imageset/bookmark@3x.png new file mode 100644 index 0000000..4379405 Binary files /dev/null and b/Example/TableViewLiaison/Images.xcassets/bookmark.imageset/bookmark@3x.png differ diff --git a/Example/TableViewLiaison/Images.xcassets/dylan.imageset/Contents.json b/Example/TableViewLiaison/Images.xcassets/chat.imageset/Contents.json similarity index 72% rename from Example/TableViewLiaison/Images.xcassets/dylan.imageset/Contents.json rename to Example/TableViewLiaison/Images.xcassets/chat.imageset/Contents.json index 43764e2..b51790e 100644 --- a/Example/TableViewLiaison/Images.xcassets/dylan.imageset/Contents.json +++ b/Example/TableViewLiaison/Images.xcassets/chat.imageset/Contents.json @@ -2,15 +2,17 @@ "images" : [ { "idiom" : "universal", - "filename" : "dylan.png", + "filename" : "chat@1x.png", "scale" : "1x" }, { "idiom" : "universal", + "filename" : "chat@2x.png", "scale" : "2x" }, { "idiom" : "universal", + "filename" : "chat@3x.png", "scale" : "3x" } ], diff --git a/Example/TableViewLiaison/Images.xcassets/chat.imageset/chat@1x.png b/Example/TableViewLiaison/Images.xcassets/chat.imageset/chat@1x.png new file mode 100644 index 0000000..45fd55c Binary files /dev/null and b/Example/TableViewLiaison/Images.xcassets/chat.imageset/chat@1x.png differ diff --git a/Example/TableViewLiaison/Images.xcassets/chat.imageset/chat@2x.png b/Example/TableViewLiaison/Images.xcassets/chat.imageset/chat@2x.png new file mode 100644 index 0000000..b97bd95 Binary files /dev/null and b/Example/TableViewLiaison/Images.xcassets/chat.imageset/chat@2x.png differ diff --git a/Example/TableViewLiaison/Images.xcassets/chat.imageset/chat@3x.png b/Example/TableViewLiaison/Images.xcassets/chat.imageset/chat@3x.png new file mode 100644 index 0000000..9dba0a4 Binary files /dev/null and b/Example/TableViewLiaison/Images.xcassets/chat.imageset/chat@3x.png differ diff --git a/Example/TableViewLiaison/Images.xcassets/dylan.imageset/dylan.png b/Example/TableViewLiaison/Images.xcassets/dylan.imageset/dylan.png deleted file mode 100644 index e02f7d9..0000000 Binary files a/Example/TableViewLiaison/Images.xcassets/dylan.imageset/dylan.png and /dev/null differ diff --git a/Example/TableViewLiaison/Images.xcassets/elephant.imageset/elephant.jpg b/Example/TableViewLiaison/Images.xcassets/elephant.imageset/elephant.jpg deleted file mode 100644 index 9d3fc09..0000000 Binary files a/Example/TableViewLiaison/Images.xcassets/elephant.imageset/elephant.jpg and /dev/null differ diff --git a/Example/TableViewLiaison/Images.xcassets/fox.imageset/fox.jpg b/Example/TableViewLiaison/Images.xcassets/fox.imageset/fox.jpg deleted file mode 100644 index c413bdf..0000000 Binary files a/Example/TableViewLiaison/Images.xcassets/fox.imageset/fox.jpg and /dev/null differ diff --git a/Example/TableViewLiaison/Images.xcassets/giraffe.imageset/Contents.json b/Example/TableViewLiaison/Images.xcassets/giraffe.imageset/Contents.json deleted file mode 100644 index 88aefa1..0000000 --- a/Example/TableViewLiaison/Images.xcassets/giraffe.imageset/Contents.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "giraffe.jpg", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/Example/TableViewLiaison/Images.xcassets/giraffe.imageset/giraffe.jpg b/Example/TableViewLiaison/Images.xcassets/giraffe.imageset/giraffe.jpg deleted file mode 100644 index 39cb716..0000000 Binary files a/Example/TableViewLiaison/Images.xcassets/giraffe.imageset/giraffe.jpg and /dev/null differ diff --git a/Example/TableViewLiaison/Images.xcassets/gorilla.imageset/Contents.json b/Example/TableViewLiaison/Images.xcassets/gorilla.imageset/Contents.json deleted file mode 100644 index 54abe67..0000000 --- a/Example/TableViewLiaison/Images.xcassets/gorilla.imageset/Contents.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "gorilla.jpg", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/Example/TableViewLiaison/Images.xcassets/gorilla.imageset/gorilla.jpg b/Example/TableViewLiaison/Images.xcassets/gorilla.imageset/gorilla.jpg deleted file mode 100644 index 0a88af7..0000000 Binary files a/Example/TableViewLiaison/Images.xcassets/gorilla.imageset/gorilla.jpg and /dev/null differ diff --git a/Example/TableViewLiaison/Images.xcassets/elephant.imageset/Contents.json b/Example/TableViewLiaison/Images.xcassets/hide.imageset/Contents.json similarity index 72% rename from Example/TableViewLiaison/Images.xcassets/elephant.imageset/Contents.json rename to Example/TableViewLiaison/Images.xcassets/hide.imageset/Contents.json index 0ed6c59..a89df58 100644 --- a/Example/TableViewLiaison/Images.xcassets/elephant.imageset/Contents.json +++ b/Example/TableViewLiaison/Images.xcassets/hide.imageset/Contents.json @@ -2,15 +2,17 @@ "images" : [ { "idiom" : "universal", - "filename" : "elephant.jpg", + "filename" : "hide@1x.png", "scale" : "1x" }, { "idiom" : "universal", + "filename" : "hide@2x.png", "scale" : "2x" }, { "idiom" : "universal", + "filename" : "hide@3x.png", "scale" : "3x" } ], diff --git a/Example/TableViewLiaison/Images.xcassets/hide.imageset/hide@1x.png b/Example/TableViewLiaison/Images.xcassets/hide.imageset/hide@1x.png new file mode 100644 index 0000000..6f28b8e Binary files /dev/null and b/Example/TableViewLiaison/Images.xcassets/hide.imageset/hide@1x.png differ diff --git a/Example/TableViewLiaison/Images.xcassets/hide.imageset/hide@2x.png b/Example/TableViewLiaison/Images.xcassets/hide.imageset/hide@2x.png new file mode 100644 index 0000000..414b0b8 Binary files /dev/null and b/Example/TableViewLiaison/Images.xcassets/hide.imageset/hide@2x.png differ diff --git a/Example/TableViewLiaison/Images.xcassets/hide.imageset/hide@3x.png b/Example/TableViewLiaison/Images.xcassets/hide.imageset/hide@3x.png new file mode 100644 index 0000000..e81936d Binary files /dev/null and b/Example/TableViewLiaison/Images.xcassets/hide.imageset/hide@3x.png differ diff --git a/Example/TableViewLiaison/Images.xcassets/bear.imageset/Contents.json b/Example/TableViewLiaison/Images.xcassets/like.imageset/Contents.json similarity index 72% rename from Example/TableViewLiaison/Images.xcassets/bear.imageset/Contents.json rename to Example/TableViewLiaison/Images.xcassets/like.imageset/Contents.json index 0c5a03c..73fbd20 100644 --- a/Example/TableViewLiaison/Images.xcassets/bear.imageset/Contents.json +++ b/Example/TableViewLiaison/Images.xcassets/like.imageset/Contents.json @@ -2,15 +2,17 @@ "images" : [ { "idiom" : "universal", - "filename" : "bear.jpg", + "filename" : "like@1x.png", "scale" : "1x" }, { "idiom" : "universal", + "filename" : "like@2x.png", "scale" : "2x" }, { "idiom" : "universal", + "filename" : "like@3x.png", "scale" : "3x" } ], diff --git a/Example/TableViewLiaison/Images.xcassets/like.imageset/like@1x.png b/Example/TableViewLiaison/Images.xcassets/like.imageset/like@1x.png new file mode 100644 index 0000000..3e8c73b Binary files /dev/null and b/Example/TableViewLiaison/Images.xcassets/like.imageset/like@1x.png differ diff --git a/Example/TableViewLiaison/Images.xcassets/like.imageset/like@2x.png b/Example/TableViewLiaison/Images.xcassets/like.imageset/like@2x.png new file mode 100644 index 0000000..cf13d75 Binary files /dev/null and b/Example/TableViewLiaison/Images.xcassets/like.imageset/like@2x.png differ diff --git a/Example/TableViewLiaison/Images.xcassets/like.imageset/like@3x.png b/Example/TableViewLiaison/Images.xcassets/like.imageset/like@3x.png new file mode 100644 index 0000000..92dfef7 Binary files /dev/null and b/Example/TableViewLiaison/Images.xcassets/like.imageset/like@3x.png differ diff --git a/Example/TableViewLiaison/Images.xcassets/moose.imageset/Contents.json b/Example/TableViewLiaison/Images.xcassets/moose.imageset/Contents.json deleted file mode 100644 index 56532a7..0000000 --- a/Example/TableViewLiaison/Images.xcassets/moose.imageset/Contents.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "moose.jpg", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/Example/TableViewLiaison/Images.xcassets/moose.imageset/moose.jpg b/Example/TableViewLiaison/Images.xcassets/moose.imageset/moose.jpg deleted file mode 100644 index 9a3f19e..0000000 Binary files a/Example/TableViewLiaison/Images.xcassets/moose.imageset/moose.jpg and /dev/null differ diff --git a/Example/TableViewLiaison/Images.xcassets/share.imageset/Contents.json b/Example/TableViewLiaison/Images.xcassets/share.imageset/Contents.json new file mode 100644 index 0000000..0fb5038 --- /dev/null +++ b/Example/TableViewLiaison/Images.xcassets/share.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "share@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "share@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "share@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Example/TableViewLiaison/Images.xcassets/share.imageset/share@1x.png b/Example/TableViewLiaison/Images.xcassets/share.imageset/share@1x.png new file mode 100644 index 0000000..286bb56 Binary files /dev/null and b/Example/TableViewLiaison/Images.xcassets/share.imageset/share@1x.png differ diff --git a/Example/TableViewLiaison/Images.xcassets/share.imageset/share@2x.png b/Example/TableViewLiaison/Images.xcassets/share.imageset/share@2x.png new file mode 100644 index 0000000..744ec17 Binary files /dev/null and b/Example/TableViewLiaison/Images.xcassets/share.imageset/share@2x.png differ diff --git a/Example/TableViewLiaison/Images.xcassets/share.imageset/share@3x.png b/Example/TableViewLiaison/Images.xcassets/share.imageset/share@3x.png new file mode 100644 index 0000000..76e62b7 Binary files /dev/null and b/Example/TableViewLiaison/Images.xcassets/share.imageset/share@3x.png differ diff --git a/Example/TableViewLiaison/Images.xcassets/fox.imageset/Contents.json b/Example/TableViewLiaison/Images.xcassets/swap.imageset/Contents.json similarity index 72% rename from Example/TableViewLiaison/Images.xcassets/fox.imageset/Contents.json rename to Example/TableViewLiaison/Images.xcassets/swap.imageset/Contents.json index e4509f1..ba261e4 100644 --- a/Example/TableViewLiaison/Images.xcassets/fox.imageset/Contents.json +++ b/Example/TableViewLiaison/Images.xcassets/swap.imageset/Contents.json @@ -2,15 +2,17 @@ "images" : [ { "idiom" : "universal", - "filename" : "fox.jpg", + "filename" : "swap@1x.png", "scale" : "1x" }, { "idiom" : "universal", + "filename" : "swap@2x.png", "scale" : "2x" }, { "idiom" : "universal", + "filename" : "swap@3x.png", "scale" : "3x" } ], diff --git a/Example/TableViewLiaison/Images.xcassets/swap.imageset/swap@1x.png b/Example/TableViewLiaison/Images.xcassets/swap.imageset/swap@1x.png new file mode 100644 index 0000000..62f282e Binary files /dev/null and b/Example/TableViewLiaison/Images.xcassets/swap.imageset/swap@1x.png differ diff --git a/Example/TableViewLiaison/Images.xcassets/swap.imageset/swap@2x.png b/Example/TableViewLiaison/Images.xcassets/swap.imageset/swap@2x.png new file mode 100644 index 0000000..8d956ed Binary files /dev/null and b/Example/TableViewLiaison/Images.xcassets/swap.imageset/swap@2x.png differ diff --git a/Example/TableViewLiaison/Images.xcassets/swap.imageset/swap@3x.png b/Example/TableViewLiaison/Images.xcassets/swap.imageset/swap@3x.png new file mode 100644 index 0000000..f32a33f Binary files /dev/null and b/Example/TableViewLiaison/Images.xcassets/swap.imageset/swap@3x.png differ diff --git a/Example/TableViewLiaison/Images.xcassets/tiger.imageset/Contents.json b/Example/TableViewLiaison/Images.xcassets/tiger.imageset/Contents.json deleted file mode 100644 index b1a80bb..0000000 --- a/Example/TableViewLiaison/Images.xcassets/tiger.imageset/Contents.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "tiger.jpg", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/Example/TableViewLiaison/Images.xcassets/tiger.imageset/tiger.jpg b/Example/TableViewLiaison/Images.xcassets/tiger.imageset/tiger.jpg deleted file mode 100644 index 568c65f..0000000 Binary files a/Example/TableViewLiaison/Images.xcassets/tiger.imageset/tiger.jpg and /dev/null differ diff --git a/Example/TableViewLiaison/Images.xcassets/zebra.imageset/Contents.json b/Example/TableViewLiaison/Images.xcassets/zebra.imageset/Contents.json deleted file mode 100644 index c47fb5c..0000000 --- a/Example/TableViewLiaison/Images.xcassets/zebra.imageset/Contents.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "zebra.jpg", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/Example/TableViewLiaison/Images.xcassets/zebra.imageset/zebra.jpg b/Example/TableViewLiaison/Images.xcassets/zebra.imageset/zebra.jpg deleted file mode 100644 index eb084e5..0000000 Binary files a/Example/TableViewLiaison/Images.xcassets/zebra.imageset/zebra.jpg and /dev/null differ diff --git a/Example/TableViewLiaison/Info.plist b/Example/TableViewLiaison/Info.plist index 7558193..9fa31e2 100644 --- a/Example/TableViewLiaison/Info.plist +++ b/Example/TableViewLiaison/Info.plist @@ -32,9 +32,13 @@ armv7 + UIStatusBarStyle + UIStatusBarStyleLightContent UISupportedInterfaceOrientations UIInterfaceOrientationPortrait + UIViewControllerBasedStatusBarAppearance + diff --git a/Example/TableViewLiaison/NetworkManager.swift b/Example/TableViewLiaison/NetworkManager.swift new file mode 100644 index 0000000..33ec7c0 --- /dev/null +++ b/Example/TableViewLiaison/NetworkManager.swift @@ -0,0 +1,141 @@ +// +// NetworkManager.swift +// TableViewLiaison_Example +// +// Created by Dylan Shine on 7/12/19. +// Copyright © 2019 CocoaPods. All rights reserved. +// + +import UIKit + +enum NetworkManager { + + private static var imageCache = [String: UIImage]() + private(set) static var factCache = [String: String]() + private static var userCahce = [String: User]() + private static var thumbnailCahce = [String: UIImage]() + + static func flushCache() { + userCahce.removeAll() + thumbnailCahce.removeAll() + imageCache.removeAll() + factCache.removeAll() + } + + static func flushCache(for id: String) { + imageCache[id] = nil + factCache[id] = nil + } + + private static func fetchData(from url: URL, completion: @escaping (Data?) -> ()) { + URLSession.shared.dataTask(with: url) { data, _, _ in + guard let data = data else { return completion(nil) } + + completion(data) + }.resume() + } + + static func fetchImage(url: String, + completion: ((UIImage?) -> ())?) { + + let url = URL(string: url)! + + fetchData(from: url) { data in + guard let data = data else { + completion?(nil) + return + } + + let image = UIImage(data: data) + + DispatchQueue.main.async() { + completion?(image) + } + } + } + + static func fetchThumbnailImage(thumbnail: String, + completion: ((UIImage?) -> ())?) { + + if let image = NetworkManager.thumbnailCahce[thumbnail] { + completion?(image) + return + } + + fetchImage(url: thumbnail) { image in + NetworkManager.thumbnailCahce[thumbnail] = image + completion?(image) + } + + } + + static func fetchRandomPostImage(id: String, + width: Int, + height: Int, + completion: ((UIImage?) -> ())?) { + + if let image = NetworkManager.imageCache[id] { + completion?(image) + return + } + + fetchImage(url: "https://picsum.photos/\(width)/\(height)") { image in + NetworkManager.imageCache[id] = image + completion?(image) + } + + } + + static func fetchRandomFact(id: String, + completion: ((String?) -> ())? = nil) { + + if let fact = NetworkManager.factCache[id] { + completion?(fact) + return + } + + let url = URL(string: "https://randomuselessfact.appspot.com/random.json?language=en")! + + fetchData(from: url) { data in + guard let data = data else { + completion?(nil) + return + } + + let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] + let fact = json?["text"] as? String + + NetworkManager.factCache[id] = fact + + DispatchQueue.main.async() { + completion?(fact) + } + } + } + + static func fetchRandomUser(id: String, + completion: ((User?) -> ())? = nil) { + + if let user = NetworkManager.userCahce[id] { + completion?(user) + return + } + + let url = URL(string: "https://randomuser.me/api")! + + fetchData(from: url) { data in + guard let data = data else { + completion?(nil) + return + } + + let user = try? JSONDecoder().decode(User.self, from: data) + + NetworkManager.userCahce[id] = user + + DispatchQueue.main.async() { + completion?(user) + } + } + } +} diff --git a/Example/TableViewLiaison/Post.swift b/Example/TableViewLiaison/Post.swift index 53100d9..2eb4964 100644 --- a/Example/TableViewLiaison/Post.swift +++ b/Example/TableViewLiaison/Post.swift @@ -3,84 +3,18 @@ // TableViewLiaison_Example // // Created by Dylan Shine on 3/30/18. -// Copyright © 2018 OkCupid. All rights reserved. +// Copyright © 2018 Shine Labs. All rights reserved. // import UIKit struct Post { - let user: User - let content: UIImage - let numberOfLikes: UInt - let caption: String - let numberOfComments: UInt - let timePosted: TimeInterval - - static func initialPosts() -> [Post] { - - let post1 = Post(user: .dylan, - content: #imageLiteral(resourceName: "bear"), - numberOfLikes: 64, - caption: "Bears are carnivoran mammals of the family Ursidae. They are classified as caniforms, or doglike carnivorans. Although only eight species of bears are extant, they are widespread, appearing in a wide variety of habitats throughout the Northern Hemisphere and partially in the Southern Hemisphere.", - numberOfComments: 25, - timePosted: 1644) - - let post2 = Post(user: .dylan, - content: #imageLiteral(resourceName: "tiger"), - numberOfLikes: 223, - caption: "The tiger (Panthera tigris) is the largest cat species, most recognizable for its pattern of dark vertical stripes on reddish-orange fur with a lighter underside. ", - numberOfComments: 112, - timePosted: 23995) - - let post3 = Post(user: .dylan, - content: #imageLiteral(resourceName: "giraffe"), - numberOfLikes: 824, - caption: "The giraffe (Giraffa) is a genus of African even-toed ungulate mammals, the tallest living terrestrial animals and the largest ruminants.", - numberOfComments: 438, - timePosted: 141355) - - let post4 = Post(user: .dylan, - content: #imageLiteral(resourceName: "gorilla"), - numberOfLikes: 997, - caption: "Gorillas are ground-dwelling, predominantly herbivorous apes that inhabit the forests of central Sub-Saharan Africa.", - numberOfComments: 621, - timePosted: 211355) - - return [post1, post2, post3, post4] - } - - static func paginatedPosts() -> [Post] { - - let post1 = Post(user: .dylan, - content: #imageLiteral(resourceName: "fox"), - numberOfLikes: 1024, - caption: "The red fox (Vulpes vulpes) is the largest of the true foxes and one of the most widely distributed members of the order Carnivora, being present across the entire Northern Hemisphere from the Arctic Circle to North Africa, North America and Eurasia.", - numberOfComments: 722, - timePosted: 441355) - - let post2 = Post(user: .dylan, - content: #imageLiteral(resourceName: "moose"), - numberOfLikes: 2121, - caption: "The moose (North America) or elk (Eurasia), Alces alces, is the largest extant species in the deer family.", - numberOfComments: 888, - timePosted: 641355) - - let post3 = Post(user: .dylan, - content: #imageLiteral(resourceName: "elephant"), - numberOfLikes: 5002, - caption: "Elephants are large mammals of the family Elephantidae and the order Proboscidea.", - numberOfComments: 1048, - timePosted: 1241355) - - let post4 = Post(user: .dylan, - content: #imageLiteral(resourceName: "zebra"), - numberOfLikes: 8002, - caption: "Zebras are several species of African equids (horse family) united by their distinctive black and white striped coats.", - numberOfComments: 2257, - timePosted: 7241355) - - return [post1, post2, post3, post4] - } + let imageSize = CGSize(width: CGFloat.random(in: 200...300), + height: CGFloat.random(in: 200...300)) + let numberOfLikes = UInt.random(in: 1...5000) + let numberOfComments = UInt.random(in: 1...600) + let timePosted = TimeInterval.random(in: 1...1000000) + let id: String = UUID().uuidString } diff --git a/Example/TableViewLiaison/PostTableViewSectionFactory.swift b/Example/TableViewLiaison/PostTableViewSectionFactory.swift index 3b39deb..cd40ff2 100644 --- a/Example/TableViewLiaison/PostTableViewSectionFactory.swift +++ b/Example/TableViewLiaison/PostTableViewSectionFactory.swift @@ -1,6 +1,6 @@ // // PostTableViewSectionFactory.swift -// OKTableViewLiaison_Example +// TableViewLiaison_Example // // Created by Dylan Shine on 5/18/18. // Copyright © 2018 CocoaPods. All rights reserved. @@ -11,19 +11,21 @@ import TableViewLiaison enum PostTableViewSectionFactory { - static func section(for post: Post, tableView: UITableView) -> TableViewSection { + static func section(for post: Post) -> TableViewSection { let rows: [AnyTableViewRow] = [ - ImageTableViewRow(image: post.content, tableView: tableView), - ActionButtonsTableViewRow(), - TextTableViewRowFactory.likesRow(numberOfLikes: post.numberOfLikes), - TextTableViewRowFactory.captionRow(user: post.user.username, caption: post.caption), - TextTableViewRowFactory.commentRow(commentCount: post.numberOfComments), - TextTableViewRowFactory.timeRow(numberOfSeconds: post.timePosted) + TableViewContentFactory.imageRow(id: post.id, imageSize: post.imageSize), + StatelessTableViewRow(registrationType:.defaultNibType), + TableViewContentFactory.likesRow(numberOfLikes: post.numberOfLikes), + TableViewContentFactory.captionRow(id: post.id), + TableViewContentFactory.commentRow(commentCount: post.numberOfComments), + TableViewContentFactory.timeRow(numberOfSeconds: post.timePosted) ] - let header = PostTableViewSectionHeaderViewComponent(user: post.user) + let header = TableViewContentFactory.postSectionHeaderComponent(id: post.id) - return TableViewSection(rows: rows, componentDisplayOption: .header(component: header)) + return TableViewSection(id: post.id, + rows: rows, + option: .header(component: header)) } } diff --git a/Example/TableViewLiaison/PostTableViewSectionHeaderView.swift b/Example/TableViewLiaison/PostTableViewSectionHeaderView.swift index e761df7..7841fe1 100644 --- a/Example/TableViewLiaison/PostTableViewSectionHeaderView.swift +++ b/Example/TableViewLiaison/PostTableViewSectionHeaderView.swift @@ -12,11 +12,14 @@ final class PostTableViewSectionHeaderView: UITableViewHeaderFooterView { @IBOutlet var imageView: UIImageView! @IBOutlet var titleLabel: UILabel! + @IBOutlet var swapButton: UIButton! + @IBOutlet var hideButton: UIButton! + var swapAction = {} + var hideAction = {} override func awakeFromNib() { super.awakeFromNib() imageView.layer.masksToBounds = true - imageView.contentMode = .scaleAspectFit } override func layoutSubviews() { @@ -26,4 +29,20 @@ final class PostTableViewSectionHeaderView: UITableViewHeaderFooterView { guard imageView != nil else { return } imageView.layer.cornerRadius = imageView.frame.height / 2 } + + override func prepareForReuse() { + super.prepareForReuse() + imageView.image = nil + titleLabel.text = nil + swapAction = {} + hideAction = {} + } + + @IBAction private func hideButtonPressed(_ sender: Any) { + hideAction() + } + + @IBAction private func swapButtonPressed(_ sender: Any) { + swapAction() + } } diff --git a/Example/TableViewLiaison/PostTableViewSectionHeaderView.xib b/Example/TableViewLiaison/PostTableViewSectionHeaderView.xib index 178f996..bea6c25 100644 --- a/Example/TableViewLiaison/PostTableViewSectionHeaderView.xib +++ b/Example/TableViewLiaison/PostTableViewSectionHeaderView.xib @@ -1,11 +1,11 @@ - + - + @@ -16,33 +16,72 @@ - - + + + + + + + + + + + + + + - + + + + + + + + + - - + + - - - - - + + + + + + - + + + + + diff --git a/Example/TableViewLiaison/PostTableViewSectionHeaderViewComponent.swift b/Example/TableViewLiaison/PostTableViewSectionHeaderViewComponent.swift deleted file mode 100644 index 926ab35..0000000 --- a/Example/TableViewLiaison/PostTableViewSectionHeaderViewComponent.swift +++ /dev/null @@ -1,33 +0,0 @@ -// -// PostTableViewSectionHeaderViewComponent.swift -// OKTableViewLiaison_Example -// -// Created by Dylan Shine on 5/30/18. -// Copyright © 2018 CocoaPods. All rights reserved. -// - -import UIKit -import TableViewLiaison - -final class PostTableViewSectionHeaderViewComponent: TableViewSectionComponent { - - public init(user: User) { - - super.init(user, registrationType: .defaultNibType) - - set(height: .height, 70) - - set(command: .configuration) { view, user, section in - view.backgroundView = UIView(frame: view.bounds) - view.backgroundView?.backgroundColor = .white - - view.imageView.image = user.avatar - view.imageView.layer.borderColor = UIColor.gray.cgColor - view.imageView.layer.borderWidth = 1 - - view.titleLabel.text = user.username - view.titleLabel.font = .systemFont(ofSize: 13, weight: .medium) - view.titleLabel.textColor = .black - } - } -} diff --git a/Example/TableViewLiaison/TableViewContentFactory.swift b/Example/TableViewLiaison/TableViewContentFactory.swift new file mode 100644 index 0000000..0338855 --- /dev/null +++ b/Example/TableViewLiaison/TableViewContentFactory.swift @@ -0,0 +1,155 @@ +// +// TableViewContentFactory.swift +// TableViewLiaison_Example +// +// Created by Dylan Shine on 7/12/19. +// Copyright © 2019 CocoaPods. All rights reserved. +// + +import TableViewLiaison +import UIKit + +enum TableViewContentFactory { + typealias ImageRow = TableViewRow + typealias TextRow = TableViewRow + + static func imageRow(id: String, imageSize: CGSize) -> AnyTableViewRow { + + var row = ImageRow((id, imageSize), registrationType: .defaultNibType) + + row.set(.height) { (_, imageSize) in + let ratio = imageSize.width / imageSize.height + return UIScreen.main.bounds.width / ratio + } + + row.set(.prefetch) { data, _ in + let (id, imageSize) = data + fetchImage(id: id, imageSize: imageSize) + } + + row.set(.configuration) { (_, cell: ImageTableViewCell, data, _) in + let (id, imageSize) = data + fetchImage(id: id, imageSize: imageSize) { [weak cell] image in + cell?.contentImage = image + } + } + + return row + } + + private static func fetchImage(id: String, + imageSize: CGSize, + completion: ((UIImage?) -> Void)? = nil) { + + let width = Int(imageSize.width * 2.0) + let height = Int(imageSize.height * 2.0) + + NetworkManager.fetchRandomPostImage(id: id, + width: width, + height: height, + completion: completion) + } + + private static func textTableViewRow() -> TextRow { + return TextRow(registrationType: .defaultNibType) + } + + static func likesRow(numberOfLikes: UInt) -> AnyTableViewRow { + + var row = textTableViewRow() + + row.set(.configuration) { _, cell, _, _ in + cell.contentTextLabel.font = .systemFont(ofSize: 13, weight: .medium) + cell.contentTextLabel.text = "\(numberOfLikes) likes" + cell.contentTextLabel.textColor = .white + } + + return row + } + + static func captionRow(id: String) -> AnyTableViewRow { + + var row = textTableViewRow() + + row.set(.estimatedHeight, 50) + + row.set(.prefetch) { _ in + NetworkManager.fetchRandomFact(id: id) + } + + row.set(.configuration) { _, cell, _, _ in + + cell.contentTextLabel.numberOfLines = 0 + cell.contentTextLabel.textColor = .white + cell.contentTextLabel.font = .systemFont(ofSize: 13) + + NetworkManager.fetchRandomFact(id: id) { [weak cell] fact in + guard let fact = fact, + let cell = cell else { return } + + cell.contentTextLabel.text = fact + } + } + + return row + } + + static func commentRow(commentCount: UInt) -> AnyTableViewRow { + + var row = textTableViewRow() + + row.set(.configuration) { _, cell, _ in + cell.contentTextLabel.font = .systemFont(ofSize: 13) + cell.contentTextLabel.text = "View all \(commentCount) comments" + cell.contentTextLabel.textColor = .gray + } + + return row + } + + static func timeRow(numberOfSeconds: TimeInterval) -> AnyTableViewRow { + + var row = textTableViewRow() + + row.set(.configuration) { _, cell, _ in + cell.contentTextLabel.font = .systemFont(ofSize: 10) + cell.contentTextLabel.text = numberOfSeconds.timeText + cell.contentTextLabel.textColor = .gray + } + + return row + } + + static func postSectionHeaderComponent(id: String) -> TableViewSectionComponent { + + var header = TableViewSectionComponent(registrationType: .defaultNibType) + + header.set(.height, 70) + + header.set(.configuration) { liaison, view, _ in + + NetworkManager.fetchRandomUser(id: id) { [weak view] user in + guard let user = user else { return } + view?.titleLabel.text = user.username + + NetworkManager.fetchImage(url: user.thumbnail) { [weak view] image in + view?.imageView.image = image + } + } + + view.swapAction = { [weak liaison] in + guard let sectionIndex = liaison?.sectionIndexes(for: id).first else { return } + liaison?.swapSection(at: sectionIndex, with: sectionIndex + 1) + } + + view.hideAction = { [weak liaison] in + NetworkManager.flushCache(for: id) + liaison?.deleteSections(with: id, animation: .fade) + } + + } + + return header + } + +} diff --git a/Example/TableViewLiaison/TextTableViewCell.swift b/Example/TableViewLiaison/TextTableViewCell.swift index 7d75d14..e88f6c5 100644 --- a/Example/TableViewLiaison/TextTableViewCell.swift +++ b/Example/TableViewLiaison/TextTableViewCell.swift @@ -3,7 +3,7 @@ // TableViewLiaison_Example // // Created by Dylan Shine on 3/29/18. -// Copyright © 2018 OkCupid. All rights reserved. +// Copyright © 2018 Shine Labs. All rights reserved. // import UIKit @@ -15,7 +15,6 @@ final class TextTableViewCell: UITableViewCell { override func prepareForReuse() { super.prepareForReuse() contentTextLabel.text = nil - contentTextLabel.textColor = .black contentTextLabel.attributedText = nil } diff --git a/Example/TableViewLiaison/TextTableViewCell.xib b/Example/TableViewLiaison/TextTableViewCell.xib index b61cc89..8ffc4d4 100644 --- a/Example/TableViewLiaison/TextTableViewCell.xib +++ b/Example/TableViewLiaison/TextTableViewCell.xib @@ -1,18 +1,18 @@ - + - + - + @@ -22,10 +22,12 @@ + + diff --git a/Example/TableViewLiaison/TextTableViewRow.swift b/Example/TableViewLiaison/TextTableViewRow.swift deleted file mode 100644 index 303c72d..0000000 --- a/Example/TableViewLiaison/TextTableViewRow.swift +++ /dev/null @@ -1,19 +0,0 @@ -// -// PostTextTableViewRow.swift -// TableViewLiaison_Example -// -// Created by Dylan Shine on 3/29/18. -// Copyright © 2018 OkCupid. All rights reserved. -// - -import UIKit -import TableViewLiaison - -final class TextTableViewRow: TableViewRow { - - init(text: String) { - super.init(text, - registrationType: .defaultNibType) - } - -} diff --git a/Example/TableViewLiaison/TextTableViewRowFactory.swift b/Example/TableViewLiaison/TextTableViewRowFactory.swift deleted file mode 100644 index 90f026a..0000000 --- a/Example/TableViewLiaison/TextTableViewRowFactory.swift +++ /dev/null @@ -1,84 +0,0 @@ -// -// TextTableViewRowFactory.swift -// OKTableViewLiaison_Example -// -// Created by Dylan Shine on 5/18/18. -// Copyright © 2018 CocoaPods. All rights reserved. -// - -import Foundation -import TableViewLiaison - -enum TextTableViewRowFactory { - - static func likesRow(numberOfLikes: UInt) -> TextTableViewRow { - - let row = TextTableViewRow(text: "\(numberOfLikes) likes") - - row.set(command: .configuration) { cell, text, _ in - cell.contentTextLabel.font = .systemFont(ofSize: 13, weight: .medium) - cell.contentTextLabel.text = text - cell.selectionStyle = .none - } - - return row - } - - static func captionRow(user: String, caption: String) -> TextTableViewRow { - - let row = TextTableViewRow(text: caption) - - row.set(command: .configuration) { cell, caption, _ in - - cell.contentTextLabel.numberOfLines = 0 - cell.selectionStyle = .none - - let mediumAttributes: [NSAttributedString.Key: Any] = [ - .font: UIFont.systemFont(ofSize: 13, weight: .medium), - .foregroundColor: UIColor.black - ] - - let regularAttributes: [NSAttributedString.Key: Any] = [ - .font: UIFont.systemFont(ofSize: 13), - .foregroundColor: UIColor.black - ] - - let attributedString = NSMutableAttributedString(string: user, attributes: mediumAttributes) - - attributedString.append(NSMutableAttributedString(string: " \(caption)", attributes: regularAttributes)) - - cell.contentTextLabel.attributedText = attributedString - } - - return row - } - - static func commentRow(commentCount: UInt) -> TextTableViewRow { - - let row = TextTableViewRow(text: "View all \(commentCount) comments") - - row.set(command: .configuration) { cell, text, _ in - cell.contentTextLabel.font = .systemFont(ofSize: 13) - cell.contentTextLabel.text = text - cell.contentTextLabel.textColor = .gray - cell.selectionStyle = .none - } - - return row - } - - static func timeRow(numberOfSeconds: TimeInterval) -> TextTableViewRow { - - let row = TextTableViewRow(text: numberOfSeconds.timeText) - - row.set(command: .configuration) { cell, text, _ in - cell.contentTextLabel.font = .systemFont(ofSize: 10) - cell.contentTextLabel.text = text - cell.contentTextLabel.textColor = .gray - cell.selectionStyle = .none - } - - return row - } - -} diff --git a/Example/TableViewLiaison/TimeInterval+SecondConversion.swift b/Example/TableViewLiaison/TimeInterval+SecondConversion.swift index 3881820..6dc84d6 100644 --- a/Example/TableViewLiaison/TimeInterval+SecondConversion.swift +++ b/Example/TableViewLiaison/TimeInterval+SecondConversion.swift @@ -3,7 +3,7 @@ // TableViewLiaison_Example // // Created by Dylan Shine on 3/29/18. -// Copyright © 2018 OkCupid. All rights reserved. +// Copyright © 2018 Shine Labs. All rights reserved. // import Foundation diff --git a/Example/TableViewLiaison/UIColor+Constants.swift b/Example/TableViewLiaison/UIColor+Constants.swift new file mode 100644 index 0000000..78b47e4 --- /dev/null +++ b/Example/TableViewLiaison/UIColor+Constants.swift @@ -0,0 +1,15 @@ +// +// UIColor+Constants.swift +// TableViewLiaison_Example +// +// Created by Dylan Shine on 7/20/19. +// Copyright © 2019 CocoaPods. All rights reserved. +// + +import UIKit + +extension UIColor { + static var mainBackground: UIColor { + return UIColor(red: 0.14, green: 0.14, blue: 0.14, alpha: 1.0) + } +} diff --git a/Example/TableViewLiaison/User.swift b/Example/TableViewLiaison/User.swift index 59f6b62..7fdacd8 100644 --- a/Example/TableViewLiaison/User.swift +++ b/Example/TableViewLiaison/User.swift @@ -1,6 +1,6 @@ // // User.swift -// OKTableViewLiaison_Example +// TableViewLiaison_Example // // Created by Dylan Shine on 5/3/18. // Copyright © 2018 CocoaPods. All rights reserved. @@ -8,13 +8,28 @@ import UIKit -struct User { - +struct User: Decodable { let username: String - let avatar: UIImage + let thumbnail: String - static var dylan: User { - return User(username: "dylan", avatar: #imageLiteral(resourceName: "dylan")) + private enum CodingKeys: String, CodingKey { + case results + case login + case username + case picture + case thumbnail } + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + + var results = try container.nestedUnkeyedContainer(forKey: .results) + let user = try results.nestedContainer(keyedBy: CodingKeys.self) + + username = try user.nestedContainer(keyedBy: CodingKeys.self, forKey: .login) + .decode(String.self, forKey: .username) + + thumbnail = try user.nestedContainer(keyedBy: CodingKeys.self, forKey: .picture) + .decode(String.self, forKey: .thumbnail) + } } diff --git a/Example/TableViewLiaison/ViewController.swift b/Example/TableViewLiaison/ViewController.swift index ee2b4a7..031d54f 100644 --- a/Example/TableViewLiaison/ViewController.swift +++ b/Example/TableViewLiaison/ViewController.swift @@ -2,8 +2,8 @@ // ViewController.swift // TableViewLiaison // -// Created by acct=dylanshine on 01/31/2019. -// Copyright (c) 2019 acct=dylanshine. All rights reserved. +// Created by Dylan Shine on 01/31/2019. +// Copyright (c) 2019 Shine Labs. All rights reserved. // import UIKit @@ -15,50 +15,55 @@ final class ViewController: UIViewController { private let liaison = TableViewLiaison() private let refreshControl = UIRefreshControl() - private var initialSections: [TableViewSection] { - return Post.initialPosts() - .map { PostTableViewSectionFactory.section(for: $0, tableView: tableView) } - } - override func viewDidLoad() { super.viewDidLoad() - + refreshControl.tintColor = .white refreshControl.addTarget(self, action: #selector(refreshSections), for: .valueChanged) tableView.addSubview(refreshControl) liaison.paginationDelegate = self liaison.liaise(tableView: tableView) + } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) - liaison.append(sections: initialSections, animated: false) + + liaison.append(sections: randomPostSections(), animated: false) + } + + override var preferredStatusBarStyle: UIStatusBarStyle { + return .lightContent + } + + private func randomPostSections() -> [TableViewSection] { + return (0...8).map { _ in + let post = Post() + return PostTableViewSectionFactory.section(for: post) + } } @objc private func refreshSections() { DispatchQueue.main.asyncAfter(deadline: .now() + 1) { - self.liaison.clearSections(replacedBy: self.initialSections, animated: false) + NetworkManager.flushCache() + self.liaison.clearSections(replacedBy: self.randomPostSections(), animated: false) self.refreshControl.endRefreshing() } } - } extension ViewController: TableViewLiaisonPaginationDelegate { func isPaginationEnabled() -> Bool { - return liaison.sections.count < 8 + return true } func paginationStarted(indexPath: IndexPath) { liaison.scroll(to: indexPath) - - let sections = Post.paginatedPosts() - .map { PostTableViewSectionFactory.section(for: $0, tableView: tableView) } - + DispatchQueue.main.asyncAfter(deadline: .now() + 2) { - self.liaison.append(sections: sections, animated: false) + self.liaison.append(sections: self.randomPostSections(), animated: false) } } diff --git a/Example/Tests/TableViewLiaison+UnitTests.swift b/Example/Tests/TableViewLiaison+UnitTests.swift index 5e0f550..fd74246 100644 --- a/Example/Tests/TableViewLiaison+UnitTests.swift +++ b/Example/Tests/TableViewLiaison+UnitTests.swift @@ -9,7 +9,7 @@ import XCTest @testable import TableViewLiaison -final class OKTableViewLiaison_UnitTests: XCTestCase { +final class TableViewLiaison_UnitTests: XCTestCase { var liaison: TableViewLiaison! var tableView: UITableView! @@ -41,9 +41,8 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { func test_liaise_setsDelegateAndDataSource() { XCTAssert(tableView.delegate === liaison) XCTAssert(tableView.dataSource === liaison) - if #available(iOS 10.0, *) { - XCTAssert(tableView.prefetchDataSource === liaison) - } + XCTAssert(tableView.prefetchDataSource === liaison) + XCTAssert(liaison.tableView == tableView) } @@ -51,17 +50,49 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { liaison.detach() XCTAssert(tableView.delegate == nil) XCTAssert(tableView.dataSource == nil) - if #available(iOS 10.0, *) { - XCTAssert(tableView.prefetchDataSource == nil) - } + XCTAssert(tableView.prefetchDataSource == nil) + XCTAssert(liaison.tableView == nil) } - func test_toggleIsEditing_togglesTableViewEditingMode() { + func test_isEditing_changesTableViewsIsEditing() { tableView.isEditing = true - liaison.toggleIsEditing() + liaison.isEditing = false XCTAssertFalse(tableView.isEditing) + XCTAssertFalse(liaison.isEditing) + } + + func test_allowSelection_changesTableViewsAllowsSelection() { + tableView.allowsSelection = true + liaison.allowsSelection = false + + XCTAssertFalse(tableView.allowsSelection) + XCTAssertFalse(liaison.allowsSelection) + } + + func test_allowsSelectionDuringEditing_changesTableViewsAllowsSelectionDuringEditing() { + tableView.allowsSelectionDuringEditing = true + liaison.allowsSelectionDuringEditing = false + + XCTAssertFalse(tableView.allowsSelectionDuringEditing) + XCTAssertFalse(liaison.allowsSelectionDuringEditing) + } + + func test_allowsMultipleSelection_changesTableViewsAllowsMultipleSelection() { + tableView.allowsMultipleSelection = true + liaison.allowsMultipleSelection = false + + XCTAssertFalse(tableView.allowsMultipleSelection) + XCTAssertFalse(liaison.allowsMultipleSelection) + } + + func test_allowsMultipleSelectionDuringEditing_changesTableViewsAllowsMultipleSelectionDuringEditing() { + tableView.allowsMultipleSelectionDuringEditing = true + liaison.allowsMultipleSelectionDuringEditing = false + + XCTAssertFalse(tableView.allowsMultipleSelectionDuringEditing) + XCTAssertFalse(liaison.allowsMultipleSelectionDuringEditing) } func test_init_initializesWithSections() { @@ -132,6 +163,57 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { XCTAssertEqual(liaison.sections.count, 1) } + func test_deleteSections_removesSectionsFromTableView() { + let section1 = TableViewSection() + let section2 = TableViewSection() + let section3 = TableViewSection() + + liaison.append(sections: [section1, section2, section3]) + + XCTAssertEqual(tableView.numberOfSections, 3) + XCTAssertEqual(liaison.sections.count, 3) + + liaison.deleteSections(at: [1,2]) + + XCTAssertEqual(tableView.numberOfSections, 1) + XCTAssertEqual(liaison.sections.count, 1) + } + + func test_deleteSections_ignoresInvalidSectionIndexes() { + let section1 = TableViewSection() + let section2 = TableViewSection() + + liaison.append(sections: [section1, section2]) + + liaison.deleteSections(at: [2]) + + XCTAssertEqual(tableView.numberOfSections, 2) + XCTAssertEqual(liaison.sections.count, 2) + } + + func test_deleteSectionWithId_removesSectionFromTableView() { + let section = TableViewSection(id: "test") + + liaison.append(section: section) + + liaison.deleteSections(with: "test") + + XCTAssertEqual(tableView.numberOfSections, 0) + XCTAssertEqual(liaison.sections.count, 0) + } + + func test_deleteSectionsWithIds_removesSectionFromTableView() { + let section1 = TableViewSection(id: "test1") + let section2 = TableViewSection(id: "test2") + + liaison.append(sections: [section1, section2]) + + liaison.deleteSections(with: ["test1", "test2"]) + + XCTAssertEqual(tableView.numberOfSections, 0) + XCTAssertEqual(liaison.sections.count, 0) + } + func test_emptySection_removesAllRowsFromSection() { let section = TableViewSection(rows: [TestTableViewRow()]) liaison.append(section: section) @@ -140,6 +222,44 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { XCTAssertEqual(tableView.numberOfRows(inSection: 0), 0) } + + func test_emptySectionsAtIndexes_removesAllRowsFromSections() { + let section1 = TableViewSection(rows: [TestTableViewRow()]) + let section2 = TableViewSection(rows: [TestTableViewRow(), TestTableViewRow()]) + let section3 = TableViewSection(rows: [TestTableViewRow()]) + + liaison.append(sections: [section1, section2, section3]) + + liaison.emptySections(at: [1,2]) + + XCTAssertEqual(tableView.numberOfRows(inSection: 0), 1) + XCTAssertEqual(tableView.numberOfRows(inSection: 1), 0) + XCTAssertEqual(tableView.numberOfRows(inSection: 2), 0) + } + + func test_emptySectionsWithId_removesAllRowsFromSection() { + let section = TableViewSection(id: "test", rows: [TestTableViewRow(), TestTableViewRow()]) + + liaison.append(section: section) + + liaison.emptySections(with: "test") + + XCTAssertEqual(tableView.numberOfRows(inSection: 0), 0) + } + + func test_emptySectionsWithIds_removesAllRowsFromSections() { + let section1 = TableViewSection(rows: [TestTableViewRow()]) + let section2 = TableViewSection(id: "test", rows: [TestTableViewRow(), TestTableViewRow()]) + let section3 = TableViewSection(rows: [TestTableViewRow()]) + + liaison.append(sections: [section1, section2, section3]) + + liaison.emptySections(ids: ["test"]) + + XCTAssertEqual(tableView.numberOfRows(inSection: 0), 1) + XCTAssertEqual(tableView.numberOfRows(inSection: 1), 0) + XCTAssertEqual(tableView.numberOfRows(inSection: 2), 1) + } func test_replaceSection_replacesSectionOfTableView() { let row = TestTableViewRow() @@ -172,17 +292,17 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { func test_reloadSection_reloadsSectionOfTableView() { - let header = TestTableViewSectionComponent() - header.set(height: .estimatedHeight, 15) + var header = TestTableViewSectionComponent() + header.set(.estimatedHeight, 15) var capturedHeader: UITableViewHeaderFooterView? let string = "Test" - header.set(command: .configuration) { view, _, _ in + header.set(.configuration) { _, view, _ in view.accessibilityIdentifier = string capturedHeader = view } - let section = TableViewSection(componentDisplayOption: .header(component: header)) + let section = TableViewSection(option: .header(component: header)) liaison.append(section: section) liaison.reloadData() @@ -194,6 +314,31 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { XCTAssertEqual(capturedHeader?.accessibilityIdentifier, string) } + func test_reloadSections_reloadsSectionsWithId() { + + var header = TestTableViewSectionComponent() + header.set(.estimatedHeight, 15) + var capturedHeader: UITableViewHeaderFooterView? + + let string = "Test" + header.set(.configuration) { _, view, _ in + view.accessibilityIdentifier = string + capturedHeader = view + } + + let section = TableViewSection(id: "section", + option: .header(component: header)) + + liaison.append(section: section) + liaison.reloadData() + + capturedHeader?.accessibilityIdentifier = "Changed" + + liaison.reloadSections(with: "section") + + XCTAssertEqual(capturedHeader?.accessibilityIdentifier, string) + } + func test_clearSections_removesAllSectionsFromTableView() { let section1 = TableViewSection() @@ -236,12 +381,12 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { func test_appendRow_appendsRowToSection() { let section = TableViewSection() - let row = TestTableViewRow() + var row = TestTableViewRow() var inserted = false var actualIndexPath: IndexPath? let expectedIndexPath = IndexPath(row: 0, section: 0) - row.set(command: .insert) { (_, _, indexPath) in + row.set(.insert) { _, _, indexPath in inserted = true actualIndexPath = indexPath } @@ -254,20 +399,43 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { } XCTAssertEqual(tableView.numberOfRows(inSection: 0), 1) - XCTAssert(liaison.sections.first?.rows.last === row) + XCTAssertTrue(inserted) + XCTAssertEqual(actualIndexPath, expectedIndexPath) + } + + func test_appendRow_appendsRowToSectionWithIdentifier() { + let section = TableViewSection(id: "test") + var row = TestTableViewRow() + + var inserted = false + var actualIndexPath: IndexPath? + let expectedIndexPath = IndexPath(row: 0, section: 0) + row.set(.insert) { _, _, indexPath in + inserted = true + actualIndexPath = indexPath + } + + liaison.append(section: section) + + tableView.stubCell = UITableViewCell() + tableView.performInSwizzledEnvironment { + liaison.append(row: row, to: "test") + } + + XCTAssertEqual(tableView.numberOfRows(inSection: 0), 1) XCTAssertTrue(inserted) XCTAssertEqual(actualIndexPath, expectedIndexPath) } func test_appendRows_appendsRowsToSection() { let section = TableViewSection() - let row1 = TestTableViewRow() - let row2 = TestTableViewRow() + var row1 = TestTableViewRow() + var row2 = TestTableViewRow() var insertedRow1 = false var actualIndexPathRow1: IndexPath? let expectedIndexPathRow1 = IndexPath(row: 0, section: 0) - row1.set(command: .insert) { (_, _, indexPath) in + row1.set(.insert) { _, _, indexPath in insertedRow1 = true actualIndexPathRow1 = indexPath } @@ -275,7 +443,7 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { var insertedRow2 = false var actualIndexPathRow2: IndexPath? let expectedIndexPathRow2 = IndexPath(row: 1, section: 0) - row2.set(command: .insert) { (_, _, indexPath) in + row2.set(.insert) { _, _, indexPath in insertedRow2 = true actualIndexPathRow2 = indexPath } @@ -290,8 +458,43 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { } XCTAssertEqual(tableView.numberOfRows(inSection: 0), 2) - XCTAssert(liaison.sections.first?.rows.first === row1) - XCTAssert(liaison.sections.first?.rows.last === row2) + XCTAssertTrue(insertedRow1) + XCTAssertTrue(insertedRow2) + XCTAssertEqual(actualIndexPathRow1, expectedIndexPathRow1) + XCTAssertEqual(actualIndexPathRow2, expectedIndexPathRow2) + } + + func test_appendRows_appendsRowsToSectionWithIdentifier() { + let section = TableViewSection(id: "test") + var row1 = TestTableViewRow() + var row2 = TestTableViewRow() + + var insertedRow1 = false + var actualIndexPathRow1: IndexPath? + let expectedIndexPathRow1 = IndexPath(row: 0, section: 0) + row1.set(.insert) { _, _, indexPath in + insertedRow1 = true + actualIndexPathRow1 = indexPath + } + + var insertedRow2 = false + var actualIndexPathRow2: IndexPath? + let expectedIndexPathRow2 = IndexPath(row: 1, section: 0) + row2.set(.insert) { _, _, indexPath in + insertedRow2 = true + actualIndexPathRow2 = indexPath + } + + liaison.append(section: section) + + XCTAssert(section.rows.count == 0) + + tableView.stubCell = UITableViewCell() + tableView.performInSwizzledEnvironment { + liaison.append(rows: [row1, row2], to: "test") + } + + XCTAssertEqual(tableView.numberOfRows(inSection: 0), 2) XCTAssertTrue(insertedRow1) XCTAssertTrue(insertedRow2) XCTAssertEqual(actualIndexPathRow1, expectedIndexPathRow1) @@ -302,7 +505,7 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { let row1 = TestTableViewRow() let row2 = TestTableViewRow() - let row3 = TestTableViewRow() + var row3 = TestTableViewRow() let section = TableViewSection(rows: [row1, row2]) @@ -312,7 +515,7 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { var insertedRow = false var actualIndexPathRow: IndexPath? - row3.set(command: .insert) { (_, _, indexPath) in + row3.set(.insert) { _, _, indexPath in insertedRow = true actualIndexPathRow = indexPath } @@ -323,7 +526,6 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { } XCTAssertEqual(tableView.numberOfRows(inSection: 0), 3) - XCTAssert(liaison.sections.first?.rows.first === row3) XCTAssertTrue(insertedRow) XCTAssertEqual(actualIndexPathRow, expectedIndexPath) } @@ -331,14 +533,14 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { func test_deleteRows_removesRowsFromTableView() { let section1 = TableViewSection() let section2 = TableViewSection() - let row1 = TestTableViewRow() - let row2 = TestTableViewRow() - let row3 = TestTableViewRow() + var row1 = TestTableViewRow() + var row2 = TestTableViewRow() + var row3 = TestTableViewRow() let row1IndexPath = IndexPath(row: 0, section: 0) var deletedRow1 = false var actualIndexPathRow1: IndexPath? - row1.set(command: .delete) { (_, _, indexPath) in + row1.set(.delete) { _, _, indexPath in deletedRow1 = true actualIndexPathRow1 = indexPath } @@ -346,7 +548,7 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { let row2IndexPath = IndexPath(row: 1, section: 0) var deletedRow2 = false var actualIndexPathRow2: IndexPath? - row2.set(command: .delete) { (_, _, indexPath) in + row2.set(.delete) { _, _, indexPath in deletedRow2 = true actualIndexPathRow2 = indexPath } @@ -354,7 +556,7 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { let row3IndexPath = IndexPath(row: 0, section: 1) var deletedRow3 = false var actualIndexPathRow3: IndexPath? - row3.set(command: .delete) { (_, _, indexPath) in + row3.set(.delete) { _, _, indexPath in deletedRow3 = true actualIndexPathRow3 = indexPath } @@ -377,15 +579,15 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { XCTAssertEqual(actualIndexPathRow2, row2IndexPath) XCTAssertEqual(actualIndexPathRow3, row3IndexPath) } - + func test_deleteRow_removesRowFromSection() { - let row1 = TestTableViewRow() + var row1 = TestTableViewRow() let row2 = TestTableViewRow() let expectedIndexPath = IndexPath(row: 0, section: 0) var deletedRow = false var actualIndexPathRow: IndexPath? - row1.set(command: .delete) { (_, _, indexPath) in + row1.set(.delete) { _, _, indexPath in deletedRow = true actualIndexPathRow = indexPath } @@ -399,23 +601,22 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { } XCTAssertEqual(tableView.numberOfRows(inSection: 0), 1) - XCTAssert(liaison.sections.first?.rows.last === row2) XCTAssertTrue(deletedRow) XCTAssertEqual(actualIndexPathRow, expectedIndexPath) } - func test_reloadRows_reloadsRowsInSection() { - let row1 = TestTableViewRow() - let row2 = TestTableViewRow() + func test_reloadRows_reloadsRowsAtIndexPaths() { + var row1 = TestTableViewRow() + var row2 = TestTableViewRow() var reloaded1 = false var reloaded2 = false - row1.set(command: .reload) { (_, _, _) in + row1.set(.reload) { _, _, _ in reloaded1 = true } - row2.set(command: .reload) { (_, _, _) in + row2.set(.reload) { _, _, _ in reloaded2 = true } @@ -435,11 +636,11 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { XCTAssertTrue(reloaded2) } - func test_reloadRow_reloadsRowInSection() { - let row = TestTableViewRow() + func test_reloadRow_reloadsRowAtIndexPath() { + var row = TestTableViewRow() var reloaded = false - row.set(command: .reload) { (_, _, _) in + row.set(.reload) { _, _, _ in reloaded = true } @@ -459,16 +660,16 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { } func test_replaceRow_replaceRowInSection() { - let row1 = TestTableViewRow() - let row2 = TestTableViewRow() + var row1 = TestTableViewRow() + var row2 = TestTableViewRow() var deleted = false - row1.set(command: .delete) { (_, _, _) in + row1.set(.delete) { _, _, _ in deleted = true } var inserted = false - row2.set(command: .insert) { (_, _, _) in + row2.set(.insert) { _, _, _ in inserted = true } @@ -481,21 +682,20 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { } XCTAssertEqual(tableView.numberOfRows(inSection: 0), 1) - XCTAssert(liaison.sections.first?.rows.first === row2) XCTAssertTrue(deleted) XCTAssertTrue(inserted) } func test_moveRow_withinSameSection() { - let row1 = TestTableViewRow() + var row1 = TestTableViewRow() let row2 = TestTableViewRow() let row3 = TestTableViewRow() var moved = false var actualDestination: IndexPath? let destination = IndexPath(row: 2, section: 0) - row1.set(command: .move) { (_, _, indexPath) in + row1.set(.move) { _, _, indexPath in moved = true actualDestination = indexPath } @@ -507,19 +707,16 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { tableView.performInSwizzledEnvironment { liaison.moveRow(from: IndexPath(row: 0, section: 0), to: destination) } - - XCTAssert(liaison.sections.first?.rows.first === row2) - XCTAssert(liaison.sections.first?.rows.last === row1) + XCTAssertTrue(moved) XCTAssertEqual(actualDestination, destination) - } func test_moveRow_intoDifferentSection() { let section1 = TableViewSection() let section2 = TableViewSection() - let row1 = TestTableViewRow() + var row1 = TestTableViewRow() let row2 = TestTableViewRow() let row3 = TestTableViewRow() let row4 = TestTableViewRow() @@ -528,7 +725,7 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { var moved = false var actualDestination: IndexPath? let destination = IndexPath(row: 2, section: 1) - row1.set(command: .move) { (_, _, indexPath) in + row1.set(.move) { _, _, indexPath in moved = true actualDestination = indexPath } @@ -545,23 +742,21 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { } XCTAssertEqual(liaison.sections.first?.rows.count, 2) - XCTAssert(liaison.sections.first?.rows.first === row2) XCTAssertEqual(liaison.sections.last?.rows.count, 3) - XCTAssert(liaison.sections.last?.rows.last === row1) XCTAssertTrue(moved) XCTAssertEqual(actualDestination, destination) } func test_swapRow_withinSameSection() { let section = TableViewSection() - let row1 = TestTableViewRow() + var row1 = TestTableViewRow() let row2 = TestTableViewRow() - let row3 = TestTableViewRow() + var row3 = TestTableViewRow() var sourceMoved = false var swappedSourceIndexPath: IndexPath? let sourceIndexPath = IndexPath(row: 0, section: 0) - row1.set(command: .move) { (_, _, indexPath) in + row1.set(.move) { _, _, indexPath in sourceMoved = true swappedSourceIndexPath = indexPath } @@ -569,7 +764,7 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { var destinationMoved = false var swappedDestinationIndexPath: IndexPath? let destinationIndexPath = IndexPath(row: 2, section: 0) - row3.set(command: .move) { (_, _, indexPath) in + row3.set(.move) { _, _, indexPath in destinationMoved = true swappedDestinationIndexPath = indexPath } @@ -582,8 +777,6 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { liaison.swapRow(at: sourceIndexPath, with: destinationIndexPath) } - XCTAssert(liaison.sections.first?.rows.first === row3) - XCTAssert(liaison.sections.first?.rows.last === row1) XCTAssertTrue(sourceMoved) XCTAssertTrue(destinationMoved) XCTAssertEqual(swappedSourceIndexPath, destinationIndexPath) @@ -595,15 +788,15 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { let section1 = TableViewSection() let section2 = TableViewSection() - let row1 = TestTableViewRow() + var row1 = TestTableViewRow() let row2 = TestTableViewRow() let row3 = TestTableViewRow() - let row4 = TestTableViewRow() + var row4 = TestTableViewRow() var sourceMoved = false var swappedSourceIndexPath: IndexPath? let sourceIndexPath = IndexPath(row: 0, section: 0) - row1.set(command: .move) { (_, _, indexPath) in + row1.set(.move) { _, _, indexPath in sourceMoved = true swappedSourceIndexPath = indexPath } @@ -611,7 +804,7 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { var destinationMoved = false var swappedDestinationIndexPath: IndexPath? let destinationIndexPath = IndexPath(row: 1, section: 1) - row4.set(command: .move) { (_, _, indexPath) in + row4.set(.move) { _, _, indexPath in destinationMoved = true swappedDestinationIndexPath = indexPath } @@ -627,8 +820,6 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { liaison.swapRow(at: sourceIndexPath, with: destinationIndexPath) } - XCTAssert(liaison.sections.first?.rows.first === row4) - XCTAssert(liaison.sections.last?.rows.last === row1) XCTAssertTrue(sourceMoved) XCTAssertTrue(destinationMoved) XCTAssertEqual(swappedSourceIndexPath, destinationIndexPath) @@ -638,9 +829,10 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { func test_tableViewCellForRow_createsCorrectCellForRow() { let section = TableViewSection() - let row = TestTableViewRow() + var row = TestTableViewRow() let string = "Test" - row.set(command: .configuration) { (cell, _, indexPath) in + + row.set(.configuration) { _, cell, _ in cell.accessibilityIdentifier = string } @@ -721,16 +913,16 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { func test_tableViewCommitEditingStyle_performsEditingActionRowForIndexPath() { let section = TableViewSection() - let row1 = TestTableViewRow(editingStyle: .delete) - let row2 = TestTableViewRow(editingStyle: .insert) + var row1 = TestTableViewRow(editingStyle: .delete) + var row2 = TestTableViewRow(editingStyle: .insert) var deleted = false var inserted = false - row1.set(command: .delete) { _, _, _ in + row1.set(.delete) { _, _, _ in deleted = true } - row2.set(command: .insert) { _, _, _ in + row2.set(.insert) { _, _, _ in inserted = true } @@ -752,8 +944,8 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { func test_moveRowAt_properlyMovesRowFromOneSourceIndexPathToDestinationIndexPath() { var moved = false - let row1 = TestTableViewRow() - row1.set(command: .move) { (_, _, _) in + var row1 = TestTableViewRow() + row1.set(.move) { _, _, _ in moved = true } @@ -772,15 +964,14 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { XCTAssertTrue(moved) XCTAssertEqual(liaison.sections.first?.rows.count, 2) - XCTAssert(liaison.sections.last?.rows.first === row1) } func test_willSelectRow_performsWillSelectCommand() { - let row = TestTableViewRow() + var row = TestTableViewRow() var willSelect = false - row.set(command: .willSelect) { _, _, _ in + row.set(.willSelect) { _, _, _ in willSelect = true } @@ -799,10 +990,10 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { } func test_didSelectRow_performsDidSelectCommand() { - let row = TestTableViewRow() + var row = TestTableViewRow() var didSelected = false - row.set(command: .didSelect) { _, _, _ in + row.set(.didSelect) { _, _, _ in didSelected = true } @@ -818,10 +1009,10 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { } func test_willDeselectRow_performsWillDeselectCommand() { - let row = TestTableViewRow() + var row = TestTableViewRow() var willDeselect = false - row.set(command: .willDeselect) { _, _, _ in + row.set(.willDeselect) { _, _, _ in willDeselect = true } @@ -840,10 +1031,10 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { } func test_didDeselectRow_performsDidDeselectCommand() { - let row = TestTableViewRow() + var row = TestTableViewRow() var didDeselect = false - row.set(command: .didDeselect) { (_, _, _) in + row.set(.didDeselect) { _, _, _ in didDeselect = true } @@ -890,10 +1081,10 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { } func test_willDisplayCell_performsWillDisplayCommand() { - let row = TestTableViewRow() + var row = TestTableViewRow() var willDisplay = false - row.set(command: .willDisplay) { (_, _, _) in + row.set(.willDisplay) { _, _, _ in willDisplay = true } @@ -939,7 +1130,7 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { liaison.tableView(tableView, willDisplay: UITableViewCell(), forRowAt: IndexPath(row: 0, section: 0)) DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { - XCTAssert(self.liaison.sections.last?.rows.first === self.liaison.paginationSection.rows.first) + XCTAssert(self.liaison.sections.last?.rows.first is TableViewRow) expectation.fulfill() } @@ -996,10 +1187,10 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { } func test_didEndDisplayingCell_performsDidEndDisplayingCommand() { - let row = TestTableViewRow() + var row = TestTableViewRow() var didEndDisplaying = false - row.set(command: .didEndDisplaying) { (_, _, _) in + row.set(.didEndDisplaying) { _, _, _ in didEndDisplaying = true } @@ -1012,10 +1203,10 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { } func test_willBeginEditingRow_performsWillBeginEditingCommand() { - let row = TestTableViewRow() + var row = TestTableViewRow() var willBeginEditing = false - row.set(command: .willBeginEditing) { (_, _, _) in + row.set(.willBeginEditing) { _, _, _ in willBeginEditing = true } @@ -1031,10 +1222,10 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { } func test_didEndEditingRow_performsDidEndEditingCommand() { - let row = TestTableViewRow() + var row = TestTableViewRow() var didEndEditing = false - row.set(command: .didEndEditing) { (_, _, _) in + row.set(.didEndEditing) { _, _, _ in didEndEditing = true } @@ -1049,10 +1240,10 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { } func test_didHighlightRow_performsDidHighlightRowCommand() { - let row = TestTableViewRow() + var row = TestTableViewRow() var didHighlight = false - row.set(command: .didHighlight) { (_, _, _) in + row.set(.didHighlight) { _, _, _ in didHighlight = true } @@ -1068,10 +1259,10 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { } func test_didUnhighlightRow_performsDidUnhighlightRowCommand() { - let row = TestTableViewRow() + var row = TestTableViewRow() var didUnhighlight = false - row.set(command: .didUnhighlight) { (_, _, _) in + row.set(.didUnhighlight) { _, _, _ in didUnhighlight = true } @@ -1088,14 +1279,14 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { func test_viewForHeaderInSection_returnCorrectHeaderForSection() { - let header = TestTableViewSectionComponent() + var header = TestTableViewSectionComponent() - header.set(command: .configuration) { view, _, section in + header.set(.configuration) { _, view, section in view.accessibilityIdentifier = "\(section)" } - let section1 = TableViewSection(componentDisplayOption: .header(component: header)) - let section2 = TableViewSection(componentDisplayOption: .header(component: header)) + let section1 = TableViewSection(option: .header(component: header)) + let section2 = TableViewSection(option: .header(component: header)) liaison.append(sections: [section1, section2]) @@ -1108,14 +1299,14 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { func test_viewForFooterInSection_returnCorrectFooterForSection() { - let footer = TestTableViewSectionComponent() + var footer = TestTableViewSectionComponent() - footer.set(command: .configuration) { view, _, section in + footer.set(.configuration) { _, view, section in view.accessibilityIdentifier = "\(section)" } - let section1 = TableViewSection(componentDisplayOption: .footer(component: footer)) - let section2 = TableViewSection(componentDisplayOption: .footer(component: footer)) + let section1 = TableViewSection(option: .footer(component: footer)) + let section2 = TableViewSection(option: .footer(component: footer)) liaison.append(sections: [section1, section2]) @@ -1127,15 +1318,13 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { } func test_heightForRow_properlySetsHeightsForRows() { - let row1 = TestTableViewRow() - let row2 = TestTableViewRow() + var row1 = TestTableViewRow() + var row2 = TestTableViewRow() let row3 = TestTableViewRow() - row1.set(height: .height) { _ -> CGFloat in - return 100 - } + row1.set(.height) { return 100 } - row2.set(height: .height, 200) + row2.set(.height, 200) let section = TableViewSection(rows: [row1, row2, row3]) liaison.append(section: section) @@ -1150,15 +1339,13 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { } func test_estimatedHeightForRow_properlySetsEstimatedHeightsForRows() { - let row1 = TestTableViewRow() - let row2 = TestTableViewRow() + var row1 = TestTableViewRow() + var row2 = TestTableViewRow() let row3 = TestTableViewRow() - row1.set(height: .estimatedHeight) { _ -> CGFloat in - return 100 - } + row1.set(.estimatedHeight) { return 100 } - row2.set(height: .estimatedHeight, 200) + row2.set(.estimatedHeight, 200) let section = TableViewSection(rows: [row1, row2, row3]) liaison.append(section: section) @@ -1227,10 +1414,10 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { } func test_accessoryButtonTapped_performsAccessoryButtonTappedCommand() { - let row = TestTableViewRow() + var row = TestTableViewRow() var accessoryButtonTapped = false - row.set(command: .accessoryButtonTapped) { (_, _, _) in + row.set(.accessoryButtonTapped) { _, _, _ in accessoryButtonTapped = true } @@ -1262,49 +1449,47 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { } func test_heightForHeader_properlySetsHeightsForSectionHeaders() { - let header1 = TestTableViewSectionComponent() - let header2 = TestTableViewSectionComponent() + var header1 = TestTableViewSectionComponent() + var header2 = TestTableViewSectionComponent() let header3 = TestTableViewSectionComponent() - header1.set(height: .height, 100) + header1.set(.height, 100) - header2.set(height: .height) { _ -> CGFloat in - return 200 - } + header2.set(.height) { return 200 } - let section1 = TableViewSection(componentDisplayOption: .header(component: header1)) - let section2 = TableViewSection(componentDisplayOption: .header(component: header2)) - let section3 = TableViewSection(componentDisplayOption: .header(component: header3)) + let section1 = TableViewSection(option: .header(component: header1)) + let section2 = TableViewSection(option: .header(component: header2)) + let section3 = TableViewSection(option: .header(component: header3)) liaison.append(sections: [section1, section2, section3]) let section1Height = liaison.tableView(tableView, heightForHeaderInSection: 0) let section2Height = liaison.tableView(tableView, heightForHeaderInSection: 1) let section3Height = liaison.tableView(tableView, heightForHeaderInSection: 2) + let section4Height = liaison.tableView(tableView, heightForHeaderInSection: 3) XCTAssertEqual(section1Height, 100) XCTAssertEqual(section2Height, 200) XCTAssertEqual(section3Height, UITableView.automaticDimension) + XCTAssertEqual(section4Height, UITableView.automaticDimension) } func test_estimatedHeightForHeader_properlySetsEstimatedHeightsForSectionHeaders() { - let header1 = TestTableViewSectionComponent() - let header2 = TestTableViewSectionComponent() - let header3 = TestTableViewSectionComponent() + var header1 = TestTableViewSectionComponent() + var header2 = TestTableViewSectionComponent() + var header3 = TestTableViewSectionComponent() let header4 = TestTableViewSectionComponent() - header1.set(height: .estimatedHeight, 100) + header1.set(.estimatedHeight, 100) - header2.set(height: .estimatedHeight) { _ -> CGFloat in - return 200 - } + header2.set(.estimatedHeight) { return 200 } - header3.set(height: .height, 300) + header3.set(.height, 300) - let section1 = TableViewSection(componentDisplayOption: .header(component: header1)) - let section2 = TableViewSection(componentDisplayOption: .header(component: header2)) - let section3 = TableViewSection(componentDisplayOption: .header(component: header3)) - let section4 = TableViewSection(componentDisplayOption: .header(component: header4)) + let section1 = TableViewSection(option: .header(component: header1)) + let section2 = TableViewSection(option: .header(component: header2)) + let section3 = TableViewSection(option: .header(component: header3)) + let section4 = TableViewSection(option: .header(component: header4)) liaison.append(sections: [section1, section2, section3, section4]) @@ -1320,19 +1505,17 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { } func test_heightForFooter_properlySetsHeightsForSectionFooters() { - let footer1 = TestTableViewSectionComponent() - let footer2 = TestTableViewSectionComponent() + var footer1 = TestTableViewSectionComponent() + var footer2 = TestTableViewSectionComponent() let footer3 = TestTableViewSectionComponent() - footer1.set(height: .height, 100) + footer1.set(.height, 100) - footer2.set(height: .height) { _ -> CGFloat in - return 200 - } + footer2.set(.height) { return 200 } - let section1 = TableViewSection(componentDisplayOption: .footer(component: footer1)) - let section2 = TableViewSection(componentDisplayOption: .footer(component: footer2)) - let section3 = TableViewSection(componentDisplayOption: .footer(component: footer3)) + let section1 = TableViewSection(option: .footer(component: footer1)) + let section2 = TableViewSection(option: .footer(component: footer2)) + let section3 = TableViewSection(option: .footer(component: footer3)) liaison.append(sections: [section1, section2, section3]) @@ -1346,23 +1529,21 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { } func test_estimatedHeightForFooter_properlySetsEstimatedHeightsForSectionFooters() { - let footer1 = TestTableViewSectionComponent() - let footer2 = TestTableViewSectionComponent() - let footer3 = TestTableViewSectionComponent() + var footer1 = TestTableViewSectionComponent() + var footer2 = TestTableViewSectionComponent() + var footer3 = TestTableViewSectionComponent() let footer4 = TestTableViewSectionComponent() - footer1.set(height: .estimatedHeight, 100) + footer1.set(.estimatedHeight, 100) - footer2.set(height: .estimatedHeight) { _ -> CGFloat in - return 200 - } + footer2.set(.estimatedHeight) { return 200 } - footer3.set(height: .height, 300) + footer3.set(.height, 300) - let section1 = TableViewSection(componentDisplayOption: .footer(component: footer1)) - let section2 = TableViewSection(componentDisplayOption: .footer(component: footer2)) - let section3 = TableViewSection(componentDisplayOption: .footer(component: footer3)) - let section4 = TableViewSection(componentDisplayOption: .footer(component: footer4)) + let section1 = TableViewSection(option: .footer(component: footer1)) + let section2 = TableViewSection(option: .footer(component: footer2)) + let section3 = TableViewSection(option: .footer(component: footer3)) + let section4 = TableViewSection(option: .footer(component: footer4)) liaison.append(sections: [section1, section2, section3, section4]) @@ -1380,14 +1561,14 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { func test_willDisplayHeaderView_performsWillDisplayHeaderViewSectionCommand() { - let header = TestTableViewSectionComponent() + var header = TestTableViewSectionComponent() var willDisplay = false - header.set(command: .willDisplay) { _, _, _ in + header.set(.willDisplay) { _, _, _ in willDisplay = true } - let section = TableViewSection(componentDisplayOption: .header(component: header)) + let section = TableViewSection(option: .header(component: header)) liaison.append(section: section) let view = UITableViewHeaderFooterView() @@ -1398,14 +1579,14 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { func test_willDisplayFooterView_performsWillDisplayFooterViewSectionCommand() { - let footer = TestTableViewSectionComponent() + var footer = TestTableViewSectionComponent() var willDisplay = false - footer.set(command: .willDisplay) { _, _, _ in + footer.set(.willDisplay) { _, _, _ in willDisplay = true } - let section = TableViewSection(componentDisplayOption: .footer(component: footer)) + let section = TableViewSection(option: .footer(component: footer)) liaison.append(section: section) let view = UITableViewHeaderFooterView() @@ -1416,14 +1597,14 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { func test_didEndDisplayingHeaderView_performsDidEndDisplayingHeaderViewSectionCommand() { - let header = TestTableViewSectionComponent() + var header = TestTableViewSectionComponent() var didEndDisplaying = false - header.set(command: .didEndDisplaying) { _, _, _ in + header.set(.didEndDisplaying) { _, _, _ in didEndDisplaying = true } - let section = TableViewSection(componentDisplayOption: .header(component: header)) + let section = TableViewSection(option: .header(component: header)) liaison.append(section: section) let view = UITableViewHeaderFooterView() @@ -1434,14 +1615,14 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { func test_didEndDisplayingFooterView_performsDidEndDisplayingFooterViewSectionCommand() { - let footer = TestTableViewSectionComponent() + var footer = TestTableViewSectionComponent() var didEndDisplaying = false - footer.set(command: .didEndDisplaying) { _, _, _ in + footer.set(.didEndDisplaying) { _, _, _ in didEndDisplaying = true } - let section = TableViewSection(componentDisplayOption: .footer(component: footer)) + let section = TableViewSection(option: .footer(component: footer)) liaison.append(section: section) let view = UITableViewHeaderFooterView() @@ -1451,9 +1632,9 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { } func test_prefetchRowsAtIndexPaths_performsPrefetchRowCommand() { - let row = TestTableViewRow() + var row = TestTableViewRow() var prefetch = false - row.set(prefetchCommand: .prefetch) { _, _ in + row.set(.prefetch) { _ in prefetch = true } @@ -1466,9 +1647,9 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { } func test_cancelPrefetchingForRowsAtIndexPaths_performsPrefetchRowCommand() { - let row = TestTableViewRow() + var row = TestTableViewRow() var cancel = false - row.set(prefetchCommand: .cancel) { _, _ in + row.set(.cancel) { _ in cancel = true } @@ -1482,14 +1663,50 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { func test_rowForIndexPath_returnsCorrectRow() { let row1 = TestTableViewRow() - let row2 = TestTableViewRow() + var row2 = TestTableViewRow() + + var correctRow = false + row2.set(.didSelect) { _, _, _ in + correctRow = true + } let section = TableViewSection(rows: [row1, row2]) liaison.append(section: section) let indexPath = IndexPath(row: 1, section: 0) let row = liaison.row(for: indexPath) - XCTAssert(row === row2) + row?.perform(.didSelect, liaison: liaison, cell: UITableViewCell(), indexPath: indexPath) + + XCTAssertTrue(correctRow) + } + + func test_rowForIndexPathGeneric_returnsCorrectRow() { + let row1 = TableViewRow() + var row2 = TableViewRow() + + var correctRow = false + row2.set(.didSelect) { _, _, _ in + correctRow = true + } + + let section = TableViewSection(rows: [row1, row2]) + liaison.append(section: section) + let indexPath = IndexPath(row: 1, section: 0) + + let row: TableViewRow? = liaison.row(for: indexPath) + row?.perform(.didSelect, liaison: liaison, cell: UITableViewCell(), indexPath: indexPath) + + XCTAssertTrue(correctRow) + } + + func test_rowForIndexPathGeneric_returnsNilForIncorrectType() { + + let section = TableViewSection(rows: [StatelessTableViewRow()]) + liaison.append(section: section) + let indexPath = IndexPath(row: 0, section: 0) + + let row: TableViewRow? = liaison.row(for: indexPath) + XCTAssertNil(row) } func test_rowForIndexPath_returnsNilForInvalidIndexPath() { @@ -1522,4 +1739,29 @@ final class OKTableViewLiaison_UnitTests: XCTestCase { XCTAssertEqual(indexPath, IndexPath(row: 1, section: 0)) } + func test_sectionIndexesForId_returnsCorrectIndexesForId() { + let identifier = "test" + let section = TableViewSection(id: identifier) + liaison.append(section: section) + + let indexes = liaison.sectionIndexes(for: identifier) + XCTAssertEqual(indexes, [0]) + } + + func test_rowIndexPaths_returnsIndexPathsForPredicate() { + let row1 = TableViewRow("test") + let row2 = TableViewRow("test") + + let section1 = TableViewSection(rows: [row1]) + let section2 = TableViewSection(rows: [row2]) + + liaison.append(sections: [section1, section2]) + + let indexPaths = liaison.rowIndexPathes { (data: String) in + return data == "test" + } + + XCTAssertEqual(indexPaths, [IndexPath(row: 0, section: 0), + IndexPath(row: 0, section: 1)]) + } } diff --git a/Example/Tests/TableViewRow+UnitTests.swift b/Example/Tests/TableViewRow+UnitTests.swift index 48b3076..575ed32 100644 --- a/Example/Tests/TableViewRow+UnitTests.swift +++ b/Example/Tests/TableViewRow+UnitTests.swift @@ -9,49 +9,57 @@ import XCTest @testable import TableViewLiaison -final class OKTableViewRow_UnitTests: XCTestCase { +final class TableViewRow_UnitTests: XCTestCase { + + var liaison: TableViewLiaison! + var tableView: UITableView! + + override func setUp() { + super.setUp() + liaison = TableViewLiaison() + tableView = UITableView() + liaison.liaise(tableView: tableView) + } func test_setCommand_setsCommandClosure() { - let row = TestTableViewRow() + var row = TableViewRow() var set = false - row.set(command: .configuration) { (_, _, _) in + row.set(.configuration) { _, _, _ in set = true } - row.perform(command: .configuration, for: UITableViewCell(), at: IndexPath()) + row.perform(.configuration, liaison: liaison, cell: UITableViewCell(), indexPath: IndexPath()) XCTAssertTrue(set) } func test_removeCommand_removesCommand() { - let row = TestTableViewRow() + var row = TestTableViewRow() var set = false - row.set(command: .configuration) { (_, _, _) in + row.set(.configuration) { _, _, _ in set = true } - row.remove(command: .configuration) - row.perform(command: .configuration, for: UITableViewCell(), at: IndexPath()) - + row.remove(.configuration) + row.perform(.configuration, liaison: liaison, cell: UITableViewCell(), indexPath: IndexPath()) + XCTAssertFalse(set) } func test_setHeight_setsHeightWithClosure() { - let row = TestTableViewRow() + var row = TestTableViewRow() - row.set(height: .height) { (_) -> CGFloat in - return 100 - } + row.set(.height) { return 100 } XCTAssertEqual(row.height, 100) } func test_setHeight_setsHeightWithValue() { - let row = TestTableViewRow() + var row = TestTableViewRow() - row.set(height: .height, 100) + row.set(.height, 100) XCTAssertEqual(row.height, 100) } @@ -63,56 +71,56 @@ final class OKTableViewRow_UnitTests: XCTestCase { } func test_removeHeight_removesAPreviouslySetHeight() { - let row = TestTableViewRow() + var row = TestTableViewRow() - row.set(height: .height, 100) - row.set(height: .estimatedHeight, 100) + row.set(.height, 100) + row.set(.estimatedHeight, 100) - row.remove(height: .height) - row.remove(height: .estimatedHeight) + row.remove(.height) + row.remove(.estimatedHeight) XCTAssertEqual(row.height, UITableView.automaticDimension) XCTAssertEqual(row.estimatedHeight, UITableView.automaticDimension) } func test_setPrefetchCommand_setPrefetchCommandClosure() { - let row = TestTableViewRow() + var row = TestTableViewRow() var prefetch = false - row.set(prefetchCommand: .prefetch) { _, _ in + row.set(.prefetch) { _ in prefetch = true } var cancel = false - row.set(prefetchCommand: .cancel) { _, _ in + row.set(.cancel) { _ in cancel = true } - row.perform(prefetchCommand: .prefetch, for: IndexPath()) - row.perform(prefetchCommand: .cancel, for: IndexPath()) + row.perform(.prefetch, for: IndexPath()) + row.perform(.cancel, for: IndexPath()) XCTAssertTrue(prefetch) XCTAssertTrue(cancel) } func test_removePrefetchCommand_removesPreviouslySetPrefetchCommands() { - let row = TestTableViewRow() + var row = TestTableViewRow() var prefetch = false - row.set(prefetchCommand: .prefetch) { _, _ in + row.set(.prefetch) { _ in prefetch = true } var cancel = false - row.set(prefetchCommand: .cancel) { _, _ in + row.set(.cancel) { _ in cancel = true } - row.remove(prefetchCommand: .prefetch) - row.remove(prefetchCommand: .cancel) + row.remove(.prefetch) + row.remove(.cancel) - row.perform(prefetchCommand: .prefetch, for: IndexPath()) - row.perform(prefetchCommand: .cancel, for: IndexPath()) + row.perform(.prefetch, for: IndexPath()) + row.perform(.cancel, for: IndexPath()) XCTAssertFalse(prefetch) XCTAssertFalse(cancel) @@ -147,9 +155,8 @@ final class OKTableViewRow_UnitTests: XCTestCase { func test_register_registersCellForRow() { let row = TestTableViewRow(registrationType: .class(reuseIdentifier: "Test")) - let tableView = UITableView() - row.register(with: tableView) + row.register(with: liaison) let cell = tableView.dequeueReusableCell(withIdentifier: "Test") @@ -157,30 +164,28 @@ final class OKTableViewRow_UnitTests: XCTestCase { } func test_cellForTableViewAt_returnsConfiguredCellForRow() { - let row = TestTableViewRow() + var row = TestTableViewRow() let string = "Test" - row.set(command: .configuration) { (cell, _, indexPath) in + row.set(.configuration) { _, cell, indexPath in cell.accessibilityIdentifier = string } + + row.register(with: liaison) - let tableView = UITableView() - - row.register(with: tableView) - - let cell = row.cell(for: tableView, at: IndexPath()) + let cell = row.cell(for: liaison, at: IndexPath()) XCTAssertEqual(cell.accessibilityIdentifier, string) } func test_perform_ignoresCommandPerformanceForIncorrectCellType() { - let row = TableViewRow() + var row = StatelessTableViewRow() var configured = false - row.set(command: .configuration) { _, _, _ in + row.set(.configuration) { _, _, _ in configured = true } - row.perform(command: .configuration, for: UITableViewCell(), at: IndexPath()) + row.perform(.configuration, liaison: liaison, cell: UITableViewCell(), indexPath: IndexPath()) XCTAssertFalse(configured) } diff --git a/Example/Tests/TableViewSection+UnitTests.swift b/Example/Tests/TableViewSection+UnitTests.swift index 79286d8..7fd1b8d 100644 --- a/Example/Tests/TableViewSection+UnitTests.swift +++ b/Example/Tests/TableViewSection+UnitTests.swift @@ -9,97 +9,99 @@ import XCTest @testable import TableViewLiaison -final class OKTableViewSection_UnitTests: XCTestCase { +final class TableViewSection_UnitTests: XCTestCase { + + var liaison: TableViewLiaison! + var tableView: UITableView! + + override func setUp() { + super.setUp() + liaison = TableViewLiaison() + tableView = UITableView() + liaison.liaise(tableView: tableView) + } func test_calculateHeight_setsHeightOfSupplementaryViewsWithClosure() { - let header = TestTableViewSectionComponent() - let footer = TestTableViewSectionComponent() + var header = TestTableViewSectionComponent() + var footer = TestTableViewSectionComponent() - header.set(height: .height) { _ -> CGFloat in - return 100 - } + header.set(.height) { return 100 } - footer.set(height: .height) { _ -> CGFloat in - return 50 - } + footer.set(.height) { return 50 } - let section = TableViewSection(componentDisplayOption: .both(headerComponent: header, footerComponent: footer)) + let section = TableViewSection(option: .both(headerComponent: header, footerComponent: footer)) - XCTAssertEqual(section.calculate(height: .height, for: .header), 100) - XCTAssertEqual(section.calculate(height: .height, for: .footer), 50) + XCTAssertEqual(section.calculate(.height, for: .header), 100) + XCTAssertEqual(section.calculate(.height, for: .footer), 50) } func test_calculateEstimatedHeight_setsEstimatedHeightOfSupplementaryViewsWithClosure() { - let header = TestTableViewSectionComponent() - let footer = TestTableViewSectionComponent() + var header = TestTableViewSectionComponent() + var footer = TestTableViewSectionComponent() - header.set(height: .estimatedHeight) { _ -> CGFloat in - return 100 - } + header.set(.estimatedHeight) { return 100 } - footer.set(height: .estimatedHeight) { _ -> CGFloat in - return 50 - } + footer.set(.estimatedHeight) { return 50 } - let section = TableViewSection(componentDisplayOption: .both(headerComponent: header, footerComponent: footer)) + let section = TableViewSection(option: .both(headerComponent: header, footerComponent: footer)) - XCTAssertEqual(section.calculate(height: .estimatedHeight, for: .header), 100) - XCTAssertEqual(section.calculate(height: .estimatedHeight, for: .footer), 50) + XCTAssertEqual(section.calculate(.estimatedHeight, for: .header), 100) + XCTAssertEqual(section.calculate(.estimatedHeight, for: .footer), 50) } func test_calculateHeight_setsHeightOfSupplementaryViewsWithValue() { - let header = TestTableViewSectionComponent() - let footer = TestTableViewSectionComponent() + var header = TestTableViewSectionComponent() + var footer = TestTableViewSectionComponent() - header.set(height: .height, 100) - footer.set(height: .height, 50) + header.set(.height, 100) + footer.set(.height, 50) - let section = TableViewSection(componentDisplayOption: .both(headerComponent: header, footerComponent: footer)) + let section = TableViewSection(option: .both(headerComponent: header, footerComponent: footer)) - XCTAssertEqual(section.calculate(height: .height, for: .header), 100) - XCTAssertEqual(section.calculate(height: .height, for: .footer), 50) + XCTAssertEqual(section.calculate(.height, for: .header), 100) + XCTAssertEqual(section.calculate(.height, for: .footer), 50) } func test_calculateEstimatedHeight_setsEstimatedHeightOfSupplementaryViewsWithValue() { - let header = TestTableViewSectionComponent() - let footer = TestTableViewSectionComponent() + var header = TestTableViewSectionComponent() + var footer = TestTableViewSectionComponent() - header.set(height: .estimatedHeight, 100) - footer.set(height: .estimatedHeight, 50) + header.set(.estimatedHeight, 100) + footer.set(.estimatedHeight, 50) - let section = TableViewSection(componentDisplayOption: .both(headerComponent: header, footerComponent: footer)) + let section = TableViewSection(option: .both(headerComponent: header, footerComponent: footer)) - XCTAssertEqual(section.calculate(height: .estimatedHeight, for: .header), 100) - XCTAssertEqual(section.calculate(height: .estimatedHeight, for: .footer), 50) + XCTAssertEqual(section.calculate(.estimatedHeight, for: .header), 100) + XCTAssertEqual(section.calculate(.estimatedHeight, for: .footer), 50) } func test_calculateHeight_returnsAutomaticDimensionForSelfSizingSupplementaryViews() { - let section = TableViewSection(componentDisplayOption: .both(headerComponent: TestTableViewSectionComponent(), + let section = TableViewSection(option: .both(headerComponent: TestTableViewSectionComponent(), footerComponent: TestTableViewSectionComponent())) - XCTAssertEqual(section.calculate(height: .height, for: .header), UITableView.automaticDimension) - XCTAssertEqual(section.calculate(height: .height, for: .footer), UITableView.automaticDimension) + XCTAssertEqual(section.calculate(.height, for: .header), UITableView.automaticDimension) + XCTAssertEqual(section.calculate(.height, for: .footer), UITableView.automaticDimension) } func test_calculateHeight_returnsZeroForNonSetEstimatedSupplementaryViewsHeights() { - let section = TableViewSection(componentDisplayOption: .both(headerComponent: TestTableViewSectionComponent(), + let section = TableViewSection(option: .both(headerComponent: TestTableViewSectionComponent(), footerComponent: TestTableViewSectionComponent())) - XCTAssertEqual(section.calculate(height: .estimatedHeight, for: .header), 0) - XCTAssertEqual(section.calculate(height: .estimatedHeight, for: .footer), 0) + XCTAssertEqual(section.calculate(.estimatedHeight, for: .header), 0) + XCTAssertEqual(section.calculate(.estimatedHeight, for: .footer), 0) } func test_calculateHeight_returnZeroForHeightOfNonDisplayedSupplementaryViews() { let section = TableViewSection() - let headerHeight = section.calculate(height: .height, for: .header) - let footerHeight = section.calculate(height: .height, for: .footer) - let headerEstimatedHeight = section.calculate(height: .estimatedHeight, for: .header) - let footerEstimatedHeight = section.calculate(height: .estimatedHeight, for: .footer) + let headerHeight = section.calculate(.height, for: .header) + let footerHeight = section.calculate(.height, for: .footer) + let headerEstimatedHeight = section.calculate(.estimatedHeight, for: .header) + let footerEstimatedHeight = section.calculate(.estimatedHeight, for: .footer) if #available(iOS 11.0, *) { XCTAssertEqual(headerHeight, .leastNormalMagnitude) @@ -115,25 +117,25 @@ final class OKTableViewSection_UnitTests: XCTestCase { } func test_removeHeight_removesHeightOfSupplementaryViews() { - let header = TestTableViewSectionComponent() - let footer = TestTableViewSectionComponent() + var header = TestTableViewSectionComponent() + var footer = TestTableViewSectionComponent() - header.set(height: .height, 40) - footer.set(height: .height, 40) - header.set(height: .estimatedHeight, 40) - footer.set(height: .estimatedHeight, 40) + header.set(.height, 40) + footer.set(.height, 40) + header.set(.estimatedHeight, 40) + footer.set(.estimatedHeight, 40) - let section = TableViewSection(componentDisplayOption: .both(headerComponent: header, footerComponent: footer)) + header.remove(.height) + footer.remove(.height) + header.remove(.estimatedHeight) + footer.remove(.estimatedHeight) - header.remove(height: .height) - footer.remove(height: .height) - header.remove(height: .estimatedHeight) - footer.remove(height: .estimatedHeight) + let section = TableViewSection(option: .both(headerComponent: header, footerComponent: footer)) - XCTAssertEqual(section.calculate(height: .height, for: .header), UITableView.automaticDimension) - XCTAssertEqual(section.calculate(height: .height, for: .footer), UITableView.automaticDimension) - XCTAssertEqual(section.calculate(height: .estimatedHeight, for: .header), 0) - XCTAssertEqual(section.calculate(height: .estimatedHeight, for: .footer), 0) + XCTAssertEqual(section.calculate(.height, for: .header), UITableView.automaticDimension) + XCTAssertEqual(section.calculate(.height, for: .footer), UITableView.automaticDimension) + XCTAssertEqual(section.calculate(.estimatedHeight, for: .header), 0) + XCTAssertEqual(section.calculate(.estimatedHeight, for: .footer), 0) } func test_appendRows_appendsNewRowsToSection() { @@ -141,58 +143,61 @@ final class OKTableViewSection_UnitTests: XCTestCase { let row1 = TestTableViewRow() let row2 = TestTableViewRow() + XCTAssertEqual(section.rows.count, 0) + section.append(rows: [row1, row2]) XCTAssertEqual(section.rows.count, 2) - XCTAssert(section.rows.first === row1) - XCTAssert(section.rows.last === row2) } func test_appendRow_appendsRowToSection() { var section = TableViewSection() let row = TestTableViewRow() + XCTAssertEqual(section.rows.count, 0) + section.append(row: row) XCTAssertEqual(section.rows.count, 1) - XCTAssert(section.rows.first === row) } func test_headerForTableView_returnsConfiguredHeaderForSection() { + let liaison = TableViewLiaison() let tableView = UITableView() - let header = TestTableViewSectionComponent() + liaison.liaise(tableView: tableView) + + var header = TestTableViewSectionComponent() let reuseIdentifier = String(describing: UITableViewHeaderFooterView.self) tableView.register(UITableViewHeaderFooterView.self, forHeaderFooterViewReuseIdentifier: reuseIdentifier) let string = "Test" - header.set(command: .configuration) { view, _, _ in + header.set(.configuration) { _, view, _ in view.accessibilityIdentifier = string } - let section = TableViewSection(componentDisplayOption: .header(component: header)) + let section = TableViewSection(option: .header(component: header)) - let headerView = section.view(componentView: .header, for: tableView, in: 0) + let headerView = section.view(componentView: .header, for: liaison, in: 0) XCTAssertEqual(headerView?.accessibilityIdentifier, string) XCTAssert(headerView is UITableViewHeaderFooterView) } func test_footerForTableView_returnsConfiguredFooterForSection() { - let tableView = UITableView() - let footer = TestTableViewSectionComponent() + var footer = TestTableViewSectionComponent() let reuseIdentifier = String(describing: UITableViewHeaderFooterView.self) tableView.register(UITableViewHeaderFooterView.self, forHeaderFooterViewReuseIdentifier: reuseIdentifier) let string = "Test" - footer.set(command: .configuration) { view, _, _ in + footer.set(.configuration) { _, view, _ in view.accessibilityIdentifier = string } - let section = TableViewSection(componentDisplayOption: .footer(component: footer)) + let section = TableViewSection(option: .footer(component: footer)) - let footerView = section.view(componentView: .footer, for: tableView, in: 0) + let footerView = section.view(componentView: .footer, for: liaison, in: 0) XCTAssertEqual(footerView?.accessibilityIdentifier, string) XCTAssert(footerView is UITableViewHeaderFooterView) @@ -200,8 +205,8 @@ final class OKTableViewSection_UnitTests: XCTestCase { func test_perform_performsSectionCommands() { - let header = TestTableViewSectionComponent() - let footer = TestTableViewSectionComponent() + var header = TestTableViewSectionComponent() + var footer = TestTableViewSectionComponent() var headerConfiguration = "" var headerDidEndDisplaying = "" @@ -210,39 +215,39 @@ final class OKTableViewSection_UnitTests: XCTestCase { var footerDidEndDisplaying = "" var footerWillDisplay = "" - header.set(command: .configuration) { view, string, section in + header.set(.configuration) { _, view, section in headerConfiguration = "Configured!" } - header.set(command: .didEndDisplaying) { view, string, section in + header.set(.didEndDisplaying) { _, view, section in headerDidEndDisplaying = "DidEndDisplaying!" } - header.set(command: .willDisplay) { view, string, section in + header.set(.willDisplay) { _, view, section in headerWillDisplay = "WillDisplay!" } - footer.set(command: .configuration) { view, string, section in + footer.set(.configuration) { _, view, section in footerConfiguration = "Configured!" } - footer.set(command: .didEndDisplaying) { view, string, section in + footer.set(.didEndDisplaying) { _, view, section in footerDidEndDisplaying = "DidEndDisplaying!" } - footer.set(command: .willDisplay) { view, string, section in + footer.set(.willDisplay) { _, view, section in footerWillDisplay = "WillDisplay!" } let view = UITableViewHeaderFooterView() - let section = TableViewSection(componentDisplayOption: .both(headerComponent: header, footerComponent: footer)) + let section = TableViewSection(option: .both(headerComponent: header, footerComponent: footer)) - section.perform(command: .configuration, componentView: .header, for: view, in: 0) - section.perform(command: .configuration, componentView: .footer, for: view, in: 0) - section.perform(command: .didEndDisplaying, componentView: .header, for: view, in: 0) - section.perform(command: .didEndDisplaying, componentView: .footer, for: view, in: 0) - section.perform(command: .willDisplay, componentView: .header, for: view, in: 0) - section.perform(command: .willDisplay, componentView: .footer, for: view, in: 0) + section.perform(.configuration, componentView: .header, liaison: liaison, view: view, section: 0) + section.perform(.configuration, componentView: .footer, liaison: liaison, view: view, section: 0) + section.perform(.didEndDisplaying, componentView: .header, liaison: liaison, view: view, section: 0) + section.perform(.didEndDisplaying, componentView: .footer, liaison: liaison, view: view, section: 0) + section.perform(.willDisplay, componentView: .header, liaison: liaison, view: view, section: 0) + section.perform(.willDisplay, componentView: .footer, liaison: liaison, view: view, section: 0) XCTAssertEqual(headerConfiguration, "Configured!") XCTAssertEqual(footerConfiguration, "Configured!") @@ -253,28 +258,43 @@ final class OKTableViewSection_UnitTests: XCTestCase { } func test_perform_ignoresCommandPerformanceForIncorrectSupplementaryViewType() { - let header = TestTableViewSectionComponent() - let footer = TestTableViewSectionComponent() + var header = TestTableViewSectionComponent() + var footer = TestTableViewSectionComponent() var headerConfiguration = "" var footerConfiguration = "" - header.set(command: .configuration) { view, string, section in + header.set(.configuration) { _, view, section in headerConfiguration = "Configured!" } - footer.set(command: .configuration) { view, string, section in + footer.set(.configuration) { _, view, section in footerConfiguration = "Configured!" } let view = UIView() - let section = TableViewSection(componentDisplayOption: .both(headerComponent: header, footerComponent: footer)) - section.perform(command: .configuration, componentView: .header, for: view, in: 0) - section.perform(command: .configuration, componentView: .footer, for: view, in: 0) + let section = TableViewSection(option: .both(headerComponent: header, footerComponent: footer)) + section.perform(.configuration, componentView: .header, liaison: liaison, view: view, section: 0) + section.perform(.configuration, componentView: .footer, liaison: liaison, view: view, section: 0) XCTAssertEqual(headerConfiguration, "") XCTAssertEqual(footerConfiguration, "") } + func test_rowIndexPaths_returnsIndexPathsForPredicate() { + let row1 = TableViewRow("test") + let row2 = TestTableViewRow() + let row3 = TableViewRow("test") + + let section = TableViewSection(rows: [row1, row2, row3]) + + let indexPaths = section.rowIndexPaths(for: 0) { (data: String) in + return data == "test" + } + + XCTAssertEqual(indexPaths, [IndexPath(row: 0, section: 0), + IndexPath(row: 2, section: 0)]) + } + } diff --git a/Example/Tests/TableViewSectionComponent+UnitTests.swift b/Example/Tests/TableViewSectionComponent+UnitTests.swift index 0c30293..f3f0c85 100644 --- a/Example/Tests/TableViewSectionComponent+UnitTests.swift +++ b/Example/Tests/TableViewSectionComponent+UnitTests.swift @@ -1,6 +1,6 @@ // // TableViewSectionComponent+UnitTests.swift -// OKTableViewLiaison_Tests +// TableViewLiaison_Tests // // Created by Dylan Shine on 5/30/18. // Copyright © 2018 CocoaPods. All rights reserved. @@ -9,55 +9,66 @@ import XCTest @testable import TableViewLiaison -final class OKTableViewSectionComponent_UnitTests: XCTestCase { +final class TableViewSectionComponent_UnitTests: XCTestCase { + var liaison: TableViewLiaison! + var tableView: UITableView! + + override func setUp() { + super.setUp() + liaison = TableViewLiaison() + tableView = UITableView() + liaison.liaise(tableView: tableView) + } func test_setCommand_setsCommandClosure() { - let component = TestTableViewSectionComponent() + var component = TestTableViewSectionComponent() var set = false - component.set(command: .configuration) { _, _, _ in + component.set(.configuration) { _, _, _ in set = true } - component.perform(command: .configuration, for: UITableViewHeaderFooterView(), in: 0) + component.perform(.configuration, + liaison: TableViewLiaison(), + view: UITableViewHeaderFooterView(), + section: 0) XCTAssertTrue(set) } func test_removeCommand_removesCommand() { - let component = TestTableViewSectionComponent() + var component = TestTableViewSectionComponent() var set = false - component.set(command: .configuration) { _, _, _ in + component.set(.configuration) { _, _, _ in set = true } - component.remove(command: .configuration) - component.perform(command: .configuration, for: UITableViewHeaderFooterView(), in: 0) + component.remove(.configuration) + component.perform(.configuration, + liaison: TableViewLiaison(), + view: UITableViewHeaderFooterView(), + section: 0) XCTAssertFalse(set) } func test_setHeight_setsHeightWithClosure() { - let component = TestTableViewSectionComponent() + var component = TestTableViewSectionComponent() - component.set(height: .height) { _ -> CGFloat in - return 100 - } + component.set(.height) { return 100 } - component.set(height: .estimatedHeight) { _ -> CGFloat in - return 150 - } + component.set(.estimatedHeight) { return 150 } XCTAssertEqual(component.height, 100) XCTAssertEqual(component.estimatedHeight, 150) } func test_setHeight_setsHeightWithValue() { - let component = TestTableViewSectionComponent() + var component = TestTableViewSectionComponent() - component.set(height: .height, 100) - component.set(height: .estimatedHeight, 105) + component.set(.height, 100) + component.set(.estimatedHeight, 105) XCTAssertEqual(component.height, 100) XCTAssertEqual(component.estimatedHeight, 105) @@ -70,29 +81,28 @@ final class OKTableViewSectionComponent_UnitTests: XCTestCase { } func test_removeHeight_removesAPreviouslySetHeight() { - let component = TestTableViewSectionComponent() + var component = TestTableViewSectionComponent() - component.set(height: .height, 100) - component.set(height: .estimatedHeight, 100) - component.remove(height: .height) - component.remove(height: .estimatedHeight) + component.set(.height, 100) + component.set(.estimatedHeight, 100) + component.remove(.height) + component.remove(.estimatedHeight) XCTAssertEqual(component.height, UITableView.automaticDimension) XCTAssertEqual(component.estimatedHeight, 0) } func test_estimatedHeight_estimatedHeightReturnsHeightIfHeightIsSetAndEstimatedHeightIsNot() { - let component = TestTableViewSectionComponent() - component.set(height: .height, 100) + var component = TestTableViewSectionComponent() + component.set(.height, 100) XCTAssertEqual(component.estimatedHeight, 100) } func test_register_registersViewForSectionComponent() { let component = TestTableViewSectionComponent(registrationType: .class(reuseIdentifier: "Test")) - let tableView = UITableView() - component.register(with: tableView) + component.register(with: liaison) let view = tableView.dequeueReusableHeaderFooterView(withIdentifier: "Test") @@ -101,29 +111,28 @@ final class OKTableViewSectionComponent_UnitTests: XCTestCase { func test_viewForTableViewInSection_returnsConfiguredViewForComponent() { - let component = TestTableViewSectionComponent() + var component = TestTableViewSectionComponent() let string = "Test" - component.set(command: .configuration) { view, _, _ in + component.set(.configuration) { _, view, _ in view.accessibilityIdentifier = string } - let tableView = UITableView() - component.register(with: tableView) + component.register(with: liaison) - let view = component.view(for: tableView, in: 0) + let view = component.view(for: liaison, in: 0) XCTAssertEqual(view?.accessibilityIdentifier, string) } func test_perform_ignoresCommandPerformanceForIncorrectViewType() { - let component = TestTableViewSectionComponent() + var component = TestTableViewSectionComponent() var configured = false - component.set(command: .configuration) { _, _, _ in + component.set(.configuration) { _, _, _ in configured = true } - component.perform(command: .configuration, for: UIView(), in: 0) + component.perform(.configuration, liaison: liaison, view: UIView(), section: 0) XCTAssertFalse(configured) } diff --git a/Example/Tests/TestTableHeaderFooterView.swift b/Example/Tests/TestTableHeaderFooterView.swift index 37e4641..cbdb81e 100644 --- a/Example/Tests/TestTableHeaderFooterView.swift +++ b/Example/Tests/TestTableHeaderFooterView.swift @@ -1,6 +1,6 @@ // // TestTableViewHeaderFooterView.swift -// OKTableViewLiaison_Example +// TableViewLiaison_Example // // Created by Dylan Shine on 8/30/18. // Copyright © 2018 CocoaPods. All rights reserved. diff --git a/Example/Tests/TestTableViewComponents.swift b/Example/Tests/TestTableViewComponents.swift new file mode 100644 index 0000000..a48e85e --- /dev/null +++ b/Example/Tests/TestTableViewComponents.swift @@ -0,0 +1,13 @@ +// +// TestTableViewComponents.swift +// TableViewLiaisonTests +// +// Created by Dylan Shine on 3/23/18. +// Copyright © 2018 Dylan Shine. All rights reserved. +// + +import UIKit +@testable import TableViewLiaison + +typealias TestTableViewRow = TableViewRow +typealias TestTableViewSectionComponent = TableViewSectionComponent diff --git a/Example/Tests/TestTableViewLiaisonPaginationDelegate.swift b/Example/Tests/TestTableViewLiaisonPaginationDelegate.swift index b5d020b..ff618c7 100644 --- a/Example/Tests/TestTableViewLiaisonPaginationDelegate.swift +++ b/Example/Tests/TestTableViewLiaisonPaginationDelegate.swift @@ -3,7 +3,7 @@ // TableViewLiaisonTests // // Created by Dylan Shine on 3/30/18. -// Copyright © 2018 OkCupid. All rights reserved. +// Copyright © 2018 Shine Labs. All rights reserved. // import Foundation diff --git a/Example/Tests/TestTableViewRow.swift b/Example/Tests/TestTableViewRow.swift deleted file mode 100644 index a8557c8..0000000 --- a/Example/Tests/TestTableViewRow.swift +++ /dev/null @@ -1,12 +0,0 @@ -// -// TestTableViewRow.swift -// TableViewLiaisonTests -// -// Created by Dylan Shine on 3/23/18. -// Copyright © 2018 Dylan Shine. All rights reserved. -// - -import UIKit -@testable import TableViewLiaison - -final class TestTableViewRow: TableViewRow {} diff --git a/Example/Tests/TestTableViewSectionComponent.swift b/Example/Tests/TestTableViewSectionComponent.swift deleted file mode 100644 index 2fcf826..0000000 --- a/Example/Tests/TestTableViewSectionComponent.swift +++ /dev/null @@ -1,12 +0,0 @@ -// -// TestTableViewSectionComponent.swift -// OKTableViewLiaison_Tests -// -// Created by Dylan Shine on 5/30/18. -// Copyright © 2018 CocoaPods. All rights reserved. -// - -import UIKit -@testable import TableViewLiaison - -final class TestTableViewSectionComponent: TableViewSectionComponent {} diff --git a/README.md b/README.md index 089ecdf..4b0a92a 100644 --- a/README.md +++ b/README.md @@ -21,12 +21,12 @@ alt="Pods Version"> ✅ | Unit Tested 🐤 | Written in Swift 5.0 -`TableViewLiaison` is 🔨 with ❤️ by [📱 @ Shine Labs](https://www.shinelabs.tech). +`TableViewLiaison` is 🔨 with ❤️ by [📱 @ Shine Labs](https://www.shinelabs.dev). ## Requirements - Xcode 10.2+ -- iOS 9.0+ +- iOS 10.0+ ## Installation @@ -55,20 +55,24 @@ let tableView = UITableView() liaison.liaise(tableView: tableView) ``` -By liaising your tableView with the liaison, the liaison becomes its `UITableViewDataSource`, `UITableViewDelegate`, and `UITableViewDataSourcePrefetching`. -In the event you would like to remove the tableView from the liaison, simply invoke `liaison.detach()`. +By liaising your `UITableView` with the `TableViewLiaison`, the `TableViewLiaison` becomes its `UITableViewDataSource`, `UITableViewDelegate`, and `UITableViewDataSourcePrefetching`. +In the event you would like to remove the `UITableView` from the `TableViewLiaison`, simply invoke `liaison.detach()`. -TableViewLiaison populates sections and rows using two main types: +`TableViewLiaison` implements a bunch of helper methods to help you manage your `UITableView`. + +`TableViewLiaison` populates sections and rows using two main types: ### Section `struct TableViewSection` -To create a section for our tableView, create an instance of `TableViewSection` and add it to the liaison. +To create a section for our `UITableView`, create an instance of `TableViewSection` and add it to the `TableViewLiaison`. ```swift -let section = TableViewSection() +let one = TableViewSection() +let two = TableViewSection(id: "ID") -let liaison = TableViewLiaison(sections: [section]) + +let liaison = TableViewLiaison(sections: [one, two]) ``` or @@ -79,61 +83,63 @@ liaison.append(section: section) ``` ### Supplementary Section Views -To notify the liaison that your `TableViewSection` will display a header and/or footer view, you must provide an instance of `TableViewSectionComponentDisplayOption` during initialization. +To notify the `TableViewLiaison` that your `TableViewSection` will display a header and/or footer view, you must provide an instance of `TableViewSectionComponentDisplayOption` during initialization. `TableViewSectionComponentDisplayOption` is an enumeration that notfies the liaison which supplementary views should be displayed for a given section. A header/footer view is represented by: -`class TableViewSectionComponent` +`class TableViewSectionComponent` ```swift -let header = TableViewSectionComponent(.dylan) -let section = TableViewSection(componentDisplayOption: .header(component: header)) +let header = TableViewSectionComponent() +let section = TableViewSection(option: .header(component: header)) ``` -You can set a static height of a section component by using either a CGFloat value or closure: +You can set a static height of a `TableViewSectionComponent` by using either a CGFloat value or closure: ```swift -header.set(height: .height, 55) +header.set(.height, 55) -header.set(height: .height) { user -> CGFloat in +header.set(.height) { + // Some arbitrary user you pass into the closure... return user.username == "dylan" ? 100 : 75 } -header.set(height: .estimatedHeight, 125) +header.set(.estimatedHeight, 125) ``` -In the event a height is not provided for a section component, the liaison will assume the supplementary view is self sizing and return a `.height` of `UITableView.automaticDimension`. Make sure you provide an `.estimatedHeight` to avoid layout complications. +In the event a height is not provided for a `TableViewSectionComponent`, the `TableViewLiaison` will assume the supplementary view is self sizing and return a `.height` of `UITableView.automaticDimension`. Make sure you provide an `.estimatedHeight` to avoid layout complications. -The `TableViewSectionComponent ` views can be customized using `func set(command: TableViewSectionComponentCommand, with closure: @escaping (View, Model, Int) -> Void)` at all the following lifecycle events: +The `TableViewSectionComponent ` views can be customized using `func set(_ command: TableViewSectionComponentCommand, with closure: @escaping (View, Int) -> Void)` at all the following lifecycle events: - configuration - didEndDisplaying - willDisplay ```swift -header.set(command: .configuration) { view, user, section in - view.textLabel?.text = user.username +header.set(.configuration) { view, section in + view.textLabel?.text = "Section \(section)" } -header.set(command: .willDisplay) { view, user, section in - print("Header: \(view) will display for Section: \(section) with User: \(user)") +header.set(.willDisplay) { view, section in + print("Header: \(view) will display for Section: \(section)") } ``` ### Rows -`class TableViewRow` +`class TableViewRow` -To add a row for a section, create an instance of `TableViewRow` and pass it to the initializer for a `TableViewSection` or if the row is added after instantiation you can perform that action via the liaison: +To add a row for a section, create an instance of `TableViewRow` and pass it to the initializer for a `TableViewSection` or if the row is added after instantiation you can perform that action via the `TableViewLiaison`: ```swift -let row = TableViewRow(model: RowModel(type: .small)) -let section = TableViewSection(rows: [row]) +let row = TableViewRow(data: 1) +let statelessRow = StatelessTableViewRow() +let section = TableViewSection(rows: [row, statelessRow]) liaison.append(section: section) ``` or ```swift -let row = TableViewRow(model: RowModel(type: .small)) +let row = TableViewRow() let section = TableViewSection() liaison.append(section: section) liaison.append(row: row) @@ -142,12 +148,12 @@ liaison.append(row: row) `TableViewRow` heights are similarly configured to `TableViewSection`: ```swift -row.set(height: .height, 300) +row.set(.height, 300) -row.set(height: .estimatedHeight, 210) +row.set(.estimatedHeight, 210) -row.set(height: .height) { model -> CGFloat in - switch model.type { +row.set(.height) { data in + switch data.type { case .large: return 400 case .medium: @@ -158,9 +164,9 @@ row.set(height: .height) { model -> CGFloat in } ``` -In the event a height is not provided, the liaison will assume the cell is self sizing and return `UITableView.automaticDimension`. +In the event a height is not provided, the `TableViewLiaison` will assume the cell is self sizing and return `UITableView.automaticDimension`. -The `TableViewRow` can be customized using `func set(command: TableViewRowCommand, with closure: @escaping (Cell, Model, IndexPath) -> Void) ` at all the following lifecycle events: +The `TableViewRow` can be customized using `func set(_ command: TableViewRowCommand, with closure: @escaping (TableViewLiaison, Cell, Data, IndexPath) -> Void) ` at all the following lifecycle events: - accessoryButtonTapped - configuration @@ -180,27 +186,27 @@ The `TableViewRow` can be customized using `func set(command: TableViewRowComman - willSelect ```swift -row.set(command: .configuration) { cell, model, indexPath in - cell.label.text = model.text +row.set(.configuration) { liaison, cell, data, indexPath in + cell.label.text = "Cell: \(cell) at IndexPath: \(indexPath) with \(data)" cell.label.font = .systemFont(ofSize: 13) cell.contentView.backgroundColor = .blue cell.selectionStyle = .none } -row.set(command: .didSelect) { cell, model, indexPath in - print("Cell: \(cell) selected at IndexPath: \(indexPath)") +row.set(.didSelect) { liaison, cell, data, indexPath in + print("Cell: \(cell) selected at IndexPath: \(indexPath) with \(data)") } ``` -`TableViewRow` can also utilize `UITableViewDataSourcePrefetching` by using `func set(prefetchCommand: TableViewPrefetchCommand, with closure: @escaping (Model, IndexPath) -> Void)` +`TableViewRow` can also utilize `UITableViewDataSourcePrefetching` by using `func set(prefetchCommand: TableViewPrefetchCommand, with closure: @escaping (IndexPath) -> Void)` ```swift -row.set(prefetchCommand: .prefetch) { model, indexPath in - model.downloadImage() +row.set(.prefetch) { cellViewModel, indexPath in + cellViewModel.downloadImage() } -row.set(prefetchCommand: .cancel) { model, indexPath in - model.cancelImageDownload() +row.set(.cancel) { cellViewModel, indexPath in + cellViewModel.cancelImageDownload() } ``` @@ -211,7 +217,7 @@ row.set(prefetchCommand: .cancel) { model, indexPath in By default, `TableViewRow` is instantiated with `TableViewRegistrationType.defaultClassType`. -`TableViewSection` supplementary view registration is encapsulated by its`TableViewSectionComponentDisplayOption`. By default, `TableViewSection` `componentDisplayOption` is instantiated with `.none`. +`TableViewSection` supplementary view registration is encapsulated by its`TableViewSectionComponentDisplayOption`. By default, `TableViewSection` `option` is instantiated with `.none`. ### Pagination `TableViewLiaison` comes equipped to handle your pagination needs. To configure the liaison for pagination, simply set its `paginationDelegate` to an instance of `TableViewLiaisonPaginationDelegate`. @@ -230,24 +236,18 @@ To use a custom pagination spinner, you can pass an instance `AnyTableViewRow` d ### Tips & Tricks -Because `TableViewSection` and `TableViewRow` utilize generic types and manage view/cell type registration, instantiating multiple different configurations of sections and rows can get verbose. Creating a subclass or utilizing a factory to create your various `TableViewRow`/`TableViewSectionComponent` types may be useful. +Because `TableViewSection` and `TableViewRow` utilize generic types and manage view/cell type registration, instantiating multiple different configurations of sections and rows can get verbose. Leveraging type aliases and/or implementing static factories may be useful. ```swift -final class TextTableViewRow: TableViewRow { - init(text: String) { - super.init(text, - registrationType: .defaultNibType) - } -} -``` -```swift +public typealias ImageRow= TableViewRow + static func imageRow(with image: UIImage) -> AnyTableViewRow { - let row = TableViewRow(image) + let row = ImageRow(data: image) - row.set(height: .height, 225) + row.set(.height, 225) - row.set(command: .configuration) { cell, image, indexPath in + row.set(.configuration) { liaison, cell, image, indexPath in cell.contentImageView.image = image cell.contentImageView.contentMode = .scaleAspectFill } @@ -262,8 +262,8 @@ static func imageRow(with image: UIImage) -> AnyTableViewRow { ## Authors -✌️ Dylan Shine, dylan@shinelabs.tech +✌️ Dylan Shine, dylan@shinelabs.dev ## License -TableViewLiaison is available under the MIT license. See the LICENSE file for more info. +TableViewLiaison is available under the MIT license. See the LICENSE file for more info. \ No newline at end of file diff --git a/TableViewLiaison.podspec b/TableViewLiaison.podspec index 7aadf72..739bb63 100644 --- a/TableViewLiaison.podspec +++ b/TableViewLiaison.podspec @@ -8,14 +8,14 @@ Pod::Spec.new do |s| s.name = 'TableViewLiaison' - s.version = '1.0.3' + s.version = '2.0.0' s.summary = 'Framework to help you better manage UITableViews.' s.description = 'TableViewLiaison abstracts and simplifies UITableView construction and management.' s.homepage = 'https://github.com/dylanshine/TableViewLiaison' s.license = { :type => 'MIT', :file => 'LICENSE' } - s.author = { 'Dylan Shine' => 'dylan@shinelabs.tech' } + s.author = { 'Dylan Shine' => 'dylan@shinelabs.dev' } s.source = { :git => 'https://github.com/dylanshine/TableViewLiaison.git', :tag => s.version.to_s } - s.ios.deployment_target = '9.0' + s.ios.deployment_target = '10.0' s.source_files = 'TableViewLiaison/Classes/**/*' s.swift_version = '5.0' end diff --git a/TableViewLiaison/Classes/Enums/TableViewSectionComponentDisplayOption.swift b/TableViewLiaison/Classes/Enums/TableViewSectionComponentDisplayOption.swift index b4a5b0e..a831a33 100644 --- a/TableViewLiaison/Classes/Enums/TableViewSectionComponentDisplayOption.swift +++ b/TableViewLiaison/Classes/Enums/TableViewSectionComponentDisplayOption.swift @@ -14,9 +14,7 @@ public enum TableViewSectionComponentDisplayOption { public var header: AnyTableViewSectionComponent? { switch self { - case .header(let header): - return header - case .both(let header, _): + case .header(let header), .both(let header, _): return header default: return nil @@ -25,9 +23,7 @@ public enum TableViewSectionComponentDisplayOption { public var footer: AnyTableViewSectionComponent? { switch self { - case .footer(let footer): - return footer - case .both(_, let footer): + case .footer(let footer), .both(_, let footer): return footer default: return nil diff --git a/TableViewLiaison/Classes/Enums/TableViewSectionComponentView.swift b/TableViewLiaison/Classes/Enums/TableViewSectionComponentViewType.swift similarity index 64% rename from TableViewLiaison/Classes/Enums/TableViewSectionComponentView.swift rename to TableViewLiaison/Classes/Enums/TableViewSectionComponentViewType.swift index f631f1c..21233b6 100644 --- a/TableViewLiaison/Classes/Enums/TableViewSectionComponentView.swift +++ b/TableViewLiaison/Classes/Enums/TableViewSectionComponentViewType.swift @@ -1,12 +1,12 @@ // -// TableViewSectionComponentView.swift +// TableViewSectionComponentViewType.swift // TableViewLiaison // // Created by Dylan Shine on 3/22/18. // Copyright © 2018 Dylan Shine. All rights reserved. // -public enum TableViewSectionComponentView { +public enum TableViewSectionComponentViewType { case header case footer } diff --git a/TableViewLiaison/Classes/Extensions/UITableView+Generic.swift b/TableViewLiaison/Classes/Extensions/UITableView+Generic.swift deleted file mode 100644 index a1abf6e..0000000 --- a/TableViewLiaison/Classes/Extensions/UITableView+Generic.swift +++ /dev/null @@ -1,37 +0,0 @@ -// -// UITableView+Generic.swift -// TableViewLiaison -// -// Created by Dylan Shine on 9/4/18. -// - -import UIKit - -extension UITableView { - - func register(_ type: T.Type, with identifier: String) { - register(T.self, forCellReuseIdentifier: identifier) - } - - func register(_ type: T.Type, with identifier: String) { - register(T.self, forHeaderFooterViewReuseIdentifier: identifier) - } - - func dequeue(_ type: T.Type, with identifier: String) -> T { - - guard let cell = dequeueReusableCell(withIdentifier: identifier) as? T else { - fatalError("Failed to dequeue cell of type \(T.self).") - } - - return cell - } - - func dequeue(_ type: T.Type, with identifier: String) -> T { - guard let view = dequeueReusableHeaderFooterView(withIdentifier: identifier) as? T else { - fatalError("Failed to dequeue view of type \(T.self).") - } - - return view - } - -} diff --git a/TableViewLiaison/Classes/Liaison/TableViewLiaison+Pagination.swift b/TableViewLiaison/Classes/Liaison/TableViewLiaison+Pagination.swift index 95c4ccf..0db4261 100644 --- a/TableViewLiaison/Classes/Liaison/TableViewLiaison+Pagination.swift +++ b/TableViewLiaison/Classes/Liaison/TableViewLiaison+Pagination.swift @@ -28,7 +28,7 @@ extension TableViewLiaison { waitingForPaginatedResults = true let paginationIndexPath = IndexPath(row: 0, section: sections.count) - // UITableViewDelegate tableView(_:willDisplay:forRowAt:) is executed on background thread + // UITableViewDelegate tableView(_:willDisplay:forRowAt:) is executed off main thread DispatchQueue.main.async { self.addPaginationSection() self.paginationDelegate?.paginationStarted(indexPath: paginationIndexPath) @@ -40,8 +40,7 @@ extension TableViewLiaison { func removePaginationSpinner(animated: Bool) { guard waitingForPaginatedResults else { return } waitingForPaginatedResults = false - - deleteSection(at: sections.lastIndex, animation: .none, animated: animated) + deleteSections(with: [paginationSectionID], animation: .none, animated: animated) } func endPagination(rows: [AnyTableViewRow], to section: Int, animation: UITableView.RowAnimation = .automatic, animated: Bool = true) { @@ -61,7 +60,7 @@ extension TableViewLiaison { guard !sections.isEmpty else { return } let firstNewIndexPath = IndexPath(row: 0, section: self.sections.count) - append(sections: sections, animation: animation, animated: animated) + append(sections: sections, with: animation, animated: animated) paginationDelegate?.paginationEnded(indexPath: firstNewIndexPath) } @@ -72,4 +71,14 @@ extension TableViewLiaison { tableView?.insertSections(indexSet, with: .none) } } + + public static let paginationRow: AnyTableViewRow = { + var commands = [TableViewRowCommand: (TableViewLiaison, PaginationTableViewCell, IndexPath) -> Void]() + + commands[.willDisplay] = { _, cell, _ in + cell.activityIndicator.startAnimating() + } + + return TableViewRow(commands: commands) + }() } diff --git a/TableViewLiaison/Classes/Liaison/TableViewLiaison+Registration.swift b/TableViewLiaison/Classes/Liaison/TableViewLiaison+Registration.swift index 14167ba..147636e 100644 --- a/TableViewLiaison/Classes/Liaison/TableViewLiaison+Registration.swift +++ b/TableViewLiaison/Classes/Liaison/TableViewLiaison+Registration.swift @@ -10,13 +10,12 @@ import Foundation extension TableViewLiaison { func register(section: TableViewSection) { - guard let tableView = tableView else { return } - section.componentDisplayOption.header?.register(with: tableView) - section.componentDisplayOption.footer?.register(with: tableView) + section.option.header?.register(with: self) + section.option.footer?.register(with: self) section.rows.forEach { - $0.register(with: tableView) + $0.register(with: self) } } @@ -25,11 +24,52 @@ extension TableViewLiaison { } func register(row: AnyTableViewRow) { - guard let tableView = tableView else { return } - row.register(with: tableView) + row.register(with: self) } func register(rows: [AnyTableViewRow]) { rows.forEach(register(row:)) } + + func register(_ type: T.Type, with identifier: String) { + tableView?.register(T.self, forCellReuseIdentifier: identifier) + } + + func register(_ type: T.Type, with identifier: String) { + tableView?.register(T.self, forHeaderFooterViewReuseIdentifier: identifier) + } + + func registerCell(nib: UINib, with identifier: String) { + tableView?.register(nib, forCellReuseIdentifier: identifier) + } + + func registerHeaderFooterView(nib: UINib, with identifier: String) { + tableView?.register(nib, forHeaderFooterViewReuseIdentifier: identifier) + } + + func dequeue(_ type: T.Type, with identifier: String) -> T { + + guard let tableView = tableView else { + fatalError("TableViewLiaison must be liased with UITableView before dequeuing cell of type \(T.self)") + } + + guard let cell = tableView.dequeueReusableCell(withIdentifier: identifier) as? T else { + fatalError("Failed to dequeue cell of type \(T.self).") + } + + return cell + } + + func dequeue(_ type: T.Type, with identifier: String) -> T { + + guard let tableView = tableView else { + fatalError("TableViewLiaison must be liased with UITableView before dequeuing view of type \(T.self)") + } + + guard let view = tableView.dequeueReusableHeaderFooterView(withIdentifier: identifier) as? T else { + fatalError("Failed to dequeue view of type \(T.self).") + } + + return view + } } diff --git a/TableViewLiaison/Classes/Liaison/TableViewLiaison+Row.swift b/TableViewLiaison/Classes/Liaison/TableViewLiaison+Row.swift index d4df414..4416f87 100644 --- a/TableViewLiaison/Classes/Liaison/TableViewLiaison+Row.swift +++ b/TableViewLiaison/Classes/Liaison/TableViewLiaison+Row.swift @@ -34,38 +34,78 @@ public extension TableViewLiaison { } zip(rows, indexPaths).forEach { row, indexPath in - if let cell = tableView?.cellForRow(at: indexPath) { - row.perform(command: .insert, for: cell, at: indexPath) + if let cell = cell(at: indexPath) { + row.perform(.insert, liaison: self, cell: cell, indexPath: indexPath) } } } + func append(rows: [AnyTableViewRow], to sectionId: String, animation: UITableView.RowAnimation = .automatic, animated: Bool = true) { + + guard !rows.isEmpty else { return } + + let sectionIndexes = self.sectionIndexes(for: sectionId) + + var rowIndexPathZip = [(AnyTableViewRow, IndexPath)]() + + for section in sectionIndexes { + var lastRowIndex = sections[section].rows.count - 1 + sections[section].append(rows: rows) + register(rows: rows) + + let zip = rows.map { row -> (AnyTableViewRow, IndexPath) in + lastRowIndex += 1 + let indexPath = IndexPath(row: lastRowIndex, section: section) + return (row, indexPath) + } + + rowIndexPathZip.append(contentsOf: zip) + } + + let indexPaths = rowIndexPathZip.map { $0.1 } + + performTableViewUpdates(animated: animated) { + tableView?.insertRows(at: indexPaths, with: animation) + } + + rowIndexPathZip.forEach { row, indexPath in + if let cell = cell(at: indexPath) { + row.perform(.insert, liaison: self, cell: cell, indexPath: indexPath) + } + } + } + func append(row: AnyTableViewRow, to section: Int = 0, animation: UITableView.RowAnimation = .automatic, animated: Bool = true) { append(rows: [row], to: section, animation: animation, animated: animated) } + func append(row: AnyTableViewRow, to sectionId: String, animation: UITableView.RowAnimation = .automatic, animated: Bool = true) { + append(rows: [row], to: sectionId, animation: animation, animated: animated) + } + func insert(row: AnyTableViewRow, at indexPath: IndexPath, with animation: UITableView.RowAnimation = .automatic, animated: Bool = true) { - guard sections.indices.contains(indexPath.section) else { return } + guard sections.indices.contains(indexPath.section), + sections[indexPath.section].rows.indices.contains(indexPath.row) else { return } - sections[indexPath.section].insert(row: row, at: indexPath) + sections[indexPath.section].insert(row: row, at: indexPath.item) register(row: row) performTableViewUpdates(animated: animated) { tableView?.insertRows(at: [indexPath], with: animation) } - if let cell = tableView?.cellForRow(at: indexPath) { - row.perform(command: .insert, for: cell, at: indexPath) - } + perform(.insert, at: indexPath) + } @discardableResult - func deleteRows(at indexPaths: [IndexPath], animation: UITableView.RowAnimation = .automatic, animated: Bool = true) -> [AnyTableViewRow] { + func deleteRows(at indexPaths: [IndexPath], with animation: UITableView.RowAnimation = .automatic, animated: Bool = true) -> [AnyTableViewRow] { guard !indexPaths.isEmpty else { return [] } + let indexPaths = Array(Set(indexPaths)) let sortedIndexPaths = indexPaths.sortBySection() var deletedRows = [AnyTableViewRow]() @@ -74,11 +114,11 @@ public extension TableViewLiaison { indexPaths.forEach { - if let row = sections[section].deleteRow(at: $0) { + if let row = sections[section].deleteRow(at: $0.item) { deletedRows.append(row) - if let cell = tableView?.cellForRow(at: $0) { - row.perform(command: .delete, for: cell, at: $0) + if let cell = cell(at: $0) { + row.perform(.delete, liaison: self, cell: cell, indexPath: $0) } } } @@ -96,12 +136,13 @@ public extension TableViewLiaison { @discardableResult func deleteRow(at indexPath: IndexPath, with animation: UITableView.RowAnimation = .automatic, animated: Bool = true) -> AnyTableViewRow? { - guard sections.indices.contains(indexPath.section) else { return nil } + guard sections.indices.contains(indexPath.section), + sections[indexPath.section].rows.indices.contains(indexPath.row)else { return nil } - let row = sections[indexPath.section].deleteRow(at: indexPath) + let row = sections[indexPath.section].deleteRow(at: indexPath.item) - if let cell = tableView?.cellForRow(at: indexPath) { - row?.perform(command: .delete, for: cell, at: indexPath) + if let cell = cell(at: indexPath) { + row?.perform(.delete, liaison: self, cell: cell, indexPath: indexPath) } performTableViewUpdates(animated: animated) { @@ -112,31 +153,28 @@ public extension TableViewLiaison { } func reloadRows(at indexPaths: [IndexPath], with animation: UITableView.RowAnimation = .automatic) { - tableView?.beginUpdates() tableView?.reloadRows(at: indexPaths, with: animation) - tableView?.endUpdates() indexPaths.forEach { - if let cell = tableView?.cellForRow(at: $0) { - row(for: $0)?.perform(command: .reload, for: cell, at: $0) - } + perform(.reload, at: $0) } } - func reloadRow(at indexPath: IndexPath, with animation: UITableView.RowAnimation = .automatic) { + func reloadRow(at indexPath: IndexPath, animation: UITableView.RowAnimation = .automatic) { reloadRows(at: [indexPath], with: animation) } func replaceRow(at indexPath: IndexPath, with row: AnyTableViewRow, animation: UITableView.RowAnimation = .automatic, animated: Bool = true) { - guard sections.indices.contains(indexPath.section) else { return } + guard sections.indices.contains(indexPath.section), + sections[indexPath.section].rows.indices.contains(indexPath.row) else { return } - let deletedRow = sections[indexPath.section].deleteRow(at: indexPath) - if let cell = tableView?.cellForRow(at: indexPath) { - deletedRow?.perform(command: .delete, for: cell, at: indexPath) + let deletedRow = sections[indexPath.section].deleteRow(at: indexPath.item) + if let cell = cell(at: indexPath) { + deletedRow?.perform(.delete, liaison: self, cell: cell, indexPath: indexPath) } - sections[indexPath.section].insert(row: row, at: indexPath) + sections[indexPath.section].insert(row: row, at: indexPath.item) register(row: row) performTableViewUpdates(animated: animated) { @@ -144,32 +182,25 @@ public extension TableViewLiaison { tableView?.insertRows(at: [indexPath], with: animation) } - if let cell = tableView?.cellForRow(at: indexPath) { - row.perform(command: .insert, for: cell, at: indexPath) - } - } - - func moveRow(from source: IndexPath, to destination: IndexPath, animation: UITableView.RowAnimation = .automatic, animated: Bool = true) { - - moveRow(from: source, to: destination) - - performTableViewUpdates(animated: animated) { - tableView?.moveRow(at: source, to: destination) + if let cell = cell(at: indexPath) { + row.perform(.insert, liaison: self, cell: cell, indexPath: indexPath) } } - func moveRow(from source: IndexPath, to destination: IndexPath) { + func moveRow(from source: IndexPath, to destination: IndexPath, animated: Bool = true) { let indices = sections.indices guard indices.contains(source.section) && indices.contains(destination.section) else { return } - guard let row = sections[source.section].deleteRow(at: source) else { + guard let row = sections[source.section].deleteRow(at: source.item) else { return } - sections[destination.section].insert(row: row, at: destination) + sections[destination.section].insert(row: row, at: destination.item) + + perform(.move, at: destination) - if let cell = tableView?.cellForRow(at: destination) { - row.perform(command: .move, for: cell, at: destination) + performTableViewUpdates(animated: animated) { + tableView?.moveRow(at: source, to: destination) } } @@ -179,15 +210,14 @@ public extension TableViewLiaison { guard indices.contains(source.section) && indices.contains(destination.section) else { return } if source.section == destination.section { - sections[source.section].swapRows(at: source, to: destination) + sections[source.section].swapRows(at: source.item, to: destination.item) } else { + guard let sourceRow = sections[source.section].deleteRow(at: source.item), + let destinationRow = sections[destination.section].deleteRow(at: destination.item) else { return } - guard let sourceRow = sections[source.section].deleteRow(at: source), - let destinationRow = sections[destination.section].deleteRow(at: destination) else { return } - - sections[source.section].insert(row: destinationRow, at: source) - sections[destination.section].insert(row: sourceRow, at: destination) + sections[source.section].insert(row: destinationRow, at: source.item) + sections[destination.section].insert(row: sourceRow, at: destination.item) } performTableViewUpdates(animated: animated) { @@ -195,12 +225,7 @@ public extension TableViewLiaison { tableView?.moveRow(at: destination, to: source) } - if let sourceCell = tableView?.cellForRow(at: source) { - row(for: source)?.perform(command: .move, for: sourceCell, at: source) - } - - if let destinationCell = tableView?.cellForRow(at: destination) { - row(for: destination)?.perform(command: .move, for: destinationCell, at: destination) - } + perform(.move, at: source) + perform(.move, at: destination) } } diff --git a/TableViewLiaison/Classes/Liaison/TableViewLiaison+Section.swift b/TableViewLiaison/Classes/Liaison/TableViewLiaison+Section.swift index 7982e84..7d80461 100644 --- a/TableViewLiaison/Classes/Liaison/TableViewLiaison+Section.swift +++ b/TableViewLiaison/Classes/Liaison/TableViewLiaison+Section.swift @@ -9,7 +9,7 @@ import UIKit public extension TableViewLiaison { - func append(sections: [TableViewSection], animation: UITableView.RowAnimation = .automatic, animated: Bool = true) { + func append(sections: [TableViewSection], with animation: UITableView.RowAnimation = .automatic, animated: Bool = true) { if waitingForPaginatedResults { endPagination(sections: sections, animation: animation, animated: animated) @@ -31,8 +31,8 @@ public extension TableViewLiaison { } - func append(section: TableViewSection, animation: UITableView.RowAnimation = .automatic, animated: Bool = true) { - append(sections: [section], animation: animation, animated: animated) + func append(section: TableViewSection, with animation: UITableView.RowAnimation = .automatic, animated: Bool = true) { + append(sections: [section], with: animation, animated: animated) } func insert(sections: [TableViewSection], startingAt index: Int, animation: UITableView.RowAnimation = .automatic, animated: Bool = true) { @@ -62,7 +62,7 @@ public extension TableViewLiaison { } } - func emptySection(at index: Int, animation: UITableView.RowAnimation = .automatic, animated: Bool = true) { + func emptySection(at index: Int, with animation: UITableView.RowAnimation = .automatic, animated: Bool = true) { guard sections.indices.contains(index) else { return } @@ -72,7 +72,40 @@ public extension TableViewLiaison { performTableViewUpdates(animated: animated) { tableView?.deleteRows(at: indexPaths, with: animation) } + } + + func emptySections(at indexes: [Int], with animation: UITableView.RowAnimation = .automatic, animated: Bool = true) { + + guard !indexes.isEmpty else { return } + + let indexes = Set(indexes) + .filter { sections.indices.contains($0) } + + var indexPaths = [IndexPath]() + indexes.forEach { index in + let sectionIndexPaths = sections[index].rowIndexPaths(for: index) + indexPaths.append(contentsOf: sectionIndexPaths) + sections[index].removeAllRows() + } + + let indexSet = IndexSet(indexes) + performTableViewUpdates(animated: animated) { + tableView?.deleteSections(indexSet, with: animation) + } + } + + func emptySections(ids: [String], with animation: UITableView.RowAnimation = .automatic, animated: Bool = true) { + guard !ids.isEmpty else { return } + + let indexes = Set(ids).map { sectionIndexes(for: $0) } + .reduce([], +) + + emptySections(at: indexes, with: animation, animated: animated) + } + + func emptySections(with id: String, animation: UITableView.RowAnimation = .automatic, animated: Bool = true) { + emptySections(ids: [id], with: animation, animated: animated) } func deleteSection(at index: Int, animation: UITableView.RowAnimation = .automatic, animated: Bool = true) { @@ -86,6 +119,35 @@ public extension TableViewLiaison { } } + func deleteSections(at indexes: [Int], animation: UITableView.RowAnimation = .automatic, animated: Bool = true) { + + guard !indexes.isEmpty else { return } + + let indexes = Set(indexes) + .filter { sections.indices.contains($0) } + .sorted(by: >) + + indexes.forEach { sections.remove(at: $0) } + + let indexSet = IndexSet(indexes) + performTableViewUpdates(animated: animated) { + tableView?.deleteSections(indexSet, with: animation) + } + } + + func deleteSections(with ids: [String], animation: UITableView.RowAnimation = .automatic, animated: Bool = true) { + guard !ids.isEmpty else { return } + + let indexes = Set(ids).map { sectionIndexes(for: $0) } + .reduce([], +) + + deleteSections(at: indexes, animation: animation, animated: animated) + } + + func deleteSections(with id: String, animation: UITableView.RowAnimation = .automatic, animated: Bool = true) { + deleteSections(with: [id], animation: animation, animated: animated) + } + func replaceSection(at index: Int, with section: TableViewSection, animation: UITableView.RowAnimation = .automatic, animated: Bool = true) { guard sections.indices.contains(index) else { return } @@ -100,10 +162,17 @@ public extension TableViewLiaison { } } - func reloadSection(at index: Int, with animation: UITableView.RowAnimation = .automatic) { - tableView?.beginUpdates() + func reloadSection(at index: Int, animation: UITableView.RowAnimation = .automatic) { tableView?.reloadSections(IndexSet(integer: index), with: animation) - tableView?.endUpdates() + } + + func reloadSections(at indexes: [Int], animation: UITableView.RowAnimation = .automatic) { + tableView?.reloadSections(IndexSet(indexes), with: animation) + } + + func reloadSections(with identifier: String, animation: UITableView.RowAnimation = .automatic) { + let indexes = Array(sectionIndexes(for: identifier)) + reloadSections(at: indexes, animation: animation) } func moveSection(at: Int, to: Int, with animation: UITableView.RowAnimation = .automatic, animated: Bool = true) { @@ -119,8 +188,8 @@ public extension TableViewLiaison { } func clearSections(replacedBy sections: [TableViewSection] = [], - animation: UITableView.RowAnimation = .automatic, - animated: Bool = true) { + animation: UITableView.RowAnimation = .automatic, + animated: Bool = true) { if !self.sections.isEmpty { let sectionsRange = 0...self.sections.lastIndex @@ -133,7 +202,7 @@ public extension TableViewLiaison { } } - append(sections: sections, animation: animation, animated: animated) + append(sections: sections, with: animation, animated: animated) } func swapSection(at source: Int, with destination: Int, animation: UITableView.RowAnimation = .automatic, animated: Bool = true) { diff --git a/TableViewLiaison/Classes/Liaison/TableViewLiaison+UITableViewDataSource.swift b/TableViewLiaison/Classes/Liaison/TableViewLiaison+UITableViewDataSource.swift index 57b32e7..81c94a0 100644 --- a/TableViewLiaison/Classes/Liaison/TableViewLiaison+UITableViewDataSource.swift +++ b/TableViewLiaison/Classes/Liaison/TableViewLiaison+UITableViewDataSource.swift @@ -19,7 +19,7 @@ extension TableViewLiaison: UITableViewDataSource { public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - guard let cell = row(for: indexPath)?.cell(for: tableView, at: indexPath) else { + guard let cell = row(for: indexPath)?.cell(for: self, at: indexPath) else { fatalError("Row does not exist for indexPath: \(indexPath)") } @@ -40,8 +40,8 @@ extension TableViewLiaison: UITableViewDataSource { guard let row = row(for: indexPath) else { return } deleteRow(at: indexPath, with: row.deleteRowAnimation) case .insert: - guard let cell = tableView.cellForRow(at: indexPath) else { return } - row(for: indexPath)?.perform(command: .insert, for: cell, at: indexPath) + guard let cell = cell(at: indexPath) else { return } + row(for: indexPath)?.perform(.insert, liaison: self, cell: cell, indexPath: indexPath) default: break } diff --git a/TableViewLiaison/Classes/Liaison/TableViewLiaison+UITableViewDataSourcePrefetching.swift b/TableViewLiaison/Classes/Liaison/TableViewLiaison+UITableViewDataSourcePrefetching.swift index 785548f..2a125a7 100644 --- a/TableViewLiaison/Classes/Liaison/TableViewLiaison+UITableViewDataSourcePrefetching.swift +++ b/TableViewLiaison/Classes/Liaison/TableViewLiaison+UITableViewDataSourcePrefetching.swift @@ -10,13 +10,13 @@ import UIKit extension TableViewLiaison: UITableViewDataSourcePrefetching { public func tableView(_ tableView: UITableView, prefetchRowsAt indexPaths: [IndexPath]) { indexPaths.forEach { - row(for: $0)?.perform(prefetchCommand: .prefetch, for: $0) + row(for: $0)?.perform(.prefetch, for: $0) } } public func tableView(_ tableView: UITableView, cancelPrefetchingForRowsAt indexPaths: [IndexPath]) { indexPaths.forEach { - row(for: $0)?.perform(prefetchCommand: .cancel, for: $0) + row(for: $0)?.perform(.cancel, for: $0) } } } diff --git a/TableViewLiaison/Classes/Liaison/TableViewLiaison+UITableViewDelegate.swift b/TableViewLiaison/Classes/Liaison/TableViewLiaison+UITableViewDelegate.swift index ad3ae47..54de235 100644 --- a/TableViewLiaison/Classes/Liaison/TableViewLiaison+UITableViewDelegate.swift +++ b/TableViewLiaison/Classes/Liaison/TableViewLiaison+UITableViewDelegate.swift @@ -9,30 +9,20 @@ import UIKit extension TableViewLiaison: UITableViewDelegate { - @discardableResult - private func perform(command: TableViewRowCommand, for tableView: UITableView, at indexPath: IndexPath) -> IndexPath? { - - guard let cell = tableView.cellForRow(at: indexPath) else { return nil } - - row(for: indexPath)?.perform(command: command, for: cell, at: indexPath) - - return indexPath - } - public func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? { - return perform(command: .willSelect, for: tableView, at: indexPath) + return perform(.willSelect, at: indexPath) } public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - perform(command: .didSelect, for: tableView, at: indexPath) + perform(.didSelect, at: indexPath) } public func tableView(_ tableView: UITableView, willDeselectRowAt indexPath: IndexPath) -> IndexPath? { - return perform(command: .willDeselect, for: tableView, at: indexPath) + return perform(.willDeselect, at: indexPath) } public func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) { - perform(command: .didDeselect, for: tableView, at: indexPath) + perform(.didDeselect, at: indexPath) } public func tableView(_ tableView: UITableView, targetIndexPathForMoveFromRowAt sourceIndexPath: IndexPath, toProposedIndexPath proposedDestinationIndexPath: IndexPath) -> IndexPath { @@ -45,37 +35,44 @@ extension TableViewLiaison: UITableViewDelegate { } public func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { - row(for: indexPath)?.perform(command: .willDisplay, for: cell, at: indexPath) + row(for: indexPath)?.perform(.willDisplay, + liaison: self, + cell: cell, + indexPath: indexPath) + showPaginationSpinner(after: indexPath) } public func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) { - row(for: indexPath)?.perform(command: .didEndDisplaying, for: cell, at: indexPath) + row(for: indexPath)?.perform(.didEndDisplaying, + liaison: self, + cell: cell, + indexPath: indexPath) } public func tableView(_ tableView: UITableView, willBeginEditingRowAt indexPath: IndexPath) { - perform(command: .willBeginEditing, for: tableView, at: indexPath) + perform(.willBeginEditing, at: indexPath) } public func tableView(_ tableView: UITableView, didEndEditingRowAt indexPath: IndexPath?) { guard let indexPath = indexPath else { return } - perform(command: .didEndEditing, for: tableView, at: indexPath) + perform(.didEndEditing, at: indexPath) } public func tableView(_ tableView: UITableView, didHighlightRowAt indexPath: IndexPath) { - perform(command: .didHighlight, for: tableView, at: indexPath) + perform(.didHighlight, at: indexPath) } public func tableView(_ tableView: UITableView, didUnhighlightRowAt indexPath: IndexPath) { - perform(command: .didUnhighlight, for: tableView, at: indexPath) + perform(.didUnhighlight, at: indexPath) } public func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { - return sections.element(at: section)?.view(componentView: .header, for: tableView, in: section) + return sections.element(at: section)?.view(componentView: .header, for: self, in: section) } public func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? { - return sections.element(at: section)?.view(componentView: .footer, for: tableView, in: section) + return sections.element(at: section)?.view(componentView: .footer, for: self, in: section) } public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { @@ -99,7 +96,7 @@ extension TableViewLiaison: UITableViewDelegate { } public func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) { - perform(command: .accessoryButtonTapped, for: tableView, at: indexPath) + perform(.accessoryButtonTapped, at: indexPath) } public func tableView(_ tableView: UITableView, titleForDeleteConfirmationButtonForRowAt indexPath: IndexPath) -> String? { @@ -107,35 +104,51 @@ extension TableViewLiaison: UITableViewDelegate { } public func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { - return sections.element(at: section)?.calculate(height: .height, for: .header) ?? UITableView.automaticDimension + return sections.element(at: section)?.calculate(.height, for: .header) ?? UITableView.automaticDimension } public func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { - return sections.element(at: section)?.calculate(height: .height, for: .footer) ?? UITableView.automaticDimension + return sections.element(at: section)?.calculate(.height, for: .footer) ?? UITableView.automaticDimension } public func tableView(_ tableView: UITableView, estimatedHeightForHeaderInSection section: Int) -> CGFloat { - return sections.element(at: section)?.calculate(height: .estimatedHeight, for: .header) ?? 0 + return sections.element(at: section)?.calculate(.estimatedHeight, for: .header) ?? 0 } public func tableView(_ tableView: UITableView, estimatedHeightForFooterInSection section: Int) -> CGFloat { - return sections.element(at: section)?.calculate(height: .estimatedHeight, for: .footer) ?? 0 + return sections.element(at: section)?.calculate(.estimatedHeight, for: .footer) ?? 0 } public func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) { - sections.element(at: section)?.perform(command: .willDisplay, componentView: .header, for: view, in: section) + sections.element(at: section)?.perform(.willDisplay, + componentView: .header, + liaison: self, + view: view, + section: section) } public func tableView(_ tableView: UITableView, willDisplayFooterView view: UIView, forSection section: Int) { - sections.element(at: section)?.perform(command: .willDisplay, componentView: .footer, for: view, in: section) + sections.element(at: section)?.perform(.willDisplay, + componentView: .footer, + liaison: self, + view: view, + section: section) } public func tableView(_ tableView: UITableView, didEndDisplayingHeaderView view: UIView, forSection section: Int) { - sections.element(at: section)?.perform(command: .didEndDisplaying, componentView: .header, for: view, in: section) + sections.element(at: section)?.perform(.didEndDisplaying, + componentView: .header, + liaison: self, + view: view, + section: section) } public func tableView(_ tableView: UITableView, didEndDisplayingFooterView view: UIView, forSection section: Int) { - sections.element(at: section)?.perform(command: .didEndDisplaying, componentView: .footer, for: view, in: section) + sections.element(at: section)?.perform(.didEndDisplaying, + componentView: .footer, + liaison: self, + view: view, + section: section) } } diff --git a/TableViewLiaison/Classes/Liaison/TableViewLiaison.swift b/TableViewLiaison/Classes/Liaison/TableViewLiaison.swift index 0502be1..d642d86 100644 --- a/TableViewLiaison/Classes/Liaison/TableViewLiaison.swift +++ b/TableViewLiaison/Classes/Liaison/TableViewLiaison.swift @@ -18,14 +18,57 @@ public final class TableViewLiaison: NSObject { public weak var paginationDelegate: TableViewLiaisonPaginationDelegate? + let paginationSectionID = UUID().uuidString let paginationSection: TableViewSection var waitingForPaginatedResults = false + public var isEditing: Bool { + get { return tableView?.isEditing ?? false } + set { tableView?.isEditing = newValue } + } + + public var allowsSelection: Bool { + get { return tableView?.allowsSelection ?? false } + set { tableView?.allowsSelection = newValue } + } + + public var allowsSelectionDuringEditing: Bool { + get { return tableView?.allowsSelectionDuringEditing ?? false } + set { tableView?.allowsSelectionDuringEditing = newValue } + } + + public var allowsMultipleSelection: Bool { + get { return tableView?.allowsMultipleSelection ?? false } + set { tableView?.allowsMultipleSelection = newValue } + } + + public var allowsMultipleSelectionDuringEditing: Bool { + get { return tableView?.allowsMultipleSelectionDuringEditing ?? false } + set { tableView?.allowsMultipleSelectionDuringEditing = newValue } + } + + public var visibleCells: [UITableViewCell] { + return tableView?.visibleCells ?? [] + } + + public var indexPathsForVisibleRows: [IndexPath] { + return tableView?.indexPathsForVisibleRows ?? [] + } + + public var indexPathForSelectedRow: IndexPath? { + return tableView?.indexPathForSelectedRow + } + + public var indexPathsForSelectedRows: [IndexPath] { + return tableView?.indexPathsForSelectedRows ?? [] + } + public init(sections: [TableViewSection] = [], - paginationRow: AnyTableViewRow = PaginationTableViewRow()) { + paginationRow: AnyTableViewRow = paginationRow) { self.sections = sections - self.paginationSection = TableViewSection(rows: [paginationRow]) + self.paginationSection = TableViewSection(id: paginationSectionID, rows: [paginationRow]) + super.init() } @@ -34,19 +77,13 @@ public final class TableViewLiaison: NSObject { tableView.dataSource = self tableView.delegate = self - - if #available(iOS 10.0, *) { - tableView.prefetchDataSource = self - } + tableView.prefetchDataSource = self } public func detach() { tableView?.delegate = nil tableView?.dataSource = nil - - if #available(iOS 10.0, *) { - tableView?.prefetchDataSource = nil - } + tableView?.prefetchDataSource = nil tableView = nil } @@ -56,20 +93,16 @@ public final class TableViewLiaison: NSObject { } public func reloadVisibleRows() { - guard let indexPaths = tableView?.indexPathsForVisibleRows else { return } - - reloadRows(at: indexPaths) + reloadRows(at: indexPathsForVisibleRows) } public func scroll(to indexPath: IndexPath, at scrollPosition: UITableView.ScrollPosition = .none, animated: Bool = true) { guard row(for: indexPath) != nil else { return } tableView?.scrollToRow(at: indexPath, at: scrollPosition, animated: animated) } - - public func toggleIsEditing() { - guard let tv = tableView else { return } - - tv.isEditing = !tv.isEditing + + public func scrollToNearestSelectedRow(at scrollPosition: UITableView.ScrollPosition = .none, animated: Bool = true) { + tableView?.scrollToNearestSelectedRow(at: scrollPosition, animated: animated) } public func lastIndexPath(in section: Int) -> IndexPath? { @@ -78,6 +111,71 @@ public final class TableViewLiaison: NSObject { return IndexPath(row: row - 1, section: section) } + public func selectRow(at indexPath: IndexPath, + animated: Bool = true, + scrollPosition: UITableView.ScrollPosition = .none) { + tableView?.selectRow(at: indexPath, animated: animated, scrollPosition: scrollPosition) + } + + public func deselectRow(at indexPath: IndexPath, animated: Bool = true) { + tableView?.deselectRow(at: indexPath, animated: animated) + } + + public func cell(at indexPath: IndexPath) -> UITableViewCell? { + return tableView?.cellForRow(at: indexPath) + } + + public func headerView(for section: Int) -> UITableViewHeaderFooterView? { + return tableView?.headerView(forSection: section) + } + + public func footerView(for section: Int) -> UITableViewHeaderFooterView? { + return tableView?.footerView(forSection: section) + } + + public func indexPath(for cell: UITableViewCell) -> IndexPath? { + return tableView?.indexPath(for: cell) + } + + public func indexPathForRow(at point: CGPoint) -> IndexPath? { + return tableView?.indexPathForRow(at: point) + } + + public func sectionIndexes(for id: String) -> [Int] { + return sections.enumerated() + .filter { $0.1.id == id } + .map { $0.0 } + } + + public func rowIndexPathes(where predicate: (T) -> Bool) -> [IndexPath] { + return sections + .enumerated() + .reduce([]) { (result, tuple) -> [IndexPath] in + let (index, section) = tuple + return result + section.rowIndexPaths(for: index, where: predicate) + } + } + + public func rect(for section: Int) -> CGRect { + return tableView?.rect(forSection: section) ?? .zero + } + + public func rectForHeader(in section: Int) -> CGRect { + return tableView?.rectForHeader(inSection: section) ?? .zero + } + + public func rectForFooter(in section: Int) -> CGRect { + return tableView?.rectForFooter(inSection: section) ?? .zero + } + + public func rectForRow(at indexPath: IndexPath) -> CGRect { + return tableView?.rectForRow(at: indexPath) ?? .zero + } + + public func row(for indexPath: IndexPath) -> TableViewRow? { + return row(for: indexPath) as? TableViewRow + } + func row(for indexPath: IndexPath) -> AnyTableViewRow? { guard let section = sections.element(at: indexPath.section) else { return nil } @@ -98,6 +196,19 @@ public final class TableViewLiaison: NSObject { } } + @discardableResult + func perform(_ command: TableViewRowCommand, at indexPath: IndexPath) -> IndexPath? { + + guard let cell = cell(at: indexPath) else { return nil } + + row(for: indexPath)?.perform(command, + liaison: self, + cell: cell, + indexPath: indexPath) + + return indexPath + } + private func registerSections() { register(section: paginationSection) register(sections: sections) diff --git a/TableViewLiaison/Classes/Protocols/AnyTableViewRow.swift b/TableViewLiaison/Classes/Protocols/AnyTableViewRow.swift index 0a56d08..f4e0eac 100644 --- a/TableViewLiaison/Classes/Protocols/AnyTableViewRow.swift +++ b/TableViewLiaison/Classes/Protocols/AnyTableViewRow.swift @@ -8,6 +8,7 @@ import UIKit public protocol AnyTableViewRow: TableViewContent { + var _data: Any? { get } var editable: Bool { get } var movable: Bool { get } var editActions: [UITableViewRowAction]? { get } @@ -15,7 +16,7 @@ public protocol AnyTableViewRow: TableViewContent { var indentWhileEditing: Bool { get } var deleteConfirmationTitle: String? { get } var deleteRowAnimation: UITableView.RowAnimation { get } - func cell(for tableView: UITableView, at indexPath: IndexPath) -> UITableViewCell - func perform(command: TableViewRowCommand, for cell: UITableViewCell, at indexPath: IndexPath) - func perform(prefetchCommand: TableViewPrefetchCommand, for indexPath: IndexPath) + func cell(for liaison: TableViewLiaison, at indexPath: IndexPath) -> UITableViewCell + func perform(_ command: TableViewRowCommand, liaison: TableViewLiaison, cell: UITableViewCell, indexPath: IndexPath) + func perform(_ prefetchCommand: TableViewPrefetchCommand, for indexPath: IndexPath) } diff --git a/TableViewLiaison/Classes/Protocols/AnyTableViewSectionComponent.swift b/TableViewLiaison/Classes/Protocols/AnyTableViewSectionComponent.swift index 079d087..119cdc8 100644 --- a/TableViewLiaison/Classes/Protocols/AnyTableViewSectionComponent.swift +++ b/TableViewLiaison/Classes/Protocols/AnyTableViewSectionComponent.swift @@ -8,6 +8,6 @@ import UIKit public protocol AnyTableViewSectionComponent: TableViewContent { - func perform(command: TableViewSectionComponentCommand, for view: UIView, in section: Int) - func view(for tableView: UITableView, in section: Int) -> UITableViewHeaderFooterView? + func perform(_ command: TableViewSectionComponentCommand, liaison: TableViewLiaison, view: UIView, section: Int) + func view(for liaison: TableViewLiaison, in section: Int) -> UITableViewHeaderFooterView? } diff --git a/TableViewLiaison/Classes/Protocols/TableViewContent.swift b/TableViewLiaison/Classes/Protocols/TableViewContent.swift index f259f3d..30a0893 100644 --- a/TableViewLiaison/Classes/Protocols/TableViewContent.swift +++ b/TableViewLiaison/Classes/Protocols/TableViewContent.swift @@ -7,9 +7,18 @@ import UIKit -public protocol TableViewContent: AnyObject { - var height: CGFloat { get } - var estimatedHeight: CGFloat { get } +public protocol TableViewContent { var reuseIdentifier: String { get } - func register(with tableView: UITableView) + func register(with liaison: TableViewLiaison) + func calculate(_ height: TableViewHeightType) -> CGFloat +} + +extension TableViewContent { + public var height: CGFloat { + return calculate(.height) + } + + public var estimatedHeight: CGFloat { + return calculate(.estimatedHeight) + } } diff --git a/TableViewLiaison/Classes/Rows/PaginationTableViewRow.swift b/TableViewLiaison/Classes/Rows/PaginationTableViewRow.swift deleted file mode 100644 index b2a64de..0000000 --- a/TableViewLiaison/Classes/Rows/PaginationTableViewRow.swift +++ /dev/null @@ -1,24 +0,0 @@ -// -// PaginationTableViewRow.swift -// TableViewLiaison -// -// Created by Dylan Shine on 3/30/18. -// - -import UIKit - -public final class PaginationTableViewRow: TableViewRow { - - public init() { - super.init(()) - - set(command: .configuration) { cell, _, _ in - cell.backgroundColor = .clear - cell.contentView.backgroundColor = .clear - } - - set(command: .willDisplay) { cell, _, _ in - cell.spinner.startAnimating() - } - } -} diff --git a/TableViewLiaison/Classes/Rows/TableViewRow+Void.swift b/TableViewLiaison/Classes/Rows/TableViewRow+Void.swift new file mode 100644 index 0000000..68edcf6 --- /dev/null +++ b/TableViewLiaison/Classes/Rows/TableViewRow+Void.swift @@ -0,0 +1,68 @@ +// +// TableViewRow.swift +// TableViewLiaison +// +// Created by Dylan Shine on 9/29/20. +// + +import UIKit + +public typealias StatelessTableViewRow = TableViewRow + +public extension TableViewRow where Data == Void { + typealias StatelessHeightClosure = () -> CGFloat + typealias StatelessCommandClosure = (TableViewLiaison, Cell, IndexPath) -> Void + typealias StatelessPrefetchCommandClosure = (IndexPath) -> Void + + init(prefetchCommands: [TableViewPrefetchCommand: StatelessPrefetchCommandClosure] = [:], + commands: [TableViewRowCommand: StatelessCommandClosure] = [:], + heights: [TableViewHeightType: StatelessHeightClosure] = [:], + editingStyle: UITableViewCell.EditingStyle = .none, + movable: Bool = false, + editActions: [UITableViewRowAction]? = nil, + indentWhileEditing: Bool = false, + deleteConfirmationTitle: String? = nil, + deleteRowAnimation: UITableView.RowAnimation = .automatic, + registrationType: TableViewRegistrationType = .defaultClassType) { + + var _heights = [TableViewHeightType: (Data) -> CGFloat]() + var _prefetchCommands = [TableViewPrefetchCommand: PrefetchCommandClosure]() + var _commands = [TableViewRowCommand: CommandClosure]() + + heights.forEach { (key: TableViewHeightType, value: @escaping StatelessHeightClosure) in + _heights[key] = { _ in value() } + } + + prefetchCommands.forEach { (key: TableViewPrefetchCommand, value: @escaping StatelessPrefetchCommandClosure) in + _prefetchCommands[key] = { _, indexPath in value(indexPath) } + } + + commands.forEach { (key: TableViewRowCommand, value: @escaping StatelessCommandClosure) in + _commands[key] = { liaison, cell, _, indexPath in value(liaison, cell, indexPath) } + } + + self.init((), + prefetchCommands: _prefetchCommands, + commands: _commands, + heights: _heights, + editingStyle: editingStyle, + movable: movable, + editActions: editActions, + indentWhileEditing: indentWhileEditing, + deleteConfirmationTitle: deleteConfirmationTitle, + deleteRowAnimation: deleteRowAnimation, + registrationType: registrationType) + } + + mutating func set(_ height: TableViewHeightType, _ closure: @escaping () -> CGFloat) { + heights[height] = { _ in closure() } + } + + mutating func set(_ command: TableViewRowCommand, with closure: @escaping StatelessCommandClosure) { + commands[command] = { liaison, cell, _, indexPath in closure(liaison, cell, indexPath) } + } + + mutating func set(_ prefetchCommand: TableViewPrefetchCommand, with closure: @escaping StatelessPrefetchCommandClosure) { + prefetchCommands[prefetchCommand] = {_, indexPath in closure(indexPath) } + } +} diff --git a/TableViewLiaison/Classes/Rows/TableViewRow.swift b/TableViewLiaison/Classes/Rows/TableViewRow.swift index a6c2216..aeac37c 100644 --- a/TableViewLiaison/Classes/Rows/TableViewRow.swift +++ b/TableViewLiaison/Classes/Rows/TableViewRow.swift @@ -8,22 +8,27 @@ import UIKit -open class TableViewRow: AnyTableViewRow { +public struct TableViewRow: AnyTableViewRow { - public let model: Model + public typealias PrefetchCommandClosure = (Data, IndexPath) -> Void + public typealias CommandClosure = (TableViewLiaison, Cell, Data, IndexPath) -> Void + + public let data: Data public var editingStyle: UITableViewCell.EditingStyle public var movable: Bool public var editActions: [UITableViewRowAction]? public var indentWhileEditing: Bool public var deleteConfirmationTitle: String? public var deleteRowAnimation: UITableView.RowAnimation - - private let registrationType: TableViewRegistrationType - private var commands = [TableViewRowCommand: (Cell, Model, IndexPath) -> Void]() - private var heights = [TableViewHeightType: (Model) -> CGFloat]() - private var prefetchCommands = [TableViewPrefetchCommand: (Model, IndexPath) -> Void]() - - public init(_ model: Model, + public let registrationType: TableViewRegistrationType + public internal(set) var prefetchCommands = [TableViewPrefetchCommand: PrefetchCommandClosure]() + public internal(set) var commands = [TableViewRowCommand: CommandClosure]() + public internal(set) var heights = [TableViewHeightType: (Data) -> CGFloat]() + + public init(_ data: Data, + prefetchCommands: [TableViewPrefetchCommand: PrefetchCommandClosure] = [:], + commands: [TableViewRowCommand: CommandClosure] = [:], + heights: [TableViewHeightType: (Data) -> CGFloat] = [:], editingStyle: UITableViewCell.EditingStyle = .none, movable: Bool = false, editActions: [UITableViewRowAction]? = nil, @@ -31,7 +36,11 @@ open class TableViewRow: AnyTableViewRow { deleteConfirmationTitle: String? = nil, deleteRowAnimation: UITableView.RowAnimation = .automatic, registrationType: TableViewRegistrationType = .defaultClassType) { - self.model = model + + self.data = data + self.prefetchCommands = prefetchCommands + self.commands = commands + self.heights = heights self.editingStyle = editingStyle self.movable = movable self.editActions = editActions @@ -42,71 +51,72 @@ open class TableViewRow: AnyTableViewRow { } // MARK: - Cell - public func cell(for tableView: UITableView, at indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeue(Cell.self, with: reuseIdentifier) - commands[.configuration]?(cell, model, indexPath) + public func cell(for liaison: TableViewLiaison, at indexPath: IndexPath) -> UITableViewCell { + let cell = liaison.dequeue(Cell.self, with: reuseIdentifier) + commands[.configuration]?(liaison, cell, data, indexPath) return cell } - public func register(with tableView: UITableView) { + public func register(with liaison: TableViewLiaison) { switch registrationType { case let .class(identifier): - tableView.register(Cell.self, with: identifier) + liaison.register(Cell.self, with: identifier) case let .nib(nib, identifier): - tableView.register(nib, forCellReuseIdentifier: identifier) + liaison.registerCell(nib: nib, with: identifier) } } // MARK: - Commands - public func perform(command: TableViewRowCommand, for cell: UITableViewCell, at indexPath: IndexPath) { + public func perform(_ command: TableViewRowCommand, liaison: TableViewLiaison, cell: UITableViewCell, indexPath: IndexPath) { guard let cell = cell as? Cell else { return } - commands[command]?(cell, model, indexPath) + commands[command]?(liaison, cell, data, indexPath) } - public func perform(prefetchCommand: TableViewPrefetchCommand, for indexPath: IndexPath) { - prefetchCommands[prefetchCommand]?(model, indexPath) + public func perform(_ prefetchCommand: TableViewPrefetchCommand, for indexPath: IndexPath) { + prefetchCommands[prefetchCommand]?(data, indexPath) } - public func set(command: TableViewRowCommand, with closure: @escaping (Cell, Model, IndexPath) -> Void) { + public mutating func set(_ command: TableViewRowCommand, with closure: @escaping CommandClosure) { commands[command] = closure } - public func remove(command: TableViewRowCommand) { + public mutating func remove(_ command: TableViewRowCommand) { commands[command] = nil } - public func set(height: TableViewHeightType, _ closure: @escaping (Model) -> CGFloat) { + public mutating func set(_ height: TableViewHeightType, _ closure: @escaping (Data) -> CGFloat) { heights[height] = closure } - public func set(height: TableViewHeightType, _ value: CGFloat) { - let closure: ((Model) -> CGFloat) = { _ -> CGFloat in return value } + public mutating func set(_ height: TableViewHeightType, _ value: CGFloat) { + let closure: ((Data) -> CGFloat) = { _ in return value } heights[height] = closure } - public func remove(height: TableViewHeightType) { + public mutating func remove(_ height: TableViewHeightType) { heights[height] = nil } - public func set(prefetchCommand: TableViewPrefetchCommand, with closure: @escaping (Model, IndexPath) -> Void) { + public mutating func set(_ prefetchCommand: TableViewPrefetchCommand, with closure: @escaping PrefetchCommandClosure) { prefetchCommands[prefetchCommand] = closure } - public func remove(prefetchCommand: TableViewPrefetchCommand) { + public mutating func remove(_ prefetchCommand: TableViewPrefetchCommand) { prefetchCommands[prefetchCommand] = nil } - // MARK: - Computed Properties - public var height: CGFloat { - return calculate(height: .height) + public func calculate(_ height: TableViewHeightType) -> CGFloat { + return heights[height]?(data) ?? UITableView.automaticDimension } - public var estimatedHeight: CGFloat { - return calculate(height: .estimatedHeight) - } + // MARK: - Computed Properties + public var _data: Any? { + return data + } + public var editable: Bool { return editingStyle != .none || editActions?.isEmpty == false } @@ -114,31 +124,5 @@ open class TableViewRow: AnyTableViewRow { public var reuseIdentifier: String { return registrationType.reuseIdentifier } - - // MARK: - Private - - private func calculate(height: TableViewHeightType) -> CGFloat { - return heights[height]?(model) ?? UITableView.automaticDimension - } -} - -public extension TableViewRow where Model == Void { - - convenience init(editingStyle: UITableViewCell.EditingStyle = .none, - movable: Bool = false, - editActions: [UITableViewRowAction]? = nil, - indentWhileEditing: Bool = false, - deleteConfirmationTitle: String? = nil, - deleteRowAnimation: UITableView.RowAnimation = .automatic, - registrationType: TableViewRegistrationType = .defaultClassType) { - - self.init((), - editingStyle: editingStyle, - movable: movable, - editActions: editActions, - indentWhileEditing: indentWhileEditing, - deleteConfirmationTitle: deleteConfirmationTitle, - deleteRowAnimation: deleteRowAnimation, - registrationType: registrationType) - } + } diff --git a/TableViewLiaison/Classes/Sections/TableViewSection.swift b/TableViewLiaison/Classes/Sections/TableViewSection.swift index 9404002..b9f36ac 100644 --- a/TableViewLiaison/Classes/Sections/TableViewSection.swift +++ b/TableViewLiaison/Classes/Sections/TableViewSection.swift @@ -11,35 +11,43 @@ public struct TableViewSection { public internal(set) var rows: [AnyTableViewRow] - public let componentDisplayOption: TableViewSectionComponentDisplayOption + public let id: String? + public let option: TableViewSectionComponentDisplayOption - public init(rows: [AnyTableViewRow] = [], - componentDisplayOption: TableViewSectionComponentDisplayOption = .none) { + public init(id: String? = nil, + rows: [AnyTableViewRow] = [], + option: TableViewSectionComponentDisplayOption = .none) { self.rows = rows - self.componentDisplayOption = componentDisplayOption + self.id = id + self.option = option } - func perform(command: TableViewSectionComponentCommand, componentView: TableViewSectionComponentView, for view: UIView, in section: Int) { + func perform(_ command: TableViewSectionComponentCommand, + componentView: TableViewSectionComponentViewType, + liaison: TableViewLiaison, + view: UIView, + section: Int) { + switch componentView { case .header: - componentDisplayOption.header?.perform(command: command, for: view, in: section) + option.header?.perform(command, liaison: liaison, view: view, section: section) case .footer: - componentDisplayOption.footer?.perform(command: command, for: view, in: section) + option.footer?.perform(command, liaison: liaison, view: view, section: section) } } - func view(componentView: TableViewSectionComponentView, for tableView: UITableView, in section: Int) -> UIView? { + func view(componentView: TableViewSectionComponentViewType, for liaison: TableViewLiaison, in section: Int) -> UIView? { switch componentView { case .header: - return componentDisplayOption.header?.view(for: tableView, in: section) + return option.header?.view(for: liaison, in: section) case .footer: - return componentDisplayOption.footer?.view(for: tableView, in: section) + return option.footer?.view(for: liaison, in: section) } } - func calculate(height: TableViewHeightType, for componentView: TableViewSectionComponentView) -> CGFloat { + func calculate(_ height: TableViewHeightType, for componentView: TableViewSectionComponentViewType) -> CGFloat { - switch (componentDisplayOption, componentView) { + switch (option, componentView) { case (.both(let header, _), .header): return calculate(height, for: header) case (.both(_, let footer), .footer): @@ -73,6 +81,18 @@ public struct TableViewSection { } } + func rowIndexPaths(for section: Int, where predicate: (T) -> Bool) -> [IndexPath] { + return rows.enumerated() + .filter { index, row in + guard let state = row._data as? T else { return false } + return predicate(state) + } + .map { item, _ -> IndexPath in + return IndexPath(item: item, section: section) + } + } + + // MARK: - Helpers mutating func append(row: AnyTableViewRow) { rows.append(row) @@ -83,19 +103,19 @@ public struct TableViewSection { } @discardableResult - mutating func deleteRow(at indexPath: IndexPath) -> AnyTableViewRow? { - guard rows.indices.contains(indexPath.item) else { return nil } - return rows.remove(at: indexPath.item) + mutating func deleteRow(at index: Int) -> AnyTableViewRow? { + guard rows.indices.contains(index) else { return nil } + return rows.remove(at: index) } - mutating func insert(row: AnyTableViewRow, at indexPath: IndexPath) { - guard rows.count >= indexPath.item else { return } - rows.insert(row, at: indexPath.item) + mutating func insert(row: AnyTableViewRow, at index: Int) { + guard rows.count >= index else { return } + rows.insert(row, at: index) } - mutating func swapRows(at source: IndexPath, to destination: IndexPath) { - guard rows.indices.contains(source.item) && rows.indices.contains(destination.item) else { return } - rows.swapAt(source.item, destination.item) + mutating func swapRows(at source: Int, to destination: Int) { + guard rows.indices.contains(source) && rows.indices.contains(destination) else { return } + rows.swapAt(source, destination) } mutating func removeAllRows() { diff --git a/TableViewLiaison/Classes/Sections/TableViewSectionComponent.swift b/TableViewLiaison/Classes/Sections/TableViewSectionComponent.swift index fd44e60..e64bc27 100644 --- a/TableViewLiaison/Classes/Sections/TableViewSectionComponent.swift +++ b/TableViewLiaison/Classes/Sections/TableViewSectionComponent.swift @@ -7,92 +7,79 @@ import Foundation -open class TableViewSectionComponent: AnyTableViewSectionComponent { - - public let model: Model - +public struct TableViewSectionComponent: AnyTableViewSectionComponent { + + public typealias CommandClosure = (TableViewLiaison, View, Int) -> Void + private let registrationType: TableViewRegistrationType - private var commands = [TableViewSectionComponentCommand: (View, Model, Int) -> Void]() - private var heights = [TableViewHeightType: (Model) -> CGFloat]() + private var commands = [TableViewSectionComponentCommand: CommandClosure]() + private var heights = [TableViewHeightType: () -> CGFloat]() - public init(_ model: Model, registrationType: TableViewRegistrationType = .defaultClassType) { - self.model = model + public init(commands: [TableViewSectionComponentCommand: CommandClosure] = [:], + heights: [TableViewHeightType: () -> CGFloat] = [:], + registrationType: TableViewRegistrationType = .defaultClassType) { + self.commands = commands + self.heights = heights self.registrationType = registrationType } - public func view(for tableView: UITableView, in section: Int) -> UITableViewHeaderFooterView? { - let view = tableView.dequeue(View.self, with: reuseIdentifier) - commands[.configuration]?(view, model, section) + public func view(for liaison: TableViewLiaison, in section: Int) -> UITableViewHeaderFooterView? { + let view = liaison.dequeue(View.self, with: reuseIdentifier) + commands[.configuration]?(liaison, view, section) return view } - public func register(with tableView: UITableView) { + public func register(with liaison: TableViewLiaison) { switch registrationType { case let .class(identifier): - tableView.register(View.self, with: identifier) + liaison.register(View.self, with: identifier) case let .nib(nib, identifier): - tableView.register(nib, forHeaderFooterViewReuseIdentifier: identifier) + liaison.registerHeaderFooterView(nib: nib, with: identifier) } } // MARK: - Commands - public func perform(command: TableViewSectionComponentCommand, for view: UIView, in section: Int) { - + public func perform(_ command: TableViewSectionComponentCommand, liaison: TableViewLiaison, view: UIView, section: Int) { guard let view = view as? View else { return } - - commands[command]?(view, model, section) + commands[command]?(liaison, view, section) } - - public func set(command: TableViewSectionComponentCommand, with closure: @escaping (View, Model, Int) -> Void) { + + public mutating func set(_ command: TableViewSectionComponentCommand, with closure: @escaping CommandClosure) { commands[command] = closure } - public func remove(command: TableViewSectionComponentCommand) { + public mutating func remove(_ command: TableViewSectionComponentCommand) { commands[command] = nil } - public func set(height: TableViewHeightType, _ closure: @escaping (Model) -> CGFloat) { + public mutating func set(_ height: TableViewHeightType, _ closure: @escaping () -> CGFloat) { heights[height] = closure } - public func set(height: TableViewHeightType, _ value: CGFloat) { - let closure: ((Model) -> CGFloat) = { _ -> CGFloat in return value } + public mutating func set(_ height: TableViewHeightType, _ value: CGFloat) { + let closure: (() -> CGFloat) = { return value } heights[height] = closure } - public func remove(height: TableViewHeightType) { + public mutating func remove(_ height: TableViewHeightType) { heights[height] = nil } - // MARK: - Computed Properties - public var height: CGFloat { - return calculate(height: .height) - } - - public var estimatedHeight: CGFloat { - return calculate(height: .estimatedHeight) - } - - public var reuseIdentifier: String { - return registrationType.reuseIdentifier - } - - // MARK: - Private - private func calculate(height: TableViewHeightType) -> CGFloat { + public func calculate(_ height: TableViewHeightType) -> CGFloat { switch height { case .height: - return heights[.height]?(model) ?? UITableView.automaticDimension + return heights[.height]?() ?? UITableView.automaticDimension case .estimatedHeight: - return heights[.estimatedHeight]?(model) ?? heights[.height]?(model) ?? 0 + return heights[.estimatedHeight]?() ?? heights[.height]?() ?? 0 } } -} - -public extension TableViewSectionComponent where Model == Void { - convenience init(registrationType: TableViewRegistrationType = .defaultClassType) { - self.init((), - registrationType: registrationType) + // MARK: - Computed Properties + + public var reuseIdentifier: String { + return registrationType.reuseIdentifier } + } + diff --git a/TableViewLiaison/Classes/Views/PaginationTableViewCell.swift b/TableViewLiaison/Classes/Views/PaginationTableViewCell.swift index 9d2346b..6247dc1 100644 --- a/TableViewLiaison/Classes/Views/PaginationTableViewCell.swift +++ b/TableViewLiaison/Classes/Views/PaginationTableViewCell.swift @@ -1,5 +1,5 @@ // -// OKPaginationTableViewCell.swift +// PaginationTableViewCell.swift // TableViewLiaison // // Created by Dylan Shine on 3/30/18. @@ -9,24 +9,28 @@ import UIKit public final class PaginationTableViewCell: UITableViewCell { - private let verticalSpacingConstant: CGFloat = 5 - let spinner = UIActivityIndicatorView(style: .gray) + private let verticalSpacingConstant: CGFloat = 8 + let activityIndicator = UIActivityIndicatorView(style: .white) override public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) - configureLayout() + configure() } required public init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") + super.init(coder: aDecoder) + configure() } - private func configureLayout() { - spinner.translatesAutoresizingMaskIntoConstraints = false - contentView.addSubview(spinner) + private func configure() { + backgroundColor = .clear + contentView.backgroundColor = .clear + + activityIndicator.translatesAutoresizingMaskIntoConstraints = false + contentView.addSubview(activityIndicator) - spinner.centerXAnchor.constraint(equalTo: contentView.centerXAnchor).isActive = true - spinner.topAnchor.constraint(equalTo: contentView.topAnchor, constant: verticalSpacingConstant).isActive = true - spinner.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -verticalSpacingConstant).isActive = true + activityIndicator.centerXAnchor.constraint(equalTo: contentView.centerXAnchor).isActive = true + activityIndicator.topAnchor.constraint(equalTo: contentView.topAnchor, constant: verticalSpacingConstant).isActive = true + activityIndicator.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -verticalSpacingConstant).isActive = true } }