├── Example ├── .DS_Store └── JHNoDataEmptyViewDemo │ ├── .DS_Store │ ├── JHNoDataEmptyViewDemo.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcuserdata │ │ │ └── apple.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── apple.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ └── xcschememanagement.plist │ ├── JHNoDataEmptyViewDemo │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── DemoViewController.h │ ├── DemoViewController.m │ ├── Info.plist │ ├── ViewController.h │ ├── ViewController.m │ └── main.m │ └── JHNoDataEmptyViewDemoTests │ ├── Info.plist │ └── JHNoDataEmptyViewDemoTests.m ├── JHNoDataEmptyView.podspec ├── JHNoDataEmptyView ├── JHNoDataEmptyView.h ├── JHNoDataEmptyView.m ├── UICollectionView+JHNoData.h ├── UICollectionView+JHNoData.m ├── UITableView+JHNoData.h └── UITableView+JHNoData.m ├── LICENSE └── README.md /Example/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xjh093/JHNoDataEmptyView/57a0e9a1086744d45f340cb81a01a75af1097d71/Example/.DS_Store -------------------------------------------------------------------------------- /Example/JHNoDataEmptyViewDemo/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xjh093/JHNoDataEmptyView/57a0e9a1086744d45f340cb81a01a75af1097d71/Example/JHNoDataEmptyViewDemo/.DS_Store -------------------------------------------------------------------------------- /Example/JHNoDataEmptyViewDemo/JHNoDataEmptyViewDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 18318CF721C34AA8003EB302 /* DemoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18318CF621C34AA8003EB302 /* DemoViewController.m */; }; 11 | 18944B3921C2179500B472FC /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 18944B3821C2179500B472FC /* AppDelegate.m */; }; 12 | 18944B3C21C2179500B472FC /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18944B3B21C2179500B472FC /* ViewController.m */; }; 13 | 18944B3F21C2179500B472FC /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 18944B3D21C2179500B472FC /* Main.storyboard */; }; 14 | 18944B4121C2179700B472FC /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 18944B4021C2179700B472FC /* Assets.xcassets */; }; 15 | 18944B4421C2179700B472FC /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 18944B4221C2179700B472FC /* LaunchScreen.storyboard */; }; 16 | 18944B4721C2179700B472FC /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 18944B4621C2179700B472FC /* main.m */; }; 17 | 18944B5121C2179700B472FC /* JHNoDataEmptyViewDemoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 18944B5021C2179700B472FC /* JHNoDataEmptyViewDemoTests.m */; }; 18 | 18944B6821C2229A00B472FC /* UITableView+JHNoData.m in Sources */ = {isa = PBXBuildFile; fileRef = 18944B6521C2229A00B472FC /* UITableView+JHNoData.m */; }; 19 | 18944B6921C2229A00B472FC /* UICollectionView+JHNoData.m in Sources */ = {isa = PBXBuildFile; fileRef = 18944B6621C2229A00B472FC /* UICollectionView+JHNoData.m */; }; 20 | 18944B6A21C2229A00B472FC /* JHNoDataEmptyView.m in Sources */ = {isa = PBXBuildFile; fileRef = 18944B6721C2229A00B472FC /* JHNoDataEmptyView.m */; }; 21 | /* End PBXBuildFile section */ 22 | 23 | /* Begin PBXContainerItemProxy section */ 24 | 18944B4D21C2179700B472FC /* PBXContainerItemProxy */ = { 25 | isa = PBXContainerItemProxy; 26 | containerPortal = 18944B2C21C2179500B472FC /* Project object */; 27 | proxyType = 1; 28 | remoteGlobalIDString = 18944B3321C2179500B472FC; 29 | remoteInfo = JHNoDataEmptyViewDemo; 30 | }; 31 | /* End PBXContainerItemProxy section */ 32 | 33 | /* Begin PBXFileReference section */ 34 | 18318CF521C34AA8003EB302 /* DemoViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DemoViewController.h; sourceTree = ""; }; 35 | 18318CF621C34AA8003EB302 /* DemoViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DemoViewController.m; sourceTree = ""; }; 36 | 18944B3421C2179500B472FC /* JHNoDataEmptyViewDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = JHNoDataEmptyViewDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 37 | 18944B3721C2179500B472FC /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 38 | 18944B3821C2179500B472FC /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 39 | 18944B3A21C2179500B472FC /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 40 | 18944B3B21C2179500B472FC /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 41 | 18944B3E21C2179500B472FC /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 42 | 18944B4021C2179700B472FC /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 43 | 18944B4321C2179700B472FC /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 44 | 18944B4521C2179700B472FC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 45 | 18944B4621C2179700B472FC /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 46 | 18944B4C21C2179700B472FC /* JHNoDataEmptyViewDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = JHNoDataEmptyViewDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 47 | 18944B5021C2179700B472FC /* JHNoDataEmptyViewDemoTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JHNoDataEmptyViewDemoTests.m; sourceTree = ""; }; 48 | 18944B5221C2179700B472FC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 49 | 18944B6221C2229A00B472FC /* UITableView+JHNoData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UITableView+JHNoData.h"; sourceTree = ""; }; 50 | 18944B6321C2229A00B472FC /* JHNoDataEmptyView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JHNoDataEmptyView.h; sourceTree = ""; }; 51 | 18944B6421C2229A00B472FC /* UICollectionView+JHNoData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UICollectionView+JHNoData.h"; sourceTree = ""; }; 52 | 18944B6521C2229A00B472FC /* UITableView+JHNoData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UITableView+JHNoData.m"; sourceTree = ""; }; 53 | 18944B6621C2229A00B472FC /* UICollectionView+JHNoData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UICollectionView+JHNoData.m"; sourceTree = ""; }; 54 | 18944B6721C2229A00B472FC /* JHNoDataEmptyView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JHNoDataEmptyView.m; sourceTree = ""; }; 55 | /* End PBXFileReference section */ 56 | 57 | /* Begin PBXFrameworksBuildPhase section */ 58 | 18944B3121C2179500B472FC /* Frameworks */ = { 59 | isa = PBXFrameworksBuildPhase; 60 | buildActionMask = 2147483647; 61 | files = ( 62 | ); 63 | runOnlyForDeploymentPostprocessing = 0; 64 | }; 65 | 18944B4921C2179700B472FC /* Frameworks */ = { 66 | isa = PBXFrameworksBuildPhase; 67 | buildActionMask = 2147483647; 68 | files = ( 69 | ); 70 | runOnlyForDeploymentPostprocessing = 0; 71 | }; 72 | /* End PBXFrameworksBuildPhase section */ 73 | 74 | /* Begin PBXGroup section */ 75 | 18944B2B21C2179500B472FC = { 76 | isa = PBXGroup; 77 | children = ( 78 | 18944B3621C2179500B472FC /* JHNoDataEmptyViewDemo */, 79 | 18944B4F21C2179700B472FC /* JHNoDataEmptyViewDemoTests */, 80 | 18944B3521C2179500B472FC /* Products */, 81 | ); 82 | sourceTree = ""; 83 | }; 84 | 18944B3521C2179500B472FC /* Products */ = { 85 | isa = PBXGroup; 86 | children = ( 87 | 18944B3421C2179500B472FC /* JHNoDataEmptyViewDemo.app */, 88 | 18944B4C21C2179700B472FC /* JHNoDataEmptyViewDemoTests.xctest */, 89 | ); 90 | name = Products; 91 | sourceTree = ""; 92 | }; 93 | 18944B3621C2179500B472FC /* JHNoDataEmptyViewDemo */ = { 94 | isa = PBXGroup; 95 | children = ( 96 | 18944B6121C2229A00B472FC /* JHNoDataEmptyView */, 97 | 18944B3721C2179500B472FC /* AppDelegate.h */, 98 | 18944B3821C2179500B472FC /* AppDelegate.m */, 99 | 18944B3A21C2179500B472FC /* ViewController.h */, 100 | 18944B3B21C2179500B472FC /* ViewController.m */, 101 | 18318CF521C34AA8003EB302 /* DemoViewController.h */, 102 | 18318CF621C34AA8003EB302 /* DemoViewController.m */, 103 | 18944B3D21C2179500B472FC /* Main.storyboard */, 104 | 18944B4021C2179700B472FC /* Assets.xcassets */, 105 | 18944B4221C2179700B472FC /* LaunchScreen.storyboard */, 106 | 18944B4521C2179700B472FC /* Info.plist */, 107 | 18944B4621C2179700B472FC /* main.m */, 108 | ); 109 | path = JHNoDataEmptyViewDemo; 110 | sourceTree = ""; 111 | }; 112 | 18944B4F21C2179700B472FC /* JHNoDataEmptyViewDemoTests */ = { 113 | isa = PBXGroup; 114 | children = ( 115 | 18944B5021C2179700B472FC /* JHNoDataEmptyViewDemoTests.m */, 116 | 18944B5221C2179700B472FC /* Info.plist */, 117 | ); 118 | path = JHNoDataEmptyViewDemoTests; 119 | sourceTree = ""; 120 | }; 121 | 18944B6121C2229A00B472FC /* JHNoDataEmptyView */ = { 122 | isa = PBXGroup; 123 | children = ( 124 | 18944B6321C2229A00B472FC /* JHNoDataEmptyView.h */, 125 | 18944B6721C2229A00B472FC /* JHNoDataEmptyView.m */, 126 | 18944B6221C2229A00B472FC /* UITableView+JHNoData.h */, 127 | 18944B6521C2229A00B472FC /* UITableView+JHNoData.m */, 128 | 18944B6421C2229A00B472FC /* UICollectionView+JHNoData.h */, 129 | 18944B6621C2229A00B472FC /* UICollectionView+JHNoData.m */, 130 | ); 131 | name = JHNoDataEmptyView; 132 | path = ../../../JHNoDataEmptyView; 133 | sourceTree = ""; 134 | }; 135 | /* End PBXGroup section */ 136 | 137 | /* Begin PBXNativeTarget section */ 138 | 18944B3321C2179500B472FC /* JHNoDataEmptyViewDemo */ = { 139 | isa = PBXNativeTarget; 140 | buildConfigurationList = 18944B5521C2179700B472FC /* Build configuration list for PBXNativeTarget "JHNoDataEmptyViewDemo" */; 141 | buildPhases = ( 142 | 18944B3021C2179500B472FC /* Sources */, 143 | 18944B3121C2179500B472FC /* Frameworks */, 144 | 18944B3221C2179500B472FC /* Resources */, 145 | ); 146 | buildRules = ( 147 | ); 148 | dependencies = ( 149 | ); 150 | name = JHNoDataEmptyViewDemo; 151 | productName = JHNoDataEmptyViewDemo; 152 | productReference = 18944B3421C2179500B472FC /* JHNoDataEmptyViewDemo.app */; 153 | productType = "com.apple.product-type.application"; 154 | }; 155 | 18944B4B21C2179700B472FC /* JHNoDataEmptyViewDemoTests */ = { 156 | isa = PBXNativeTarget; 157 | buildConfigurationList = 18944B5821C2179700B472FC /* Build configuration list for PBXNativeTarget "JHNoDataEmptyViewDemoTests" */; 158 | buildPhases = ( 159 | 18944B4821C2179700B472FC /* Sources */, 160 | 18944B4921C2179700B472FC /* Frameworks */, 161 | 18944B4A21C2179700B472FC /* Resources */, 162 | ); 163 | buildRules = ( 164 | ); 165 | dependencies = ( 166 | 18944B4E21C2179700B472FC /* PBXTargetDependency */, 167 | ); 168 | name = JHNoDataEmptyViewDemoTests; 169 | productName = JHNoDataEmptyViewDemoTests; 170 | productReference = 18944B4C21C2179700B472FC /* JHNoDataEmptyViewDemoTests.xctest */; 171 | productType = "com.apple.product-type.bundle.unit-test"; 172 | }; 173 | /* End PBXNativeTarget section */ 174 | 175 | /* Begin PBXProject section */ 176 | 18944B2C21C2179500B472FC /* Project object */ = { 177 | isa = PBXProject; 178 | attributes = { 179 | LastUpgradeCheck = 1010; 180 | ORGANIZATIONNAME = HaoCold; 181 | TargetAttributes = { 182 | 18944B3321C2179500B472FC = { 183 | CreatedOnToolsVersion = 10.1; 184 | }; 185 | 18944B4B21C2179700B472FC = { 186 | CreatedOnToolsVersion = 10.1; 187 | TestTargetID = 18944B3321C2179500B472FC; 188 | }; 189 | }; 190 | }; 191 | buildConfigurationList = 18944B2F21C2179500B472FC /* Build configuration list for PBXProject "JHNoDataEmptyViewDemo" */; 192 | compatibilityVersion = "Xcode 9.3"; 193 | developmentRegion = en; 194 | hasScannedForEncodings = 0; 195 | knownRegions = ( 196 | en, 197 | Base, 198 | ); 199 | mainGroup = 18944B2B21C2179500B472FC; 200 | productRefGroup = 18944B3521C2179500B472FC /* Products */; 201 | projectDirPath = ""; 202 | projectRoot = ""; 203 | targets = ( 204 | 18944B3321C2179500B472FC /* JHNoDataEmptyViewDemo */, 205 | 18944B4B21C2179700B472FC /* JHNoDataEmptyViewDemoTests */, 206 | ); 207 | }; 208 | /* End PBXProject section */ 209 | 210 | /* Begin PBXResourcesBuildPhase section */ 211 | 18944B3221C2179500B472FC /* Resources */ = { 212 | isa = PBXResourcesBuildPhase; 213 | buildActionMask = 2147483647; 214 | files = ( 215 | 18944B4421C2179700B472FC /* LaunchScreen.storyboard in Resources */, 216 | 18944B4121C2179700B472FC /* Assets.xcassets in Resources */, 217 | 18944B3F21C2179500B472FC /* Main.storyboard in Resources */, 218 | ); 219 | runOnlyForDeploymentPostprocessing = 0; 220 | }; 221 | 18944B4A21C2179700B472FC /* Resources */ = { 222 | isa = PBXResourcesBuildPhase; 223 | buildActionMask = 2147483647; 224 | files = ( 225 | ); 226 | runOnlyForDeploymentPostprocessing = 0; 227 | }; 228 | /* End PBXResourcesBuildPhase section */ 229 | 230 | /* Begin PBXSourcesBuildPhase section */ 231 | 18944B3021C2179500B472FC /* Sources */ = { 232 | isa = PBXSourcesBuildPhase; 233 | buildActionMask = 2147483647; 234 | files = ( 235 | 18944B6A21C2229A00B472FC /* JHNoDataEmptyView.m in Sources */, 236 | 18944B3C21C2179500B472FC /* ViewController.m in Sources */, 237 | 18318CF721C34AA8003EB302 /* DemoViewController.m in Sources */, 238 | 18944B6921C2229A00B472FC /* UICollectionView+JHNoData.m in Sources */, 239 | 18944B4721C2179700B472FC /* main.m in Sources */, 240 | 18944B6821C2229A00B472FC /* UITableView+JHNoData.m in Sources */, 241 | 18944B3921C2179500B472FC /* AppDelegate.m in Sources */, 242 | ); 243 | runOnlyForDeploymentPostprocessing = 0; 244 | }; 245 | 18944B4821C2179700B472FC /* Sources */ = { 246 | isa = PBXSourcesBuildPhase; 247 | buildActionMask = 2147483647; 248 | files = ( 249 | 18944B5121C2179700B472FC /* JHNoDataEmptyViewDemoTests.m in Sources */, 250 | ); 251 | runOnlyForDeploymentPostprocessing = 0; 252 | }; 253 | /* End PBXSourcesBuildPhase section */ 254 | 255 | /* Begin PBXTargetDependency section */ 256 | 18944B4E21C2179700B472FC /* PBXTargetDependency */ = { 257 | isa = PBXTargetDependency; 258 | target = 18944B3321C2179500B472FC /* JHNoDataEmptyViewDemo */; 259 | targetProxy = 18944B4D21C2179700B472FC /* PBXContainerItemProxy */; 260 | }; 261 | /* End PBXTargetDependency section */ 262 | 263 | /* Begin PBXVariantGroup section */ 264 | 18944B3D21C2179500B472FC /* Main.storyboard */ = { 265 | isa = PBXVariantGroup; 266 | children = ( 267 | 18944B3E21C2179500B472FC /* Base */, 268 | ); 269 | name = Main.storyboard; 270 | sourceTree = ""; 271 | }; 272 | 18944B4221C2179700B472FC /* LaunchScreen.storyboard */ = { 273 | isa = PBXVariantGroup; 274 | children = ( 275 | 18944B4321C2179700B472FC /* Base */, 276 | ); 277 | name = LaunchScreen.storyboard; 278 | sourceTree = ""; 279 | }; 280 | /* End PBXVariantGroup section */ 281 | 282 | /* Begin XCBuildConfiguration section */ 283 | 18944B5321C2179700B472FC /* Debug */ = { 284 | isa = XCBuildConfiguration; 285 | buildSettings = { 286 | ALWAYS_SEARCH_USER_PATHS = NO; 287 | CLANG_ANALYZER_NONNULL = YES; 288 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 289 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 290 | CLANG_CXX_LIBRARY = "libc++"; 291 | CLANG_ENABLE_MODULES = YES; 292 | CLANG_ENABLE_OBJC_ARC = YES; 293 | CLANG_ENABLE_OBJC_WEAK = YES; 294 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 295 | CLANG_WARN_BOOL_CONVERSION = YES; 296 | CLANG_WARN_COMMA = YES; 297 | CLANG_WARN_CONSTANT_CONVERSION = YES; 298 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 299 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 300 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 301 | CLANG_WARN_EMPTY_BODY = YES; 302 | CLANG_WARN_ENUM_CONVERSION = YES; 303 | CLANG_WARN_INFINITE_RECURSION = YES; 304 | CLANG_WARN_INT_CONVERSION = YES; 305 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 306 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 307 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 308 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 309 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 310 | CLANG_WARN_STRICT_PROTOTYPES = YES; 311 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 312 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 313 | CLANG_WARN_UNREACHABLE_CODE = YES; 314 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 315 | CODE_SIGN_IDENTITY = "iPhone Developer"; 316 | COPY_PHASE_STRIP = NO; 317 | DEBUG_INFORMATION_FORMAT = dwarf; 318 | ENABLE_STRICT_OBJC_MSGSEND = YES; 319 | ENABLE_TESTABILITY = YES; 320 | GCC_C_LANGUAGE_STANDARD = gnu11; 321 | GCC_DYNAMIC_NO_PIC = NO; 322 | GCC_NO_COMMON_BLOCKS = YES; 323 | GCC_OPTIMIZATION_LEVEL = 0; 324 | GCC_PREPROCESSOR_DEFINITIONS = ( 325 | "DEBUG=1", 326 | "$(inherited)", 327 | ); 328 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 329 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 330 | GCC_WARN_UNDECLARED_SELECTOR = YES; 331 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 332 | GCC_WARN_UNUSED_FUNCTION = YES; 333 | GCC_WARN_UNUSED_VARIABLE = YES; 334 | IPHONEOS_DEPLOYMENT_TARGET = 12.1; 335 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 336 | MTL_FAST_MATH = YES; 337 | ONLY_ACTIVE_ARCH = YES; 338 | SDKROOT = iphoneos; 339 | }; 340 | name = Debug; 341 | }; 342 | 18944B5421C2179700B472FC /* Release */ = { 343 | isa = XCBuildConfiguration; 344 | buildSettings = { 345 | ALWAYS_SEARCH_USER_PATHS = NO; 346 | CLANG_ANALYZER_NONNULL = YES; 347 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 348 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 349 | CLANG_CXX_LIBRARY = "libc++"; 350 | CLANG_ENABLE_MODULES = YES; 351 | CLANG_ENABLE_OBJC_ARC = YES; 352 | CLANG_ENABLE_OBJC_WEAK = YES; 353 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 354 | CLANG_WARN_BOOL_CONVERSION = YES; 355 | CLANG_WARN_COMMA = YES; 356 | CLANG_WARN_CONSTANT_CONVERSION = YES; 357 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 358 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 359 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 360 | CLANG_WARN_EMPTY_BODY = YES; 361 | CLANG_WARN_ENUM_CONVERSION = YES; 362 | CLANG_WARN_INFINITE_RECURSION = YES; 363 | CLANG_WARN_INT_CONVERSION = YES; 364 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 365 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 366 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 367 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 368 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 369 | CLANG_WARN_STRICT_PROTOTYPES = YES; 370 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 371 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 372 | CLANG_WARN_UNREACHABLE_CODE = YES; 373 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 374 | CODE_SIGN_IDENTITY = "iPhone Developer"; 375 | COPY_PHASE_STRIP = NO; 376 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 377 | ENABLE_NS_ASSERTIONS = NO; 378 | ENABLE_STRICT_OBJC_MSGSEND = YES; 379 | GCC_C_LANGUAGE_STANDARD = gnu11; 380 | GCC_NO_COMMON_BLOCKS = YES; 381 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 382 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 383 | GCC_WARN_UNDECLARED_SELECTOR = YES; 384 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 385 | GCC_WARN_UNUSED_FUNCTION = YES; 386 | GCC_WARN_UNUSED_VARIABLE = YES; 387 | IPHONEOS_DEPLOYMENT_TARGET = 12.1; 388 | MTL_ENABLE_DEBUG_INFO = NO; 389 | MTL_FAST_MATH = YES; 390 | SDKROOT = iphoneos; 391 | VALIDATE_PRODUCT = YES; 392 | }; 393 | name = Release; 394 | }; 395 | 18944B5621C2179700B472FC /* Debug */ = { 396 | isa = XCBuildConfiguration; 397 | buildSettings = { 398 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 399 | CODE_SIGN_STYLE = Manual; 400 | DEVELOPMENT_TEAM = ""; 401 | INFOPLIST_FILE = JHNoDataEmptyViewDemo/Info.plist; 402 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 403 | LD_RUNPATH_SEARCH_PATHS = ( 404 | "$(inherited)", 405 | "@executable_path/Frameworks", 406 | ); 407 | PRODUCT_BUNDLE_IDENTIFIER = haocold.JHNoDataEmptyViewDemo; 408 | PRODUCT_NAME = "$(TARGET_NAME)"; 409 | PROVISIONING_PROFILE_SPECIFIER = ""; 410 | TARGETED_DEVICE_FAMILY = "1,2"; 411 | }; 412 | name = Debug; 413 | }; 414 | 18944B5721C2179700B472FC /* Release */ = { 415 | isa = XCBuildConfiguration; 416 | buildSettings = { 417 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 418 | CODE_SIGN_STYLE = Manual; 419 | DEVELOPMENT_TEAM = ""; 420 | INFOPLIST_FILE = JHNoDataEmptyViewDemo/Info.plist; 421 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 422 | LD_RUNPATH_SEARCH_PATHS = ( 423 | "$(inherited)", 424 | "@executable_path/Frameworks", 425 | ); 426 | PRODUCT_BUNDLE_IDENTIFIER = haocold.JHNoDataEmptyViewDemo; 427 | PRODUCT_NAME = "$(TARGET_NAME)"; 428 | PROVISIONING_PROFILE_SPECIFIER = ""; 429 | TARGETED_DEVICE_FAMILY = "1,2"; 430 | }; 431 | name = Release; 432 | }; 433 | 18944B5921C2179700B472FC /* Debug */ = { 434 | isa = XCBuildConfiguration; 435 | buildSettings = { 436 | BUNDLE_LOADER = "$(TEST_HOST)"; 437 | CODE_SIGN_STYLE = Automatic; 438 | INFOPLIST_FILE = JHNoDataEmptyViewDemoTests/Info.plist; 439 | LD_RUNPATH_SEARCH_PATHS = ( 440 | "$(inherited)", 441 | "@executable_path/Frameworks", 442 | "@loader_path/Frameworks", 443 | ); 444 | PRODUCT_BUNDLE_IDENTIFIER = haocold.JHNoDataEmptyViewDemoTests; 445 | PRODUCT_NAME = "$(TARGET_NAME)"; 446 | TARGETED_DEVICE_FAMILY = "1,2"; 447 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/JHNoDataEmptyViewDemo.app/JHNoDataEmptyViewDemo"; 448 | }; 449 | name = Debug; 450 | }; 451 | 18944B5A21C2179700B472FC /* Release */ = { 452 | isa = XCBuildConfiguration; 453 | buildSettings = { 454 | BUNDLE_LOADER = "$(TEST_HOST)"; 455 | CODE_SIGN_STYLE = Automatic; 456 | INFOPLIST_FILE = JHNoDataEmptyViewDemoTests/Info.plist; 457 | LD_RUNPATH_SEARCH_PATHS = ( 458 | "$(inherited)", 459 | "@executable_path/Frameworks", 460 | "@loader_path/Frameworks", 461 | ); 462 | PRODUCT_BUNDLE_IDENTIFIER = haocold.JHNoDataEmptyViewDemoTests; 463 | PRODUCT_NAME = "$(TARGET_NAME)"; 464 | TARGETED_DEVICE_FAMILY = "1,2"; 465 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/JHNoDataEmptyViewDemo.app/JHNoDataEmptyViewDemo"; 466 | }; 467 | name = Release; 468 | }; 469 | /* End XCBuildConfiguration section */ 470 | 471 | /* Begin XCConfigurationList section */ 472 | 18944B2F21C2179500B472FC /* Build configuration list for PBXProject "JHNoDataEmptyViewDemo" */ = { 473 | isa = XCConfigurationList; 474 | buildConfigurations = ( 475 | 18944B5321C2179700B472FC /* Debug */, 476 | 18944B5421C2179700B472FC /* Release */, 477 | ); 478 | defaultConfigurationIsVisible = 0; 479 | defaultConfigurationName = Release; 480 | }; 481 | 18944B5521C2179700B472FC /* Build configuration list for PBXNativeTarget "JHNoDataEmptyViewDemo" */ = { 482 | isa = XCConfigurationList; 483 | buildConfigurations = ( 484 | 18944B5621C2179700B472FC /* Debug */, 485 | 18944B5721C2179700B472FC /* Release */, 486 | ); 487 | defaultConfigurationIsVisible = 0; 488 | defaultConfigurationName = Release; 489 | }; 490 | 18944B5821C2179700B472FC /* Build configuration list for PBXNativeTarget "JHNoDataEmptyViewDemoTests" */ = { 491 | isa = XCConfigurationList; 492 | buildConfigurations = ( 493 | 18944B5921C2179700B472FC /* Debug */, 494 | 18944B5A21C2179700B472FC /* Release */, 495 | ); 496 | defaultConfigurationIsVisible = 0; 497 | defaultConfigurationName = Release; 498 | }; 499 | /* End XCConfigurationList section */ 500 | }; 501 | rootObject = 18944B2C21C2179500B472FC /* Project object */; 502 | } 503 | -------------------------------------------------------------------------------- /Example/JHNoDataEmptyViewDemo/JHNoDataEmptyViewDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/JHNoDataEmptyViewDemo/JHNoDataEmptyViewDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Example/JHNoDataEmptyViewDemo/JHNoDataEmptyViewDemo.xcodeproj/project.xcworkspace/xcuserdata/apple.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xjh093/JHNoDataEmptyView/57a0e9a1086744d45f340cb81a01a75af1097d71/Example/JHNoDataEmptyViewDemo/JHNoDataEmptyViewDemo.xcodeproj/project.xcworkspace/xcuserdata/apple.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Example/JHNoDataEmptyViewDemo/JHNoDataEmptyViewDemo.xcodeproj/xcuserdata/apple.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /Example/JHNoDataEmptyViewDemo/JHNoDataEmptyViewDemo.xcodeproj/xcuserdata/apple.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | JHNoDataEmptyViewDemo.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Example/JHNoDataEmptyViewDemo/JHNoDataEmptyViewDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // JHNoDataEmptyViewDemo 4 | // 5 | // Created by HaoCold on 2018/12/13. 6 | // Copyright © 2018 HaoCold. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /Example/JHNoDataEmptyViewDemo/JHNoDataEmptyViewDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // JHNoDataEmptyViewDemo 4 | // 5 | // Created by HaoCold on 2018/12/13. 6 | // Copyright © 2018 HaoCold. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | 24 | - (void)applicationWillResignActive:(UIApplication *)application { 25 | // 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. 26 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 27 | } 28 | 29 | 30 | - (void)applicationDidEnterBackground:(UIApplication *)application { 31 | // 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. 32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 33 | } 34 | 35 | 36 | - (void)applicationWillEnterForeground:(UIApplication *)application { 37 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 38 | } 39 | 40 | 41 | - (void)applicationDidBecomeActive:(UIApplication *)application { 42 | // 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. 43 | } 44 | 45 | 46 | - (void)applicationWillTerminate:(UIApplication *)application { 47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 48 | } 49 | 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /Example/JHNoDataEmptyViewDemo/JHNoDataEmptyViewDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /Example/JHNoDataEmptyViewDemo/JHNoDataEmptyViewDemo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Example/JHNoDataEmptyViewDemo/JHNoDataEmptyViewDemo/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 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /Example/JHNoDataEmptyViewDemo/JHNoDataEmptyViewDemo/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 | -------------------------------------------------------------------------------- /Example/JHNoDataEmptyViewDemo/JHNoDataEmptyViewDemo/DemoViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // DemoViewController.h 3 | // JHNoDataEmptyViewDemo 4 | // 5 | // Created by HaoCold on 2018/12/14. 6 | // Copyright © 2018 HaoCold. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface DemoViewController : UIViewController 14 | @property (nonatomic, assign) NSInteger row; 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /Example/JHNoDataEmptyViewDemo/JHNoDataEmptyViewDemo/DemoViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // DemoViewController.m 3 | // JHNoDataEmptyViewDemo 4 | // 5 | // Created by HaoCold on 2018/12/14. 6 | // Copyright © 2018 HaoCold. All rights reserved. 7 | // 8 | 9 | #import "DemoViewController.h" 10 | #import "UITableView+JHNoData.h" 11 | 12 | @interface DemoViewController () 13 | @property (nonatomic, strong) UITableView *tableView; 14 | @property (nonatomic, strong) NSArray *dataArray; 15 | 16 | @property (nonatomic, strong) UIButton *button; 17 | 18 | @end 19 | 20 | @implementation DemoViewController 21 | 22 | - (void)viewDidLoad { 23 | [super viewDidLoad]; 24 | // Do any additional setup after loading the view. 25 | 26 | _dataArray = @[@"",@"",@"",@"",@"",@"",@"",@"",@"",@"",@"",@"",@"",@""]; 27 | [self xjh_setupViews]; 28 | 29 | } 30 | 31 | #pragma mark -------------------------------------视图------------------------------------------- 32 | 33 | - (void)xjh_setupViews 34 | { 35 | self.view.backgroundColor = [UIColor whiteColor]; 36 | [self.view addSubview:self.tableView]; 37 | self.tableView.jh_showNoDataEmptyView = YES; 38 | 39 | self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:({ 40 | UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; 41 | button.frame = CGRectMake(0, 0, 40, 40); 42 | button.titleLabel.font = [UIFont systemFontOfSize:16]; 43 | [button setTitle:@"清空" forState:0]; 44 | [button setTitleColor:[UIColor blackColor] forState:0]; 45 | [button setImage:nil forState:0]; 46 | [button addTarget:self action:@selector(buttonEvent) forControlEvents:1<<6]; 47 | _button = button; 48 | button; 49 | })]; 50 | 51 | if (_row == 0) { 52 | 53 | }else if (_row == 1) { 54 | self.tableView.tableHeaderView = ({ 55 | UILabel *label = [[UILabel alloc] init]; 56 | label.frame = CGRectMake(0, 0, CGRectGetWidth(self.view.frame), 900); 57 | label.text = @"This\nis\na\ntable\nheader\nview\nit\nis\nvery\nhigh!!!"; 58 | label.textColor = [UIColor blackColor]; 59 | label.font = [UIFont systemFontOfSize:14]; 60 | label.textAlignment = NSTextAlignmentCenter; 61 | label.backgroundColor = [UIColor lightGrayColor]; 62 | label.numberOfLines = 0; 63 | label; 64 | }); 65 | }else if (_row == 2) { 66 | self.tableView.tableFooterView = ({ 67 | UILabel *label = [[UILabel alloc] init]; 68 | label.frame = CGRectMake(0, 0, CGRectGetWidth(self.view.frame), 900); 69 | label.text = @"This\nis\na\ntable\nfooter\nview\nit\nis\nvery\nhigh!!!"; 70 | label.textColor = [UIColor blackColor]; 71 | label.font = [UIFont systemFontOfSize:14]; 72 | label.textAlignment = NSTextAlignmentCenter; 73 | label.backgroundColor = [UIColor lightGrayColor]; 74 | label.numberOfLines = 0; 75 | label; 76 | }); 77 | }else if (_row == 3) { 78 | self.tableView.tableHeaderView = ({ 79 | UILabel *label = [[UILabel alloc] init]; 80 | label.frame = CGRectMake(0, 0, CGRectGetWidth(self.view.frame), 100); 81 | label.text = @"This is a table header view"; 82 | label.textColor = [UIColor blackColor]; 83 | label.font = [UIFont systemFontOfSize:14]; 84 | label.textAlignment = NSTextAlignmentCenter; 85 | label.backgroundColor = [UIColor lightGrayColor]; 86 | label.numberOfLines = 0; 87 | label; 88 | }); 89 | 90 | self.tableView.tableFooterView = ({ 91 | UILabel *label = [[UILabel alloc] init]; 92 | label.frame = CGRectMake(0, 0, CGRectGetWidth(self.view.frame), 100); 93 | label.text = @"This is a table header view"; 94 | label.textColor = [UIColor blackColor]; 95 | label.font = [UIFont systemFontOfSize:14]; 96 | label.textAlignment = NSTextAlignmentCenter; 97 | label.backgroundColor = [UIColor lightGrayColor]; 98 | label.numberOfLines = 0; 99 | label; 100 | }); 101 | } 102 | } 103 | 104 | #pragma mark -------------------------------------事件------------------------------------------- 105 | 106 | - (void)buttonEvent 107 | { 108 | if ([_button.currentTitle isEqualToString:@"清空"]) { 109 | [_button setTitle:@"重置" forState:0]; 110 | _dataArray = @[]; 111 | }else{ 112 | [_button setTitle:@"清空" forState:0]; 113 | _dataArray = @[@"",@"",@"",@"",@"",@"",@"",@"",@"",@"",@"",@"",@"",@""]; 114 | } 115 | [_tableView reloadData]; 116 | } 117 | 118 | #pragma mark --- JHNoDataUITableViewDelegate 119 | 120 | /// offer a image to show some infomation for user. 121 | - (UIImageView *)imageViewForTableViewWhenDataSourceIsEmpty 122 | { 123 | // you imageView 124 | return nil; 125 | } 126 | 127 | /// offer a label to show some infomation for user. 128 | - (UILabel *)labelForTableViewWhenDataSourceIsEmpty 129 | { 130 | // you label 131 | 132 | if (_row == 3) { 133 | UILabel *label = [[UILabel alloc] init]; 134 | label.frame = CGRectMake(0, 0, 200, 80); 135 | label.text = @"if you don't want to show this empty view,you can hide it."; 136 | label.textColor = [UIColor blackColor]; 137 | label.font = [UIFont systemFontOfSize:14]; 138 | label.textAlignment = NSTextAlignmentLeft; 139 | label.numberOfLines = 0; 140 | return label; 141 | } 142 | return nil; 143 | } 144 | 145 | /// the empty view that add to tableView. you can add more custom view. 146 | - (void)emptyViewForTableViewWhenDataSourceIsEmpty:(UIView *)emptyView 147 | { 148 | // you can add some custom view, button etc. 149 | 150 | if (_row == 3) { // Example 4 151 | // there are table header view and table footer view 152 | // if you don't want to show the emptyview, hide it. 153 | // emptyView.hidden = YES; 154 | // or 155 | // self.tableView.jh_showNoDataEmptyView = NO; 156 | // this will effect at next reload. 157 | } 158 | } 159 | 160 | #pragma mark --- UITableViewDataSource 161 | 162 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 163 | { 164 | return _dataArray.count; 165 | } 166 | 167 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 168 | { 169 | static NSString *ID = @"resueID"; 170 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; 171 | if (cell == nil) { 172 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID]; 173 | } 174 | cell.textLabel.text = [NSString stringWithFormat:@"第%@行",@(indexPath.row)]; 175 | return cell; 176 | } 177 | 178 | #pragma mark -------------------------------------懒加载----------------------------------------- 179 | 180 | - (UITableView *)tableView{ 181 | if (!_tableView) { 182 | UITableView *tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:0]; 183 | tableView.delegate = self; 184 | tableView.dataSource = self; 185 | tableView.rowHeight = 40; 186 | tableView.tableFooterView = [[UIView alloc] init]; 187 | tableView.showsVerticalScrollIndicator = NO; 188 | _tableView = tableView; 189 | } 190 | return _tableView; 191 | } 192 | 193 | 194 | 195 | /* 196 | #pragma mark - Navigation 197 | 198 | // In a storyboard-based application, you will often want to do a little preparation before navigation 199 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 200 | // Get the new view controller using [segue destinationViewController]. 201 | // Pass the selected object to the new view controller. 202 | } 203 | */ 204 | 205 | @end 206 | -------------------------------------------------------------------------------- /Example/JHNoDataEmptyViewDemo/JHNoDataEmptyViewDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /Example/JHNoDataEmptyViewDemo/JHNoDataEmptyViewDemo/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // JHNoDataEmptyViewDemo 4 | // 5 | // Created by HaoCold on 2018/12/13. 6 | // Copyright © 2018 HaoCold. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /Example/JHNoDataEmptyViewDemo/JHNoDataEmptyViewDemo/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // JHNoDataEmptyViewDemo 4 | // 5 | // Created by HaoCold on 2018/12/13. 6 | // Copyright © 2018 HaoCold. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "DemoViewController.h" 11 | 12 | @interface ViewController () 13 | @property (strong, nonatomic) UITableView *tableView; 14 | 15 | @end 16 | 17 | @implementation ViewController 18 | 19 | - (void)viewDidLoad { 20 | [super viewDidLoad]; 21 | // Do any additional setup after loading the view, typically from a nib. 22 | 23 | self.navigationItem.title = @"JHNoDataEmptyView"; 24 | [self xjh_setupViews]; 25 | } 26 | 27 | #pragma mark -------------------------------------视图------------------------------------------- 28 | 29 | - (void)xjh_setupViews 30 | { 31 | [self.view addSubview:self.tableView]; 32 | } 33 | 34 | #pragma mark -------------------------------------事件------------------------------------------- 35 | 36 | #pragma mark ---UITableViewDataSource 37 | 38 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 39 | { 40 | return 4; 41 | } 42 | 43 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 44 | { 45 | static NSString *ID = @"resueID"; 46 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; 47 | if (cell == nil) { 48 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID]; 49 | } 50 | cell.textLabel.text = [NSString stringWithFormat:@"Example %@",@(indexPath.row+1)]; 51 | return cell; 52 | } 53 | 54 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 55 | { 56 | DemoViewController *vc = [[DemoViewController alloc] init]; 57 | vc.row = indexPath.row; 58 | vc.navigationItem.title = [NSString stringWithFormat:@"Example %@",@(indexPath.row+1)]; 59 | [self.navigationController pushViewController:vc animated:YES]; 60 | } 61 | 62 | #pragma mark -------------------------------------懒加载----------------------------------------- 63 | 64 | - (UITableView *)tableView{ 65 | if (!_tableView) { 66 | UITableView *tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:0]; 67 | tableView.delegate = self; 68 | tableView.dataSource = self; 69 | tableView.rowHeight = 40; 70 | tableView.tableFooterView = [[UIView alloc] init]; 71 | tableView.showsVerticalScrollIndicator = NO; 72 | _tableView = tableView; 73 | } 74 | return _tableView; 75 | } 76 | 77 | @end 78 | -------------------------------------------------------------------------------- /Example/JHNoDataEmptyViewDemo/JHNoDataEmptyViewDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // JHNoDataEmptyViewDemo 4 | // 5 | // Created by HaoCold on 2018/12/13. 6 | // Copyright © 2018 HaoCold. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Example/JHNoDataEmptyViewDemo/JHNoDataEmptyViewDemoTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Example/JHNoDataEmptyViewDemo/JHNoDataEmptyViewDemoTests/JHNoDataEmptyViewDemoTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // JHNoDataEmptyViewDemoTests.m 3 | // JHNoDataEmptyViewDemoTests 4 | // 5 | // Created by HaoCold on 2018/12/13. 6 | // Copyright © 2018 HaoCold. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface JHNoDataEmptyViewDemoTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation JHNoDataEmptyViewDemoTests 16 | 17 | - (void)setUp { 18 | // Put setup code here. This method is called before the invocation of each test method in the class. 19 | } 20 | 21 | - (void)tearDown { 22 | // Put teardown code here. This method is called after the invocation of each test method in the class. 23 | } 24 | 25 | - (void)testExample { 26 | // This is an example of a functional test case. 27 | // Use XCTAssert and related functions to verify your tests produce the correct results. 28 | } 29 | 30 | - (void)testPerformanceExample { 31 | // This is an example of a performance test case. 32 | [self measureBlock:^{ 33 | // Put the code you want to measure the time of here. 34 | }]; 35 | } 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /JHNoDataEmptyView.podspec: -------------------------------------------------------------------------------- 1 | 2 | Pod::Spec.new do |s| 3 | s.name = 'JHNoDataEmptyView' 4 | s.summary = 'A simple empty view for tableview and collectionview.' 5 | s.version = '1.2.0' 6 | s.license = { :type => 'MIT'} 7 | s.authors = { 'Haocold' => 'xjh093@126.com' } 8 | s.homepage = 'https://github.com/xjh093/JHNoDataEmptyViewForT-C' 9 | 10 | s.ios.deployment_target = '8.0' 11 | 12 | s.source = { :git => 'https://github.com/xjh093/JHNoDataEmptyViewForT-C.git', :tag => s.version} 13 | 14 | s.source_files = 'JHNoDataEmptyView/*.{h,m}' 15 | s.requires_arc = true 16 | s.framework = 'UIKit' 17 | 18 | end -------------------------------------------------------------------------------- /JHNoDataEmptyView/JHNoDataEmptyView.h: -------------------------------------------------------------------------------- 1 | // 2 | // JHNoDataEmptyView.h 3 | // JHKit 4 | // 5 | // Created by HaoCold on 2018/1/2. 6 | // Copyright © 2018年 HaoCold. All rights reserved. 7 | // 8 | // MIT License 9 | // 10 | // Copyright (c) 2017 xjh093 11 | // 12 | // Permission is hereby granted, free of charge, to any person obtaining a copy 13 | // of this software and associated documentation files (the "Software"), to deal 14 | // in the Software without restriction, including without limitation the rights 15 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | // copies of the Software, and to permit persons to whom the Software is 17 | // furnished to do so, subject to the following conditions: 18 | // 19 | // The above copyright notice and this permission notice shall be included in all 20 | // copies or substantial portions of the Software. 21 | // 22 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | // SOFTWARE. 29 | 30 | #import 31 | 32 | @interface JHNoDataEmptyView : UIView 33 | 34 | /// a empty view with specificed size, contain a label and a image, if both nil will use default label. 35 | + (JHNoDataEmptyView *)jh_emptyViewWithLabel:(UILabel *)label imageView:(UIImageView *)imageView bounds:(CGRect)bounds backgroundColor:(UIColor *)backgroundColor; 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /JHNoDataEmptyView/JHNoDataEmptyView.m: -------------------------------------------------------------------------------- 1 | // 2 | // JHNoDataEmptyView.m 3 | // JHKit 4 | // 5 | // Created by HaoCold on 2018/1/2. 6 | // Copyright © 2018年 HaoCold. All rights reserved. 7 | // 8 | // MIT License 9 | // 10 | // Copyright (c) 2017 xjh093 11 | // 12 | // Permission is hereby granted, free of charge, to any person obtaining a copy 13 | // of this software and associated documentation files (the "Software"), to deal 14 | // in the Software without restriction, including without limitation the rights 15 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | // copies of the Software, and to permit persons to whom the Software is 17 | // furnished to do so, subject to the following conditions: 18 | // 19 | // The above copyright notice and this permission notice shall be included in all 20 | // copies or substantial portions of the Software. 21 | // 22 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | // SOFTWARE. 29 | 30 | #import "JHNoDataEmptyView.h" 31 | 32 | @implementation JHNoDataEmptyView 33 | 34 | - (instancetype)init{ 35 | if (self = [super init]) { 36 | self.backgroundColor = [UIColor colorWithRed:239/255.0 green:239/255.0 blue:244/255.0 alpha:1]; 37 | } 38 | return self; 39 | } 40 | 41 | + (JHNoDataEmptyView *)jh_emptyViewWithLabel:(UILabel *)label imageView:(UIImageView *)imageView bounds:(CGRect)bounds backgroundColor:(UIColor *)backgroundColor 42 | { 43 | JHNoDataEmptyView *emptyView = nil; 44 | 45 | if (label && imageView) { 46 | emptyView = [self jh_addLabel:label imageView:imageView bounds:bounds]; 47 | }else if (label){ 48 | emptyView = [self jh_addLabel:label bounds:bounds]; 49 | }else if (imageView){ 50 | emptyView = [self jh_addImageView:imageView bounds:bounds]; 51 | }else{ 52 | emptyView = [self jh_addDefaultLabel:bounds]; 53 | } 54 | 55 | if (backgroundColor) { 56 | emptyView.backgroundColor = backgroundColor; 57 | } 58 | 59 | return emptyView; 60 | } 61 | 62 | + (JHNoDataEmptyView *)jh_addLabel:(UILabel *)label imageView:(UIImageView *)imageView bounds:(CGRect)bounds 63 | { 64 | JHNoDataEmptyView *emptyView = [[JHNoDataEmptyView alloc] init]; 65 | emptyView.frame = bounds; 66 | 67 | [emptyView addSubview:imageView]; 68 | [emptyView addSubview:label]; 69 | 70 | CGFloat centerY = CGRectGetHeight(emptyView.frame) * 0.5; 71 | imageView.center = CGPointMake(emptyView.center.x, centerY - imageView.bounds.size.height * 0.5 - 5); 72 | label.center = CGPointMake(emptyView.center.x, centerY + label.bounds.size.height * 0.5 + 5); 73 | 74 | return emptyView; 75 | } 76 | 77 | + (JHNoDataEmptyView *)jh_addLabel:(UILabel *)label bounds:(CGRect)bounds 78 | { 79 | JHNoDataEmptyView *emptyView = [[JHNoDataEmptyView alloc] init]; 80 | emptyView.frame = bounds; 81 | 82 | label.center = CGPointMake(CGRectGetWidth(emptyView.frame)*0.5, CGRectGetHeight(emptyView.frame)*0.5); 83 | [emptyView addSubview:label]; 84 | 85 | return emptyView; 86 | } 87 | 88 | + (JHNoDataEmptyView *)jh_addImageView:(UIImageView *)imageView bounds:(CGRect)bounds 89 | { 90 | JHNoDataEmptyView *emptyView = [[JHNoDataEmptyView alloc] init]; 91 | emptyView.frame = bounds; 92 | 93 | imageView.center = CGPointMake(CGRectGetWidth(emptyView.frame)*0.5, CGRectGetHeight(emptyView.frame)*0.5); 94 | [emptyView addSubview:imageView]; 95 | 96 | return emptyView; 97 | } 98 | 99 | + (JHNoDataEmptyView *)jh_addDefaultLabel:(CGRect)bounds 100 | { 101 | JHNoDataEmptyView *emptyView = [[JHNoDataEmptyView alloc] init]; 102 | emptyView.frame = bounds; 103 | 104 | UILabel *label = [[UILabel alloc] init]; 105 | label.frame = emptyView.bounds; 106 | label.numberOfLines = 0; 107 | label.text = @"暂无数据哦~\noops~\nThere is nothing here~"; 108 | label.textColor = [UIColor grayColor]; 109 | label.font = [UIFont systemFontOfSize:16]; 110 | label.textAlignment = NSTextAlignmentCenter; 111 | [emptyView addSubview:label]; 112 | 113 | return emptyView; 114 | } 115 | 116 | @end 117 | -------------------------------------------------------------------------------- /JHNoDataEmptyView/UICollectionView+JHNoData.h: -------------------------------------------------------------------------------- 1 | // 2 | // UICollectionView+JHNoData.h 3 | // JHKit 4 | // 5 | // Created by HaoCold on 2017/12/29. 6 | // Copyright © 2017年 HaoCold. All rights reserved. 7 | // 8 | // MIT License 9 | // 10 | // Copyright (c) 2017 xjh093 11 | // 12 | // Permission is hereby granted, free of charge, to any person obtaining a copy 13 | // of this software and associated documentation files (the "Software"), to deal 14 | // in the Software without restriction, including without limitation the rights 15 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | // copies of the Software, and to permit persons to whom the Software is 17 | // furnished to do so, subject to the following conditions: 18 | // 19 | // The above copyright notice and this permission notice shall be included in all 20 | // copies or substantial portions of the Software. 21 | // 22 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | // SOFTWARE. 29 | 30 | #import 31 | 32 | @protocol JHNoDataUICollectionViewDelegate 33 | 34 | @optional 35 | 36 | /// offer a image to show some infomation for user. 37 | - (UIImageView *)imageViewForCollectionViewWhenDataSourceIsEmpty; 38 | 39 | /// offer a label to show some infomation for user. 40 | - (UILabel *)labelForCollectionViewWhenDataSourceIsEmpty; 41 | 42 | /// the empty view that add to tableView. you can add more custom view. 43 | - (void)emptyViewForCollectionViewWhenDataSourceIsEmpty:(UIView *)emptyView; 44 | 45 | @end 46 | 47 | @interface UICollectionView (JHNoData) 48 | 49 | /** 50 | 'NO' is default. 51 | If you want to show 'JHNoDataEmptyView' in one of your 'UICollectionView', you should set 'YES'. 52 | */ 53 | @property (nonatomic, assign) BOOL jh_showNoDataEmptyView; 54 | 55 | @end 56 | -------------------------------------------------------------------------------- /JHNoDataEmptyView/UICollectionView+JHNoData.m: -------------------------------------------------------------------------------- 1 | // 2 | // UICollectionView+JHNoData.m 3 | // JHKit 4 | // 5 | // Created by HaoCold on 2017/12/29. 6 | // Copyright © 2017年 HaoCold. All rights reserved. 7 | // 8 | // MIT License 9 | // 10 | // Copyright (c) 2017 xjh093 11 | // 12 | // Permission is hereby granted, free of charge, to any person obtaining a copy 13 | // of this software and associated documentation files (the "Software"), to deal 14 | // in the Software without restriction, including without limitation the rights 15 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | // copies of the Software, and to permit persons to whom the Software is 17 | // furnished to do so, subject to the following conditions: 18 | // 19 | // The above copyright notice and this permission notice shall be included in all 20 | // copies or substantial portions of the Software. 21 | // 22 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | // SOFTWARE. 29 | 30 | #import "UICollectionView+JHNoData.h" 31 | #import "JHNoDataEmptyView.h" 32 | 33 | #import 34 | 35 | @implementation UICollectionView (JHNoData) 36 | 37 | /// exchange methods 38 | + (void)load{ 39 | 40 | Method old = class_getInstanceMethod(self, @selector(reloadData)); 41 | Method new = class_getInstanceMethod(self, @selector(jh_reloadData)); 42 | 43 | method_exchangeImplementations(old, new); 44 | } 45 | 46 | - (void)setJh_showNoDataEmptyView:(BOOL)jh_showNoDataEmptyView{ 47 | objc_setAssociatedObject(self, @selector(jh_showNoDataEmptyView), @(jh_showNoDataEmptyView), OBJC_ASSOCIATION_ASSIGN); 48 | } 49 | 50 | - (BOOL)jh_showNoDataEmptyView{ 51 | return [objc_getAssociatedObject(self, _cmd) boolValue]; 52 | } 53 | 54 | /// custom method 55 | - (void)jh_reloadData 56 | { 57 | [self jh_reloadData]; 58 | 59 | if (![self jh_showNoDataEmptyView]) { 60 | return; 61 | } 62 | 63 | // issue: self.visibleCells.count == 0 64 | // https://stackoverflow.com/questions/26055626/uicollectionview-visiblecells-returns-0-before-scrolling 65 | [self layoutIfNeeded]; 66 | 67 | // if self.visibleCells.count > 0, so collectionView is not empty. 68 | if (self.visibleCells.count) { 69 | 70 | // remove custom views 71 | [self.subviews enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(__kindof UIView * _Nonnull subview, NSUInteger idx, BOOL * _Nonnull stop) { 72 | if ([subview isKindOfClass:[JHNoDataEmptyView class]]) { 73 | [subview removeFromSuperview]; 74 | *stop = YES; 75 | } 76 | }]; 77 | 78 | }else{ 79 | 80 | // add custom views to offer some infomation. 81 | 82 | UILabel *label = nil; 83 | UIImageView *imageView = nil; 84 | 85 | if ([self.dataSource respondsToSelector:@selector(labelForCollectionViewWhenDataSourceIsEmpty)]) { 86 | label = [self.dataSource performSelector:@selector(labelForCollectionViewWhenDataSourceIsEmpty)]; 87 | } else if ([self respondsToSelector:@selector(labelForCollectionViewWhenDataSourceIsEmpty)]) { 88 | label = [self performSelector:@selector(labelForCollectionViewWhenDataSourceIsEmpty)]; 89 | } 90 | 91 | if ([self.dataSource respondsToSelector:@selector(imageViewForCollectionViewWhenDataSourceIsEmpty)]) { 92 | imageView = [self.dataSource performSelector:@selector(imageViewForCollectionViewWhenDataSourceIsEmpty)]; 93 | } else if ([self respondsToSelector:@selector(imageViewForCollectionViewWhenDataSourceIsEmpty)]) { 94 | imageView = [self performSelector:@selector(imageViewForCollectionViewWhenDataSourceIsEmpty)]; 95 | } 96 | 97 | // empty view 98 | [[self viewWithTag:20231009] removeFromSuperview]; 99 | 100 | JHNoDataEmptyView *emptyView = [JHNoDataEmptyView jh_emptyViewWithLabel:label imageView:imageView bounds:CGRectMake(0, 0, CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds)) backgroundColor:nil]; 101 | emptyView.tag = 20231009; 102 | [self addSubview:emptyView]; 103 | 104 | if ([self.dataSource respondsToSelector:@selector(emptyViewForCollectionViewWhenDataSourceIsEmpty:)]) { 105 | [self.dataSource performSelector:@selector(emptyViewForCollectionViewWhenDataSourceIsEmpty:) withObject:emptyView]; 106 | } else if ([self respondsToSelector:@selector(emptyViewForCollectionViewWhenDataSourceIsEmpty:)]) { 107 | [self performSelector:@selector(emptyViewForCollectionViewWhenDataSourceIsEmpty:) withObject:emptyView]; 108 | } 109 | } 110 | } 111 | 112 | @end 113 | -------------------------------------------------------------------------------- /JHNoDataEmptyView/UITableView+JHNoData.h: -------------------------------------------------------------------------------- 1 | // 2 | // UITableView+JHNoData.h 3 | // JHKit 4 | // 5 | // Created by HaoCold on 2017/12/29. 6 | // Copyright © 2017年 HaoCold. All rights reserved. 7 | // 8 | // MIT License 9 | // 10 | // Copyright (c) 2017 xjh093 11 | // 12 | // Permission is hereby granted, free of charge, to any person obtaining a copy 13 | // of this software and associated documentation files (the "Software"), to deal 14 | // in the Software without restriction, including without limitation the rights 15 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | // copies of the Software, and to permit persons to whom the Software is 17 | // furnished to do so, subject to the following conditions: 18 | // 19 | // The above copyright notice and this permission notice shall be included in all 20 | // copies or substantial portions of the Software. 21 | // 22 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | // SOFTWARE. 29 | 30 | #import 31 | 32 | @protocol JHNoDataUITableViewDelegate 33 | 34 | @optional 35 | 36 | /// offer a image to show some infomation for user. 37 | - (UIImageView *)imageViewForTableViewWhenDataSourceIsEmpty; 38 | 39 | /// offer a label to show some infomation for user. 40 | - (UILabel *)labelForTableViewWhenDataSourceIsEmpty; 41 | 42 | /// the empty view that add to tableView. you can add more custom view. 43 | - (void)emptyViewForTableViewWhenDataSourceIsEmpty:(UIView *)emptyView; 44 | 45 | @end 46 | 47 | @interface UITableView (JHNoData) 48 | 49 | /** 50 | 'NO' is default. 51 | If you want to show 'JHNoDataEmptyView' in one of your 'UITableView', you should set 'YES'. 52 | */ 53 | @property (nonatomic, assign) BOOL jh_showNoDataEmptyView; 54 | 55 | @end 56 | -------------------------------------------------------------------------------- /JHNoDataEmptyView/UITableView+JHNoData.m: -------------------------------------------------------------------------------- 1 | // 2 | // UITableView+JHNoData.m 3 | // JHKit 4 | // 5 | // Created by HaoCold on 2017/12/29. 6 | // Copyright © 2017年 HaoCold. All rights reserved. 7 | // 8 | // MIT License 9 | // 10 | // Copyright (c) 2017 xjh093 11 | // 12 | // Permission is hereby granted, free of charge, to any person obtaining a copy 13 | // of this software and associated documentation files (the "Software"), to deal 14 | // in the Software without restriction, including without limitation the rights 15 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | // copies of the Software, and to permit persons to whom the Software is 17 | // furnished to do so, subject to the following conditions: 18 | // 19 | // The above copyright notice and this permission notice shall be included in all 20 | // copies or substantial portions of the Software. 21 | // 22 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | // SOFTWARE. 29 | 30 | #import "UITableView+JHNoData.h" 31 | #import "JHNoDataEmptyView.h" 32 | #import 33 | 34 | @implementation UITableView (JHNoData) 35 | 36 | /// exchange methods 37 | + (void)load{ 38 | 39 | Method old = class_getInstanceMethod(self, @selector(reloadData)); 40 | Method new = class_getInstanceMethod(self, @selector(jh_reloadData)); 41 | 42 | method_exchangeImplementations(old, new); 43 | } 44 | 45 | - (void)setJh_showNoDataEmptyView:(BOOL)jh_showNoDataEmptyView{ 46 | objc_setAssociatedObject(self, @selector(jh_showNoDataEmptyView), @(jh_showNoDataEmptyView), OBJC_ASSOCIATION_ASSIGN); 47 | } 48 | 49 | - (BOOL)jh_showNoDataEmptyView{ 50 | return [objc_getAssociatedObject(self, _cmd) boolValue]; 51 | } 52 | 53 | /// custom method 54 | - (void)jh_reloadData 55 | { 56 | [self jh_reloadData]; 57 | 58 | if (![self jh_showNoDataEmptyView]) { 59 | return; 60 | } 61 | 62 | // find UITableViewWrapperView in self.subviews before iOS 11 63 | UIView *mmdView = nil; 64 | Class class = NSClassFromString(@"UITableViewWrapperView"); 65 | for (UIView *view in self.subviews) { 66 | if ([view isKindOfClass:class]) { 67 | mmdView = view; 68 | break; 69 | } 70 | } 71 | 72 | if (!mmdView) { 73 | mmdView = self; 74 | } 75 | 76 | NSInteger totalRows = 0; 77 | 78 | // if self.visibleCells.count > 0, tableView may be not empty. 79 | totalRows = self.visibleCells.count; 80 | 81 | // if self.visibleCells.count == 0, maybe tableHeaderView is too high!!! 82 | if (totalRows == 0) { 83 | for (NSInteger section = 0; section < self.numberOfSections; section++) { 84 | NSInteger rows = [self numberOfRowsInSection:section]; 85 | totalRows += rows; 86 | } 87 | } 88 | 89 | if (totalRows > 0) { 90 | // remove custom views 91 | [mmdView.subviews enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(__kindof UIView * _Nonnull subview, NSUInteger idx, BOOL * _Nonnull stop) { 92 | if ([subview isKindOfClass:[JHNoDataEmptyView class]]) { 93 | [subview removeFromSuperview]; 94 | *stop = YES; 95 | } 96 | }]; 97 | 98 | }else{ 99 | 100 | CGFloat tableHeaderViewHeight = 0; 101 | CGFloat tableFooterViewHeight = 0; 102 | if (self.tableHeaderView) { 103 | tableHeaderViewHeight = CGRectGetHeight(self.tableHeaderView.frame); 104 | } 105 | if (self.tableFooterView) { 106 | tableFooterViewHeight = CGRectGetHeight(self.tableFooterView.frame); 107 | } 108 | 109 | CGFloat height = tableHeaderViewHeight + tableFooterViewHeight; 110 | CGFloat tableViewHeight = CGRectGetHeight(self.frame); 111 | // if headerView's height and footerView' height is bigger than tableView's Height 112 | // there is not need to show the emptyview, because the tableview is full 113 | if (height > tableViewHeight) { 114 | return; 115 | } 116 | 117 | // add custom views in UITableViewWrapperView to offer some infomation. 118 | UILabel *label = nil; 119 | UIImageView *imageView = nil; 120 | 121 | if ([self.dataSource respondsToSelector:@selector(labelForTableViewWhenDataSourceIsEmpty)]) { 122 | label = [self.dataSource performSelector:@selector(labelForTableViewWhenDataSourceIsEmpty)]; 123 | } else if ([self respondsToSelector:@selector(labelForTableViewWhenDataSourceIsEmpty)]) { 124 | label = [self performSelector:@selector(labelForTableViewWhenDataSourceIsEmpty)]; 125 | } 126 | 127 | if ([self.dataSource respondsToSelector:@selector(imageViewForTableViewWhenDataSourceIsEmpty)]) { 128 | imageView = [self.dataSource performSelector:@selector(imageViewForTableViewWhenDataSourceIsEmpty)]; 129 | } else if ([self respondsToSelector:@selector(imageViewForTableViewWhenDataSourceIsEmpty)]) { 130 | imageView = [self performSelector:@selector(imageViewForTableViewWhenDataSourceIsEmpty)]; 131 | } 132 | 133 | // empty view 134 | [[mmdView viewWithTag:20231009] removeFromSuperview]; 135 | 136 | CGFloat offsetY = self.contentOffset.y < 0 ? self.contentOffset.y : 0; 137 | CGRect bounds = CGRectMake(0, height, CGRectGetWidth(mmdView.frame), tableViewHeight - height + offsetY); 138 | JHNoDataEmptyView *emptyView = [JHNoDataEmptyView jh_emptyViewWithLabel:label imageView:imageView bounds:bounds backgroundColor:nil]; 139 | emptyView.tag = 20231009; 140 | [mmdView addSubview:emptyView]; 141 | 142 | if ([self.dataSource respondsToSelector:@selector(emptyViewForTableViewWhenDataSourceIsEmpty:)]) { 143 | [self.dataSource performSelector:@selector(emptyViewForTableViewWhenDataSourceIsEmpty:) withObject:emptyView]; 144 | } else if ([self respondsToSelector:@selector(emptyViewForTableViewWhenDataSourceIsEmpty:)]) { 145 | [self performSelector:@selector(emptyViewForTableViewWhenDataSourceIsEmpty:) withObject:emptyView]; 146 | } 147 | } 148 | } 149 | 150 | @end 151 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 HaoCold 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 | # JHNoDataEmptyView 2 | empty view for tableview and collectionview 3 | - tableview 与 collectionview 的空白占位图 4 | 5 | --- 6 | 7 | # Version 8 | Latest release version: 9 | - [1.2.0](https://github.com/xjh093/JHNoDataEmptyView/releases) 10 | 11 | --- 12 | 13 | # Cocoapods 14 | `pod "JHNoDataEmptyView"` 15 | 16 | --- 17 | 18 | # Logs 19 | ### 2023-10-10 20 | - fix bugs.(Download the master, pod is out of date.) 21 | 22 | ### 2018-12-14 23 | - add Demo and fix bugs. 24 | - header view or footer view is too high. 25 | - remove property 'jh_hideNoDataEmptyView'. 26 | 27 | ### 2018-9-5 28 | - add property 'jh_showNoDataEmptyView'. 29 | - suggest you to use this property, 'jh_hideNoDataEmptyView' is also keeped. You can choose one of them. 30 | - automatic show effect too big, some system's collectionView is also effected. 31 | 32 | ### 2018-7-24 33 | - replace 'jh_showAutomatic' to 'jh_hideNoDataEmptyView'. 34 | - set 'YES' if you do not want to show the 'JHNoDataEmptyView' 35 | 36 | ### 2018-07-23 37 | - ~1.add property 'jh_showAutomatic'.~ 38 | - ~default is 'YES'~ 39 | - ~set 'NO' if you do not want to show the 'JHNoDataEmptyView'~ 40 | 41 | --- 42 | 43 | # More detail in Demo :) 44 | --------------------------------------------------------------------------------