├── ATTableView.podspec ├── Demo ├── .gitignore ├── Demo.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata ├── Demo.xcworkspace │ └── contents.xcworkspacedata ├── Demo │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── Contents.json │ │ ├── bg_0.imageset │ │ │ ├── Contents.json │ │ │ └── bg_15.png │ │ ├── bg_1.imageset │ │ │ ├── Contents.json │ │ │ └── bg_14.png │ │ ├── bg_2.imageset │ │ │ ├── Contents.json │ │ │ └── bg_12.png │ │ ├── bg_3.imageset │ │ │ ├── Contents.json │ │ │ └── bg_3.png │ │ ├── bg_4.imageset │ │ │ ├── Contents.json │ │ │ └── bg_4.png │ │ ├── bg_5.imageset │ │ │ ├── Contents.json │ │ │ └── bg_5.png │ │ ├── bg_6.imageset │ │ │ ├── Contents.json │ │ │ └── meshup-background-toplocalfood.png │ │ ├── icon-bookmark.imageset │ │ │ ├── Contents.json │ │ │ ├── bookmark-icon-inactive.png │ │ │ ├── bookmark-icon-inactive@2x.png │ │ │ └── bookmark-icon-inactive@3x.png │ │ ├── icon-distance.imageset │ │ │ ├── Contents.json │ │ │ ├── distance-icon.png │ │ │ ├── distance-icon@2x.png │ │ │ └── distance-icon@3x.png │ │ ├── icon-event.imageset │ │ │ ├── Contents.json │ │ │ ├── event-tag-icon@1x.png │ │ │ ├── event-tag-icon@2x.png │ │ │ └── event-tag-icon@3x.png │ │ ├── icon-hotel.imageset │ │ │ ├── Contents.json │ │ │ ├── stay-tag-icon.png │ │ │ ├── stay-tag-icon@2x.png │ │ │ └── stay-tag-icon@3x.png │ │ ├── icon-restaurant.imageset │ │ │ ├── Contents.json │ │ │ ├── dine-tag-icon.png │ │ │ ├── dine-tag-icon@2x.png │ │ │ └── dine-tag-icon@3x.png │ │ └── icon-tip.imageset │ │ │ ├── Contents.json │ │ │ ├── tips-icon.png │ │ │ ├── tips-icon@2x.png │ │ │ └── tips-icon@3x.png │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Info.plist │ ├── Models │ │ ├── Event.swift │ │ ├── Hotel.swift │ │ ├── Restaurant.swift │ │ └── Tip.swift │ ├── TableViewCells │ │ ├── EventTableViewCell.swift │ │ ├── EventTableViewCell.xib │ │ ├── HotelTableViewCell.swift │ │ ├── HotelTableViewCell.xib │ │ ├── OfferTableViewCell.swift │ │ ├── OfferTableViewCell.xib │ │ ├── RestaurantTableViewCell.swift │ │ ├── RestaurantTableViewCell.xib │ │ ├── TipTableViewCell.swift │ │ └── TipTableViewCell.xib │ ├── ViewController.swift │ └── data.json ├── Podfile ├── Podfile.lock ├── Pods │ ├── Local Podspecs │ │ ├── LazyTableView.podspec.json │ │ └── ReactiveTableView.podspec.json │ ├── Manifest.lock │ ├── Pods.xcodeproj │ │ ├── project.pbxproj │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ ├── LazyTableView.xcscheme │ │ │ └── ReactiveTableView.xcscheme │ └── Target Support Files │ │ └── Pods │ │ ├── Info.plist │ │ ├── Pods-acknowledgements.markdown │ │ ├── Pods-acknowledgements.plist │ │ ├── Pods-dummy.m │ │ ├── Pods-frameworks.sh │ │ ├── Pods-resources.sh │ │ ├── Pods-umbrella.h │ │ ├── Pods.debug.xcconfig │ │ ├── Pods.modulemap │ │ └── Pods.release.xcconfig └── data.json ├── Doc ├── Assets │ ├── Demo.gif │ ├── LazyWay.png │ └── OldWay.png └── Examples.md ├── LICENSE ├── README.md └── Source ├── ATSignal.swift ├── ATTableView.swift ├── ATTableViewCellProtocol.swift └── ATTableViewSection.swift /ATTableView.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "ATTableView" 3 | s.version = "1.2" 4 | s.summary = "A lazy way for smart developers to deal with UITableView." 5 | 6 | s.description = <<-DESC 7 | How many times do you have to implement UITableViewDatasource and UITableViewDelegate? 8 | Is it boring? And how to deal with different UITableViewCells in one TableView? 9 | 10 | You're smart so you need to find a smart way to do it. 11 | ATTableView is for you, it's easy to display model in UITableView. Also support different UITableViewCells. 12 | DESC 13 | 14 | s.homepage = "https://github.com/tuanphung/ATTableView" 15 | 16 | s.license = "MIT" 17 | 18 | s.author = { "Tuan Phung" => "tuanphunglk@gmail.com" } 19 | s.social_media_url = "https://github.com/tuanphung" 20 | 21 | s.platform = :ios, "8.0" 22 | 23 | s.source = { :git => "https://github.com/tuanphung/ATTableView.git", :tag => s.version } 24 | s.source_files = "Source/*.swift" 25 | 26 | s.requires_arc = true 27 | 28 | end 29 | -------------------------------------------------------------------------------- /Demo/.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | *.xccheckout 14 | *.moved-aside 15 | DerivedData 16 | *.hmap 17 | *.ipa 18 | *.xcuserstate 19 | 20 | # CocoaPods 21 | # 22 | # We recommend against adding the Pods directory to your .gitignore. However 23 | # you should judge for yourself, the pros and cons are mentioned at: 24 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 25 | # 26 | Pods/ 27 | 28 | # Carthage 29 | # 30 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 31 | # Carthage/Checkouts 32 | 33 | Carthage/Build 34 | -------------------------------------------------------------------------------- /Demo/Demo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 8204B1551B9AD5B1005B658F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8204B1541B9AD5B1005B658F /* AppDelegate.swift */; }; 11 | 8204B1571B9AD5B1005B658F /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8204B1561B9AD5B1005B658F /* ViewController.swift */; }; 12 | 8204B15A1B9AD5B1005B658F /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8204B1581B9AD5B1005B658F /* Main.storyboard */; }; 13 | 8204B15C1B9AD5B1005B658F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8204B15B1B9AD5B1005B658F /* Assets.xcassets */; }; 14 | 8204B15F1B9AD5B1005B658F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8204B15D1B9AD5B1005B658F /* LaunchScreen.storyboard */; }; 15 | 822FAA381C36284000E48CDF /* TipTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 822FAA1D1C36284000E48CDF /* TipTableViewCell.swift */; }; 16 | 822FAA391C36284000E48CDF /* TipTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 822FAA1E1C36284000E48CDF /* TipTableViewCell.xib */; }; 17 | 822FAA3C1C36339000E48CDF /* RestaurantTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 822FAA3A1C36339000E48CDF /* RestaurantTableViewCell.swift */; }; 18 | 822FAA3D1C36339000E48CDF /* RestaurantTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 822FAA3B1C36339000E48CDF /* RestaurantTableViewCell.xib */; }; 19 | 822FAA401C3644B000E48CDF /* HotelTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 822FAA3E1C3644B000E48CDF /* HotelTableViewCell.swift */; }; 20 | 822FAA411C3644B000E48CDF /* HotelTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 822FAA3F1C3644B000E48CDF /* HotelTableViewCell.xib */; }; 21 | 822FAA431C36BCAD00E48CDF /* data.json in Resources */ = {isa = PBXBuildFile; fileRef = 822FAA421C36BCAD00E48CDF /* data.json */; }; 22 | 822FAA461C36C7E000E48CDF /* EventTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 822FAA441C36C7E000E48CDF /* EventTableViewCell.swift */; }; 23 | 822FAA471C36C7E000E48CDF /* EventTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 822FAA451C36C7E000E48CDF /* EventTableViewCell.xib */; }; 24 | 822FAA4C1C36D0BE00E48CDF /* Event.swift in Sources */ = {isa = PBXBuildFile; fileRef = 822FAA481C36D0BE00E48CDF /* Event.swift */; }; 25 | 822FAA4D1C36D0BE00E48CDF /* Hotel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 822FAA491C36D0BE00E48CDF /* Hotel.swift */; }; 26 | 822FAA4E1C36D0BE00E48CDF /* Restaurant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 822FAA4A1C36D0BE00E48CDF /* Restaurant.swift */; }; 27 | 822FAA4F1C36D0BE00E48CDF /* Tip.swift in Sources */ = {isa = PBXBuildFile; fileRef = 822FAA4B1C36D0BE00E48CDF /* Tip.swift */; }; 28 | A605E9A913C68F93919B3350 /* Pods.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB854E4A72DB90E379CE3205 /* Pods.framework */; }; 29 | /* End PBXBuildFile section */ 30 | 31 | /* Begin PBXContainerItemProxy section */ 32 | 8204B1661B9AD5B1005B658F /* PBXContainerItemProxy */ = { 33 | isa = PBXContainerItemProxy; 34 | containerPortal = 8204B1491B9AD5B1005B658F /* Project object */; 35 | proxyType = 1; 36 | remoteGlobalIDString = 8204B1501B9AD5B1005B658F; 37 | remoteInfo = Demo; 38 | }; 39 | 8204B1711B9AD5B1005B658F /* PBXContainerItemProxy */ = { 40 | isa = PBXContainerItemProxy; 41 | containerPortal = 8204B1491B9AD5B1005B658F /* Project object */; 42 | proxyType = 1; 43 | remoteGlobalIDString = 8204B1501B9AD5B1005B658F; 44 | remoteInfo = Demo; 45 | }; 46 | /* End PBXContainerItemProxy section */ 47 | 48 | /* Begin PBXFileReference section */ 49 | 263FC6EB36B7F8224E390C6D /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = ""; }; 50 | 8204B1511B9AD5B1005B658F /* Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Demo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 51 | 8204B1541B9AD5B1005B658F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 52 | 8204B1561B9AD5B1005B658F /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 53 | 8204B1591B9AD5B1005B658F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 54 | 8204B15B1B9AD5B1005B658F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 55 | 8204B15E1B9AD5B1005B658F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 56 | 8204B1601B9AD5B1005B658F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 57 | 8204B1651B9AD5B1005B658F /* DemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 58 | 8204B1701B9AD5B1005B658F /* DemoUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DemoUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 59 | 822FAA1D1C36284000E48CDF /* TipTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TipTableViewCell.swift; sourceTree = ""; }; 60 | 822FAA1E1C36284000E48CDF /* TipTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = TipTableViewCell.xib; sourceTree = ""; }; 61 | 822FAA3A1C36339000E48CDF /* RestaurantTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RestaurantTableViewCell.swift; sourceTree = ""; }; 62 | 822FAA3B1C36339000E48CDF /* RestaurantTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = RestaurantTableViewCell.xib; sourceTree = ""; }; 63 | 822FAA3E1C3644B000E48CDF /* HotelTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HotelTableViewCell.swift; sourceTree = ""; }; 64 | 822FAA3F1C3644B000E48CDF /* HotelTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = HotelTableViewCell.xib; sourceTree = ""; }; 65 | 822FAA421C36BCAD00E48CDF /* data.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = data.json; sourceTree = ""; }; 66 | 822FAA441C36C7E000E48CDF /* EventTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EventTableViewCell.swift; sourceTree = ""; }; 67 | 822FAA451C36C7E000E48CDF /* EventTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = EventTableViewCell.xib; sourceTree = ""; }; 68 | 822FAA481C36D0BE00E48CDF /* Event.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Event.swift; sourceTree = ""; }; 69 | 822FAA491C36D0BE00E48CDF /* Hotel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Hotel.swift; sourceTree = ""; }; 70 | 822FAA4A1C36D0BE00E48CDF /* Restaurant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Restaurant.swift; sourceTree = ""; }; 71 | 822FAA4B1C36D0BE00E48CDF /* Tip.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Tip.swift; sourceTree = ""; }; 72 | AB854E4A72DB90E379CE3205 /* Pods.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 73 | CBEA691718A8F1E7DF929BA8 /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = ""; }; 74 | /* End PBXFileReference section */ 75 | 76 | /* Begin PBXFrameworksBuildPhase section */ 77 | 8204B14E1B9AD5B1005B658F /* Frameworks */ = { 78 | isa = PBXFrameworksBuildPhase; 79 | buildActionMask = 2147483647; 80 | files = ( 81 | A605E9A913C68F93919B3350 /* Pods.framework in Frameworks */, 82 | ); 83 | runOnlyForDeploymentPostprocessing = 0; 84 | }; 85 | 8204B1621B9AD5B1005B658F /* Frameworks */ = { 86 | isa = PBXFrameworksBuildPhase; 87 | buildActionMask = 2147483647; 88 | files = ( 89 | ); 90 | runOnlyForDeploymentPostprocessing = 0; 91 | }; 92 | 8204B16D1B9AD5B1005B658F /* Frameworks */ = { 93 | isa = PBXFrameworksBuildPhase; 94 | buildActionMask = 2147483647; 95 | files = ( 96 | ); 97 | runOnlyForDeploymentPostprocessing = 0; 98 | }; 99 | /* End PBXFrameworksBuildPhase section */ 100 | 101 | /* Begin PBXGroup section */ 102 | 37DBA718683F54EF85A87B96 /* Pods */ = { 103 | isa = PBXGroup; 104 | children = ( 105 | CBEA691718A8F1E7DF929BA8 /* Pods.debug.xcconfig */, 106 | 263FC6EB36B7F8224E390C6D /* Pods.release.xcconfig */, 107 | ); 108 | name = Pods; 109 | sourceTree = ""; 110 | }; 111 | 8204B1481B9AD5B1005B658F = { 112 | isa = PBXGroup; 113 | children = ( 114 | 8204B1531B9AD5B1005B658F /* Demo */, 115 | 8204B1521B9AD5B1005B658F /* Products */, 116 | 37DBA718683F54EF85A87B96 /* Pods */, 117 | F9CC449424D50573A21F044A /* Frameworks */, 118 | ); 119 | sourceTree = ""; 120 | }; 121 | 8204B1521B9AD5B1005B658F /* Products */ = { 122 | isa = PBXGroup; 123 | children = ( 124 | 8204B1511B9AD5B1005B658F /* Demo.app */, 125 | 8204B1651B9AD5B1005B658F /* DemoTests.xctest */, 126 | 8204B1701B9AD5B1005B658F /* DemoUITests.xctest */, 127 | ); 128 | name = Products; 129 | sourceTree = ""; 130 | }; 131 | 8204B1531B9AD5B1005B658F /* Demo */ = { 132 | isa = PBXGroup; 133 | children = ( 134 | 822FAA421C36BCAD00E48CDF /* data.json */, 135 | 822FAA001C36284000E48CDF /* Models */, 136 | 822FAA121C36284000E48CDF /* TableViewCells */, 137 | 8204B1541B9AD5B1005B658F /* AppDelegate.swift */, 138 | 8204B1561B9AD5B1005B658F /* ViewController.swift */, 139 | 8204B1581B9AD5B1005B658F /* Main.storyboard */, 140 | 8204B15B1B9AD5B1005B658F /* Assets.xcassets */, 141 | 8204B15D1B9AD5B1005B658F /* LaunchScreen.storyboard */, 142 | 8204B1601B9AD5B1005B658F /* Info.plist */, 143 | ); 144 | path = Demo; 145 | sourceTree = ""; 146 | }; 147 | 822FAA001C36284000E48CDF /* Models */ = { 148 | isa = PBXGroup; 149 | children = ( 150 | 822FAA481C36D0BE00E48CDF /* Event.swift */, 151 | 822FAA491C36D0BE00E48CDF /* Hotel.swift */, 152 | 822FAA4A1C36D0BE00E48CDF /* Restaurant.swift */, 153 | 822FAA4B1C36D0BE00E48CDF /* Tip.swift */, 154 | ); 155 | path = Models; 156 | sourceTree = ""; 157 | }; 158 | 822FAA121C36284000E48CDF /* TableViewCells */ = { 159 | isa = PBXGroup; 160 | children = ( 161 | 822FAA441C36C7E000E48CDF /* EventTableViewCell.swift */, 162 | 822FAA451C36C7E000E48CDF /* EventTableViewCell.xib */, 163 | 822FAA3E1C3644B000E48CDF /* HotelTableViewCell.swift */, 164 | 822FAA3F1C3644B000E48CDF /* HotelTableViewCell.xib */, 165 | 822FAA3A1C36339000E48CDF /* RestaurantTableViewCell.swift */, 166 | 822FAA3B1C36339000E48CDF /* RestaurantTableViewCell.xib */, 167 | 822FAA1D1C36284000E48CDF /* TipTableViewCell.swift */, 168 | 822FAA1E1C36284000E48CDF /* TipTableViewCell.xib */, 169 | ); 170 | path = TableViewCells; 171 | sourceTree = ""; 172 | }; 173 | F9CC449424D50573A21F044A /* Frameworks */ = { 174 | isa = PBXGroup; 175 | children = ( 176 | AB854E4A72DB90E379CE3205 /* Pods.framework */, 177 | ); 178 | name = Frameworks; 179 | sourceTree = ""; 180 | }; 181 | /* End PBXGroup section */ 182 | 183 | /* Begin PBXNativeTarget section */ 184 | 8204B1501B9AD5B1005B658F /* Demo */ = { 185 | isa = PBXNativeTarget; 186 | buildConfigurationList = 8204B1791B9AD5B1005B658F /* Build configuration list for PBXNativeTarget "Demo" */; 187 | buildPhases = ( 188 | E6A09CFEF30A812652A4028A /* Check Pods Manifest.lock */, 189 | 8204B14D1B9AD5B1005B658F /* Sources */, 190 | 8204B14E1B9AD5B1005B658F /* Frameworks */, 191 | 8204B14F1B9AD5B1005B658F /* Resources */, 192 | 56168C4EF45F517CEE902DF3 /* Embed Pods Frameworks */, 193 | B84554CAB5886CB572619A17 /* Copy Pods Resources */, 194 | ); 195 | buildRules = ( 196 | ); 197 | dependencies = ( 198 | ); 199 | name = Demo; 200 | productName = Demo; 201 | productReference = 8204B1511B9AD5B1005B658F /* Demo.app */; 202 | productType = "com.apple.product-type.application"; 203 | }; 204 | 8204B1641B9AD5B1005B658F /* DemoTests */ = { 205 | isa = PBXNativeTarget; 206 | buildConfigurationList = 8204B17C1B9AD5B1005B658F /* Build configuration list for PBXNativeTarget "DemoTests" */; 207 | buildPhases = ( 208 | 8204B1611B9AD5B1005B658F /* Sources */, 209 | 8204B1621B9AD5B1005B658F /* Frameworks */, 210 | 8204B1631B9AD5B1005B658F /* Resources */, 211 | ); 212 | buildRules = ( 213 | ); 214 | dependencies = ( 215 | 8204B1671B9AD5B1005B658F /* PBXTargetDependency */, 216 | ); 217 | name = DemoTests; 218 | productName = DemoTests; 219 | productReference = 8204B1651B9AD5B1005B658F /* DemoTests.xctest */; 220 | productType = "com.apple.product-type.bundle.unit-test"; 221 | }; 222 | 8204B16F1B9AD5B1005B658F /* DemoUITests */ = { 223 | isa = PBXNativeTarget; 224 | buildConfigurationList = 8204B17F1B9AD5B1005B658F /* Build configuration list for PBXNativeTarget "DemoUITests" */; 225 | buildPhases = ( 226 | 8204B16C1B9AD5B1005B658F /* Sources */, 227 | 8204B16D1B9AD5B1005B658F /* Frameworks */, 228 | 8204B16E1B9AD5B1005B658F /* Resources */, 229 | ); 230 | buildRules = ( 231 | ); 232 | dependencies = ( 233 | 8204B1721B9AD5B1005B658F /* PBXTargetDependency */, 234 | ); 235 | name = DemoUITests; 236 | productName = DemoUITests; 237 | productReference = 8204B1701B9AD5B1005B658F /* DemoUITests.xctest */; 238 | productType = "com.apple.product-type.bundle.ui-testing"; 239 | }; 240 | /* End PBXNativeTarget section */ 241 | 242 | /* Begin PBXProject section */ 243 | 8204B1491B9AD5B1005B658F /* Project object */ = { 244 | isa = PBXProject; 245 | attributes = { 246 | LastUpgradeCheck = 0700; 247 | ORGANIZATIONNAME = "Tuan Phung"; 248 | TargetAttributes = { 249 | 8204B1501B9AD5B1005B658F = { 250 | CreatedOnToolsVersion = 7.0; 251 | DevelopmentTeam = YCDYG6QC73; 252 | }; 253 | 8204B1641B9AD5B1005B658F = { 254 | CreatedOnToolsVersion = 7.0; 255 | TestTargetID = 8204B1501B9AD5B1005B658F; 256 | }; 257 | 8204B16F1B9AD5B1005B658F = { 258 | CreatedOnToolsVersion = 7.0; 259 | TestTargetID = 8204B1501B9AD5B1005B658F; 260 | }; 261 | }; 262 | }; 263 | buildConfigurationList = 8204B14C1B9AD5B1005B658F /* Build configuration list for PBXProject "Demo" */; 264 | compatibilityVersion = "Xcode 3.2"; 265 | developmentRegion = English; 266 | hasScannedForEncodings = 0; 267 | knownRegions = ( 268 | en, 269 | Base, 270 | ); 271 | mainGroup = 8204B1481B9AD5B1005B658F; 272 | productRefGroup = 8204B1521B9AD5B1005B658F /* Products */; 273 | projectDirPath = ""; 274 | projectRoot = ""; 275 | targets = ( 276 | 8204B1501B9AD5B1005B658F /* Demo */, 277 | 8204B1641B9AD5B1005B658F /* DemoTests */, 278 | 8204B16F1B9AD5B1005B658F /* DemoUITests */, 279 | ); 280 | }; 281 | /* End PBXProject section */ 282 | 283 | /* Begin PBXResourcesBuildPhase section */ 284 | 8204B14F1B9AD5B1005B658F /* Resources */ = { 285 | isa = PBXResourcesBuildPhase; 286 | buildActionMask = 2147483647; 287 | files = ( 288 | 8204B15F1B9AD5B1005B658F /* LaunchScreen.storyboard in Resources */, 289 | 822FAA431C36BCAD00E48CDF /* data.json in Resources */, 290 | 822FAA3D1C36339000E48CDF /* RestaurantTableViewCell.xib in Resources */, 291 | 822FAA411C3644B000E48CDF /* HotelTableViewCell.xib in Resources */, 292 | 822FAA471C36C7E000E48CDF /* EventTableViewCell.xib in Resources */, 293 | 8204B15C1B9AD5B1005B658F /* Assets.xcassets in Resources */, 294 | 8204B15A1B9AD5B1005B658F /* Main.storyboard in Resources */, 295 | 822FAA391C36284000E48CDF /* TipTableViewCell.xib in Resources */, 296 | ); 297 | runOnlyForDeploymentPostprocessing = 0; 298 | }; 299 | 8204B1631B9AD5B1005B658F /* Resources */ = { 300 | isa = PBXResourcesBuildPhase; 301 | buildActionMask = 2147483647; 302 | files = ( 303 | ); 304 | runOnlyForDeploymentPostprocessing = 0; 305 | }; 306 | 8204B16E1B9AD5B1005B658F /* Resources */ = { 307 | isa = PBXResourcesBuildPhase; 308 | buildActionMask = 2147483647; 309 | files = ( 310 | ); 311 | runOnlyForDeploymentPostprocessing = 0; 312 | }; 313 | /* End PBXResourcesBuildPhase section */ 314 | 315 | /* Begin PBXShellScriptBuildPhase section */ 316 | 56168C4EF45F517CEE902DF3 /* Embed Pods Frameworks */ = { 317 | isa = PBXShellScriptBuildPhase; 318 | buildActionMask = 2147483647; 319 | files = ( 320 | ); 321 | inputPaths = ( 322 | ); 323 | name = "Embed Pods Frameworks"; 324 | outputPaths = ( 325 | ); 326 | runOnlyForDeploymentPostprocessing = 0; 327 | shellPath = /bin/sh; 328 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-frameworks.sh\"\n"; 329 | showEnvVarsInLog = 0; 330 | }; 331 | B84554CAB5886CB572619A17 /* Copy Pods Resources */ = { 332 | isa = PBXShellScriptBuildPhase; 333 | buildActionMask = 2147483647; 334 | files = ( 335 | ); 336 | inputPaths = ( 337 | ); 338 | name = "Copy Pods Resources"; 339 | outputPaths = ( 340 | ); 341 | runOnlyForDeploymentPostprocessing = 0; 342 | shellPath = /bin/sh; 343 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n"; 344 | showEnvVarsInLog = 0; 345 | }; 346 | E6A09CFEF30A812652A4028A /* Check Pods Manifest.lock */ = { 347 | isa = PBXShellScriptBuildPhase; 348 | buildActionMask = 2147483647; 349 | files = ( 350 | ); 351 | inputPaths = ( 352 | ); 353 | name = "Check Pods Manifest.lock"; 354 | outputPaths = ( 355 | ); 356 | runOnlyForDeploymentPostprocessing = 0; 357 | shellPath = /bin/sh; 358 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; 359 | showEnvVarsInLog = 0; 360 | }; 361 | /* End PBXShellScriptBuildPhase section */ 362 | 363 | /* Begin PBXSourcesBuildPhase section */ 364 | 8204B14D1B9AD5B1005B658F /* Sources */ = { 365 | isa = PBXSourcesBuildPhase; 366 | buildActionMask = 2147483647; 367 | files = ( 368 | 822FAA381C36284000E48CDF /* TipTableViewCell.swift in Sources */, 369 | 822FAA461C36C7E000E48CDF /* EventTableViewCell.swift in Sources */, 370 | 822FAA4D1C36D0BE00E48CDF /* Hotel.swift in Sources */, 371 | 8204B1571B9AD5B1005B658F /* ViewController.swift in Sources */, 372 | 8204B1551B9AD5B1005B658F /* AppDelegate.swift in Sources */, 373 | 822FAA401C3644B000E48CDF /* HotelTableViewCell.swift in Sources */, 374 | 822FAA4C1C36D0BE00E48CDF /* Event.swift in Sources */, 375 | 822FAA4F1C36D0BE00E48CDF /* Tip.swift in Sources */, 376 | 822FAA3C1C36339000E48CDF /* RestaurantTableViewCell.swift in Sources */, 377 | 822FAA4E1C36D0BE00E48CDF /* Restaurant.swift in Sources */, 378 | ); 379 | runOnlyForDeploymentPostprocessing = 0; 380 | }; 381 | 8204B1611B9AD5B1005B658F /* Sources */ = { 382 | isa = PBXSourcesBuildPhase; 383 | buildActionMask = 2147483647; 384 | files = ( 385 | ); 386 | runOnlyForDeploymentPostprocessing = 0; 387 | }; 388 | 8204B16C1B9AD5B1005B658F /* Sources */ = { 389 | isa = PBXSourcesBuildPhase; 390 | buildActionMask = 2147483647; 391 | files = ( 392 | ); 393 | runOnlyForDeploymentPostprocessing = 0; 394 | }; 395 | /* End PBXSourcesBuildPhase section */ 396 | 397 | /* Begin PBXTargetDependency section */ 398 | 8204B1671B9AD5B1005B658F /* PBXTargetDependency */ = { 399 | isa = PBXTargetDependency; 400 | target = 8204B1501B9AD5B1005B658F /* Demo */; 401 | targetProxy = 8204B1661B9AD5B1005B658F /* PBXContainerItemProxy */; 402 | }; 403 | 8204B1721B9AD5B1005B658F /* PBXTargetDependency */ = { 404 | isa = PBXTargetDependency; 405 | target = 8204B1501B9AD5B1005B658F /* Demo */; 406 | targetProxy = 8204B1711B9AD5B1005B658F /* PBXContainerItemProxy */; 407 | }; 408 | /* End PBXTargetDependency section */ 409 | 410 | /* Begin PBXVariantGroup section */ 411 | 8204B1581B9AD5B1005B658F /* Main.storyboard */ = { 412 | isa = PBXVariantGroup; 413 | children = ( 414 | 8204B1591B9AD5B1005B658F /* Base */, 415 | ); 416 | name = Main.storyboard; 417 | sourceTree = ""; 418 | }; 419 | 8204B15D1B9AD5B1005B658F /* LaunchScreen.storyboard */ = { 420 | isa = PBXVariantGroup; 421 | children = ( 422 | 8204B15E1B9AD5B1005B658F /* Base */, 423 | ); 424 | name = LaunchScreen.storyboard; 425 | sourceTree = ""; 426 | }; 427 | /* End PBXVariantGroup section */ 428 | 429 | /* Begin XCBuildConfiguration section */ 430 | 8204B1771B9AD5B1005B658F /* Debug */ = { 431 | isa = XCBuildConfiguration; 432 | buildSettings = { 433 | ALWAYS_SEARCH_USER_PATHS = NO; 434 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 435 | CLANG_CXX_LIBRARY = "libc++"; 436 | CLANG_ENABLE_MODULES = YES; 437 | CLANG_ENABLE_OBJC_ARC = YES; 438 | CLANG_WARN_BOOL_CONVERSION = YES; 439 | CLANG_WARN_CONSTANT_CONVERSION = YES; 440 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 441 | CLANG_WARN_EMPTY_BODY = YES; 442 | CLANG_WARN_ENUM_CONVERSION = YES; 443 | CLANG_WARN_INT_CONVERSION = YES; 444 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 445 | CLANG_WARN_UNREACHABLE_CODE = YES; 446 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 447 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 448 | COPY_PHASE_STRIP = NO; 449 | DEBUG_INFORMATION_FORMAT = dwarf; 450 | ENABLE_STRICT_OBJC_MSGSEND = YES; 451 | ENABLE_TESTABILITY = YES; 452 | GCC_C_LANGUAGE_STANDARD = gnu99; 453 | GCC_DYNAMIC_NO_PIC = NO; 454 | GCC_NO_COMMON_BLOCKS = YES; 455 | GCC_OPTIMIZATION_LEVEL = 0; 456 | GCC_PREPROCESSOR_DEFINITIONS = ( 457 | "DEBUG=1", 458 | "$(inherited)", 459 | ); 460 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 461 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 462 | GCC_WARN_UNDECLARED_SELECTOR = YES; 463 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 464 | GCC_WARN_UNUSED_FUNCTION = YES; 465 | GCC_WARN_UNUSED_VARIABLE = YES; 466 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 467 | MTL_ENABLE_DEBUG_INFO = YES; 468 | ONLY_ACTIVE_ARCH = YES; 469 | SDKROOT = iphoneos; 470 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 471 | }; 472 | name = Debug; 473 | }; 474 | 8204B1781B9AD5B1005B658F /* Release */ = { 475 | isa = XCBuildConfiguration; 476 | buildSettings = { 477 | ALWAYS_SEARCH_USER_PATHS = NO; 478 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 479 | CLANG_CXX_LIBRARY = "libc++"; 480 | CLANG_ENABLE_MODULES = YES; 481 | CLANG_ENABLE_OBJC_ARC = YES; 482 | CLANG_WARN_BOOL_CONVERSION = YES; 483 | CLANG_WARN_CONSTANT_CONVERSION = YES; 484 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 485 | CLANG_WARN_EMPTY_BODY = YES; 486 | CLANG_WARN_ENUM_CONVERSION = YES; 487 | CLANG_WARN_INT_CONVERSION = YES; 488 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 489 | CLANG_WARN_UNREACHABLE_CODE = YES; 490 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 491 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 492 | COPY_PHASE_STRIP = NO; 493 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 494 | ENABLE_NS_ASSERTIONS = NO; 495 | ENABLE_STRICT_OBJC_MSGSEND = YES; 496 | GCC_C_LANGUAGE_STANDARD = gnu99; 497 | GCC_NO_COMMON_BLOCKS = YES; 498 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 499 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 500 | GCC_WARN_UNDECLARED_SELECTOR = YES; 501 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 502 | GCC_WARN_UNUSED_FUNCTION = YES; 503 | GCC_WARN_UNUSED_VARIABLE = YES; 504 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 505 | MTL_ENABLE_DEBUG_INFO = NO; 506 | SDKROOT = iphoneos; 507 | VALIDATE_PRODUCT = YES; 508 | }; 509 | name = Release; 510 | }; 511 | 8204B17A1B9AD5B1005B658F /* Debug */ = { 512 | isa = XCBuildConfiguration; 513 | baseConfigurationReference = CBEA691718A8F1E7DF929BA8 /* Pods.debug.xcconfig */; 514 | buildSettings = { 515 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 516 | CODE_SIGN_IDENTITY = "iPhone Developer"; 517 | INFOPLIST_FILE = Demo/Info.plist; 518 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 519 | PRODUCT_BUNDLE_IDENTIFIER = com.tuanphung.Debug; 520 | PRODUCT_NAME = "$(TARGET_NAME)"; 521 | }; 522 | name = Debug; 523 | }; 524 | 8204B17B1B9AD5B1005B658F /* Release */ = { 525 | isa = XCBuildConfiguration; 526 | baseConfigurationReference = 263FC6EB36B7F8224E390C6D /* Pods.release.xcconfig */; 527 | buildSettings = { 528 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 529 | CODE_SIGN_IDENTITY = "iPhone Developer"; 530 | INFOPLIST_FILE = Demo/Info.plist; 531 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 532 | PRODUCT_BUNDLE_IDENTIFIER = com.tuanphung.Debug; 533 | PRODUCT_NAME = "$(TARGET_NAME)"; 534 | }; 535 | name = Release; 536 | }; 537 | 8204B17D1B9AD5B1005B658F /* Debug */ = { 538 | isa = XCBuildConfiguration; 539 | buildSettings = { 540 | BUNDLE_LOADER = "$(TEST_HOST)"; 541 | INFOPLIST_FILE = DemoTests/Info.plist; 542 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 543 | PRODUCT_BUNDLE_IDENTIFIER = com.tuanphung.DemoTests; 544 | PRODUCT_NAME = "$(TARGET_NAME)"; 545 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Demo.app/Demo"; 546 | }; 547 | name = Debug; 548 | }; 549 | 8204B17E1B9AD5B1005B658F /* Release */ = { 550 | isa = XCBuildConfiguration; 551 | buildSettings = { 552 | BUNDLE_LOADER = "$(TEST_HOST)"; 553 | INFOPLIST_FILE = DemoTests/Info.plist; 554 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 555 | PRODUCT_BUNDLE_IDENTIFIER = com.tuanphung.DemoTests; 556 | PRODUCT_NAME = "$(TARGET_NAME)"; 557 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Demo.app/Demo"; 558 | }; 559 | name = Release; 560 | }; 561 | 8204B1801B9AD5B1005B658F /* Debug */ = { 562 | isa = XCBuildConfiguration; 563 | buildSettings = { 564 | INFOPLIST_FILE = DemoUITests/Info.plist; 565 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 566 | PRODUCT_BUNDLE_IDENTIFIER = com.tuanphung.DemoUITests; 567 | PRODUCT_NAME = "$(TARGET_NAME)"; 568 | TEST_TARGET_NAME = Demo; 569 | USES_XCTRUNNER = YES; 570 | }; 571 | name = Debug; 572 | }; 573 | 8204B1811B9AD5B1005B658F /* Release */ = { 574 | isa = XCBuildConfiguration; 575 | buildSettings = { 576 | INFOPLIST_FILE = DemoUITests/Info.plist; 577 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 578 | PRODUCT_BUNDLE_IDENTIFIER = com.tuanphung.DemoUITests; 579 | PRODUCT_NAME = "$(TARGET_NAME)"; 580 | TEST_TARGET_NAME = Demo; 581 | USES_XCTRUNNER = YES; 582 | }; 583 | name = Release; 584 | }; 585 | /* End XCBuildConfiguration section */ 586 | 587 | /* Begin XCConfigurationList section */ 588 | 8204B14C1B9AD5B1005B658F /* Build configuration list for PBXProject "Demo" */ = { 589 | isa = XCConfigurationList; 590 | buildConfigurations = ( 591 | 8204B1771B9AD5B1005B658F /* Debug */, 592 | 8204B1781B9AD5B1005B658F /* Release */, 593 | ); 594 | defaultConfigurationIsVisible = 0; 595 | defaultConfigurationName = Release; 596 | }; 597 | 8204B1791B9AD5B1005B658F /* Build configuration list for PBXNativeTarget "Demo" */ = { 598 | isa = XCConfigurationList; 599 | buildConfigurations = ( 600 | 8204B17A1B9AD5B1005B658F /* Debug */, 601 | 8204B17B1B9AD5B1005B658F /* Release */, 602 | ); 603 | defaultConfigurationIsVisible = 0; 604 | defaultConfigurationName = Release; 605 | }; 606 | 8204B17C1B9AD5B1005B658F /* Build configuration list for PBXNativeTarget "DemoTests" */ = { 607 | isa = XCConfigurationList; 608 | buildConfigurations = ( 609 | 8204B17D1B9AD5B1005B658F /* Debug */, 610 | 8204B17E1B9AD5B1005B658F /* Release */, 611 | ); 612 | defaultConfigurationIsVisible = 0; 613 | defaultConfigurationName = Release; 614 | }; 615 | 8204B17F1B9AD5B1005B658F /* Build configuration list for PBXNativeTarget "DemoUITests" */ = { 616 | isa = XCConfigurationList; 617 | buildConfigurations = ( 618 | 8204B1801B9AD5B1005B658F /* Debug */, 619 | 8204B1811B9AD5B1005B658F /* Release */, 620 | ); 621 | defaultConfigurationIsVisible = 0; 622 | defaultConfigurationName = Release; 623 | }; 624 | /* End XCConfigurationList section */ 625 | }; 626 | rootObject = 8204B1491B9AD5B1005B658F /* Project object */; 627 | } 628 | -------------------------------------------------------------------------------- /Demo/Demo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Demo/Demo.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Demo/Demo/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 PHUNG ANH TUAN. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | import UIKit 23 | 24 | @UIApplicationMain 25 | class AppDelegate: UIResponder, UIApplicationDelegate { 26 | 27 | var window: UIWindow? 28 | 29 | 30 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 31 | UIApplication.sharedApplication().statusBarStyle = .LightContent 32 | 33 | return true 34 | } 35 | 36 | func applicationWillResignActive(application: UIApplication) { 37 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 38 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 39 | } 40 | 41 | func applicationDidEnterBackground(application: UIApplication) { 42 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 43 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 44 | } 45 | 46 | func applicationWillEnterForeground(application: UIApplication) { 47 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 48 | } 49 | 50 | func applicationDidBecomeActive(application: UIApplication) { 51 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 52 | } 53 | 54 | func applicationWillTerminate(application: UIApplication) { 55 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 56 | } 57 | 58 | 59 | } 60 | 61 | -------------------------------------------------------------------------------- /Demo/Demo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "3x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "3x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "57x57", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "57x57", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "iphone", 45 | "size" : "60x60", 46 | "scale" : "3x" 47 | } 48 | ], 49 | "info" : { 50 | "version" : 1, 51 | "author" : "xcode" 52 | } 53 | } -------------------------------------------------------------------------------- /Demo/Demo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Demo/Demo/Assets.xcassets/bg_0.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "bg_15.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Demo/Demo/Assets.xcassets/bg_0.imageset/bg_15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanphung/SmartTableView/1c7d16955b714d1af734c71c0718d57bc99b9837/Demo/Demo/Assets.xcassets/bg_0.imageset/bg_15.png -------------------------------------------------------------------------------- /Demo/Demo/Assets.xcassets/bg_1.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "bg_14.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Demo/Demo/Assets.xcassets/bg_1.imageset/bg_14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanphung/SmartTableView/1c7d16955b714d1af734c71c0718d57bc99b9837/Demo/Demo/Assets.xcassets/bg_1.imageset/bg_14.png -------------------------------------------------------------------------------- /Demo/Demo/Assets.xcassets/bg_2.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "bg_12.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Demo/Demo/Assets.xcassets/bg_2.imageset/bg_12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanphung/SmartTableView/1c7d16955b714d1af734c71c0718d57bc99b9837/Demo/Demo/Assets.xcassets/bg_2.imageset/bg_12.png -------------------------------------------------------------------------------- /Demo/Demo/Assets.xcassets/bg_3.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "bg_3.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Demo/Demo/Assets.xcassets/bg_3.imageset/bg_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanphung/SmartTableView/1c7d16955b714d1af734c71c0718d57bc99b9837/Demo/Demo/Assets.xcassets/bg_3.imageset/bg_3.png -------------------------------------------------------------------------------- /Demo/Demo/Assets.xcassets/bg_4.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "bg_4.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Demo/Demo/Assets.xcassets/bg_4.imageset/bg_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanphung/SmartTableView/1c7d16955b714d1af734c71c0718d57bc99b9837/Demo/Demo/Assets.xcassets/bg_4.imageset/bg_4.png -------------------------------------------------------------------------------- /Demo/Demo/Assets.xcassets/bg_5.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "bg_5.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Demo/Demo/Assets.xcassets/bg_5.imageset/bg_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanphung/SmartTableView/1c7d16955b714d1af734c71c0718d57bc99b9837/Demo/Demo/Assets.xcassets/bg_5.imageset/bg_5.png -------------------------------------------------------------------------------- /Demo/Demo/Assets.xcassets/bg_6.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "meshup-background-toplocalfood.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Demo/Demo/Assets.xcassets/bg_6.imageset/meshup-background-toplocalfood.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanphung/SmartTableView/1c7d16955b714d1af734c71c0718d57bc99b9837/Demo/Demo/Assets.xcassets/bg_6.imageset/meshup-background-toplocalfood.png -------------------------------------------------------------------------------- /Demo/Demo/Assets.xcassets/icon-bookmark.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "bookmark-icon-inactive.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "bookmark-icon-inactive@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "bookmark-icon-inactive@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Demo/Demo/Assets.xcassets/icon-bookmark.imageset/bookmark-icon-inactive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanphung/SmartTableView/1c7d16955b714d1af734c71c0718d57bc99b9837/Demo/Demo/Assets.xcassets/icon-bookmark.imageset/bookmark-icon-inactive.png -------------------------------------------------------------------------------- /Demo/Demo/Assets.xcassets/icon-bookmark.imageset/bookmark-icon-inactive@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanphung/SmartTableView/1c7d16955b714d1af734c71c0718d57bc99b9837/Demo/Demo/Assets.xcassets/icon-bookmark.imageset/bookmark-icon-inactive@2x.png -------------------------------------------------------------------------------- /Demo/Demo/Assets.xcassets/icon-bookmark.imageset/bookmark-icon-inactive@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanphung/SmartTableView/1c7d16955b714d1af734c71c0718d57bc99b9837/Demo/Demo/Assets.xcassets/icon-bookmark.imageset/bookmark-icon-inactive@3x.png -------------------------------------------------------------------------------- /Demo/Demo/Assets.xcassets/icon-distance.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "distance-icon.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "distance-icon@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "distance-icon@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Demo/Demo/Assets.xcassets/icon-distance.imageset/distance-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanphung/SmartTableView/1c7d16955b714d1af734c71c0718d57bc99b9837/Demo/Demo/Assets.xcassets/icon-distance.imageset/distance-icon.png -------------------------------------------------------------------------------- /Demo/Demo/Assets.xcassets/icon-distance.imageset/distance-icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanphung/SmartTableView/1c7d16955b714d1af734c71c0718d57bc99b9837/Demo/Demo/Assets.xcassets/icon-distance.imageset/distance-icon@2x.png -------------------------------------------------------------------------------- /Demo/Demo/Assets.xcassets/icon-distance.imageset/distance-icon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanphung/SmartTableView/1c7d16955b714d1af734c71c0718d57bc99b9837/Demo/Demo/Assets.xcassets/icon-distance.imageset/distance-icon@3x.png -------------------------------------------------------------------------------- /Demo/Demo/Assets.xcassets/icon-event.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "event-tag-icon@1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "event-tag-icon@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "event-tag-icon@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Demo/Demo/Assets.xcassets/icon-event.imageset/event-tag-icon@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanphung/SmartTableView/1c7d16955b714d1af734c71c0718d57bc99b9837/Demo/Demo/Assets.xcassets/icon-event.imageset/event-tag-icon@1x.png -------------------------------------------------------------------------------- /Demo/Demo/Assets.xcassets/icon-event.imageset/event-tag-icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanphung/SmartTableView/1c7d16955b714d1af734c71c0718d57bc99b9837/Demo/Demo/Assets.xcassets/icon-event.imageset/event-tag-icon@2x.png -------------------------------------------------------------------------------- /Demo/Demo/Assets.xcassets/icon-event.imageset/event-tag-icon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanphung/SmartTableView/1c7d16955b714d1af734c71c0718d57bc99b9837/Demo/Demo/Assets.xcassets/icon-event.imageset/event-tag-icon@3x.png -------------------------------------------------------------------------------- /Demo/Demo/Assets.xcassets/icon-hotel.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "stay-tag-icon.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "stay-tag-icon@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "stay-tag-icon@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Demo/Demo/Assets.xcassets/icon-hotel.imageset/stay-tag-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanphung/SmartTableView/1c7d16955b714d1af734c71c0718d57bc99b9837/Demo/Demo/Assets.xcassets/icon-hotel.imageset/stay-tag-icon.png -------------------------------------------------------------------------------- /Demo/Demo/Assets.xcassets/icon-hotel.imageset/stay-tag-icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanphung/SmartTableView/1c7d16955b714d1af734c71c0718d57bc99b9837/Demo/Demo/Assets.xcassets/icon-hotel.imageset/stay-tag-icon@2x.png -------------------------------------------------------------------------------- /Demo/Demo/Assets.xcassets/icon-hotel.imageset/stay-tag-icon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanphung/SmartTableView/1c7d16955b714d1af734c71c0718d57bc99b9837/Demo/Demo/Assets.xcassets/icon-hotel.imageset/stay-tag-icon@3x.png -------------------------------------------------------------------------------- /Demo/Demo/Assets.xcassets/icon-restaurant.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "dine-tag-icon.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "dine-tag-icon@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "dine-tag-icon@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Demo/Demo/Assets.xcassets/icon-restaurant.imageset/dine-tag-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanphung/SmartTableView/1c7d16955b714d1af734c71c0718d57bc99b9837/Demo/Demo/Assets.xcassets/icon-restaurant.imageset/dine-tag-icon.png -------------------------------------------------------------------------------- /Demo/Demo/Assets.xcassets/icon-restaurant.imageset/dine-tag-icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanphung/SmartTableView/1c7d16955b714d1af734c71c0718d57bc99b9837/Demo/Demo/Assets.xcassets/icon-restaurant.imageset/dine-tag-icon@2x.png -------------------------------------------------------------------------------- /Demo/Demo/Assets.xcassets/icon-restaurant.imageset/dine-tag-icon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanphung/SmartTableView/1c7d16955b714d1af734c71c0718d57bc99b9837/Demo/Demo/Assets.xcassets/icon-restaurant.imageset/dine-tag-icon@3x.png -------------------------------------------------------------------------------- /Demo/Demo/Assets.xcassets/icon-tip.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "tips-icon.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "tips-icon@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "tips-icon@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Demo/Demo/Assets.xcassets/icon-tip.imageset/tips-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanphung/SmartTableView/1c7d16955b714d1af734c71c0718d57bc99b9837/Demo/Demo/Assets.xcassets/icon-tip.imageset/tips-icon.png -------------------------------------------------------------------------------- /Demo/Demo/Assets.xcassets/icon-tip.imageset/tips-icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanphung/SmartTableView/1c7d16955b714d1af734c71c0718d57bc99b9837/Demo/Demo/Assets.xcassets/icon-tip.imageset/tips-icon@2x.png -------------------------------------------------------------------------------- /Demo/Demo/Assets.xcassets/icon-tip.imageset/tips-icon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanphung/SmartTableView/1c7d16955b714d1af734c71c0718d57bc99b9837/Demo/Demo/Assets.xcassets/icon-tip.imageset/tips-icon@3x.png -------------------------------------------------------------------------------- /Demo/Demo/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Demo/Demo/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /Demo/Demo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | LazyTableView 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UIViewControllerBasedStatusBarAppearance 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /Demo/Demo/Models/Event.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 PHUNG ANH TUAN. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | import Foundation 23 | import SwiftyJSON 24 | 25 | class Event { 26 | // Properties 27 | var name: String = "" 28 | var imageName: String = "" 29 | var numberOfReviews: Int = 0 30 | var rating: Double = 0 31 | var startDate: NSDate? 32 | var endDate: NSDate? 33 | 34 | init(json: JSON) { 35 | self.name = json["name"].stringValue 36 | self.imageName = json["imageName"].stringValue 37 | self.rating = json["rating"].doubleValue 38 | 39 | let dateFormatter = NSDateFormatter() 40 | dateFormatter.locale = NSLocale(localeIdentifier: "en_US") 41 | dateFormatter.dateFormat = "yyyyMMdd" 42 | 43 | self.startDate = dateFormatter.dateFromString(json["startDate"].stringValue) 44 | self.endDate = dateFormatter.dateFromString(json["endDate"].stringValue) 45 | } 46 | } -------------------------------------------------------------------------------- /Demo/Demo/Models/Hotel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 PHUNG ANH TUAN. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | import Foundation 23 | import SwiftyJSON 24 | 25 | class Hotel { 26 | // Properties 27 | var name: String = "" 28 | var imageName: String = "" 29 | var price: Double = 0 30 | var userRating: Double = 0 31 | var rating: Double = 0 32 | 33 | init(json: JSON) { 34 | self.name = json["name"].stringValue 35 | self.imageName = json["imageName"].stringValue 36 | self.price = json["price"].doubleValue 37 | self.userRating = json["userRating"].doubleValue 38 | self.rating = json["rating"].doubleValue 39 | } 40 | } -------------------------------------------------------------------------------- /Demo/Demo/Models/Restaurant.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 PHUNG ANH TUAN. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | import Foundation 23 | import SwiftyJSON 24 | 25 | class Restaurant { 26 | // Properties 27 | var name: String = "" 28 | var imageName: String = "" 29 | var numberOfReviews: Int = 0 30 | var rating: Double = 0 31 | 32 | init(json: JSON) { 33 | self.name = json["name"].stringValue 34 | self.imageName = json["imageName"].stringValue 35 | self.numberOfReviews = json["numberOfReviews"].intValue 36 | self.rating = json["rating"].doubleValue 37 | } 38 | } -------------------------------------------------------------------------------- /Demo/Demo/Models/Tip.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 PHUNG ANH TUAN. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | import Foundation 23 | import SwiftyJSON 24 | 25 | class Tip { 26 | // Properties 27 | var name: String = "" 28 | 29 | init(json: JSON) { 30 | self.name = json["name"].stringValue 31 | } 32 | } -------------------------------------------------------------------------------- /Demo/Demo/TableViewCells/EventTableViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // EventTableViewCell.swift 3 | // goru 4 | // 5 | // Copyright (c) 2016 PHUNG ANH TUAN. All rights reserved. 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | 25 | import UIKit 26 | import ATTableView 27 | import HCSStarRatingView 28 | 29 | class EventTableViewCell: UITableViewCell { 30 | // MARK: - IBOutlets 31 | @IBOutlet weak var topImageView: UIImageView! 32 | @IBOutlet weak var titleLabel: UILabel! 33 | @IBOutlet weak var starRatingView: HCSStarRatingView! 34 | @IBOutlet weak var startDateLabel: UILabel! 35 | @IBOutlet weak var endDateLabel: UILabel! 36 | 37 | override func prepareForReuse() { 38 | super.prepareForReuse() 39 | 40 | self.selectionStyle = .None 41 | } 42 | } 43 | 44 | // MARK: TableViewCell Configurations 45 | extension EventTableViewCell: ATTableViewCellProtocol { 46 | typealias ModelType = Event 47 | 48 | static func height(event: ModelType) -> CGFloat { 49 | return 265 50 | } 51 | 52 | func configureCell(event: ModelType) { 53 | self.topImageView.image = UIImage(named: event.imageName) 54 | 55 | self.titleLabel.text = event.name 56 | self.starRatingView.value = CGFloat(event.rating) 57 | 58 | let dateFormatter = NSDateFormatter() 59 | dateFormatter.locale = NSLocale(localeIdentifier: "en_US") 60 | dateFormatter.dateFormat = "DDD, MMM dd, yyyy" 61 | 62 | self.startDateLabel.text = "-" 63 | if let startDate = event.startDate { 64 | self.startDateLabel.text = "\(dateFormatter.stringFromDate(startDate))" 65 | } 66 | 67 | self.endDateLabel.text = "-" 68 | if let endDate = event.startDate { 69 | self.endDateLabel.text = "\(dateFormatter.stringFromDate(endDate))" 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /Demo/Demo/TableViewCells/EventTableViewCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 34 | 43 | 52 | 61 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | -------------------------------------------------------------------------------- /Demo/Demo/TableViewCells/HotelTableViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 PHUNG ANH TUAN. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | import UIKit 23 | import ATTableView 24 | import HCSStarRatingView 25 | 26 | class HotelTableViewCell: UITableViewCell { 27 | // MARK: - IBOutlets 28 | @IBOutlet weak var topImageView: UIImageView! 29 | @IBOutlet weak var ratingPointLabel: UILabel! 30 | @IBOutlet weak var ratingTextLabel: UILabel! 31 | @IBOutlet weak var titleLabel: UILabel! 32 | @IBOutlet weak var starRatingView: HCSStarRatingView! 33 | @IBOutlet weak var priceLabel: UILabel! 34 | 35 | override func prepareForReuse() { 36 | super.prepareForReuse() 37 | 38 | self.selectionStyle = .None 39 | } 40 | } 41 | 42 | // MARK: TableViewCell Configurations 43 | extension HotelTableViewCell: ATTableViewCellProtocol { 44 | typealias ModelType = Hotel 45 | 46 | static func height(hotel: ModelType) -> CGFloat { 47 | return 250 48 | } 49 | 50 | func configureCell(hotel: ModelType) { 51 | self.titleLabel.text = hotel.name 52 | self.topImageView.image = UIImage(named: hotel.imageName) 53 | self.starRatingView.value = CGFloat(hotel.rating) 54 | self.ratingPointLabel.text = "\(hotel.userRating)" 55 | self.priceLabel.text = "\(hotel.price) $" 56 | } 57 | } -------------------------------------------------------------------------------- /Demo/Demo/TableViewCells/HotelTableViewCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | SFUIDisplay-Medium 10 | 11 | 12 | SFUIText-Regular 13 | SFUIText-Regular 14 | SFUIText-Regular 15 | SFUIText-Regular 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 84 | 94 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | -------------------------------------------------------------------------------- /Demo/Demo/TableViewCells/OfferTableViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GoLocalListTableViewCell.swift 3 | // goru 4 | // 5 | // Created by Pham Ba Tho on 18/11/15. 6 | // Copyright © 2015 Silicon Straits. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class OfferTableViewCell: UITableViewCell { 12 | // MARK: - IBOutlets 13 | @IBOutlet weak var topImageView: UIImageView! 14 | @IBOutlet weak var titleLabel: UILabel! 15 | @IBOutlet weak var descriptionLabel: UILabel! 16 | @IBOutlet weak var dateExpiresLabel: UILabel! 17 | 18 | override func prepareForReuse() { 19 | super.prepareForReuse() 20 | 21 | self.selectionStyle = .None 22 | self.topImageView.sd_cancelCurrentImageLoad() 23 | } 24 | } 25 | 26 | // MARK: TableViewCell Configurations 27 | extension OfferTableViewCell: StatefulTableViewCellProtocol { 28 | func configureCell(model: AnyObject) { 29 | guard let offer = model as? Offer else { return } 30 | 31 | self.titleLabel.text = offer.name 32 | self.descriptionLabel.text = offer.description 33 | 34 | if let expiredDate = offer.expiredDate { 35 | self.dateExpiresLabel.text = expiredDate.ex_toString("MMM dd, yyyy") 36 | } 37 | 38 | self.topImageView.sd_setImageWithURL(NSURL(string: offer.image), placeholderImage: UIImage(named: "meshup-background-placeholder")) 39 | } 40 | } -------------------------------------------------------------------------------- /Demo/Demo/TableViewCells/OfferTableViewCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | SFUIDisplay-Light 11 | 12 | 13 | SFUIDisplay-Regular 14 | 15 | 16 | SFUIText-Medium 17 | 18 | 19 | SFUIText-Regular 20 | SFUIText-Regular 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 94 | 101 | 111 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | -------------------------------------------------------------------------------- /Demo/Demo/TableViewCells/RestaurantTableViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 PHUNG ANH TUAN. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | import UIKit 23 | import ATTableView 24 | import HCSStarRatingView 25 | 26 | class RestaurantTableViewCell: UITableViewCell { 27 | // MARK: - IBOutlets 28 | @IBOutlet weak var topImageView: UIImageView! 29 | @IBOutlet weak var titleLabel: UILabel! 30 | @IBOutlet weak var reviewLabel: UILabel! 31 | @IBOutlet weak var starRatingView: HCSStarRatingView! 32 | 33 | override func prepareForReuse() { 34 | super.prepareForReuse() 35 | 36 | self.selectionStyle = .None 37 | } 38 | } 39 | 40 | // MARK: TableViewCell Configurations 41 | extension RestaurantTableViewCell: ATTableViewCellProtocol { 42 | typealias ModelType = Restaurant 43 | 44 | static func height(restaurant: ModelType) -> CGFloat { 45 | return 230 46 | } 47 | 48 | func configureCell(restaurant: ModelType) { 49 | self.titleLabel.text = restaurant.name 50 | self.reviewLabel.text = "\(restaurant.numberOfReviews) review" + (restaurant.numberOfReviews > 1 ? "s" : "") 51 | self.topImageView.image = UIImage(named: restaurant.imageName) 52 | self.starRatingView.value = CGFloat(restaurant.rating) 53 | } 54 | } -------------------------------------------------------------------------------- /Demo/Demo/TableViewCells/RestaurantTableViewCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | -------------------------------------------------------------------------------- /Demo/Demo/TableViewCells/TipTableViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 PHUNG ANH TUAN. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | import UIKit 23 | import ATTableView 24 | 25 | class TipTableViewCell: UITableViewCell { 26 | // MARK: - IBOutlets 27 | @IBOutlet weak var nameLabel: UILabel! 28 | 29 | override func prepareForReuse() { 30 | super.prepareForReuse() 31 | 32 | self.selectionStyle = .None 33 | } 34 | } 35 | 36 | // MARK: TableViewCell Configurations 37 | extension TipTableViewCell: ATTableViewCellProtocol { 38 | typealias ModelType = Tip 39 | 40 | static func height(tip: ModelType) -> CGFloat { 41 | return 60 42 | } 43 | 44 | func configureCell(tip: ModelType) { 45 | self.nameLabel.text = tip.name 46 | } 47 | } -------------------------------------------------------------------------------- /Demo/Demo/TableViewCells/TipTableViewCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /Demo/Demo/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 PHUNG ANH TUAN. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | import UIKit 23 | import ATTableView 24 | import SwiftyJSON 25 | 26 | enum ModelType: Int { 27 | case Restaurant, Hotel, Tip, Event 28 | } 29 | 30 | class ViewController: UIViewController { 31 | @IBOutlet var tableView: ATTableView! 32 | 33 | override func viewDidLoad() { 34 | super.viewDidLoad() 35 | 36 | self.title = "ATTableView" 37 | 38 | self.tableView.register(RestaurantTableViewCell.self) 39 | self.tableView.register(HotelTableViewCell.self) 40 | self.tableView.register(EventTableViewCell.self) 41 | self.tableView.register(TipTableViewCell.self) 42 | 43 | self.tableView.addObjects(self.generateModels()) 44 | 45 | self.tableView.onDidSelectItem = { item in 46 | // Do something here. 47 | print(item) 48 | } 49 | } 50 | 51 | // Load sample data from local json file. 52 | func generateModels() -> [AnyObject] { 53 | var models = [AnyObject]() 54 | 55 | let path = NSBundle.mainBundle().pathForResource("data", ofType: "json") 56 | let data = NSData(contentsOfFile: path!)! 57 | let json = JSON(data: data) 58 | 59 | for (_, subJson) in json { 60 | if let type = ModelType(rawValue: subJson["type"].intValue) { 61 | switch type { 62 | case .Restaurant: 63 | models.append(Restaurant(json: subJson)) 64 | case .Hotel: 65 | models.append(Hotel(json: subJson)) 66 | case .Tip: 67 | models.append(Tip(json: subJson)) 68 | case .Event: 69 | models.append(Event(json: subJson)) 70 | } 71 | } 72 | } 73 | 74 | return models 75 | } 76 | 77 | } 78 | 79 | -------------------------------------------------------------------------------- /Demo/Demo/data.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "type": 0, 4 | "name": "Restaurant 1", 5 | "imageName": "bg_4", 6 | "numberOfReviews": 10, 7 | "rating": 4.5 8 | }, 9 | { 10 | "type": 0, 11 | "name": "Restaurant 2", 12 | "imageName": "bg_6", 13 | "numberOfReviews": 20, 14 | "rating": 4.5 15 | }, 16 | { 17 | "type": 1, 18 | "name": "Hotel 1", 19 | "imageName": "bg_1", 20 | "price": 300, 21 | "userRating": 9.5, 22 | "rating": 4 23 | }, 24 | { 25 | "type": 1, 26 | "name": "Hotel 2", 27 | "imageName": "bg_2", 28 | "price": 200, 29 | "userRating": 9.5, 30 | "rating": 4 31 | }, 32 | { 33 | "type": 3, 34 | "name": "Event 1", 35 | "imageName": "bg_5", 36 | "rating": 4, 37 | "startDate": "20161221", 38 | "endateDate": "20171221", 39 | }, 40 | { 41 | "type": 3, 42 | "name": "Event 2", 43 | "imageName": "bg_3", 44 | "rating": 5, 45 | "startDate": "20161116", 46 | "endateDate": "20171116", 47 | }, 48 | { 49 | "type": 2, 50 | "name": "Tip Tip Tip 1", 51 | }, 52 | { 53 | "type": 2, 54 | "name": "Tip Tip Tip 2", 55 | }, 56 | ] -------------------------------------------------------------------------------- /Demo/Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, '8.0' 2 | 3 | source 'https://github.com/CocoaPods/Specs.git' 4 | 5 | # ignore all warnings from all pods 6 | inhibit_all_warnings! 7 | 8 | # wrap all Pods into framework, then you can import directly in Swift file, no need to use Bridging-Header. 9 | # This was added from CocoaPods 0.36, to support libraries is written by Swift. 10 | use_frameworks! 11 | 12 | pod 'ATTableView', :path => '../' 13 | 14 | pod 'HCSStarRatingView' 15 | pod 'LoremIpsum', '~> 1.0.0' 16 | pod 'SwiftyJSON', '~> 2.3.2' 17 | -------------------------------------------------------------------------------- /Demo/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - ATTableView (1.1) 3 | - HCSStarRatingView (1.4.3) 4 | - LoremIpsum (1.0.0) 5 | - SwiftyJSON (2.3.2) 6 | 7 | DEPENDENCIES: 8 | - ATTableView (from `../`) 9 | - HCSStarRatingView 10 | - LoremIpsum (~> 1.0.0) 11 | - SwiftyJSON (~> 2.3.2) 12 | 13 | EXTERNAL SOURCES: 14 | ATTableView: 15 | :path: ../ 16 | 17 | SPEC CHECKSUMS: 18 | ATTableView: 6dc6dad4ae43685edbddc42ef296f1261c4bd387 19 | HCSStarRatingView: bada6ae98258c3019531e0218030e2d5ad10765a 20 | LoremIpsum: 9029c55d36501b2ee0b05cc9ecda11d3a0479160 21 | SwiftyJSON: 04ccea08915aa0109039157c7974cf0298da292a 22 | 23 | COCOAPODS: 0.39.0 24 | -------------------------------------------------------------------------------- /Demo/Pods/Local Podspecs/LazyTableView.podspec.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "LazyTableView", 3 | "version": "1.0", 4 | "summary": "A lazy way for smart developers to deal with UITableView.", 5 | "description": "How many times do you have to implement UITableViewDatasource and UITableViewDelegate?\nIs it boring? And how to deal with different UITableViewCells in one TableView?\n\nYou're smart so you need to find a smart way to do it.\nLazyTableView is for you, it's easy to display model in UITableView. Also support different UITableViewCells.", 6 | "homepage": "https://github.com/tuanphung/LazyTableView", 7 | "license": "MIT", 8 | "authors": { 9 | "Tuan Phung": "tuanphunglk@gmail.com" 10 | }, 11 | "social_media_url": "https://twitter.com/tuanphunglk", 12 | "platforms": { 13 | "ios": "8.0" 14 | }, 15 | "source": { 16 | "git": "https://github.com/tuanphung/LazyTableView.git", 17 | "tag": "1.0" 18 | }, 19 | "source_files": "Source/*.swift", 20 | "requires_arc": true 21 | } 22 | -------------------------------------------------------------------------------- /Demo/Pods/Local Podspecs/ReactiveTableView.podspec.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ReactiveTableView", 3 | "version": "0.1", 4 | "summary": "An extension allow you present an alert with new UIAlertController from any ViewController quickly.", 5 | "description": "Allow you present an UIAlertController with one of two styles (Alert or ActionSheet).\nQuickly, Simply in use, and Event handling by closure.", 6 | "homepage": "https://github.com/tuanphung/ReactiveTableView", 7 | "license": "MIT", 8 | "authors": { 9 | "Tuan Phung": "tuanphunglk@gmail.com" 10 | }, 11 | "social_media_url": "https://twitter.com/tuanphunglk", 12 | "platforms": { 13 | "ios": "8.0" 14 | }, 15 | "source": { 16 | "git": "https://github.com/tuanphung/ReactiveTableView.git", 17 | "tag": "0.1" 18 | }, 19 | "source_files": "Source/*.swift", 20 | "requires_arc": true 21 | } 22 | -------------------------------------------------------------------------------- /Demo/Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - ATTableView (1.1) 3 | - HCSStarRatingView (1.4.3) 4 | - LoremIpsum (1.0.0) 5 | - SwiftyJSON (2.3.2) 6 | 7 | DEPENDENCIES: 8 | - ATTableView (from `../`) 9 | - HCSStarRatingView 10 | - LoremIpsum (~> 1.0.0) 11 | - SwiftyJSON (~> 2.3.2) 12 | 13 | EXTERNAL SOURCES: 14 | ATTableView: 15 | :path: ../ 16 | 17 | SPEC CHECKSUMS: 18 | ATTableView: 6dc6dad4ae43685edbddc42ef296f1261c4bd387 19 | HCSStarRatingView: bada6ae98258c3019531e0218030e2d5ad10765a 20 | LoremIpsum: 9029c55d36501b2ee0b05cc9ecda11d3a0479160 21 | SwiftyJSON: 04ccea08915aa0109039157c7974cf0298da292a 22 | 23 | COCOAPODS: 0.39.0 24 | -------------------------------------------------------------------------------- /Demo/Pods/Pods.xcodeproj/xcshareddata/xcschemes/LazyTableView.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 45 | 46 | 52 | 53 | 55 | 56 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /Demo/Pods/Pods.xcodeproj/xcshareddata/xcschemes/ReactiveTableView.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 47 | 48 | 54 | 55 | 57 | 58 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /Demo/Pods/Target Support Files/Pods/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Demo/Pods/Target Support Files/Pods/Pods-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## ATTableView 5 | 6 | The MIT License (MIT) 7 | 8 | Copyright (c) 2016 tuanphung 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all 18 | copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | 28 | 29 | ## HCSStarRatingView 30 | 31 | Copyright (c) 2015 Hugo Sousa 32 | 33 | Permission is hereby granted, free of charge, to any person obtaining a copy 34 | of this software and associated documentation files (the "Software"), to deal 35 | in the Software without restriction, including without limitation the rights 36 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 37 | copies of the Software, and to permit persons to whom the Software is 38 | furnished to do so, subject to the following conditions: 39 | 40 | The above copyright notice and this permission notice shall be included in 41 | all copies or substantial portions of the Software. 42 | 43 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 44 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 45 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 46 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 47 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 48 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 49 | THE SOFTWARE. 50 | 51 | 52 | ## LoremIpsum 53 | 54 | Copyright (c) 2013 Lukas Kubanek. 55 | 56 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 57 | 58 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 59 | 60 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 61 | 62 | ## SwiftyJSON 63 | 64 | The MIT License (MIT) 65 | 66 | Copyright (c) 2014 Ruoyu Fu 67 | 68 | Permission is hereby granted, free of charge, to any person obtaining a copy 69 | of this software and associated documentation files (the "Software"), to deal 70 | in the Software without restriction, including without limitation the rights 71 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 72 | copies of the Software, and to permit persons to whom the Software is 73 | furnished to do so, subject to the following conditions: 74 | 75 | The above copyright notice and this permission notice shall be included in 76 | all copies or substantial portions of the Software. 77 | 78 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 79 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 80 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 81 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 82 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 83 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 84 | THE SOFTWARE. 85 | 86 | Generated by CocoaPods - http://cocoapods.org 87 | -------------------------------------------------------------------------------- /Demo/Pods/Target Support Files/Pods/Pods-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | The MIT License (MIT) 18 | 19 | Copyright (c) 2016 tuanphung 20 | 21 | Permission is hereby granted, free of charge, to any person obtaining a copy 22 | of this software and associated documentation files (the "Software"), to deal 23 | in the Software without restriction, including without limitation the rights 24 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 25 | copies of the Software, and to permit persons to whom the Software is 26 | furnished to do so, subject to the following conditions: 27 | 28 | The above copyright notice and this permission notice shall be included in all 29 | copies or substantial portions of the Software. 30 | 31 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 32 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 33 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 34 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 35 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 36 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 37 | SOFTWARE. 38 | 39 | Title 40 | ATTableView 41 | Type 42 | PSGroupSpecifier 43 | 44 | 45 | FooterText 46 | Copyright (c) 2015 Hugo Sousa 47 | 48 | Permission is hereby granted, free of charge, to any person obtaining a copy 49 | of this software and associated documentation files (the "Software"), to deal 50 | in the Software without restriction, including without limitation the rights 51 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 52 | copies of the Software, and to permit persons to whom the Software is 53 | furnished to do so, subject to the following conditions: 54 | 55 | The above copyright notice and this permission notice shall be included in 56 | all copies or substantial portions of the Software. 57 | 58 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 59 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 60 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 61 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 62 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 63 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 64 | THE SOFTWARE. 65 | 66 | Title 67 | HCSStarRatingView 68 | Type 69 | PSGroupSpecifier 70 | 71 | 72 | FooterText 73 | Copyright (c) 2013 Lukas Kubanek. 74 | 75 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 76 | 77 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 78 | 79 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 80 | Title 81 | LoremIpsum 82 | Type 83 | PSGroupSpecifier 84 | 85 | 86 | FooterText 87 | The MIT License (MIT) 88 | 89 | Copyright (c) 2014 Ruoyu Fu 90 | 91 | Permission is hereby granted, free of charge, to any person obtaining a copy 92 | of this software and associated documentation files (the "Software"), to deal 93 | in the Software without restriction, including without limitation the rights 94 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 95 | copies of the Software, and to permit persons to whom the Software is 96 | furnished to do so, subject to the following conditions: 97 | 98 | The above copyright notice and this permission notice shall be included in 99 | all copies or substantial portions of the Software. 100 | 101 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 102 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 103 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 104 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 105 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 106 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 107 | THE SOFTWARE. 108 | 109 | Title 110 | SwiftyJSON 111 | Type 112 | PSGroupSpecifier 113 | 114 | 115 | FooterText 116 | Generated by CocoaPods - http://cocoapods.org 117 | Title 118 | 119 | Type 120 | PSGroupSpecifier 121 | 122 | 123 | StringsTable 124 | Acknowledgements 125 | Title 126 | Acknowledgements 127 | 128 | 129 | -------------------------------------------------------------------------------- /Demo/Pods/Target Support Files/Pods/Pods-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods : NSObject 3 | @end 4 | @implementation PodsDummy_Pods 5 | @end 6 | -------------------------------------------------------------------------------- /Demo/Pods/Target Support Files/Pods/Pods-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 5 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 6 | 7 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 8 | 9 | install_framework() 10 | { 11 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 12 | local source="${BUILT_PRODUCTS_DIR}/$1" 13 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 14 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 15 | elif [ -r "$1" ]; then 16 | local source="$1" 17 | fi 18 | 19 | local destination="${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 20 | 21 | if [ -L "${source}" ]; then 22 | echo "Symlinked..." 23 | source="$(readlink "${source}")" 24 | fi 25 | 26 | # use filter instead of exclude so missing patterns dont' throw errors 27 | echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 28 | rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 29 | 30 | local basename 31 | basename="$(basename -s .framework "$1")" 32 | binary="${destination}/${basename}.framework/${basename}" 33 | if ! [ -r "$binary" ]; then 34 | binary="${destination}/${basename}" 35 | fi 36 | 37 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 38 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 39 | strip_invalid_archs "$binary" 40 | fi 41 | 42 | # Resign the code if required by the build settings to avoid unstable apps 43 | code_sign_if_enabled "${destination}/$(basename "$1")" 44 | 45 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 46 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 47 | local swift_runtime_libs 48 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) 49 | for lib in $swift_runtime_libs; do 50 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 51 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 52 | code_sign_if_enabled "${destination}/${lib}" 53 | done 54 | fi 55 | } 56 | 57 | # Signs a framework with the provided identity 58 | code_sign_if_enabled() { 59 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 60 | # Use the current code_sign_identitiy 61 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 62 | echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements \"$1\"" 63 | /usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements "$1" 64 | fi 65 | } 66 | 67 | # Strip invalid architectures 68 | strip_invalid_archs() { 69 | binary="$1" 70 | # Get architectures for current file 71 | archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)" 72 | stripped="" 73 | for arch in $archs; do 74 | if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then 75 | # Strip non-valid architectures in-place 76 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1 77 | stripped="$stripped $arch" 78 | fi 79 | done 80 | if [[ "$stripped" ]]; then 81 | echo "Stripped $binary of architectures:$stripped" 82 | fi 83 | } 84 | 85 | 86 | if [[ "$CONFIGURATION" == "Debug" ]]; then 87 | install_framework "Pods/ATTableView.framework" 88 | install_framework "Pods/HCSStarRatingView.framework" 89 | install_framework "Pods/LoremIpsum.framework" 90 | install_framework "Pods/SwiftyJSON.framework" 91 | fi 92 | if [[ "$CONFIGURATION" == "Release" ]]; then 93 | install_framework "Pods/ATTableView.framework" 94 | install_framework "Pods/HCSStarRatingView.framework" 95 | install_framework "Pods/LoremIpsum.framework" 96 | install_framework "Pods/SwiftyJSON.framework" 97 | fi 98 | -------------------------------------------------------------------------------- /Demo/Pods/Target Support Files/Pods/Pods-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 5 | 6 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 7 | > "$RESOURCES_TO_COPY" 8 | 9 | XCASSET_FILES=() 10 | 11 | realpath() { 12 | DIRECTORY="$(cd "${1%/*}" && pwd)" 13 | FILENAME="${1##*/}" 14 | echo "$DIRECTORY/$FILENAME" 15 | } 16 | 17 | install_resource() 18 | { 19 | case $1 in 20 | *.storyboard) 21 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc ${PODS_ROOT}/$1 --sdk ${SDKROOT}" 22 | ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc" "${PODS_ROOT}/$1" --sdk "${SDKROOT}" 23 | ;; 24 | *.xib) 25 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib ${PODS_ROOT}/$1 --sdk ${SDKROOT}" 26 | ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib" "${PODS_ROOT}/$1" --sdk "${SDKROOT}" 27 | ;; 28 | *.framework) 29 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 30 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 31 | echo "rsync -av ${PODS_ROOT}/$1 ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 32 | rsync -av "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 33 | ;; 34 | *.xcdatamodel) 35 | echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1"`.mom\"" 36 | xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodel`.mom" 37 | ;; 38 | *.xcdatamodeld) 39 | echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd\"" 40 | xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd" 41 | ;; 42 | *.xcmappingmodel) 43 | echo "xcrun mapc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm\"" 44 | xcrun mapc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm" 45 | ;; 46 | *.xcassets) 47 | ABSOLUTE_XCASSET_FILE=$(realpath "${PODS_ROOT}/$1") 48 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 49 | ;; 50 | /*) 51 | echo "$1" 52 | echo "$1" >> "$RESOURCES_TO_COPY" 53 | ;; 54 | *) 55 | echo "${PODS_ROOT}/$1" 56 | echo "${PODS_ROOT}/$1" >> "$RESOURCES_TO_COPY" 57 | ;; 58 | esac 59 | } 60 | 61 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 62 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 63 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 64 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 65 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 66 | fi 67 | rm -f "$RESOURCES_TO_COPY" 68 | 69 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] 70 | then 71 | case "${TARGETED_DEVICE_FAMILY}" in 72 | 1,2) 73 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 74 | ;; 75 | 1) 76 | TARGET_DEVICE_ARGS="--target-device iphone" 77 | ;; 78 | 2) 79 | TARGET_DEVICE_ARGS="--target-device ipad" 80 | ;; 81 | *) 82 | TARGET_DEVICE_ARGS="--target-device mac" 83 | ;; 84 | esac 85 | 86 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 87 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 88 | while read line; do 89 | if [[ $line != "`realpath $PODS_ROOT`*" ]]; then 90 | XCASSET_FILES+=("$line") 91 | fi 92 | done <<<"$OTHER_XCASSETS" 93 | 94 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${IPHONEOS_DEPLOYMENT_TARGET}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 95 | fi 96 | -------------------------------------------------------------------------------- /Demo/Pods/Target Support Files/Pods/Pods-umbrella.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | FOUNDATION_EXPORT double PodsVersionNumber; 5 | FOUNDATION_EXPORT const unsigned char PodsVersionString[]; 6 | 7 | -------------------------------------------------------------------------------- /Demo/Pods/Target Support Files/Pods/Pods.debug.xcconfig: -------------------------------------------------------------------------------- 1 | EMBEDDED_CONTENT_CONTAINS_SWIFT = YES 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 4 | OTHER_CFLAGS = $(inherited) -iquote "$CONFIGURATION_BUILD_DIR/ATTableView.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/HCSStarRatingView.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/LoremIpsum.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/SwiftyJSON.framework/Headers" 5 | OTHER_LDFLAGS = $(inherited) -framework "ATTableView" -framework "HCSStarRatingView" -framework "LoremIpsum" -framework "SwiftyJSON" 6 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 7 | PODS_FRAMEWORK_BUILD_PATH = $(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Pods 8 | PODS_ROOT = ${SRCROOT}/Pods -------------------------------------------------------------------------------- /Demo/Pods/Target Support Files/Pods/Pods.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods { 2 | umbrella header "Pods-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Demo/Pods/Target Support Files/Pods/Pods.release.xcconfig: -------------------------------------------------------------------------------- 1 | EMBEDDED_CONTENT_CONTAINS_SWIFT = YES 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 4 | OTHER_CFLAGS = $(inherited) -iquote "$CONFIGURATION_BUILD_DIR/ATTableView.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/HCSStarRatingView.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/LoremIpsum.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/SwiftyJSON.framework/Headers" 5 | OTHER_LDFLAGS = $(inherited) -framework "ATTableView" -framework "HCSStarRatingView" -framework "LoremIpsum" -framework "SwiftyJSON" 6 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 7 | PODS_FRAMEWORK_BUILD_PATH = $(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Pods 8 | PODS_ROOT = ${SRCROOT}/Pods -------------------------------------------------------------------------------- /Demo/data.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanphung/SmartTableView/1c7d16955b714d1af734c71c0718d57bc99b9837/Demo/data.json -------------------------------------------------------------------------------- /Doc/Assets/Demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanphung/SmartTableView/1c7d16955b714d1af734c71c0718d57bc99b9837/Doc/Assets/Demo.gif -------------------------------------------------------------------------------- /Doc/Assets/LazyWay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanphung/SmartTableView/1c7d16955b714d1af734c71c0718d57bc99b9837/Doc/Assets/LazyWay.png -------------------------------------------------------------------------------- /Doc/Assets/OldWay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tuanphung/SmartTableView/1c7d16955b714d1af734c71c0718d57bc99b9837/Doc/Assets/OldWay.png -------------------------------------------------------------------------------- /Doc/Examples.md: -------------------------------------------------------------------------------- 1 | #Examples 2 | 3 | ## Setup Your Model 4 | Nothing special, just reuse models you made before. 5 | 6 | For example, I created two models below: 7 | ```swift 8 | class Restaurant { 9 | // Properties 10 | var name: String = "" 11 | var imageName: String = "" 12 | var numberOfReviews: Int = 0 13 | var rating: Double = 0 14 | } 15 | ``` 16 | 17 | ```swift 18 | class Hotel { 19 | // Properties 20 | var name: String = "" 21 | var imageName: String = "" 22 | var price: Double = 0 23 | var userRating: Double = 0 24 | var rating: Double = 0 25 | } 26 | ``` 27 | 28 | ## Setup your UITableViewCell 29 | ATTableViewCellProtocol have already supported Generic and Associated types. So, no type casts required.
30 | ModelType can be Any. Your cell will automatically pick up instances of ModelType and display, other ModelType will be ignored. 31 | 32 | `By default, your cell Identifier is same to ClassName. If you use XIB to layout cell, you have to set Identifier is your ClassName.` 33 | 34 | ### RestaurantTableViewCell 35 | ```swift 36 | class RestaurantTableViewCell: UITableViewCell { 37 | // MARK: - IBOutlets 38 | @IBOutlet weak var topImageView: UIImageView! 39 | @IBOutlet weak var titleLabel: UILabel! 40 | @IBOutlet weak var reviewLabel: UILabel! 41 | @IBOutlet weak var starRatingView: HCSStarRatingView! 42 | } 43 | 44 | extension RestaurantTableViewCell: ATTableViewCellProtocol { 45 | typealias ModelType = Restaurant 46 | 47 | static func height(restaurant: ModelType) -> CGFloat { 48 | return 230 49 | } 50 | 51 | func configureCell(restaurant: ModelType) { 52 | self.titleLabel.text = restaurant.name 53 | self.reviewLabel.text = "\(restaurant.numberOfReviews) review" + (restaurant.numberOfReviews > 1 ? "s" : "") 54 | self.topImageView.image = UIImage(named: restaurant.imageName) 55 | self.starRatingView.value = CGFloat(restaurant.rating) 56 | } 57 | } 58 | ``` 59 | `RestaurantTableViewCell` will only accept `Restaurant` model. Others will be ignored. 60 | 61 | ### HotelTableViewCell 62 | ```swift 63 | class HotelTableViewCell: UITableViewCell { 64 | // MARK: - IBOutlets 65 | @IBOutlet weak var topImageView: UIImageView! 66 | @IBOutlet weak var ratingPointLabel: UILabel! 67 | @IBOutlet weak var ratingTextLabel: UILabel! 68 | @IBOutlet weak var titleLabel: UILabel! 69 | @IBOutlet weak var starRatingView: HCSStarRatingView! 70 | @IBOutlet weak var priceLabel: UILabel! 71 | } 72 | 73 | extension HotelTableViewCell: ATTableViewCellProtocol { 74 | typealias ModelType = Hotel 75 | 76 | static func height(hotel: ModelType) -> CGFloat { 77 | return 250 78 | } 79 | 80 | func configureCell(hotel: ModelType) { 81 | self.titleLabel.text = hotel.name 82 | self.topImageView.image = UIImage(named: hotel.imageName) 83 | self.starRatingView.value = CGFloat(hotel.rating) 84 | self.ratingPointLabel.text = "\(hotel.userRating)" 85 | self.priceLabel.text = "\(hotel.price) $" 86 | } 87 | } 88 | ``` 89 | `HotelTableViewCell` will only accept `Hotel` model. Others will be ignored. 90 | 91 | ## Displaying Models 92 | Finally! Your cells are ready to use. Now, let's display models on cells, actually it's really easy.
93 | 94 | In your ViewController: 95 | 96 | 1.Register your cells: 97 | ```swift 98 | self.tableView.register(RestaurantTableViewCell.self) 99 | self.tableView.register(HotelTableViewCell.self) 100 | ``` 101 | 2.Push your models: 102 | ```swift 103 | let restaurant = Restaurant() 104 | ... // Some extra initializion 105 | 106 | let hotel = Hotel() 107 | ... // Some extra initializion 108 | 109 | self.tableView.addObjects([restaurant, hotel]) 110 | ``` 111 | 112 | 3.Enjoy it! 113 | 114 | ## Handle click event on Cell 115 | ```swift 116 | self.tableView.onDidSelectItem = { [weak self] item in 117 | // Handle selected item here 118 | ... 119 | } 120 | ``` 121 | 122 | ## Lazy loading models from Network 123 | Coming soon... 124 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 tuanphung 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #ATTableView 2 | A lazy way for smart developers to deal with UITableView. 3 | 4 | Why ATTableView? 5 | -------------- 6 | How many times do you have to implement UITableViewDatasource and UITableViewDelegate?
7 | Is it boring? And how to deal with different UITableViewCells in one TableView? 8 | 9 | > You're smart, so you need a smart way to do it.
10 | ATTableView is for you, it's easy to display model in UITableView. Also support different UITableViewCells. 11 | 12 | ### Traditional way 13 | ![alt tag] (/Doc/Assets/OldWay.png) 14 | 15 | Your ViewController has to: 16 | - Implement a lot of methods to adapt UITableViewDatasource and UITableViewDelegate. 17 | - Do some sucked things like `if else` condition if you need to display different UITableViewCells in one TableView. 18 | - Maintain models. 19 | - Hard to reuse UITableView. 20 | 21 | ### Lazy way 22 | ![alt tag] (/Doc/Assets/LazyWay.png) 23 | 24 | So now: 25 | - Don't need to implement any methods of UITableViewDatasource and UITableViewDelegate. Most should be done in UITableViewCell. 26 | - It's super easy to reuse UITableViewCell. 27 | - Models are managed by ATTableView, not ViewController anymore. 28 | - Allow displaying UITableViewCells base on model type without pain. After some setup, just push models to ATTableView, then cell will automatically pick up models and display them. 29 | - Support Generic and Associated types. So no type casts required. 30 | 31 | Introduce ATTableViewCellProtocol 32 | -------------- 33 | ```swift 34 | public protocol ATTableViewCellProtocol: NSObjectProtocol { 35 | typealias ModelType 36 | 37 | // Optional, default is ClassName 38 | static func reuseIdentifier() -> String 39 | 40 | // Optional, default is ClassName 41 | static func nibName() -> String? 42 | 43 | // Optional, default is `UITableViewAutomaticDimension` 44 | static func height(model: ModelType) -> CGFloat 45 | 46 | // Define how to map properties of model to UI. 47 | // This method must be implemented. 48 | func configureCell(model: ModelType) 49 | } 50 | ``` 51 | ATTableView requires some implementations in your cell, so your cell must implement this protocol.
52 | * Don't need to implement all, some methods already have default implementation. 53 | * No type casts required. ModelType is based on your definition. 54 | 55 | Sample Project 56 | -------------- 57 | There's a sample project in the Demo directory. Or follow the instructions [here] (Doc/Examples.md).
58 | Have fun! 59 | 60 | Usage 61 | -------------- 62 | After [some setup](Doc/Examples.md), using ATTableView is really simple. In your ViewController, just follow these steps below: 63 | 64 | 1.Register your cells: 65 | ```swift 66 | self.tableView.register(RestaurantTableViewCell.self) 67 | self.tableView.register(HotelTableViewCell.self) 68 | ``` 69 | 2.Push your models: 70 | ```swift 71 | let restaurant = Restaurant() 72 | ... // Some extra initializions 73 | 74 | let hotel = Hotel() 75 | ... // Some extra initializions 76 | 77 | self.tableView.addObjects([restaurant, hotel]) 78 | ``` 79 | 80 | 3.Enjoy it! 81 | 82 | ![alt tag](Doc/Assets/Demo.gif) 83 | 84 | ### Handle click event on Cell 85 | Just easy like this: 86 | ```swift 87 | self.tableView.onDidSelectItem = { [weak self] item in 88 | // Handle selected item here 89 | ... 90 | } 91 | ``` 92 | 93 | ### Lazy loading models from Network 94 | Coming soon... 95 | 96 | Requirements 97 | -------------- 98 | - iOS 8.0+ / Mac OS X 10.9+ 99 | - Xcode 6.4 100 | 101 | Installation 102 | -------------- 103 | [CocoaPods](http://cocoapods.org) is a dependency manager for Cocoa projects. 104 | 105 | CocoaPods 0.36 adds supports for Swift and embedded frameworks. You can install it with the following command: 106 | 107 | ```bash 108 | $ gem install cocoapods 109 | ``` 110 | To integrate ATTableView into your Xcode project using CocoaPods, specify it in your `Podfile`: 111 | 112 | ```ruby 113 | source 'https://github.com/CocoaPods/Specs.git' 114 | platform :ios, '8.0' 115 | use_frameworks! 116 | 117 | pod 'ATTableView', '1.2' 118 | ``` 119 | 120 | Then, run the following command: 121 | 122 | ```bash 123 | $ pod install 124 | ``` 125 | 126 | License 127 | -------------- 128 | ATTableView is released under the MIT license. See LICENSE for details. 129 | -------------------------------------------------------------------------------- /Source/ATSignal.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ATSignal.swift 3 | // Pods 4 | // 5 | // Created by Tuan Phung on 1/10/16. 6 | // 7 | // 8 | 9 | import Foundation 10 | 11 | public class ATSignal { 12 | public var identifier: String 13 | public var associatedObject: Any? 14 | 15 | init(identifider: String, associatedObject: Any?) { 16 | self.identifier = identifider 17 | self.associatedObject = associatedObject 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Source/ATTableView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 PHUNG ANH TUAN. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | import UIKit 23 | 24 | var UITableLoadingViewKey = "UITableLoadingViewKey" 25 | 26 | typealias Mapping = (heightBlock:((model: Any) -> CGFloat), configureCellBlock: (cell: UITableViewCell, model: Any) -> (), identifier: String, modelType: Any.Type) 27 | 28 | public class ATTableViewDelegateConfiguration { 29 | public var scrollViewDidScroll: ((scrollView: UIScrollView) -> ())? 30 | } 31 | 32 | public class ATTableView: UITableView { 33 | public var defaultSection = ATTableViewSection() 34 | 35 | public var delegateConfiguration = ATTableViewDelegateConfiguration() 36 | 37 | public var onDidSelectItem: ((item: Any) -> ())? 38 | 39 | // Abstract the way to implement LoadMore feature. 40 | // Under implementation. 41 | public var shouldLoadMore: Bool = false 42 | private var isLoadingMore = false 43 | public var onLoadMore: (() -> ())? 44 | 45 | private var signalMonitorHandler: ((signal: ATSignal) -> ())? 46 | 47 | public func loadDataCompletedWithItems(items: [Any]) { 48 | self.shouldLoadMore = (items.count == 0) ? false : true 49 | self.addItems(items) 50 | 51 | isLoadingMore = false 52 | } 53 | 54 | // Keep referrence to models, encapsulated into LazyTableViewSection. 55 | private var source = [ATTableViewSection]() 56 | 57 | // Keep all setup for each CellType registered. 58 | private var mappings = [Mapping]() 59 | 60 | // Find registed cell type that accept model. 61 | private func mappingForModel(model: Any) -> Mapping? { 62 | for mapping in mappings { 63 | if mapping.modelType == model.dynamicType { 64 | return mapping 65 | } 66 | } 67 | 68 | return nil 69 | } 70 | 71 | // MARK: - Loading View 72 | public var loadingView: UIView? 73 | public var centerOffset = CGPointZero 74 | 75 | public func showLoadingIndicator(centerOffset: CGPoint = CGPointZero) { 76 | self.centerOffset = centerOffset 77 | 78 | if let loadingView = self.loadingView { 79 | if loadingView.superview == nil { 80 | self.addSubview(loadingView) 81 | } 82 | 83 | loadingView.hidden = false 84 | self.bringSubviewToFront(loadingView) 85 | } 86 | } 87 | 88 | public func hideLoadingIndicator() { 89 | self.loadingView?.hidden = true 90 | } 91 | 92 | public override func layoutSubviews() { 93 | super.layoutSubviews() 94 | 95 | self.adjustSizeOfLoadingIndicator() 96 | } 97 | 98 | func adjustSizeOfLoadingIndicator() { 99 | if let loadingView = self.loadingView { 100 | let bounds = self.frame 101 | loadingView.center = CGPoint(x: bounds.width / 2 + self.centerOffset.x, y: bounds.height / 2 + centerOffset.y) 102 | } 103 | } 104 | 105 | // Initializers 106 | public override init(frame: CGRect, style: UITableViewStyle) { 107 | super.init(frame: frame, style: style) 108 | 109 | self.initialize() 110 | } 111 | 112 | public required init?(coder aDecoder: NSCoder) { 113 | super.init(coder: aDecoder) 114 | 115 | self.initialize() 116 | } 117 | 118 | public func initialize() { 119 | self.dataSource = self 120 | self.delegate = self 121 | self.scrollsToTop = false 122 | 123 | // Auto Setup first section 124 | self.source.append(defaultSection) 125 | } 126 | 127 | public func addSection(section: ATTableViewSection, atIndex index: Int) { 128 | self.source.insert(section, atIndex: index) 129 | } 130 | 131 | public func addSection(section: ATTableViewSection) { 132 | self.source.append(section) 133 | 134 | // Render data 135 | self.reloadData() 136 | } 137 | 138 | public func addItems(items: [Any], section: Int) { 139 | let sectionData = self.source[section] 140 | sectionData.addItems(items) 141 | 142 | // Render data 143 | self.reloadData() 144 | } 145 | 146 | public func addItems(items: [Any]) { 147 | self.addItems(items, section: 0) 148 | } 149 | 150 | // To fix issue `array cannot be bridged from Objective-C` when push array of AnyObject. 151 | // https://forums.developer.apple.com/thread/28678 152 | public func addObjects(objects: [AnyObject]) { 153 | self.addObjects(objects, section: 0) 154 | } 155 | 156 | public func addObjects(objects: [AnyObject], section: Int) { 157 | let section = self.source[section] 158 | section.addItems(objects.map { $0 as AnyObject }) 159 | 160 | // Render data 161 | self.reloadData() 162 | } 163 | 164 | // Register cell, setup some code blocks and store them to execute later. 165 | public func register(cellType: T.Type) { 166 | let identifier = cellType.reuseIdentifier() 167 | 168 | guard let _ = self.dequeueReusableCellWithIdentifier(identifier) else { 169 | // Create block code to execute class method `height:` 170 | // This block will be executed in `tableView:heightForRowAtIndexPath:` 171 | let heightBlock = { (model: Any) -> CGFloat in 172 | if let model = model as? T.ModelType { 173 | return cellType.height(model) 174 | } 175 | return 0 176 | } 177 | 178 | // Create block code to execute method `configureCell:` of cell 179 | // This block will be executed in `tableView:cellForRowAtIndexPath:` 180 | let configureCellBlock = { (cell: UITableViewCell, model: Any) in 181 | if let cell = cell as? T, let model = model as? T.ModelType { 182 | cell.configureCell(model) 183 | } 184 | } 185 | 186 | self.mappings.append(Mapping(heightBlock, configureCellBlock, identifier, T.ModelType.self)) 187 | 188 | if let nibName = cellType.nibName() { 189 | self.registerNib(UINib(nibName: nibName, bundle: nil), forCellReuseIdentifier: identifier) 190 | } 191 | else { 192 | self.registerClass(cellType, forCellReuseIdentifier: identifier) 193 | } 194 | return 195 | } 196 | } 197 | 198 | public func clearAll() { 199 | for section in self.source { 200 | section.clear() 201 | } 202 | 203 | self.reloadData() 204 | } 205 | 206 | public func clearItemsAtSection(section: Int) { 207 | self.source[section].clear() 208 | 209 | self.reloadData() 210 | } 211 | 212 | public override func reloadData() { 213 | 214 | super.reloadData() 215 | } 216 | 217 | public func startMonitorSignal(handler: (signal: ATSignal) -> ()) { 218 | self.signalMonitorHandler = handler 219 | } 220 | 221 | internal func fireSignal(signal: ATSignal) { 222 | self.signalMonitorHandler?(signal: signal) 223 | } 224 | } 225 | 226 | extension ATTableView: UITableViewDataSource { 227 | // Configure sections 228 | public func numberOfSectionsInTableView(tableView: UITableView) -> Int { 229 | return self.source.count 230 | } 231 | 232 | // Configure header for section 233 | public func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? { 234 | return self.source[section].headerTitle 235 | } 236 | 237 | // Configure footer for section 238 | public func tableView(tableView: UITableView, titleForFooterInSection section: Int) -> String? { 239 | return self.source[section].footerTitle 240 | } 241 | 242 | // Configure cells 243 | public func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 244 | return self.source[section].items.count 245 | } 246 | 247 | public func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 248 | let model: Any = self.source[indexPath.section].items[indexPath.row] 249 | 250 | if let mapping = self.mappingForModel(model) { 251 | let cell = tableView.dequeueReusableCellWithIdentifier(mapping.identifier, forIndexPath: indexPath) 252 | mapping.configureCellBlock(cell: cell, model: model) 253 | return cell 254 | 255 | } 256 | return UITableViewCell() 257 | } 258 | 259 | public func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { 260 | let model: Any = self.source[indexPath.section].items[indexPath.row] 261 | 262 | if let mapping = self.mappingForModel(model) { 263 | return mapping.heightBlock(model: model) 264 | } 265 | 266 | return 0 267 | } 268 | } 269 | 270 | extension ATTableView: UITableViewDelegate { 271 | // Customize Section Header 272 | public func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { 273 | return self.source[section].customHeaderView?() 274 | } 275 | 276 | public func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { 277 | return self.source[section].headerHeight 278 | } 279 | 280 | // Customize Section Footer 281 | public func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? { 282 | return self.source[section].customFooterView?() 283 | } 284 | 285 | public func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { 286 | return self.source[section].footerHeight 287 | } 288 | 289 | // Handle actions 290 | public func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { 291 | tableView.deselectRowAtIndexPath(indexPath, animated: true) 292 | 293 | self.onDidSelectItem?(item: self.source[indexPath.section].items[indexPath.row]) 294 | } 295 | 296 | // ScrollViewDelegate 297 | public func scrollViewDidEndDecelerating(scrollView: UIScrollView) { 298 | let currentOffset = scrollView.contentOffset.y 299 | let maximumOffset = scrollView.contentSize.height - scrollView.frame.size.height; 300 | 301 | let threhold = maximumOffset - currentOffset 302 | if threhold <= 10 && (shouldLoadMore && !isLoadingMore) { 303 | isLoadingMore = true 304 | self.onLoadMore?() 305 | } 306 | } 307 | 308 | public func scrollViewDidScroll(scrollView: UIScrollView) { 309 | self.delegateConfiguration.scrollViewDidScroll?(scrollView: scrollView) 310 | } 311 | } -------------------------------------------------------------------------------- /Source/ATTableViewCellProtocol.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 PHUNG ANH TUAN. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | import UIKit 23 | 24 | public protocol ATTableViewCellProtocol: NSObjectProtocol { 25 | typealias ModelType 26 | 27 | // Optional, default is ClassName 28 | static func reuseIdentifier() -> String 29 | 30 | // Optional, default is ClassName 31 | static func nibName() -> String? 32 | 33 | // Draft behaviour 34 | // In case a model is displayed by multiple Cells, use pairCode to match model and cell. 35 | // Paircode only is checked if model have a paircode setup. 36 | // If paircode is not setup in model, just need to check mapping class type. 37 | // If paircode is setup in model, and it's same to cell's paircode, it's matched. Otherwise, cell will not pick up that model to display. 38 | static func pairCode() -> Int? 39 | 40 | // Optional, default is `UITableViewAutomaticDimension` 41 | static func height(model: ModelType) -> CGFloat 42 | 43 | // Define how to map properties of model to UI. 44 | // This method must be implemented. 45 | func configureCell(model: ModelType) 46 | } 47 | 48 | public extension ATTableViewCellProtocol { 49 | static func reuseIdentifier() -> String { return "\(self)" } 50 | 51 | static func nibName() -> String? { return "\(self)" } 52 | 53 | static func nib() -> UINib? { 54 | guard let nibName = nibName() else { return nil } 55 | 56 | return UINib(nibName: nibName, bundle: nil) 57 | } 58 | 59 | static func pairCode() -> Int? { return nil } 60 | 61 | static func height(model: ModelType) -> CGFloat { return UITableViewAutomaticDimension } 62 | } 63 | 64 | public extension UITableViewCell { 65 | public func fireSignal(identifier: String, associatedObject: Any?) { 66 | var view = self.superview 67 | while (view != nil && view!.isKindOfClass(ATTableView.self) == false) { 68 | view = view?.superview 69 | } 70 | 71 | if let tableView = view as? ATTableView { 72 | tableView.fireSignal(ATSignal(identifider: identifier, associatedObject: associatedObject)) 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /Source/ATTableViewSection.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 PHUNG ANH TUAN. All rights reserved. 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE. 21 | 22 | import UIKit 23 | 24 | public class ATTableViewSection { 25 | let DefaultHeaderHeight: CGFloat = 22 26 | let DefaultFooterHeight: CGFloat = 22 27 | 28 | public var headerTitle: String? { 29 | didSet { 30 | // Set default header height in case title != nil and headerHeight is not set. 31 | if let title = self.headerTitle where title != "" && self.headerHeight == 0 { 32 | self.headerHeight = DefaultHeaderHeight 33 | } 34 | } 35 | } 36 | 37 | public var headerHeight: CGFloat = 0.0 38 | public var customHeaderView: (() -> UIView?)? 39 | 40 | public var footerTitle: String? { 41 | didSet { 42 | // Set default footer height in case title != nil and footerHeight is not set. 43 | if let title = self.footerTitle where title != "" && self.footerHeight == 0 { 44 | self.footerHeight = DefaultFooterHeight 45 | } 46 | } 47 | } 48 | 49 | public var footerHeight: CGFloat = 0.0 50 | public var customFooterView: (() -> UIView?)? 51 | 52 | var items: [Any] 53 | 54 | public init(headerTitle: String?, footerTitle: String?, items: [Any]) { 55 | self.headerTitle = headerTitle 56 | self.footerTitle = footerTitle 57 | self.items = items 58 | } 59 | 60 | public convenience init() { 61 | self.init(headerTitle: nil, footerTitle: nil, items: []) 62 | } 63 | 64 | public convenience init(items: [Any]) { 65 | self.init(headerTitle: nil, footerTitle: nil, items: items) 66 | } 67 | 68 | public func getItems() -> [Any] { 69 | return self.items 70 | } 71 | 72 | func addItems(newItems: [Any]?) { 73 | guard let newItems = newItems else { return } 74 | 75 | self.items.appendContentsOf(newItems) 76 | } 77 | 78 | func clear() { 79 | self.items.removeAll() 80 | } 81 | } 82 | --------------------------------------------------------------------------------