diff --git a/HRVTableView.xcodeproj/project.pbxproj b/HRVTableView.xcodeproj/project.pbxproj new file mode 100644 index 0000000..ab243b5 --- /dev/null +++ b/HRVTableView.xcodeproj/project.pbxproj @@ -0,0 +1,518 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 037FD1CC1843383B00D142A2 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 037FD1CB1843383B00D142A2 /* Foundation.framework */; }; + 037FD1CE1843383B00D142A2 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 037FD1CD1843383B00D142A2 /* CoreGraphics.framework */; }; + 037FD1D01843383B00D142A2 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 037FD1CF1843383B00D142A2 /* UIKit.framework */; }; + 037FD1D61843383B00D142A2 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 037FD1D41843383B00D142A2 /* InfoPlist.strings */; }; + 037FD1D81843383B00D142A2 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 037FD1D71843383B00D142A2 /* main.m */; }; + 037FD1DC1843383B00D142A2 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 037FD1DB1843383B00D142A2 /* AppDelegate.m */; }; + 037FD1DE1843383B00D142A2 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 037FD1DD1843383B00D142A2 /* Images.xcassets */; }; + 037FD1E51843383C00D142A2 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 037FD1E41843383C00D142A2 /* XCTest.framework */; }; + 037FD1E61843383C00D142A2 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 037FD1CB1843383B00D142A2 /* Foundation.framework */; }; + 037FD1E71843383C00D142A2 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 037FD1CF1843383B00D142A2 /* UIKit.framework */; }; + 037FD1EF1843383C00D142A2 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 037FD1ED1843383C00D142A2 /* InfoPlist.strings */; }; + 037FD1F11843383C00D142A2 /* HRVTableViewTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 037FD1F01843383C00D142A2 /* HRVTableViewTests.m */; }; + 037FD1FD1843397A00D142A2 /* rootViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 037FD1FB1843397A00D142A2 /* rootViewController.m */; }; + 037FD1FE1843397A00D142A2 /* rootViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 037FD1FC1843397A00D142A2 /* rootViewController.xib */; }; + 037FD20118433BBF00D142A2 /* HVTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 037FD20018433BBF00D142A2 /* HVTableView.m */; }; + 037FD2071843B43C00D142A2 /* 1.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 037FD2021843B43C00D142A2 /* 1.jpg */; }; + 037FD2081843B43C00D142A2 /* 2.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 037FD2031843B43C00D142A2 /* 2.jpg */; }; + 037FD2091843B43C00D142A2 /* 3.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 037FD2041843B43C00D142A2 /* 3.jpg */; }; + 037FD20A1843B43C00D142A2 /* 4.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 037FD2051843B43C00D142A2 /* 4.jpg */; }; + 037FD20B1843B43C00D142A2 /* 5.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 037FD2061843B43C00D142A2 /* 5.jpg */; }; + 037FD2111843B4A400D142A2 /* 6.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 037FD20C1843B4A400D142A2 /* 6.jpg */; }; + 037FD2121843B4A400D142A2 /* 7.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 037FD20D1843B4A400D142A2 /* 7.jpg */; }; + 037FD2131843B4A400D142A2 /* 8.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 037FD20E1843B4A400D142A2 /* 8.jpg */; }; + 037FD2141843B4A400D142A2 /* 9.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 037FD20F1843B4A400D142A2 /* 9.jpg */; }; + 037FD2151843B4A400D142A2 /* 10.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 037FD2101843B4A400D142A2 /* 10.jpg */; }; + 037FD2171843BB4E00D142A2 /* expandGlyph.png in Resources */ = {isa = PBXBuildFile; fileRef = 037FD2161843BB4E00D142A2 /* expandGlyph.png */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 037FD1E81843383C00D142A2 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 037FD1C01843383B00D142A2 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 037FD1C71843383B00D142A2; + remoteInfo = HRVTableView; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 037FD1C81843383B00D142A2 /* HRVTableView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HRVTableView.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 037FD1CB1843383B00D142A2 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 037FD1CD1843383B00D142A2 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + 037FD1CF1843383B00D142A2 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + 037FD1D31843383B00D142A2 /* HRVTableView-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "HRVTableView-Info.plist"; sourceTree = ""; }; + 037FD1D51843383B00D142A2 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + 037FD1D71843383B00D142A2 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 037FD1D91843383B00D142A2 /* HRVTableView-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "HRVTableView-Prefix.pch"; sourceTree = ""; }; + 037FD1DA1843383B00D142A2 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 037FD1DB1843383B00D142A2 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 037FD1DD1843383B00D142A2 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + 037FD1E31843383C00D142A2 /* HRVTableViewTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = HRVTableViewTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 037FD1E41843383C00D142A2 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; + 037FD1EC1843383C00D142A2 /* HRVTableViewTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "HRVTableViewTests-Info.plist"; sourceTree = ""; }; + 037FD1EE1843383C00D142A2 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + 037FD1F01843383C00D142A2 /* HRVTableViewTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HRVTableViewTests.m; sourceTree = ""; }; + 037FD1FA1843397A00D142A2 /* rootViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rootViewController.h; sourceTree = ""; }; + 037FD1FB1843397A00D142A2 /* rootViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = rootViewController.m; sourceTree = ""; }; + 037FD1FC1843397A00D142A2 /* rootViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = rootViewController.xib; sourceTree = ""; }; + 037FD1FF18433BBF00D142A2 /* HVTableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HVTableView.h; sourceTree = ""; }; + 037FD20018433BBF00D142A2 /* HVTableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HVTableView.m; sourceTree = ""; }; + 037FD2021843B43C00D142A2 /* 1.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = 1.jpg; sourceTree = ""; }; + 037FD2031843B43C00D142A2 /* 2.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = 2.jpg; sourceTree = ""; }; + 037FD2041843B43C00D142A2 /* 3.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = 3.jpg; sourceTree = ""; }; + 037FD2051843B43C00D142A2 /* 4.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = 4.jpg; sourceTree = ""; }; + 037FD2061843B43C00D142A2 /* 5.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = 5.jpg; sourceTree = ""; }; + 037FD20C1843B4A400D142A2 /* 6.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = 6.jpg; sourceTree = ""; }; + 037FD20D1843B4A400D142A2 /* 7.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = 7.jpg; sourceTree = ""; }; + 037FD20E1843B4A400D142A2 /* 8.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = 8.jpg; sourceTree = ""; }; + 037FD20F1843B4A400D142A2 /* 9.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = 9.jpg; sourceTree = ""; }; + 037FD2101843B4A400D142A2 /* 10.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = 10.jpg; sourceTree = ""; }; + 037FD2161843BB4E00D142A2 /* expandGlyph.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = expandGlyph.png; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 037FD1C51843383B00D142A2 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 037FD1CE1843383B00D142A2 /* CoreGraphics.framework in Frameworks */, + 037FD1D01843383B00D142A2 /* UIKit.framework in Frameworks */, + 037FD1CC1843383B00D142A2 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 037FD1E01843383C00D142A2 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 037FD1E51843383C00D142A2 /* XCTest.framework in Frameworks */, + 037FD1E71843383C00D142A2 /* UIKit.framework in Frameworks */, + 037FD1E61843383C00D142A2 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 037FD1BF1843383B00D142A2 = { + isa = PBXGroup; + children = ( + 037FD1D11843383B00D142A2 /* HRVTableView */, + 037FD1EA1843383C00D142A2 /* HRVTableViewTests */, + 037FD1CA1843383B00D142A2 /* Frameworks */, + 037FD1C91843383B00D142A2 /* Products */, + ); + sourceTree = ""; + }; + 037FD1C91843383B00D142A2 /* Products */ = { + isa = PBXGroup; + children = ( + 037FD1C81843383B00D142A2 /* HRVTableView.app */, + 037FD1E31843383C00D142A2 /* HRVTableViewTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 037FD1CA1843383B00D142A2 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 037FD1CB1843383B00D142A2 /* Foundation.framework */, + 037FD1CD1843383B00D142A2 /* CoreGraphics.framework */, + 037FD1CF1843383B00D142A2 /* UIKit.framework */, + 037FD1E41843383C00D142A2 /* XCTest.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 037FD1D11843383B00D142A2 /* HRVTableView */ = { + isa = PBXGroup; + children = ( + 037FD1FF18433BBF00D142A2 /* HVTableView.h */, + 037FD20018433BBF00D142A2 /* HVTableView.m */, + 037FD1FA1843397A00D142A2 /* rootViewController.h */, + 037FD1FB1843397A00D142A2 /* rootViewController.m */, + 037FD1FC1843397A00D142A2 /* rootViewController.xib */, + 037FD1DA1843383B00D142A2 /* AppDelegate.h */, + 037FD1DB1843383B00D142A2 /* AppDelegate.m */, + 037FD1DD1843383B00D142A2 /* Images.xcassets */, + 037FD1D21843383B00D142A2 /* Supporting Files */, + ); + path = HRVTableView; + sourceTree = ""; + }; + 037FD1D21843383B00D142A2 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 037FD2161843BB4E00D142A2 /* expandGlyph.png */, + 037FD2021843B43C00D142A2 /* 1.jpg */, + 037FD2031843B43C00D142A2 /* 2.jpg */, + 037FD2041843B43C00D142A2 /* 3.jpg */, + 037FD2051843B43C00D142A2 /* 4.jpg */, + 037FD2061843B43C00D142A2 /* 5.jpg */, + 037FD20C1843B4A400D142A2 /* 6.jpg */, + 037FD20D1843B4A400D142A2 /* 7.jpg */, + 037FD20E1843B4A400D142A2 /* 8.jpg */, + 037FD20F1843B4A400D142A2 /* 9.jpg */, + 037FD2101843B4A400D142A2 /* 10.jpg */, + 037FD1D31843383B00D142A2 /* HRVTableView-Info.plist */, + 037FD1D41843383B00D142A2 /* InfoPlist.strings */, + 037FD1D71843383B00D142A2 /* main.m */, + 037FD1D91843383B00D142A2 /* HRVTableView-Prefix.pch */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 037FD1EA1843383C00D142A2 /* HRVTableViewTests */ = { + isa = PBXGroup; + children = ( + 037FD1F01843383C00D142A2 /* HRVTableViewTests.m */, + 037FD1EB1843383C00D142A2 /* Supporting Files */, + ); + path = HRVTableViewTests; + sourceTree = ""; + }; + 037FD1EB1843383C00D142A2 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 037FD1EC1843383C00D142A2 /* HRVTableViewTests-Info.plist */, + 037FD1ED1843383C00D142A2 /* InfoPlist.strings */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 037FD1C71843383B00D142A2 /* HRVTableView */ = { + isa = PBXNativeTarget; + buildConfigurationList = 037FD1F41843383C00D142A2 /* Build configuration list for PBXNativeTarget "HRVTableView" */; + buildPhases = ( + 037FD1C41843383B00D142A2 /* Sources */, + 037FD1C51843383B00D142A2 /* Frameworks */, + 037FD1C61843383B00D142A2 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = HRVTableView; + productName = HRVTableView; + productReference = 037FD1C81843383B00D142A2 /* HRVTableView.app */; + productType = "com.apple.product-type.application"; + }; + 037FD1E21843383C00D142A2 /* HRVTableViewTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 037FD1F71843383C00D142A2 /* Build configuration list for PBXNativeTarget "HRVTableViewTests" */; + buildPhases = ( + 037FD1DF1843383C00D142A2 /* Sources */, + 037FD1E01843383C00D142A2 /* Frameworks */, + 037FD1E11843383C00D142A2 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 037FD1E91843383C00D142A2 /* PBXTargetDependency */, + ); + name = HRVTableViewTests; + productName = HRVTableViewTests; + productReference = 037FD1E31843383C00D142A2 /* HRVTableViewTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 037FD1C01843383B00D142A2 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0500; + ORGANIZATIONNAME = "Hamidreza Vakilian"; + TargetAttributes = { + 037FD1E21843383C00D142A2 = { + TestTargetID = 037FD1C71843383B00D142A2; + }; + }; + }; + buildConfigurationList = 037FD1C31843383B00D142A2 /* Build configuration list for PBXProject "HRVTableView" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 037FD1BF1843383B00D142A2; + productRefGroup = 037FD1C91843383B00D142A2 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 037FD1C71843383B00D142A2 /* HRVTableView */, + 037FD1E21843383C00D142A2 /* HRVTableViewTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 037FD1C61843383B00D142A2 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 037FD2151843B4A400D142A2 /* 10.jpg in Resources */, + 037FD2131843B4A400D142A2 /* 8.jpg in Resources */, + 037FD2111843B4A400D142A2 /* 6.jpg in Resources */, + 037FD1D61843383B00D142A2 /* InfoPlist.strings in Resources */, + 037FD2171843BB4E00D142A2 /* expandGlyph.png in Resources */, + 037FD20B1843B43C00D142A2 /* 5.jpg in Resources */, + 037FD20A1843B43C00D142A2 /* 4.jpg in Resources */, + 037FD2071843B43C00D142A2 /* 1.jpg in Resources */, + 037FD2081843B43C00D142A2 /* 2.jpg in Resources */, + 037FD2091843B43C00D142A2 /* 3.jpg in Resources */, + 037FD2121843B4A400D142A2 /* 7.jpg in Resources */, + 037FD2141843B4A400D142A2 /* 9.jpg in Resources */, + 037FD1DE1843383B00D142A2 /* Images.xcassets in Resources */, + 037FD1FE1843397A00D142A2 /* rootViewController.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 037FD1E11843383C00D142A2 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 037FD1EF1843383C00D142A2 /* InfoPlist.strings in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 037FD1C41843383B00D142A2 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 037FD1DC1843383B00D142A2 /* AppDelegate.m in Sources */, + 037FD20118433BBF00D142A2 /* HVTableView.m in Sources */, + 037FD1FD1843397A00D142A2 /* rootViewController.m in Sources */, + 037FD1D81843383B00D142A2 /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 037FD1DF1843383C00D142A2 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 037FD1F11843383C00D142A2 /* HRVTableViewTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 037FD1E91843383C00D142A2 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 037FD1C71843383B00D142A2 /* HRVTableView */; + targetProxy = 037FD1E81843383C00D142A2 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 037FD1D41843383B00D142A2 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 037FD1D51843383B00D142A2 /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; + 037FD1ED1843383C00D142A2 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 037FD1EE1843383C00D142A2 /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 037FD1F21843383C00D142A2 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = 2; + }; + name = Debug; + }; + 037FD1F31843383C00D142A2 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = YES; + ENABLE_NS_ASSERTIONS = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 7.0; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = 2; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 037FD1F51843383C00D142A2 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "HRVTableView/HRVTableView-Prefix.pch"; + INFOPLIST_FILE = "HRVTableView/HRVTableView-Info.plist"; + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = app; + }; + name = Debug; + }; + 037FD1F61843383C00D142A2 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "HRVTableView/HRVTableView-Prefix.pch"; + INFOPLIST_FILE = "HRVTableView/HRVTableView-Info.plist"; + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = app; + }; + name = Release; + }; + 037FD1F81843383C00D142A2 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; + BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/HRVTableView.app/HRVTableView"; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + "$(DEVELOPER_FRAMEWORKS_DIR)", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "HRVTableView/HRVTableView-Prefix.pch"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = "HRVTableViewTests/HRVTableViewTests-Info.plist"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUNDLE_LOADER)"; + WRAPPER_EXTENSION = xctest; + }; + name = Debug; + }; + 037FD1F91843383C00D142A2 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)"; + BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/HRVTableView.app/HRVTableView"; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + "$(DEVELOPER_FRAMEWORKS_DIR)", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "HRVTableView/HRVTableView-Prefix.pch"; + INFOPLIST_FILE = "HRVTableViewTests/HRVTableViewTests-Info.plist"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUNDLE_LOADER)"; + WRAPPER_EXTENSION = xctest; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 037FD1C31843383B00D142A2 /* Build configuration list for PBXProject "HRVTableView" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 037FD1F21843383C00D142A2 /* Debug */, + 037FD1F31843383C00D142A2 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 037FD1F41843383C00D142A2 /* Build configuration list for PBXNativeTarget "HRVTableView" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 037FD1F51843383C00D142A2 /* Debug */, + 037FD1F61843383C00D142A2 /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; + 037FD1F71843383C00D142A2 /* Build configuration list for PBXNativeTarget "HRVTableViewTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 037FD1F81843383C00D142A2 /* Debug */, + 037FD1F91843383C00D142A2 /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; +/* End XCConfigurationList section */ + }; + rootObject = 037FD1C01843383B00D142A2 /* Project object */; +} diff --git a/HRVTableView.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/HRVTableView.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..cd86997 --- /dev/null +++ b/HRVTableView.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/HRVTableView.xcodeproj/project.xcworkspace/xcuserdata/Hamid.xcuserdatad/UserInterfaceState.xcuserstate b/HRVTableView.xcodeproj/project.xcworkspace/xcuserdata/Hamid.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..ec397a9 Binary files /dev/null and b/HRVTableView.xcodeproj/project.xcworkspace/xcuserdata/Hamid.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/HRVTableView.xcodeproj/xcuserdata/Hamid.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/HRVTableView.xcodeproj/xcuserdata/Hamid.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist new file mode 100644 index 0000000..fe2b454 --- /dev/null +++ b/HRVTableView.xcodeproj/xcuserdata/Hamid.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -0,0 +1,5 @@ + + + diff --git a/HRVTableView.xcodeproj/xcuserdata/Hamid.xcuserdatad/xcschemes/HRVTableView.xcscheme b/HRVTableView.xcodeproj/xcuserdata/Hamid.xcuserdatad/xcschemes/HRVTableView.xcscheme new file mode 100644 index 0000000..aad2713 --- /dev/null +++ b/HRVTableView.xcodeproj/xcuserdata/Hamid.xcuserdatad/xcschemes/HRVTableView.xcscheme @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/HRVTableView.xcodeproj/xcuserdata/Hamid.xcuserdatad/xcschemes/xcschememanagement.plist b/HRVTableView.xcodeproj/xcuserdata/Hamid.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..0553333 --- /dev/null +++ b/HRVTableView.xcodeproj/xcuserdata/Hamid.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,27 @@ + + + + + SchemeUserState + + HRVTableView.xcscheme + + orderHint + 0 + + + SuppressBuildableAutocreation + + 037FD1C71843383B00D142A2 + + primary + + + 037FD1E21843383C00D142A2 + + primary + + + + + diff --git a/HRVTableView/1.jpg b/HRVTableView/1.jpg new file mode 100644 index 0000000..ed48479 Binary files /dev/null and b/HRVTableView/1.jpg differ diff --git a/HRVTableView/10.jpg b/HRVTableView/10.jpg new file mode 100644 index 0000000..577cfcf Binary files /dev/null and b/HRVTableView/10.jpg differ diff --git a/HRVTableView/2.jpg b/HRVTableView/2.jpg new file mode 100644 index 0000000..02d308f Binary files /dev/null and b/HRVTableView/2.jpg differ diff --git a/HRVTableView/3.jpg b/HRVTableView/3.jpg new file mode 100644 index 0000000..bb99003 Binary files /dev/null and b/HRVTableView/3.jpg differ diff --git a/HRVTableView/4.jpg b/HRVTableView/4.jpg new file mode 100644 index 0000000..d1ac462 Binary files /dev/null and b/HRVTableView/4.jpg differ diff --git a/HRVTableView/5.jpg b/HRVTableView/5.jpg new file mode 100644 index 0000000..0e284b3 Binary files /dev/null and b/HRVTableView/5.jpg differ diff --git a/HRVTableView/6.jpg b/HRVTableView/6.jpg new file mode 100644 index 0000000..fe49dca Binary files /dev/null and b/HRVTableView/6.jpg differ diff --git a/HRVTableView/7.jpg b/HRVTableView/7.jpg new file mode 100644 index 0000000..6fb1cbc Binary files /dev/null and b/HRVTableView/7.jpg differ diff --git a/HRVTableView/8.jpg b/HRVTableView/8.jpg new file mode 100644 index 0000000..e06fbcc Binary files /dev/null and b/HRVTableView/8.jpg differ diff --git a/HRVTableView/9.jpg b/HRVTableView/9.jpg new file mode 100644 index 0000000..4b2de03 Binary files /dev/null and b/HRVTableView/9.jpg differ diff --git a/HRVTableView/AppDelegate.h b/HRVTableView/AppDelegate.h new file mode 100644 index 0000000..eb17151 --- /dev/null +++ b/HRVTableView/AppDelegate.h @@ -0,0 +1,20 @@ +// +// AppDelegate.h +// HRVTableView +// +// Created by Hamidreza Vakilian on 25/11/2013 +// Copyright (c) 2013 Hamidreza Vakilian. All rights reserved. +// Website: http://www.infracyber.com/ +// Email: xerxes235@yahoo.com +// + +#import +@class rootViewController; + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + +@property (strong, nonatomic) rootViewController *viewController; + +@end diff --git a/HRVTableView/AppDelegate.m b/HRVTableView/AppDelegate.m new file mode 100644 index 0000000..3b776c3 --- /dev/null +++ b/HRVTableView/AppDelegate.m @@ -0,0 +1,60 @@ +// +// AppDelegate.m +// HRVTableView +// +// Created by Hamidreza Vakilian on 25/11/2013 +// Copyright (c) 2013 Hamidreza Vakilian. All rights reserved. +// Website: http://www.infracyber.com/ +// Email: xerxes235@yahoo.com +// + +#import "AppDelegate.h" +#import "rootViewController.h" + +@implementation AppDelegate +//@synthesize viewController; + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait]; + [[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide]; + + self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; + // Override point for customization after application launch. + + self.viewController = [[rootViewController alloc] initWithNibName:@"rootViewController" bundle:nil]; + self.window.rootViewController = self.viewController; + + self.window.backgroundColor = [UIColor whiteColor]; + [self.window makeKeyAndVisible]; + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application +{ + // 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. + // 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. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application +{ + // 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. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application +{ + // 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. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application +{ + // 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. +} + +- (void)applicationWillTerminate:(UIApplication *)application +{ + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/HRVTableView/HRVTableView-Info.plist b/HRVTableView/HRVTableView-Info.plist new file mode 100644 index 0000000..09538c4 --- /dev/null +++ b/HRVTableView/HRVTableView-Info.plist @@ -0,0 +1,41 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + ${PRODUCT_NAME} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + infracyber.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + LSRequiresIPhoneOS + + UIViewControllerBasedStatusBarAppearance + + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/HRVTableView/HRVTableView-Prefix.pch b/HRVTableView/HRVTableView-Prefix.pch new file mode 100644 index 0000000..ccc4f43 --- /dev/null +++ b/HRVTableView/HRVTableView-Prefix.pch @@ -0,0 +1,16 @@ +// +// Prefix header +// +// The contents of this file are implicitly included at the beginning of every source file. +// + +#import + +#ifndef __IPHONE_3_0 +#warning "This project uses features only available in iOS SDK 3.0 and later." +#endif + +#ifdef __OBJC__ + #import + #import +#endif diff --git a/HRVTableView/HVTableView.h b/HRVTableView/HVTableView.h new file mode 100644 index 0000000..24b0c61 --- /dev/null +++ b/HRVTableView/HVTableView.h @@ -0,0 +1,154 @@ +// +// HVTableView.h +// HRVTableView +// +// Created by Hamidreza Vakilian on 25/11/2013 +// Copyright (c) 2013 Hamidreza Vakilian. All rights reserved. +// Website: http://www.infracyber.com/ +// Email: xerxes235@yahoo.com +// + + +// +//*************** HVTableView - UITableView with expand/collapse feature ***************************** +// by hamidreza vakilian +// +// +// This is a subclass of UITableView with expand/collapse feature that may come so handy in many apps. +// The developer can save a lot of time using an expand/collapse tableView instead of creating a detail viewController for +// every cell. I mean the details of each cell can be displayed immediately on the same table without switching to +// another view. On the other hand in my opinion it far more impressive and eye-catching from a regular user's view. +// +// To create an instance of HVTableView you go by code. +// (currently I you can't do it from xib - I will work on that later) +// That's simple as: +// +// HVTableView* myTable = [[HVTableView alloc] initWithFrame:CGRectMake(84, 250, 600, 600) expandOnlyOneCell:NO enableAutoScroll:YES]; +// myTable.HVTableViewDelegate = self; +// myTable.HVTableViewDataSource = self; +// [myTable reloadData]; +// [self.view addSubview:myTable]; + +// Two important parameters when initializing the HVTableView +// if expandOnlyOneCell==TRUE: Just one cell will be expanded at a time. +// if expandOnlyOneCell==FALSE: multiple cells can be expanded at a time +// +// if enableAutoScroll==TRUE: when the user touches a cell, the HVTableView will automatically scroll to it +// if enableAutoScroll==FALSE: when the user touches a cell, the HVTableView won't scroll. but the if the cell was close to the bottom of the table; the lower part of it may go invisible because it grows +// +// +// Your viewController must conform to HVTableViewDelegate, HVTableViewDataSource protocols. Just like the regular +// UITableView +// +// Like before you implement these familiar delegate functions: +// -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView +// -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section +// +// I added a boolean parameter the heightForRowAtIndexPath function so you will return different values for an expanded or a collapsed cell. +// (isExpanded==TRUE: return the size of the cell in expanded state) +// (isExpanded==FALSE: return the size of the cell in collapsed (initial) state) +// +// -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath isExpanded:(BOOL)isexpanded +// +// +// I also added a boolean parameter to the cellForRowAtIndexPath function too. update the cell's content respecting it's state (isExpanded) +// -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath isExpanded:(BOOL)isExpanded +// +// +// Now the interesting functions are here. Implement this function and it will be fired when a cell is going to expand. You can perform your drawings, animations, etc. in this function: +// -(void)tableView:(UITableView *)tableView collapseCell: (UITableViewCell*)cell withIndexPath:(NSIndexPath*) indexPath; +// +// Implement this function. it will be fired when a cell is going to collapse. You can perform your drawings, animations, etc. or clearing up the cell in this function: +// -(void)tableView:(UITableView *)tableView expandCell: (UITableViewCell*)cell withIndexPath:(NSIndexPath*) indexPath; +// +// IMPORTANT NOTE: there are some delegate functions from UITableViewDelegate that I have commented their forwarding. If you need to implement those on your viewController or smth, go to HVTableView.m and uncomment those delegate functions. If you don't uncomment them; your delegate functions won't fire up. +// +// +// This code may contain bugs. I don't garauntee its functionality, but use it on your own risk. I also tried to craft it with best performance, yet it can be optimized more. +// +// +// Please don't hesitate to mail me your feedbacks and suggestions or a bug report. I would be very thankful of your responses. +// +// ON THE BOTTOM LINE: I allow you to use my code in your applications with freedom in making any modifications, but if you are going to do so, or you just like it and want further updates and bug fixes please consider donating me via this url: +// https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=xerxes235%40yahoo%2ecom&lc=AE&item_name=Hamidreza%20Vakilian&item_number=HVTableView%20donation¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted +// +// +// Thanks,.... +// *************************************************************************************************************** + +#import + +@protocol HVTableViewDataSource +@required +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section; +-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath isExpanded:(BOOL)isExpanded; +-(void)tableView:(UITableView *)tableView collapseCell: (UITableViewCell*)cell withIndexPath:(NSIndexPath*) indexPath; +-(void)tableView:(UITableView *)tableView expandCell: (UITableViewCell*)cell withIndexPath:(NSIndexPath*) indexPath; +@optional + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView; +- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section; +- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section; +- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath; +- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath; +- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView; +- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index; +- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath; +- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath; +@end + + +@protocol HVTableViewDelegate +@optional +- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; +- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section NS_AVAILABLE_IOS(6_0); +- (void)tableView:(UITableView *)tableView willDisplayFooterView:(UIView *)view forSection:(NSInteger)section NS_AVAILABLE_IOS(6_0); +- (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath*)indexPath NS_AVAILABLE_IOS(6_0); +- (void)tableView:(UITableView *)tableView didEndDisplayingHeaderView:(UIView *)view forSection:(NSInteger)section NS_AVAILABLE_IOS(6_0); +- (void)tableView:(UITableView *)tableView didEndDisplayingFooterView:(UIView *)view forSection:(NSInteger)section NS_AVAILABLE_IOS(6_0); +-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath isExpanded:(BOOL)isExpanded; +- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section; +- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section; +- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(7_0); +- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForHeaderInSection:(NSInteger)section NS_AVAILABLE_IOS(7_0); +- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForFooterInSection:(NSInteger)section NS_AVAILABLE_IOS(7_0); +- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section; +- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section; +- (UITableViewCellAccessoryType)tableView:(UITableView *)tableView accessoryTypeForRowWithIndexPath:(NSIndexPath *)indexPath NS_DEPRECATED_IOS(2_0, 3_0); +- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath; +- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(6_0); +- (void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(6_0); +- (void)tableView:(UITableView *)tableView didUnhighlightRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(6_0); +- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath; +- (NSIndexPath *)tableView:(UITableView *)tableView willDeselectRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(3_0); +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath; +- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(3_0); +- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath; +- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(3_0); +- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath; +- (void)tableView:(UITableView*)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath; +- (void)tableView:(UITableView*)tableView didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath; +- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath; +- (NSInteger)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath; +- (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(5_0); +- (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender NS_AVAILABLE_IOS(5_0); +- (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender NS_AVAILABLE_IOS(5_0); +@end + +@interface HVTableView : UITableView +{ + + NSIndexPath *selectedIndexPath; + int actionToTake; + NSMutableArray* expandedIndexPaths; + BOOL expandOnlyOneCell; + BOOL enableAutoScroll; +} + +@property (weak,nonatomic) id HVTableViewDelegate; +@property (weak,nonatomic) id HVTableViewDataSource; + +- (id)initWithFrame:(CGRect)frame expandOnlyOneCell:(BOOL)_expandOnlyOneCell enableAutoScroll: (BOOL)_enableAutoScroll; + +@end + diff --git a/HRVTableView/HVTableView.m b/HRVTableView/HVTableView.m new file mode 100644 index 0000000..8723f51 --- /dev/null +++ b/HRVTableView/HVTableView.m @@ -0,0 +1,453 @@ +// +// HVTableView.m +// HRVTableView +// +// Created by Hamidreza Vakilian on 25/11/2013 +// Copyright (c) 2013 Hamidreza Vakilian. All rights reserved. +// Website: http://www.infracyber.com/ +// Email: xerxes235@yahoo.com +// + +#import "HVTableView.h" + +@implementation HVTableView +@synthesize HVTableViewDelegate, HVTableViewDataSource; + +- (id)initWithFrame:(CGRect)frame expandOnlyOneCell:(BOOL)_expandOnlyOneCell enableAutoScroll: (BOOL)_enableAutoScroll +{ + self = [super initWithFrame:frame]; + if (self) { + // Initialization code + expandOnlyOneCell = _expandOnlyOneCell; + if (!expandOnlyOneCell) + expandedIndexPaths = [[NSMutableArray alloc] init]; + + enableAutoScroll = _enableAutoScroll; + + self.delegate = self; + self.dataSource = self; + + } + return self; +} + + +//////// IMPORTANT!!!!!!!!!!!!!!!!!!!!! +//////// UITableViewDataSource Protocol Forwarding +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section +{ + return [HVTableViewDataSource tableView:tableView numberOfRowsInSection:section]; +} + +-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView +{ + return [HVTableViewDataSource numberOfSectionsInTableView:tableView]; +} + +- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section +{ + if ([HVTableViewDataSource respondsToSelector:@selector(tableView:titleForHeaderInSection:)]) + return [HVTableViewDataSource tableView:tableView titleForHeaderInSection:section]; + return nil; +} + +- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section +{ if ([HVTableViewDataSource respondsToSelector:@selector(tableView:titleForFooterInSection:)]) + return [HVTableViewDataSource tableView:tableView titleForFooterInSection:section]; + return nil; +} + +- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath +{ if ([HVTableViewDataSource respondsToSelector:@selector(tableView:canEditRowAtIndexPath:)]) + return [HVTableViewDataSource tableView:tableView canEditRowAtIndexPath:indexPath]; + return NO; +} + +- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([HVTableViewDataSource respondsToSelector:@selector(tableView:canMoveRowAtIndexPath:)]) + return [HVTableViewDataSource tableView:tableView canMoveRowAtIndexPath:indexPath]; + return NO; +} + +- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView +{ + if ([HVTableViewDataSource respondsToSelector:@selector(sectionIndexTitlesForTableView:)]) + return [HVTableViewDataSource sectionIndexTitlesForTableView:tableView]; + return nil; +} + +- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index +{ + if ([HVTableViewDataSource respondsToSelector:@selector(tableView:sectionForSectionIndexTitle:atIndex:)]) + return [HVTableViewDataSource tableView:tableView sectionForSectionIndexTitle:title atIndex:index]; + return 0; +} + +- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([HVTableViewDataSource respondsToSelector:@selector(tableView:commitEditingStyle:forRowAtIndexPath:)]) + return [HVTableViewDataSource tableView:tableView commitEditingStyle:editingStyle forRowAtIndexPath:indexPath]; +} + +- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath +{ + if ([HVTableViewDataSource respondsToSelector:@selector(tableView:moveRowAtIndexPath:toIndexPath:)]) + return [HVTableViewDataSource tableView:tableView moveRowAtIndexPath:sourceIndexPath toIndexPath:destinationIndexPath]; +} + + +-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath +{ + UITableViewCell* cell = [HVTableViewDataSource tableView:tableView cellForRowAtIndexPath:indexPath isExpanded:NO]; + + if (expandOnlyOneCell) + { + if (actionToTake == 0) // e.g. the first time or an expanded cell from before gets in to view + { + if (selectedIndexPath) + if (selectedIndexPath.row == indexPath.row && selectedIndexPath.section == indexPath.section) + { + cell = [HVTableViewDataSource tableView:tableView cellForRowAtIndexPath:indexPath isExpanded:YES];//i want it expanded + return cell; + } + + return cell; //it's already collapsed! + } + + if(actionToTake == -1) + { + [HVTableViewDataSource tableView:tableView collapseCell:cell withIndexPath:indexPath]; + actionToTake = 0; + } + else + { + [HVTableViewDataSource tableView:tableView expandCell:cell withIndexPath:indexPath]; + actionToTake = 0; + } + } + else + { + if (actionToTake == 0) // e.g. the first time or an expanded cell from before gets in to view + { + BOOL alreadyExpanded = NO; + NSIndexPath* correspondingIndexPath; + for (NSIndexPath* anIndexPath in expandedIndexPaths) { + if (anIndexPath.row == indexPath.row && anIndexPath.section == indexPath.section) + {alreadyExpanded = YES; correspondingIndexPath = anIndexPath;} + } + + if (alreadyExpanded) + cell = [HVTableViewDataSource tableView:tableView cellForRowAtIndexPath:indexPath isExpanded:YES]; + else + cell = [HVTableViewDataSource tableView:tableView cellForRowAtIndexPath:indexPath isExpanded:NO]; + + return cell; //it's already collapsed! + + } + + if(actionToTake == -1) + { + [HVTableViewDataSource tableView:tableView collapseCell:cell withIndexPath:indexPath]; + actionToTake = 0; + } + else + { + [HVTableViewDataSource tableView:tableView expandCell:cell withIndexPath:indexPath]; + actionToTake = 0; + } + } + + return cell; +} + +//////// IMPORTANT!!!!!!!!!!!!!!!!!!!!! +//////// IMPORTANT!!!!!!!!!!!!!!!!!!!!! +//////// IMPORTANT!!!!!!!!!!!!!!!!!!!!! +//////// IMPORTANT!!!!!!!!!!!!!!!!!!!!! +//////// IMPORTANT!!!!!!!!!!!!!!!!!!!!! +//////// UITableViewDelegate Protocol Forwarding +//////// NOTE::::: If you want to use any of these protocols in your code; you must uncomment it. I have comment them for performance reasons +/* +- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([HVTableViewDelegate respondsToSelector:@selector(tableView:willDisplayCell:forRowAtIndexPath:)]) + [HVTableViewDelegate tableView:tableView willDisplayCell:cell forRowAtIndexPath:indexPath]; +} + +-(void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section +{ + if ([HVTableViewDelegate respondsToSelector:@selector(tableView:willDisplayHeaderView:forSection:)]) + [HVTableViewDelegate tableView:tableView willDisplayHeaderView:view forSection:section]; +} + +-(void)tableView:(UITableView *)tableView willDisplayFooterView:(UIView *)view forSection:(NSInteger)section +{ + if ([HVTableViewDelegate respondsToSelector:@selector(tableView:willDisplayFooterView:forSection:)]) + [HVTableViewDelegate tableView:tableView willDisplayFooterView:view forSection:section]; +} + +-(void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([HVTableViewDelegate respondsToSelector:@selector(tableView:didEndDisplayingCell:forRowAtIndexPath:)]) + [HVTableViewDelegate tableView:tableView didEndDisplayingCell:cell forRowAtIndexPath:indexPath]; +} + +- (void)tableView:(UITableView *)tableView didEndDisplayingHeaderView:(UIView *)view forSection:(NSInteger)section +{ + if ([HVTableViewDelegate respondsToSelector:@selector(tableView:didEndDisplayingHeaderView:forSection:)]) + [HVTableViewDelegate tableView:tableView didEndDisplayingHeaderView:view forSection:section]; +} + +- (void)tableView:(UITableView *)tableView didEndDisplayingFooterView:(UIView *)view forSection:(NSInteger)section +{ + if ([HVTableViewDelegate respondsToSelector:@selector(tableView:didEndDisplayingFooterView:forSection:)]) + [HVTableViewDelegate tableView:tableView didEndDisplayingFooterView:view forSection:section]; +} +- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section +{ + if ([HVTableViewDelegate respondsToSelector:@selector(tableView:heightForHeaderInSection:)]) + return [HVTableViewDelegate tableView:tableView heightForHeaderInSection:section]; + return 0; +} + +- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section +{ + if ([HVTableViewDelegate respondsToSelector:@selector(tableView:heightForFooterInSection:)]) + return [HVTableViewDelegate tableView:tableView heightForFooterInSection:section]; + return 0; +} + +- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(7_0) +{ + if ([HVTableViewDelegate respondsToSelector:@selector(tableView:estimatedHeightForRowAtIndexPath:)]) + return [HVTableViewDelegate tableView:tableView estimatedHeightForRowAtIndexPath:indexPath]; + return 100; +} + +- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForHeaderInSection:(NSInteger)section NS_AVAILABLE_IOS(7_0) +{ + if ([HVTableViewDelegate respondsToSelector:@selector(tableView:estimatedHeightForHeaderInSection:)]) + return [HVTableViewDelegate tableView:tableView estimatedHeightForHeaderInSection:section]; + return 0; +} + +- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForFooterInSection:(NSInteger)section NS_AVAILABLE_IOS(7_0); +{ + if ([HVTableViewDelegate respondsToSelector:@selector(tableView:estimatedHeightForFooterInSection:)]) + return [HVTableViewDelegate tableView:tableView estimatedHeightForFooterInSection:section]; + return 0; +} + +- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section +{ + if ([HVTableViewDelegate respondsToSelector:@selector(tableView:viewForHeaderInSection:)]) + return [HVTableViewDelegate tableView:tableView viewForHeaderInSection:section]; + return nil; +} +- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section +{ + if ([HVTableViewDelegate respondsToSelector:@selector(tableView:viewForFooterInSection:)]) + return [HVTableViewDelegate tableView:tableView viewForFooterInSection:section]; + return nil; +} + +- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath +{ + if ([HVTableViewDelegate respondsToSelector:@selector(tableView:accessoryButtonTappedForRowWithIndexPath:)]) + [HVTableViewDelegate tableView:tableView accessoryButtonTappedForRowWithIndexPath:indexPath]; +} + +- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([HVTableViewDelegate respondsToSelector:@selector(tableView:shouldHighlightRowAtIndexPath:)]) + return [HVTableViewDelegate tableView:tableView shouldHighlightRowAtIndexPath:indexPath]; + return YES; +} +- (void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([HVTableViewDelegate respondsToSelector:@selector(tableView:didHighlightRowAtIndexPath:)]) + [HVTableViewDelegate tableView:tableView didHighlightRowAtIndexPath:indexPath]; +} +- (void)tableView:(UITableView *)tableView didUnhighlightRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([HVTableViewDelegate respondsToSelector:@selector(tableView:didUnhighlightRowAtIndexPath:)]) + [HVTableViewDelegate tableView:tableView didUnhighlightRowAtIndexPath:indexPath]; +} +- (NSIndexPath *)tableView:(UITableView *)tableView willDeselectRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([HVTableViewDelegate respondsToSelector:@selector(tableView:willDeselectRowAtIndexPath:)]) + return [HVTableViewDelegate tableView:tableView willDeselectRowAtIndexPath:indexPath]; + return nil; +} + +- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([HVTableViewDelegate respondsToSelector:@selector(tableView:didDeselectRowAtIndexPath:)]) + [HVTableViewDelegate tableView:tableView didDeselectRowAtIndexPath:indexPath]; +} +- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([HVTableViewDelegate respondsToSelector:@selector(tableView:editingStyleForRowAtIndexPath:)]) + return [HVTableViewDelegate tableView:tableView editingStyleForRowAtIndexPath:indexPath]; + return UITableViewCellEditingStyleNone; +} +- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([HVTableViewDelegate respondsToSelector:@selector(tableView:titleForDeleteConfirmationButtonForRowAtIndexPath:)]) + return [HVTableViewDelegate tableView:tableView titleForDeleteConfirmationButtonForRowAtIndexPath:indexPath]; + return nil; +} +- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([HVTableViewDelegate respondsToSelector:@selector(tableView:shouldIndentWhileEditingRowAtIndexPath:)]) + return [HVTableViewDelegate tableView:tableView shouldIndentWhileEditingRowAtIndexPath:indexPath]; + return NO; +} +- (void)tableView:(UITableView*)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([HVTableViewDelegate respondsToSelector:@selector(tableView:willBeginEditingRowAtIndexPath:)]) + [HVTableViewDelegate tableView:tableView willBeginEditingRowAtIndexPath:indexPath]; +} +- (void)tableView:(UITableView*)tableView didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([HVTableViewDelegate respondsToSelector:@selector(tableView:didEndEditingRowAtIndexPath:)]) + [HVTableViewDelegate tableView:tableView didEndEditingRowAtIndexPath:indexPath]; +} +- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath +{ + if ([HVTableViewDelegate respondsToSelector:@selector(tableView:targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath:)]) + return [HVTableViewDelegate tableView:tableView targetIndexPathForMoveFromRowAtIndexPath:sourceIndexPath toProposedIndexPath:proposedDestinationIndexPath]; + return nil; +} +- (NSInteger)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([HVTableViewDelegate respondsToSelector:@selector(tableView:indentationLevelForRowAtIndexPath:)]) + return [HVTableViewDelegate tableView:tableView indentationLevelForRowAtIndexPath:indexPath]; + return 0; +} +- (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([HVTableViewDelegate respondsToSelector:@selector(tableView:shouldShowMenuForRowAtIndexPath:)]) + return [HVTableViewDelegate tableView:tableView shouldShowMenuForRowAtIndexPath:indexPath]; + return YES; +} +- (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender +{ + if ([HVTableViewDelegate respondsToSelector:@selector(tableView:canPerformAction:forRowAtIndexPath:withSender:)]) + return [HVTableViewDelegate tableView:tableView canPerformAction:action forRowAtIndexPath:indexPath withSender:sender]; + return NO; +} +- (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender +{ + if ([HVTableViewDelegate respondsToSelector:@selector(tableView:performAction:forRowAtIndexPath:withSender:)]) + return [HVTableViewDelegate tableView:tableView performAction:action forRowAtIndexPath:indexPath withSender:sender]; +} +*/ + +-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath +{ + if (expandOnlyOneCell) + { + if (selectedIndexPath) + if(selectedIndexPath.row == indexPath.row && selectedIndexPath.section == indexPath.section) + return [HVTableViewDelegate tableView:tableView heightForRowAtIndexPath:indexPath isExpanded:YES]; + + return [HVTableViewDelegate tableView:tableView heightForRowAtIndexPath:indexPath isExpanded:NO]; + } + else + { + BOOL alreadyExpanded = NO; + NSIndexPath* correspondingIndexPath; + for (NSIndexPath* anIndexPath in expandedIndexPaths) { + if (anIndexPath.row == indexPath.row && anIndexPath.section == indexPath.section) + {alreadyExpanded = YES; correspondingIndexPath = anIndexPath;} + } + if (alreadyExpanded) + return [HVTableViewDelegate tableView:tableView heightForRowAtIndexPath:indexPath isExpanded:YES]; + else + return [HVTableViewDelegate tableView:tableView heightForRowAtIndexPath:indexPath isExpanded:NO]; + } +} + + +-(NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath +{ + return indexPath; +} + +-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath +{ + + if (expandOnlyOneCell) + { + if (selectedIndexPath) + if (selectedIndexPath.row != -1 && selectedIndexPath.row != -2) //collapse the last expanded item (if any) + { + BOOL dontExpandNewCell = NO; + if (selectedIndexPath.row == indexPath.row && selectedIndexPath.section == indexPath.section) + dontExpandNewCell = YES; + + NSIndexPath* tmp = [NSIndexPath indexPathForRow:selectedIndexPath.row inSection:selectedIndexPath.section];//tmp now holds the last expanded item + selectedIndexPath = [NSIndexPath indexPathForRow:-1 inSection:0]; + + actionToTake = -1; + + [tableView beginUpdates]; + [tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:tmp] withRowAnimation:UITableViewRowAnimationAutomatic]; + [tableView endUpdates]; + + if (dontExpandNewCell) return; //the same expanded cell was touched and now I collapsed it. No new cell is touched + } + + actionToTake = 1; + ///expand the new touched item + + selectedIndexPath = indexPath; + [tableView beginUpdates]; + [tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; + [tableView endUpdates]; + if (enableAutoScroll) + [tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES]; + + } + else + { + BOOL alreadyExpanded = NO; + NSIndexPath* correspondingIndexPath; + for (NSIndexPath* anIndexPath in expandedIndexPaths) { + if (anIndexPath.row == indexPath.row && anIndexPath.section == indexPath.section) + {alreadyExpanded = YES; correspondingIndexPath = anIndexPath;} + } + + if (alreadyExpanded)////collapse it! + { + actionToTake = -1; + [expandedIndexPaths removeObject:correspondingIndexPath]; + [tableView beginUpdates]; + [tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; + [tableView endUpdates]; + } + else ///expand it! + { + actionToTake = 1; + [expandedIndexPaths addObject:indexPath]; + [tableView beginUpdates]; + [tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; + [tableView endUpdates]; + if (enableAutoScroll) + [tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES]; + } + } +} + +/* +// Only override drawRect: if you perform custom drawing. +// An empty implementation adversely affects performance during animation. +- (void)drawRect:(CGRect)rect +{ + // Drawing code +} +*/ + +@end diff --git a/HRVTableView/Images.xcassets/AppIcon.appiconset/Contents.json b/HRVTableView/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..a4645e6 --- /dev/null +++ b/HRVTableView/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,38 @@ +{ + "images" : [ + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/HRVTableView/Images.xcassets/LaunchImage.launchimage/Contents.json b/HRVTableView/Images.xcassets/LaunchImage.launchimage/Contents.json new file mode 100644 index 0000000..a0ad363 --- /dev/null +++ b/HRVTableView/Images.xcassets/LaunchImage.launchimage/Contents.json @@ -0,0 +1,36 @@ +{ + "images" : [ + { + "orientation" : "portrait", + "idiom" : "ipad", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "1x" + }, + { + "orientation" : "landscape", + "idiom" : "ipad", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "1x" + }, + { + "orientation" : "portrait", + "idiom" : "ipad", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "2x" + }, + { + "orientation" : "landscape", + "idiom" : "ipad", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/HRVTableView/en.lproj/InfoPlist.strings b/HRVTableView/en.lproj/InfoPlist.strings new file mode 100644 index 0000000..477b28f --- /dev/null +++ b/HRVTableView/en.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ + diff --git a/HRVTableView/expandGlyph.png b/HRVTableView/expandGlyph.png new file mode 100644 index 0000000..09bb787 Binary files /dev/null and b/HRVTableView/expandGlyph.png differ diff --git a/HRVTableView/main.m b/HRVTableView/main.m new file mode 100644 index 0000000..98a2faf --- /dev/null +++ b/HRVTableView/main.m @@ -0,0 +1,18 @@ +// +// main.m +// HRVTableView +// +// Created by hAmidReza on 9/4/92. +// Copyright (c) 1392 hAmidReza. All rights reserved. +// + +#import + +#import "AppDelegate.h" + +int main(int argc, char * argv[]) +{ + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/HRVTableView/rootViewController.h b/HRVTableView/rootViewController.h new file mode 100644 index 0000000..c411a53 --- /dev/null +++ b/HRVTableView/rootViewController.h @@ -0,0 +1,21 @@ +// +// rootViewController.h +// HRVTableView +// +// Created by Hamidreza Vakilian on 25/11/2013 +// Copyright (c) 2013 Hamidreza Vakilian. All rights reserved. +// Website: http://www.infracyber.com/ +// Email: xerxes235@yahoo.com +// + +#import +#import "HVTableView.h" + + +@interface rootViewController : UIViewController +{ + HVTableView* myTable; + NSArray* cellTitles; +} + +@end diff --git a/HRVTableView/rootViewController.m b/HRVTableView/rootViewController.m new file mode 100644 index 0000000..fd44bea --- /dev/null +++ b/HRVTableView/rootViewController.m @@ -0,0 +1,163 @@ +// +// rootViewController.m +// HRVTableView +// +// Created by Hamidreza Vakilian on 25/11/2013 +// Copyright (c) 2013 Hamidreza Vakilian. All rights reserved. +// Website: http://www.infracyber.com/ +// Email: xerxes235@yahoo.com +// + +// *************************** MUST READ ****************************************************** +// +// This is a working example of HVTableView class. I used some stock photos to present it +// in a more fantastic way, So please don't use any of included jpegs in this project anywhere. +// +// I didn't subclass a UITableViewCell. As you will see I will create the "purchase now!" button and +// I remove very soon. This is not the best way. You would better off subclassing UITableViewCell +// and reuse the subviews on the cell, not recreating each time it appears. I didn't have much time +// to do that for simple example. Just to show you, how easily you can work with HVTableView and +// use it in your apps. +// +// ************************************************************************************************* + + +#import "rootViewController.h" + +@interface rootViewController () + +@end + +@implementation rootViewController + +- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil +{ + self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; + if (self) { + // TABLE CREATION - currently only availble through code! because I have customized the init function! + myTable = [[HVTableView alloc] initWithFrame:CGRectMake(84, 250, 600, 600) expandOnlyOneCell:NO enableAutoScroll:YES]; + myTable.HVTableViewDelegate = self; + myTable.HVTableViewDataSource = self; + [myTable reloadData]; + [self.view addSubview:myTable]; + + /////////////SETTING TABLEVIEW LAYOUT + [myTable setTranslatesAutoresizingMaskIntoConstraints:NO]; + NSLayoutConstraint* myTableWidthCon = [NSLayoutConstraint constraintWithItem:myTable attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:600]; + NSLayoutConstraint* myTableBottomCon = [NSLayoutConstraint constraintWithItem:myTable attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1.0 constant:-110]; + NSLayoutConstraint* myTableCenterXCon = [NSLayoutConstraint constraintWithItem:myTable attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0]; + NSLayoutConstraint* myTableTopCon = [NSLayoutConstraint constraintWithItem:myTable attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0 constant:+165]; + [self.view addConstraints:@[myTableBottomCon, myTableCenterXCon, myTableWidthCon, myTableTopCon]]; + + ////////////storing the title labels in an array so we will use it in cellForRowAtIndexPath + cellTitles = @[@"Twitowie", @"Bill Greyskull", @"Moonglampers", @"Psit", @"Duncan WJ Palmer", @"Sajuma", @"Victor_lee", @"Jugger-naut", @"Javiersanagustin", @"Velouria!"]; + + } + return self; +} + +//perform your expand stuff (may include animation) for cell here. It will be called when the user touches a cell +-(void)tableView:(UITableView *)tableView expandCell:(UITableViewCell *)cell withIndexPath:(NSIndexPath *)indexPath +{ + [[cell.contentView viewWithTag:10] removeFromSuperview]; + UIButton* purchaseButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; + purchaseButton.frame = CGRectMake(600, 150, 120, 40); + purchaseButton.alpha = 0; + [purchaseButton setTitle:@"Purchase Now!" forState:UIControlStateNormal]; + purchaseButton.titleLabel.font = [UIFont fontWithName:@"HelveticaNeue-LightItalic" size:13]; + purchaseButton.backgroundColor = [UIColor grayColor]; + [purchaseButton setTintColor:[UIColor whiteColor]]; + [cell.contentView addSubview:purchaseButton]; + purchaseButton.tag = 10; + + [UIView animateWithDuration:.5 animations:^{ + cell.detailTextLabel.text = @"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."; + purchaseButton.frame = CGRectMake(450, 150, 120, 40); + purchaseButton.alpha = 1; + [cell.contentView viewWithTag:7].transform = CGAffineTransformMakeRotation(3.14); + }]; +} + +//perform your collapse stuff (may include animation) for cell here. It will be called when the user touches an expanded cell so it gets collapsed or the table is in the expandOnlyOneCell satate and the user touches another item, So the last expanded item has to collapse +-(void)tableView:(UITableView *)tableView collapseCell:(UITableViewCell *)cell withIndexPath:(NSIndexPath *)indexPath +{ + [cell.contentView viewWithTag:7].transform = CGAffineTransformMakeRotation(0); +} + +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + +-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView +{ + return 1; +} + +-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section +{ + return 10; +} + +-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath isExpanded:(BOOL)isexpanded +{ + //you can define different heights for each cell. (then you probably have to calculate the height or e.g. read pre-calculated heights from an array + if (isexpanded) + return 200; + + return 100; +} + +-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath isExpanded:(BOOL)isExpanded +{ + static NSString *CellIdentifier = @"aCell"; + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; + if (!cell) + { + cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier]; + cell.selectionStyle = UITableViewCellSelectionStyleNone; + + UIImageView* expandGlyph = [[UIImageView alloc] initWithFrame:CGRectMake(560, 45, 15, 10)]; + expandGlyph.image = [UIImage imageNamed:@"expandGlyph.png"]; + expandGlyph.tag = 7; + [cell.contentView addSubview:expandGlyph]; + cell.detailTextLabel.lineBreakMode = NSLineBreakByWordWrapping; + cell.detailTextLabel.numberOfLines = 0; + } + + //alternative background colors for better division ;) + if (indexPath.row %2 ==1) + cell.backgroundColor = [UIColor colorWithRed:.9 green:.9 blue:.9 alpha:1]; + else + cell.backgroundColor = [UIColor colorWithRed:.8 green:.8 blue:.8 alpha:1]; + + + cell.textLabel.text = [cellTitles objectAtIndex:indexPath.row % 10 ]; + cell.imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"%d.jpg", indexPath.row % 10 + 1]]; + + + if (!isExpanded) //prepare the cell as if it was collapsed! (without any animation!) + { + cell.detailTextLabel.text = @"Lorem ipsum dolor sit amet"; + [cell.contentView viewWithTag:7].transform = CGAffineTransformMakeRotation(0); + } + else ///prepare the cell as if it was expanded! (without any animation!) + { + cell.detailTextLabel.text = @"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."; + [cell.contentView viewWithTag:7].transform = CGAffineTransformMakeRotation(3.14); + + [[cell.contentView viewWithTag:10] removeFromSuperview]; + UIButton* purchaseButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; + purchaseButton.frame = CGRectMake(500, 150, 80, 40); + [purchaseButton setTitle:@"Purchase Now!" forState:UIControlStateNormal]; + purchaseButton.titleLabel.font = [UIFont fontWithName:@"HelveticaNeue-LightItalic" size:10]; + purchaseButton.backgroundColor = [UIColor grayColor]; + [purchaseButton setTintColor:[UIColor whiteColor]]; + [cell.contentView addSubview:purchaseButton]; + purchaseButton.tag = 10; + } + return cell; +} + +@end diff --git a/HRVTableView/rootViewController.xib b/HRVTableView/rootViewController.xib new file mode 100644 index 0000000..bb49b60 --- /dev/null +++ b/HRVTableView/rootViewController.xib @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/HRVTableViewTests/HRVTableViewTests-Info.plist b/HRVTableViewTests/HRVTableViewTests-Info.plist new file mode 100644 index 0000000..a9cd398 --- /dev/null +++ b/HRVTableViewTests/HRVTableViewTests-Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + infracyber.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/HRVTableViewTests/HRVTableViewTests.m b/HRVTableViewTests/HRVTableViewTests.m new file mode 100644 index 0000000..3c46c88 --- /dev/null +++ b/HRVTableViewTests/HRVTableViewTests.m @@ -0,0 +1,34 @@ +// +// HRVTableViewTests.m +// HRVTableViewTests +// +// Created by hAmidReza on 9/4/92. +// Copyright (c) 1392 hAmidReza. All rights reserved. +// + +#import + +@interface HRVTableViewTests : XCTestCase + +@end + +@implementation HRVTableViewTests + +- (void)setUp +{ + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown +{ + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)testExample +{ + XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__); +} + +@end diff --git a/HRVTableViewTests/en.lproj/InfoPlist.strings b/HRVTableViewTests/en.lproj/InfoPlist.strings new file mode 100644 index 0000000..477b28f --- /dev/null +++ b/HRVTableViewTests/en.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ + diff --git a/README.md b/README.md new file mode 100644 index 0000000..821f3dd --- /dev/null +++ b/README.md @@ -0,0 +1,66 @@ +// +//*************** HVTableView - UITableView with expand/collapse feature ***************************** +// by hamidreza vakilian +// +// +// This is a subclass of UITableView with expand/collapse feature that may come so handy in many apps. +// The developer can save a lot of time using an expand/collapse tableView instead of creating a detail viewController for +// every cell. I mean the details of each cell can be displayed immediately on the same table without switching to +// another view. On the other hand in my opinion it far more impressive and eye-catching from a regular user's view. +// +// To create an instance of HVTableView you go by code. +// (currently I you can't do it from xib - I will work on that later) +// That's simple as: +// +// HVTableView* myTable = [[HVTableView alloc] initWithFrame:CGRectMake(84, 250, 600, 600) expandOnlyOneCell:NO enableAutoScroll:YES]; +// myTable.HVTableViewDelegate = self; +// myTable.HVTableViewDataSource = self; +// [myTable reloadData]; +// [self.view addSubview:myTable]; + +// Two important parameters when initializing the HVTableView +// if expandOnlyOneCell==TRUE: Just one cell will be expanded at a time. +// if expandOnlyOneCell==FALSE: multiple cells can be expanded at a time +// +// if enableAutoScroll==TRUE: when the user touches a cell, the HVTableView will automatically scroll to it +// if enableAutoScroll==FALSE: when the user touches a cell, the HVTableView won't scroll. but the if the cell was close to the bottom of the table; the lower part of it may go invisible because it grows +// +// +// Your viewController must conform to HVTableViewDelegate, HVTableViewDataSource protocols. Just like the regular +// UITableView +// +// Like before you implement these familiar delegate functions: +// -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView +// -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section +// +// I added a boolean parameter the heightForRowAtIndexPath function so you will return different values for an expanded or a collapsed cell. +// (isExpanded==TRUE: return the size of the cell in expanded state) +// (isExpanded==FALSE: return the size of the cell in collapsed (initial) state) +// +// -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath isExpanded:(BOOL)isexpanded +// +// +// I also added a boolean parameter to the cellForRowAtIndexPath function too. update the cell's content respecting it's state (isExpanded) +// -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath isExpanded:(BOOL)isExpanded +// +// +// Now the interesting functions are here. Implement this function and it will be fired when a cell is going to expand. You can perform your drawings, animations, etc. in this function: +// -(void)tableView:(UITableView *)tableView collapseCell: (UITableViewCell*)cell withIndexPath:(NSIndexPath*) indexPath; +// +// Implement this function. it will be fired when a cell is going to collapse. You can perform your drawings, animations, etc. or clearing up the cell in this function: +// -(void)tableView:(UITableView *)tableView expandCell: (UITableViewCell*)cell withIndexPath:(NSIndexPath*) indexPath; +// +// IMPORTANT NOTE: there are some delegate functions from UITableViewDelegate that I have commented their forwarding. If you need to implement those on your viewController or smth, go to HVTableView.m and uncomment those delegate functions. If you don't uncomment them; your delegate functions won't fire up. +// +// +// This code may contain bugs. I don't garauntee its functionality, but use it on your own risk. I also tried to craft it with best performance, yet it can be optimized more. +// +// +// Please don't hesitate to mail me your feedbacks and suggestions or a bug report. I would be very thankful of your responses. +// +// ON THE BOTTOM LINE: I allow you to use my code in your applications with freedom in making any modifications, but if you are going to do so, or you just like it and want further updates and bug fixes please consider donating me via this url: +// https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=xerxes235%40yahoo%2ecom&lc=AE&item_name=Hamidreza%20Vakilian&item_number=HVTableView%20donation¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted +// +// +// Thanks,.... +// *************************************************************************************************************** \ No newline at end of file