├── .DS_Store ├── JhScrollActionSheetView.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ │ ├── jh.xcuserdatad │ │ └── UserInterfaceState.xcuserstate │ │ └── lantongmac.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ ├── jh.xcuserdatad │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ │ └── xcschememanagement.plist │ └── lantongmac.xcuserdatad │ └── xcschemes │ └── xcschememanagement.plist ├── JhScrollActionSheetView ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ ├── .DS_Store │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── Contents.json │ ├── other │ │ ├── Contents.json │ │ ├── copylink.imageset │ │ │ ├── Contents.json │ │ │ ├── copylink@2x.png │ │ │ └── copylink@3x.png │ │ └── fontsize.imageset │ │ │ ├── Contents.json │ │ │ ├── fontsize@2x.png │ │ │ └── fontsize@3x.png │ └── share │ │ ├── Contents.json │ │ ├── friends.imageset │ │ ├── Contents.json │ │ ├── friends@2x.png │ │ └── friends@3x.png │ │ ├── kongjian.imageset │ │ ├── Contents.json │ │ ├── kongjian@2x.png │ │ └── kongjian@3x.png │ │ ├── qq.imageset │ │ ├── Contents.json │ │ ├── qq@2x.png │ │ └── qq@3x.png │ │ ├── sina.imageset │ │ ├── Contents.json │ │ ├── sina@2x.png │ │ └── sina@3x.png │ │ └── weixing.imageset │ │ ├── Contents.json │ │ ├── weixing@2x.png │ │ └── weixing@3x.png ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Info.plist ├── JhScrollActionSheet │ ├── JhPageItemCell.h │ ├── JhPageItemCell.m │ ├── JhPageItemCell.xib │ ├── JhPageItemModel.h │ ├── JhPageItemModel.m │ ├── JhScrollActionSheetView.h │ └── JhScrollActionSheetView.m ├── MJExtension │ ├── LICENSE │ ├── MJExtension │ │ ├── MJExtension.h │ │ ├── MJExtensionConst.h │ │ ├── MJExtensionConst.m │ │ ├── MJFoundation.h │ │ ├── MJFoundation.m │ │ ├── MJProperty.h │ │ ├── MJProperty.m │ │ ├── MJPropertyKey.h │ │ ├── MJPropertyKey.m │ │ ├── MJPropertyType.h │ │ ├── MJPropertyType.m │ │ ├── NSObject+MJClass.h │ │ ├── NSObject+MJClass.m │ │ ├── NSObject+MJCoding.h │ │ ├── NSObject+MJCoding.m │ │ ├── NSObject+MJKeyValue.h │ │ ├── NSObject+MJKeyValue.m │ │ ├── NSObject+MJProperty.h │ │ ├── NSObject+MJProperty.m │ │ ├── NSString+MJExtension.h │ │ └── NSString+MJExtension.m │ └── README.md ├── ViewController.h ├── ViewController.m ├── main.m └── screenshots │ ├── .DS_Store │ ├── 0.gif │ ├── 1.png │ ├── 2.png │ └── 3.png ├── JhScrollActionSheetViewTests ├── Info.plist └── JhScrollActionSheetViewTests.m ├── JhScrollActionSheetViewUITests ├── Info.plist └── JhScrollActionSheetViewUITests.m └── README.md /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iotjin/JhScrollActionSheetView/074153497b9d9ca5d9bf8f1bb640de4d73a837ab/.DS_Store -------------------------------------------------------------------------------- /JhScrollActionSheetView.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | E92F7BB821ACF2F200BC3817 /* 0.gif in Resources */ = {isa = PBXBuildFile; fileRef = E92F7BB421ACF2F100BC3817 /* 0.gif */; }; 11 | E92F7BB921ACF2F200BC3817 /* 2.png in Resources */ = {isa = PBXBuildFile; fileRef = E92F7BB521ACF2F100BC3817 /* 2.png */; }; 12 | E92F7BBA21ACF2F200BC3817 /* 3.png in Resources */ = {isa = PBXBuildFile; fileRef = E92F7BB621ACF2F100BC3817 /* 3.png */; }; 13 | E92F7BBB21ACF2F200BC3817 /* 1.png in Resources */ = {isa = PBXBuildFile; fileRef = E92F7BB721ACF2F100BC3817 /* 1.png */; }; 14 | E9CFAA5221AB864E003066A1 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = E9CFAA5121AB864E003066A1 /* AppDelegate.m */; }; 15 | E9CFAA5521AB864E003066A1 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E9CFAA5421AB864E003066A1 /* ViewController.m */; }; 16 | E9CFAA5821AB864E003066A1 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E9CFAA5621AB864E003066A1 /* Main.storyboard */; }; 17 | E9CFAA5A21AB864F003066A1 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E9CFAA5921AB864F003066A1 /* Assets.xcassets */; }; 18 | E9CFAA5D21AB864F003066A1 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E9CFAA5B21AB864F003066A1 /* LaunchScreen.storyboard */; }; 19 | E9CFAA6021AB864F003066A1 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = E9CFAA5F21AB864F003066A1 /* main.m */; }; 20 | E9CFAA6A21AB864F003066A1 /* JhScrollActionSheetViewTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E9CFAA6921AB864F003066A1 /* JhScrollActionSheetViewTests.m */; }; 21 | E9CFAA7521AB864F003066A1 /* JhScrollActionSheetViewUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = E9CFAA7421AB864F003066A1 /* JhScrollActionSheetViewUITests.m */; }; 22 | E9CFAA8421AB8673003066A1 /* JhScrollActionSheetView.m in Sources */ = {isa = PBXBuildFile; fileRef = E9CFAA8321AB8673003066A1 /* JhScrollActionSheetView.m */; }; 23 | E9CFAA8F21AB9444003066A1 /* JhPageItemCell.m in Sources */ = {isa = PBXBuildFile; fileRef = E9CFAA8A21AB9443003066A1 /* JhPageItemCell.m */; }; 24 | E9CFAA9021AB9444003066A1 /* JhPageItemModel.m in Sources */ = {isa = PBXBuildFile; fileRef = E9CFAA8B21AB9443003066A1 /* JhPageItemModel.m */; }; 25 | E9CFAA9121AB9444003066A1 /* JhPageItemCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = E9CFAA8C21AB9443003066A1 /* JhPageItemCell.xib */; }; 26 | E9CFAAAB21AB9795003066A1 /* MJPropertyType.m in Sources */ = {isa = PBXBuildFile; fileRef = E9CFAA9721AB9795003066A1 /* MJPropertyType.m */; }; 27 | E9CFAAAC21AB9795003066A1 /* NSObject+MJKeyValue.m in Sources */ = {isa = PBXBuildFile; fileRef = E9CFAA9A21AB9795003066A1 /* NSObject+MJKeyValue.m */; }; 28 | E9CFAAAD21AB9795003066A1 /* MJProperty.m in Sources */ = {isa = PBXBuildFile; fileRef = E9CFAA9B21AB9795003066A1 /* MJProperty.m */; }; 29 | E9CFAAAE21AB9795003066A1 /* NSObject+MJCoding.m in Sources */ = {isa = PBXBuildFile; fileRef = E9CFAA9D21AB9795003066A1 /* NSObject+MJCoding.m */; }; 30 | E9CFAAAF21AB9795003066A1 /* MJExtensionConst.m in Sources */ = {isa = PBXBuildFile; fileRef = E9CFAA9F21AB9795003066A1 /* MJExtensionConst.m */; }; 31 | E9CFAAB021AB9795003066A1 /* NSObject+MJProperty.m in Sources */ = {isa = PBXBuildFile; fileRef = E9CFAAA021AB9795003066A1 /* NSObject+MJProperty.m */; }; 32 | E9CFAAB121AB9795003066A1 /* NSObject+MJClass.m in Sources */ = {isa = PBXBuildFile; fileRef = E9CFAAA221AB9795003066A1 /* NSObject+MJClass.m */; }; 33 | E9CFAAB221AB9795003066A1 /* NSString+MJExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = E9CFAAA321AB9795003066A1 /* NSString+MJExtension.m */; }; 34 | E9CFAAB321AB9795003066A1 /* MJPropertyKey.m in Sources */ = {isa = PBXBuildFile; fileRef = E9CFAAA421AB9795003066A1 /* MJPropertyKey.m */; }; 35 | E9CFAAB421AB9795003066A1 /* MJFoundation.m in Sources */ = {isa = PBXBuildFile; fileRef = E9CFAAA821AB9795003066A1 /* MJFoundation.m */; }; 36 | E9CFAAB521AB9795003066A1 /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = E9CFAAA921AB9795003066A1 /* LICENSE */; }; 37 | E9CFAAB621AB9795003066A1 /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = E9CFAAAA21AB9795003066A1 /* README.md */; }; 38 | /* End PBXBuildFile section */ 39 | 40 | /* Begin PBXContainerItemProxy section */ 41 | E9CFAA6621AB864F003066A1 /* PBXContainerItemProxy */ = { 42 | isa = PBXContainerItemProxy; 43 | containerPortal = E9CFAA4521AB864E003066A1 /* Project object */; 44 | proxyType = 1; 45 | remoteGlobalIDString = E9CFAA4C21AB864E003066A1; 46 | remoteInfo = JhScrollActionSheetView; 47 | }; 48 | E9CFAA7121AB864F003066A1 /* PBXContainerItemProxy */ = { 49 | isa = PBXContainerItemProxy; 50 | containerPortal = E9CFAA4521AB864E003066A1 /* Project object */; 51 | proxyType = 1; 52 | remoteGlobalIDString = E9CFAA4C21AB864E003066A1; 53 | remoteInfo = JhScrollActionSheetView; 54 | }; 55 | /* End PBXContainerItemProxy section */ 56 | 57 | /* Begin PBXFileReference section */ 58 | E92F7BB421ACF2F100BC3817 /* 0.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = 0.gif; sourceTree = ""; }; 59 | E92F7BB521ACF2F100BC3817 /* 2.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = 2.png; sourceTree = ""; }; 60 | E92F7BB621ACF2F100BC3817 /* 3.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = 3.png; sourceTree = ""; }; 61 | E92F7BB721ACF2F100BC3817 /* 1.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = 1.png; sourceTree = ""; }; 62 | E9CFAA4D21AB864E003066A1 /* JhScrollActionSheetView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = JhScrollActionSheetView.app; sourceTree = BUILT_PRODUCTS_DIR; }; 63 | E9CFAA5021AB864E003066A1 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 64 | E9CFAA5121AB864E003066A1 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 65 | E9CFAA5321AB864E003066A1 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 66 | E9CFAA5421AB864E003066A1 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 67 | E9CFAA5721AB864E003066A1 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 68 | E9CFAA5921AB864F003066A1 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 69 | E9CFAA5C21AB864F003066A1 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 70 | E9CFAA5E21AB864F003066A1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 71 | E9CFAA5F21AB864F003066A1 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 72 | E9CFAA6521AB864F003066A1 /* JhScrollActionSheetViewTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = JhScrollActionSheetViewTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 73 | E9CFAA6921AB864F003066A1 /* JhScrollActionSheetViewTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JhScrollActionSheetViewTests.m; sourceTree = ""; }; 74 | E9CFAA6B21AB864F003066A1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 75 | E9CFAA7021AB864F003066A1 /* JhScrollActionSheetViewUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = JhScrollActionSheetViewUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 76 | E9CFAA7421AB864F003066A1 /* JhScrollActionSheetViewUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JhScrollActionSheetViewUITests.m; sourceTree = ""; }; 77 | E9CFAA7621AB864F003066A1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 78 | E9CFAA8221AB8673003066A1 /* JhScrollActionSheetView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JhScrollActionSheetView.h; sourceTree = ""; }; 79 | E9CFAA8321AB8673003066A1 /* JhScrollActionSheetView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JhScrollActionSheetView.m; sourceTree = ""; }; 80 | E9CFAA8A21AB9443003066A1 /* JhPageItemCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JhPageItemCell.m; sourceTree = ""; }; 81 | E9CFAA8B21AB9443003066A1 /* JhPageItemModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JhPageItemModel.m; sourceTree = ""; }; 82 | E9CFAA8C21AB9443003066A1 /* JhPageItemCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = JhPageItemCell.xib; sourceTree = ""; }; 83 | E9CFAA8D21AB9443003066A1 /* JhPageItemCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JhPageItemCell.h; sourceTree = ""; }; 84 | E9CFAA8E21AB9443003066A1 /* JhPageItemModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JhPageItemModel.h; sourceTree = ""; }; 85 | E9CFAA9421AB9795003066A1 /* MJPropertyKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MJPropertyKey.h; sourceTree = ""; }; 86 | E9CFAA9521AB9795003066A1 /* NSObject+MJClass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+MJClass.h"; sourceTree = ""; }; 87 | E9CFAA9621AB9795003066A1 /* NSString+MJExtension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+MJExtension.h"; sourceTree = ""; }; 88 | E9CFAA9721AB9795003066A1 /* MJPropertyType.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MJPropertyType.m; sourceTree = ""; }; 89 | E9CFAA9821AB9795003066A1 /* NSObject+MJProperty.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+MJProperty.h"; sourceTree = ""; }; 90 | E9CFAA9921AB9795003066A1 /* MJExtensionConst.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MJExtensionConst.h; sourceTree = ""; }; 91 | E9CFAA9A21AB9795003066A1 /* NSObject+MJKeyValue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+MJKeyValue.m"; sourceTree = ""; }; 92 | E9CFAA9B21AB9795003066A1 /* MJProperty.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MJProperty.m; sourceTree = ""; }; 93 | E9CFAA9C21AB9795003066A1 /* MJFoundation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MJFoundation.h; sourceTree = ""; }; 94 | E9CFAA9D21AB9795003066A1 /* NSObject+MJCoding.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+MJCoding.m"; sourceTree = ""; }; 95 | E9CFAA9E21AB9795003066A1 /* MJExtension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MJExtension.h; sourceTree = ""; }; 96 | E9CFAA9F21AB9795003066A1 /* MJExtensionConst.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MJExtensionConst.m; sourceTree = ""; }; 97 | E9CFAAA021AB9795003066A1 /* NSObject+MJProperty.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+MJProperty.m"; sourceTree = ""; }; 98 | E9CFAAA121AB9795003066A1 /* MJPropertyType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MJPropertyType.h; sourceTree = ""; }; 99 | E9CFAAA221AB9795003066A1 /* NSObject+MJClass.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+MJClass.m"; sourceTree = ""; }; 100 | E9CFAAA321AB9795003066A1 /* NSString+MJExtension.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+MJExtension.m"; sourceTree = ""; }; 101 | E9CFAAA421AB9795003066A1 /* MJPropertyKey.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MJPropertyKey.m; sourceTree = ""; }; 102 | E9CFAAA521AB9795003066A1 /* MJProperty.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MJProperty.h; sourceTree = ""; }; 103 | E9CFAAA621AB9795003066A1 /* NSObject+MJKeyValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+MJKeyValue.h"; sourceTree = ""; }; 104 | E9CFAAA721AB9795003066A1 /* NSObject+MJCoding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+MJCoding.h"; sourceTree = ""; }; 105 | E9CFAAA821AB9795003066A1 /* MJFoundation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MJFoundation.m; sourceTree = ""; }; 106 | E9CFAAA921AB9795003066A1 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; 107 | E9CFAAAA21AB9795003066A1 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; 108 | /* End PBXFileReference section */ 109 | 110 | /* Begin PBXFrameworksBuildPhase section */ 111 | E9CFAA4A21AB864E003066A1 /* Frameworks */ = { 112 | isa = PBXFrameworksBuildPhase; 113 | buildActionMask = 2147483647; 114 | files = ( 115 | ); 116 | runOnlyForDeploymentPostprocessing = 0; 117 | }; 118 | E9CFAA6221AB864F003066A1 /* Frameworks */ = { 119 | isa = PBXFrameworksBuildPhase; 120 | buildActionMask = 2147483647; 121 | files = ( 122 | ); 123 | runOnlyForDeploymentPostprocessing = 0; 124 | }; 125 | E9CFAA6D21AB864F003066A1 /* Frameworks */ = { 126 | isa = PBXFrameworksBuildPhase; 127 | buildActionMask = 2147483647; 128 | files = ( 129 | ); 130 | runOnlyForDeploymentPostprocessing = 0; 131 | }; 132 | /* End PBXFrameworksBuildPhase section */ 133 | 134 | /* Begin PBXGroup section */ 135 | E92F7BB321ACF2F100BC3817 /* screenshots */ = { 136 | isa = PBXGroup; 137 | children = ( 138 | E92F7BB421ACF2F100BC3817 /* 0.gif */, 139 | E92F7BB521ACF2F100BC3817 /* 2.png */, 140 | E92F7BB621ACF2F100BC3817 /* 3.png */, 141 | E92F7BB721ACF2F100BC3817 /* 1.png */, 142 | ); 143 | path = screenshots; 144 | sourceTree = ""; 145 | }; 146 | E92F7BBC21ACF34800BC3817 /* JhScrollActionSheet */ = { 147 | isa = PBXGroup; 148 | children = ( 149 | E9CFAA8221AB8673003066A1 /* JhScrollActionSheetView.h */, 150 | E9CFAA8321AB8673003066A1 /* JhScrollActionSheetView.m */, 151 | E9CFAA8D21AB9443003066A1 /* JhPageItemCell.h */, 152 | E9CFAA8A21AB9443003066A1 /* JhPageItemCell.m */, 153 | E9CFAA8C21AB9443003066A1 /* JhPageItemCell.xib */, 154 | E9CFAA8E21AB9443003066A1 /* JhPageItemModel.h */, 155 | E9CFAA8B21AB9443003066A1 /* JhPageItemModel.m */, 156 | ); 157 | path = JhScrollActionSheet; 158 | sourceTree = ""; 159 | }; 160 | E9CFAA4421AB864E003066A1 = { 161 | isa = PBXGroup; 162 | children = ( 163 | E9CFAA4F21AB864E003066A1 /* JhScrollActionSheetView */, 164 | E9CFAA6821AB864F003066A1 /* JhScrollActionSheetViewTests */, 165 | E9CFAA7321AB864F003066A1 /* JhScrollActionSheetViewUITests */, 166 | E9CFAA4E21AB864E003066A1 /* Products */, 167 | ); 168 | sourceTree = ""; 169 | }; 170 | E9CFAA4E21AB864E003066A1 /* Products */ = { 171 | isa = PBXGroup; 172 | children = ( 173 | E9CFAA4D21AB864E003066A1 /* JhScrollActionSheetView.app */, 174 | E9CFAA6521AB864F003066A1 /* JhScrollActionSheetViewTests.xctest */, 175 | E9CFAA7021AB864F003066A1 /* JhScrollActionSheetViewUITests.xctest */, 176 | ); 177 | name = Products; 178 | sourceTree = ""; 179 | }; 180 | E9CFAA4F21AB864E003066A1 /* JhScrollActionSheetView */ = { 181 | isa = PBXGroup; 182 | children = ( 183 | E92F7BBC21ACF34800BC3817 /* JhScrollActionSheet */, 184 | E92F7BB321ACF2F100BC3817 /* screenshots */, 185 | E9CFAA9221AB9795003066A1 /* MJExtension */, 186 | E9CFAA5021AB864E003066A1 /* AppDelegate.h */, 187 | E9CFAA5121AB864E003066A1 /* AppDelegate.m */, 188 | E9CFAA5321AB864E003066A1 /* ViewController.h */, 189 | E9CFAA5421AB864E003066A1 /* ViewController.m */, 190 | E9CFAA5621AB864E003066A1 /* Main.storyboard */, 191 | E9CFAA5921AB864F003066A1 /* Assets.xcassets */, 192 | E9CFAA5B21AB864F003066A1 /* LaunchScreen.storyboard */, 193 | E9CFAA5E21AB864F003066A1 /* Info.plist */, 194 | E9CFAA5F21AB864F003066A1 /* main.m */, 195 | ); 196 | path = JhScrollActionSheetView; 197 | sourceTree = ""; 198 | }; 199 | E9CFAA6821AB864F003066A1 /* JhScrollActionSheetViewTests */ = { 200 | isa = PBXGroup; 201 | children = ( 202 | E9CFAA6921AB864F003066A1 /* JhScrollActionSheetViewTests.m */, 203 | E9CFAA6B21AB864F003066A1 /* Info.plist */, 204 | ); 205 | path = JhScrollActionSheetViewTests; 206 | sourceTree = ""; 207 | }; 208 | E9CFAA7321AB864F003066A1 /* JhScrollActionSheetViewUITests */ = { 209 | isa = PBXGroup; 210 | children = ( 211 | E9CFAA7421AB864F003066A1 /* JhScrollActionSheetViewUITests.m */, 212 | E9CFAA7621AB864F003066A1 /* Info.plist */, 213 | ); 214 | path = JhScrollActionSheetViewUITests; 215 | sourceTree = ""; 216 | }; 217 | E9CFAA9221AB9795003066A1 /* MJExtension */ = { 218 | isa = PBXGroup; 219 | children = ( 220 | E9CFAA9321AB9795003066A1 /* MJExtension */, 221 | E9CFAAA921AB9795003066A1 /* LICENSE */, 222 | E9CFAAAA21AB9795003066A1 /* README.md */, 223 | ); 224 | path = MJExtension; 225 | sourceTree = ""; 226 | }; 227 | E9CFAA9321AB9795003066A1 /* MJExtension */ = { 228 | isa = PBXGroup; 229 | children = ( 230 | E9CFAA9421AB9795003066A1 /* MJPropertyKey.h */, 231 | E9CFAA9521AB9795003066A1 /* NSObject+MJClass.h */, 232 | E9CFAA9621AB9795003066A1 /* NSString+MJExtension.h */, 233 | E9CFAA9721AB9795003066A1 /* MJPropertyType.m */, 234 | E9CFAA9821AB9795003066A1 /* NSObject+MJProperty.h */, 235 | E9CFAA9921AB9795003066A1 /* MJExtensionConst.h */, 236 | E9CFAA9A21AB9795003066A1 /* NSObject+MJKeyValue.m */, 237 | E9CFAA9B21AB9795003066A1 /* MJProperty.m */, 238 | E9CFAA9C21AB9795003066A1 /* MJFoundation.h */, 239 | E9CFAA9D21AB9795003066A1 /* NSObject+MJCoding.m */, 240 | E9CFAA9E21AB9795003066A1 /* MJExtension.h */, 241 | E9CFAA9F21AB9795003066A1 /* MJExtensionConst.m */, 242 | E9CFAAA021AB9795003066A1 /* NSObject+MJProperty.m */, 243 | E9CFAAA121AB9795003066A1 /* MJPropertyType.h */, 244 | E9CFAAA221AB9795003066A1 /* NSObject+MJClass.m */, 245 | E9CFAAA321AB9795003066A1 /* NSString+MJExtension.m */, 246 | E9CFAAA421AB9795003066A1 /* MJPropertyKey.m */, 247 | E9CFAAA521AB9795003066A1 /* MJProperty.h */, 248 | E9CFAAA621AB9795003066A1 /* NSObject+MJKeyValue.h */, 249 | E9CFAAA721AB9795003066A1 /* NSObject+MJCoding.h */, 250 | E9CFAAA821AB9795003066A1 /* MJFoundation.m */, 251 | ); 252 | path = MJExtension; 253 | sourceTree = ""; 254 | }; 255 | /* End PBXGroup section */ 256 | 257 | /* Begin PBXNativeTarget section */ 258 | E9CFAA4C21AB864E003066A1 /* JhScrollActionSheetView */ = { 259 | isa = PBXNativeTarget; 260 | buildConfigurationList = E9CFAA7921AB864F003066A1 /* Build configuration list for PBXNativeTarget "JhScrollActionSheetView" */; 261 | buildPhases = ( 262 | E9CFAA4921AB864E003066A1 /* Sources */, 263 | E9CFAA4A21AB864E003066A1 /* Frameworks */, 264 | E9CFAA4B21AB864E003066A1 /* Resources */, 265 | ); 266 | buildRules = ( 267 | ); 268 | dependencies = ( 269 | ); 270 | name = JhScrollActionSheetView; 271 | productName = JhScrollActionSheetView; 272 | productReference = E9CFAA4D21AB864E003066A1 /* JhScrollActionSheetView.app */; 273 | productType = "com.apple.product-type.application"; 274 | }; 275 | E9CFAA6421AB864F003066A1 /* JhScrollActionSheetViewTests */ = { 276 | isa = PBXNativeTarget; 277 | buildConfigurationList = E9CFAA7C21AB864F003066A1 /* Build configuration list for PBXNativeTarget "JhScrollActionSheetViewTests" */; 278 | buildPhases = ( 279 | E9CFAA6121AB864F003066A1 /* Sources */, 280 | E9CFAA6221AB864F003066A1 /* Frameworks */, 281 | E9CFAA6321AB864F003066A1 /* Resources */, 282 | ); 283 | buildRules = ( 284 | ); 285 | dependencies = ( 286 | E9CFAA6721AB864F003066A1 /* PBXTargetDependency */, 287 | ); 288 | name = JhScrollActionSheetViewTests; 289 | productName = JhScrollActionSheetViewTests; 290 | productReference = E9CFAA6521AB864F003066A1 /* JhScrollActionSheetViewTests.xctest */; 291 | productType = "com.apple.product-type.bundle.unit-test"; 292 | }; 293 | E9CFAA6F21AB864F003066A1 /* JhScrollActionSheetViewUITests */ = { 294 | isa = PBXNativeTarget; 295 | buildConfigurationList = E9CFAA7F21AB864F003066A1 /* Build configuration list for PBXNativeTarget "JhScrollActionSheetViewUITests" */; 296 | buildPhases = ( 297 | E9CFAA6C21AB864F003066A1 /* Sources */, 298 | E9CFAA6D21AB864F003066A1 /* Frameworks */, 299 | E9CFAA6E21AB864F003066A1 /* Resources */, 300 | ); 301 | buildRules = ( 302 | ); 303 | dependencies = ( 304 | E9CFAA7221AB864F003066A1 /* PBXTargetDependency */, 305 | ); 306 | name = JhScrollActionSheetViewUITests; 307 | productName = JhScrollActionSheetViewUITests; 308 | productReference = E9CFAA7021AB864F003066A1 /* JhScrollActionSheetViewUITests.xctest */; 309 | productType = "com.apple.product-type.bundle.ui-testing"; 310 | }; 311 | /* End PBXNativeTarget section */ 312 | 313 | /* Begin PBXProject section */ 314 | E9CFAA4521AB864E003066A1 /* Project object */ = { 315 | isa = PBXProject; 316 | attributes = { 317 | LastUpgradeCheck = 1010; 318 | ORGANIZATIONNAME = Jh; 319 | TargetAttributes = { 320 | E9CFAA4C21AB864E003066A1 = { 321 | CreatedOnToolsVersion = 10.1; 322 | }; 323 | E9CFAA6421AB864F003066A1 = { 324 | CreatedOnToolsVersion = 10.1; 325 | TestTargetID = E9CFAA4C21AB864E003066A1; 326 | }; 327 | E9CFAA6F21AB864F003066A1 = { 328 | CreatedOnToolsVersion = 10.1; 329 | TestTargetID = E9CFAA4C21AB864E003066A1; 330 | }; 331 | }; 332 | }; 333 | buildConfigurationList = E9CFAA4821AB864E003066A1 /* Build configuration list for PBXProject "JhScrollActionSheetView" */; 334 | compatibilityVersion = "Xcode 9.3"; 335 | developmentRegion = en; 336 | hasScannedForEncodings = 0; 337 | knownRegions = ( 338 | en, 339 | Base, 340 | ); 341 | mainGroup = E9CFAA4421AB864E003066A1; 342 | productRefGroup = E9CFAA4E21AB864E003066A1 /* Products */; 343 | projectDirPath = ""; 344 | projectRoot = ""; 345 | targets = ( 346 | E9CFAA4C21AB864E003066A1 /* JhScrollActionSheetView */, 347 | E9CFAA6421AB864F003066A1 /* JhScrollActionSheetViewTests */, 348 | E9CFAA6F21AB864F003066A1 /* JhScrollActionSheetViewUITests */, 349 | ); 350 | }; 351 | /* End PBXProject section */ 352 | 353 | /* Begin PBXResourcesBuildPhase section */ 354 | E9CFAA4B21AB864E003066A1 /* Resources */ = { 355 | isa = PBXResourcesBuildPhase; 356 | buildActionMask = 2147483647; 357 | files = ( 358 | E9CFAAB621AB9795003066A1 /* README.md in Resources */, 359 | E92F7BB821ACF2F200BC3817 /* 0.gif in Resources */, 360 | E92F7BB921ACF2F200BC3817 /* 2.png in Resources */, 361 | E92F7BBA21ACF2F200BC3817 /* 3.png in Resources */, 362 | E9CFAA5D21AB864F003066A1 /* LaunchScreen.storyboard in Resources */, 363 | E9CFAA9121AB9444003066A1 /* JhPageItemCell.xib in Resources */, 364 | E9CFAA5A21AB864F003066A1 /* Assets.xcassets in Resources */, 365 | E9CFAA5821AB864E003066A1 /* Main.storyboard in Resources */, 366 | E9CFAAB521AB9795003066A1 /* LICENSE in Resources */, 367 | E92F7BBB21ACF2F200BC3817 /* 1.png in Resources */, 368 | ); 369 | runOnlyForDeploymentPostprocessing = 0; 370 | }; 371 | E9CFAA6321AB864F003066A1 /* Resources */ = { 372 | isa = PBXResourcesBuildPhase; 373 | buildActionMask = 2147483647; 374 | files = ( 375 | ); 376 | runOnlyForDeploymentPostprocessing = 0; 377 | }; 378 | E9CFAA6E21AB864F003066A1 /* Resources */ = { 379 | isa = PBXResourcesBuildPhase; 380 | buildActionMask = 2147483647; 381 | files = ( 382 | ); 383 | runOnlyForDeploymentPostprocessing = 0; 384 | }; 385 | /* End PBXResourcesBuildPhase section */ 386 | 387 | /* Begin PBXSourcesBuildPhase section */ 388 | E9CFAA4921AB864E003066A1 /* Sources */ = { 389 | isa = PBXSourcesBuildPhase; 390 | buildActionMask = 2147483647; 391 | files = ( 392 | E9CFAAAF21AB9795003066A1 /* MJExtensionConst.m in Sources */, 393 | E9CFAAB121AB9795003066A1 /* NSObject+MJClass.m in Sources */, 394 | E9CFAAAC21AB9795003066A1 /* NSObject+MJKeyValue.m in Sources */, 395 | E9CFAA5521AB864E003066A1 /* ViewController.m in Sources */, 396 | E9CFAA6021AB864F003066A1 /* main.m in Sources */, 397 | E9CFAA5221AB864E003066A1 /* AppDelegate.m in Sources */, 398 | E9CFAAAE21AB9795003066A1 /* NSObject+MJCoding.m in Sources */, 399 | E9CFAAB421AB9795003066A1 /* MJFoundation.m in Sources */, 400 | E9CFAAB321AB9795003066A1 /* MJPropertyKey.m in Sources */, 401 | E9CFAAAD21AB9795003066A1 /* MJProperty.m in Sources */, 402 | E9CFAAB021AB9795003066A1 /* NSObject+MJProperty.m in Sources */, 403 | E9CFAA9021AB9444003066A1 /* JhPageItemModel.m in Sources */, 404 | E9CFAAB221AB9795003066A1 /* NSString+MJExtension.m in Sources */, 405 | E9CFAA8F21AB9444003066A1 /* JhPageItemCell.m in Sources */, 406 | E9CFAAAB21AB9795003066A1 /* MJPropertyType.m in Sources */, 407 | E9CFAA8421AB8673003066A1 /* JhScrollActionSheetView.m in Sources */, 408 | ); 409 | runOnlyForDeploymentPostprocessing = 0; 410 | }; 411 | E9CFAA6121AB864F003066A1 /* Sources */ = { 412 | isa = PBXSourcesBuildPhase; 413 | buildActionMask = 2147483647; 414 | files = ( 415 | E9CFAA6A21AB864F003066A1 /* JhScrollActionSheetViewTests.m in Sources */, 416 | ); 417 | runOnlyForDeploymentPostprocessing = 0; 418 | }; 419 | E9CFAA6C21AB864F003066A1 /* Sources */ = { 420 | isa = PBXSourcesBuildPhase; 421 | buildActionMask = 2147483647; 422 | files = ( 423 | E9CFAA7521AB864F003066A1 /* JhScrollActionSheetViewUITests.m in Sources */, 424 | ); 425 | runOnlyForDeploymentPostprocessing = 0; 426 | }; 427 | /* End PBXSourcesBuildPhase section */ 428 | 429 | /* Begin PBXTargetDependency section */ 430 | E9CFAA6721AB864F003066A1 /* PBXTargetDependency */ = { 431 | isa = PBXTargetDependency; 432 | target = E9CFAA4C21AB864E003066A1 /* JhScrollActionSheetView */; 433 | targetProxy = E9CFAA6621AB864F003066A1 /* PBXContainerItemProxy */; 434 | }; 435 | E9CFAA7221AB864F003066A1 /* PBXTargetDependency */ = { 436 | isa = PBXTargetDependency; 437 | target = E9CFAA4C21AB864E003066A1 /* JhScrollActionSheetView */; 438 | targetProxy = E9CFAA7121AB864F003066A1 /* PBXContainerItemProxy */; 439 | }; 440 | /* End PBXTargetDependency section */ 441 | 442 | /* Begin PBXVariantGroup section */ 443 | E9CFAA5621AB864E003066A1 /* Main.storyboard */ = { 444 | isa = PBXVariantGroup; 445 | children = ( 446 | E9CFAA5721AB864E003066A1 /* Base */, 447 | ); 448 | name = Main.storyboard; 449 | sourceTree = ""; 450 | }; 451 | E9CFAA5B21AB864F003066A1 /* LaunchScreen.storyboard */ = { 452 | isa = PBXVariantGroup; 453 | children = ( 454 | E9CFAA5C21AB864F003066A1 /* Base */, 455 | ); 456 | name = LaunchScreen.storyboard; 457 | sourceTree = ""; 458 | }; 459 | /* End PBXVariantGroup section */ 460 | 461 | /* Begin XCBuildConfiguration section */ 462 | E9CFAA7721AB864F003066A1 /* Debug */ = { 463 | isa = XCBuildConfiguration; 464 | buildSettings = { 465 | ALWAYS_SEARCH_USER_PATHS = NO; 466 | CLANG_ANALYZER_NONNULL = YES; 467 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 468 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 469 | CLANG_CXX_LIBRARY = "libc++"; 470 | CLANG_ENABLE_MODULES = YES; 471 | CLANG_ENABLE_OBJC_ARC = YES; 472 | CLANG_ENABLE_OBJC_WEAK = YES; 473 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 474 | CLANG_WARN_BOOL_CONVERSION = YES; 475 | CLANG_WARN_COMMA = YES; 476 | CLANG_WARN_CONSTANT_CONVERSION = YES; 477 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 478 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 479 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 480 | CLANG_WARN_EMPTY_BODY = YES; 481 | CLANG_WARN_ENUM_CONVERSION = YES; 482 | CLANG_WARN_INFINITE_RECURSION = YES; 483 | CLANG_WARN_INT_CONVERSION = YES; 484 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 485 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 486 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 487 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 488 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 489 | CLANG_WARN_STRICT_PROTOTYPES = YES; 490 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 491 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 492 | CLANG_WARN_UNREACHABLE_CODE = YES; 493 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 494 | CODE_SIGN_IDENTITY = "iPhone Developer"; 495 | COPY_PHASE_STRIP = NO; 496 | DEBUG_INFORMATION_FORMAT = dwarf; 497 | ENABLE_STRICT_OBJC_MSGSEND = YES; 498 | ENABLE_TESTABILITY = YES; 499 | GCC_C_LANGUAGE_STANDARD = gnu11; 500 | GCC_DYNAMIC_NO_PIC = NO; 501 | GCC_NO_COMMON_BLOCKS = YES; 502 | GCC_OPTIMIZATION_LEVEL = 0; 503 | GCC_PREPROCESSOR_DEFINITIONS = ( 504 | "DEBUG=1", 505 | "$(inherited)", 506 | ); 507 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 508 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 509 | GCC_WARN_UNDECLARED_SELECTOR = YES; 510 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 511 | GCC_WARN_UNUSED_FUNCTION = YES; 512 | GCC_WARN_UNUSED_VARIABLE = YES; 513 | IPHONEOS_DEPLOYMENT_TARGET = 12.1; 514 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 515 | MTL_FAST_MATH = YES; 516 | ONLY_ACTIVE_ARCH = YES; 517 | SDKROOT = iphoneos; 518 | }; 519 | name = Debug; 520 | }; 521 | E9CFAA7821AB864F003066A1 /* Release */ = { 522 | isa = XCBuildConfiguration; 523 | buildSettings = { 524 | ALWAYS_SEARCH_USER_PATHS = NO; 525 | CLANG_ANALYZER_NONNULL = YES; 526 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 527 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 528 | CLANG_CXX_LIBRARY = "libc++"; 529 | CLANG_ENABLE_MODULES = YES; 530 | CLANG_ENABLE_OBJC_ARC = YES; 531 | CLANG_ENABLE_OBJC_WEAK = YES; 532 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 533 | CLANG_WARN_BOOL_CONVERSION = YES; 534 | CLANG_WARN_COMMA = YES; 535 | CLANG_WARN_CONSTANT_CONVERSION = YES; 536 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 537 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 538 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 539 | CLANG_WARN_EMPTY_BODY = YES; 540 | CLANG_WARN_ENUM_CONVERSION = YES; 541 | CLANG_WARN_INFINITE_RECURSION = YES; 542 | CLANG_WARN_INT_CONVERSION = YES; 543 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 544 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 545 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 546 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 547 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 548 | CLANG_WARN_STRICT_PROTOTYPES = YES; 549 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 550 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 551 | CLANG_WARN_UNREACHABLE_CODE = YES; 552 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 553 | CODE_SIGN_IDENTITY = "iPhone Developer"; 554 | COPY_PHASE_STRIP = NO; 555 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 556 | ENABLE_NS_ASSERTIONS = NO; 557 | ENABLE_STRICT_OBJC_MSGSEND = YES; 558 | GCC_C_LANGUAGE_STANDARD = gnu11; 559 | GCC_NO_COMMON_BLOCKS = YES; 560 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 561 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 562 | GCC_WARN_UNDECLARED_SELECTOR = YES; 563 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 564 | GCC_WARN_UNUSED_FUNCTION = YES; 565 | GCC_WARN_UNUSED_VARIABLE = YES; 566 | IPHONEOS_DEPLOYMENT_TARGET = 12.1; 567 | MTL_ENABLE_DEBUG_INFO = NO; 568 | MTL_FAST_MATH = YES; 569 | SDKROOT = iphoneos; 570 | VALIDATE_PRODUCT = YES; 571 | }; 572 | name = Release; 573 | }; 574 | E9CFAA7A21AB864F003066A1 /* Debug */ = { 575 | isa = XCBuildConfiguration; 576 | buildSettings = { 577 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 578 | CODE_SIGN_STYLE = Automatic; 579 | DEVELOPMENT_TEAM = ""; 580 | INFOPLIST_FILE = JhScrollActionSheetView/Info.plist; 581 | LD_RUNPATH_SEARCH_PATHS = ( 582 | "$(inherited)", 583 | "@executable_path/Frameworks", 584 | ); 585 | PRODUCT_BUNDLE_IDENTIFIER = com.Jh.JhScrollActionSheetView; 586 | PRODUCT_NAME = "$(TARGET_NAME)"; 587 | TARGETED_DEVICE_FAMILY = "1,2"; 588 | }; 589 | name = Debug; 590 | }; 591 | E9CFAA7B21AB864F003066A1 /* Release */ = { 592 | isa = XCBuildConfiguration; 593 | buildSettings = { 594 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 595 | CODE_SIGN_STYLE = Automatic; 596 | DEVELOPMENT_TEAM = ""; 597 | INFOPLIST_FILE = JhScrollActionSheetView/Info.plist; 598 | LD_RUNPATH_SEARCH_PATHS = ( 599 | "$(inherited)", 600 | "@executable_path/Frameworks", 601 | ); 602 | PRODUCT_BUNDLE_IDENTIFIER = com.Jh.JhScrollActionSheetView; 603 | PRODUCT_NAME = "$(TARGET_NAME)"; 604 | TARGETED_DEVICE_FAMILY = "1,2"; 605 | }; 606 | name = Release; 607 | }; 608 | E9CFAA7D21AB864F003066A1 /* Debug */ = { 609 | isa = XCBuildConfiguration; 610 | buildSettings = { 611 | BUNDLE_LOADER = "$(TEST_HOST)"; 612 | CODE_SIGN_STYLE = Automatic; 613 | DEVELOPMENT_TEAM = 8ZH8KFMR9N; 614 | INFOPLIST_FILE = JhScrollActionSheetViewTests/Info.plist; 615 | LD_RUNPATH_SEARCH_PATHS = ( 616 | "$(inherited)", 617 | "@executable_path/Frameworks", 618 | "@loader_path/Frameworks", 619 | ); 620 | PRODUCT_BUNDLE_IDENTIFIER = com.bjdsst.JhScrollActionSheetViewTests; 621 | PRODUCT_NAME = "$(TARGET_NAME)"; 622 | TARGETED_DEVICE_FAMILY = "1,2"; 623 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/JhScrollActionSheetView.app/JhScrollActionSheetView"; 624 | }; 625 | name = Debug; 626 | }; 627 | E9CFAA7E21AB864F003066A1 /* Release */ = { 628 | isa = XCBuildConfiguration; 629 | buildSettings = { 630 | BUNDLE_LOADER = "$(TEST_HOST)"; 631 | CODE_SIGN_STYLE = Automatic; 632 | DEVELOPMENT_TEAM = 8ZH8KFMR9N; 633 | INFOPLIST_FILE = JhScrollActionSheetViewTests/Info.plist; 634 | LD_RUNPATH_SEARCH_PATHS = ( 635 | "$(inherited)", 636 | "@executable_path/Frameworks", 637 | "@loader_path/Frameworks", 638 | ); 639 | PRODUCT_BUNDLE_IDENTIFIER = com.bjdsst.JhScrollActionSheetViewTests; 640 | PRODUCT_NAME = "$(TARGET_NAME)"; 641 | TARGETED_DEVICE_FAMILY = "1,2"; 642 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/JhScrollActionSheetView.app/JhScrollActionSheetView"; 643 | }; 644 | name = Release; 645 | }; 646 | E9CFAA8021AB864F003066A1 /* Debug */ = { 647 | isa = XCBuildConfiguration; 648 | buildSettings = { 649 | CODE_SIGN_STYLE = Automatic; 650 | DEVELOPMENT_TEAM = 8ZH8KFMR9N; 651 | INFOPLIST_FILE = JhScrollActionSheetViewUITests/Info.plist; 652 | LD_RUNPATH_SEARCH_PATHS = ( 653 | "$(inherited)", 654 | "@executable_path/Frameworks", 655 | "@loader_path/Frameworks", 656 | ); 657 | PRODUCT_BUNDLE_IDENTIFIER = com.bjdsst.JhScrollActionSheetViewUITests; 658 | PRODUCT_NAME = "$(TARGET_NAME)"; 659 | TARGETED_DEVICE_FAMILY = "1,2"; 660 | TEST_TARGET_NAME = JhScrollActionSheetView; 661 | }; 662 | name = Debug; 663 | }; 664 | E9CFAA8121AB864F003066A1 /* Release */ = { 665 | isa = XCBuildConfiguration; 666 | buildSettings = { 667 | CODE_SIGN_STYLE = Automatic; 668 | DEVELOPMENT_TEAM = 8ZH8KFMR9N; 669 | INFOPLIST_FILE = JhScrollActionSheetViewUITests/Info.plist; 670 | LD_RUNPATH_SEARCH_PATHS = ( 671 | "$(inherited)", 672 | "@executable_path/Frameworks", 673 | "@loader_path/Frameworks", 674 | ); 675 | PRODUCT_BUNDLE_IDENTIFIER = com.bjdsst.JhScrollActionSheetViewUITests; 676 | PRODUCT_NAME = "$(TARGET_NAME)"; 677 | TARGETED_DEVICE_FAMILY = "1,2"; 678 | TEST_TARGET_NAME = JhScrollActionSheetView; 679 | }; 680 | name = Release; 681 | }; 682 | /* End XCBuildConfiguration section */ 683 | 684 | /* Begin XCConfigurationList section */ 685 | E9CFAA4821AB864E003066A1 /* Build configuration list for PBXProject "JhScrollActionSheetView" */ = { 686 | isa = XCConfigurationList; 687 | buildConfigurations = ( 688 | E9CFAA7721AB864F003066A1 /* Debug */, 689 | E9CFAA7821AB864F003066A1 /* Release */, 690 | ); 691 | defaultConfigurationIsVisible = 0; 692 | defaultConfigurationName = Release; 693 | }; 694 | E9CFAA7921AB864F003066A1 /* Build configuration list for PBXNativeTarget "JhScrollActionSheetView" */ = { 695 | isa = XCConfigurationList; 696 | buildConfigurations = ( 697 | E9CFAA7A21AB864F003066A1 /* Debug */, 698 | E9CFAA7B21AB864F003066A1 /* Release */, 699 | ); 700 | defaultConfigurationIsVisible = 0; 701 | defaultConfigurationName = Release; 702 | }; 703 | E9CFAA7C21AB864F003066A1 /* Build configuration list for PBXNativeTarget "JhScrollActionSheetViewTests" */ = { 704 | isa = XCConfigurationList; 705 | buildConfigurations = ( 706 | E9CFAA7D21AB864F003066A1 /* Debug */, 707 | E9CFAA7E21AB864F003066A1 /* Release */, 708 | ); 709 | defaultConfigurationIsVisible = 0; 710 | defaultConfigurationName = Release; 711 | }; 712 | E9CFAA7F21AB864F003066A1 /* Build configuration list for PBXNativeTarget "JhScrollActionSheetViewUITests" */ = { 713 | isa = XCConfigurationList; 714 | buildConfigurations = ( 715 | E9CFAA8021AB864F003066A1 /* Debug */, 716 | E9CFAA8121AB864F003066A1 /* Release */, 717 | ); 718 | defaultConfigurationIsVisible = 0; 719 | defaultConfigurationName = Release; 720 | }; 721 | /* End XCConfigurationList section */ 722 | }; 723 | rootObject = E9CFAA4521AB864E003066A1 /* Project object */; 724 | } 725 | -------------------------------------------------------------------------------- /JhScrollActionSheetView.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /JhScrollActionSheetView.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /JhScrollActionSheetView.xcodeproj/project.xcworkspace/xcuserdata/jh.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iotjin/JhScrollActionSheetView/074153497b9d9ca5d9bf8f1bb640de4d73a837ab/JhScrollActionSheetView.xcodeproj/project.xcworkspace/xcuserdata/jh.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /JhScrollActionSheetView.xcodeproj/project.xcworkspace/xcuserdata/lantongmac.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iotjin/JhScrollActionSheetView/074153497b9d9ca5d9bf8f1bb640de4d73a837ab/JhScrollActionSheetView.xcodeproj/project.xcworkspace/xcuserdata/lantongmac.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /JhScrollActionSheetView.xcodeproj/xcuserdata/jh.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /JhScrollActionSheetView.xcodeproj/xcuserdata/jh.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | JhScrollActionSheetView.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /JhScrollActionSheetView.xcodeproj/xcuserdata/lantongmac.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | JhScrollActionSheetView.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /JhScrollActionSheetView/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // JhScrollActionSheetView 4 | // 5 | // Created by Jh on 2018/11/26. 6 | // Copyright © 2018 Jh. 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 | -------------------------------------------------------------------------------- /JhScrollActionSheetView/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // JhScrollActionSheetView 4 | // 5 | // Created by Jh on 2018/11/26. 6 | // Copyright © 2018 Jh. 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 | -------------------------------------------------------------------------------- /JhScrollActionSheetView/Assets.xcassets/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iotjin/JhScrollActionSheetView/074153497b9d9ca5d9bf8f1bb640de4d73a837ab/JhScrollActionSheetView/Assets.xcassets/.DS_Store -------------------------------------------------------------------------------- /JhScrollActionSheetView/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 | } -------------------------------------------------------------------------------- /JhScrollActionSheetView/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /JhScrollActionSheetView/Assets.xcassets/other/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /JhScrollActionSheetView/Assets.xcassets/other/copylink.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "copylink@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "copylink@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /JhScrollActionSheetView/Assets.xcassets/other/copylink.imageset/copylink@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iotjin/JhScrollActionSheetView/074153497b9d9ca5d9bf8f1bb640de4d73a837ab/JhScrollActionSheetView/Assets.xcassets/other/copylink.imageset/copylink@2x.png -------------------------------------------------------------------------------- /JhScrollActionSheetView/Assets.xcassets/other/copylink.imageset/copylink@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iotjin/JhScrollActionSheetView/074153497b9d9ca5d9bf8f1bb640de4d73a837ab/JhScrollActionSheetView/Assets.xcassets/other/copylink.imageset/copylink@3x.png -------------------------------------------------------------------------------- /JhScrollActionSheetView/Assets.xcassets/other/fontsize.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "fontsize@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "fontsize@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /JhScrollActionSheetView/Assets.xcassets/other/fontsize.imageset/fontsize@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iotjin/JhScrollActionSheetView/074153497b9d9ca5d9bf8f1bb640de4d73a837ab/JhScrollActionSheetView/Assets.xcassets/other/fontsize.imageset/fontsize@2x.png -------------------------------------------------------------------------------- /JhScrollActionSheetView/Assets.xcassets/other/fontsize.imageset/fontsize@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iotjin/JhScrollActionSheetView/074153497b9d9ca5d9bf8f1bb640de4d73a837ab/JhScrollActionSheetView/Assets.xcassets/other/fontsize.imageset/fontsize@3x.png -------------------------------------------------------------------------------- /JhScrollActionSheetView/Assets.xcassets/share/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /JhScrollActionSheetView/Assets.xcassets/share/friends.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "friends@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "friends@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /JhScrollActionSheetView/Assets.xcassets/share/friends.imageset/friends@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iotjin/JhScrollActionSheetView/074153497b9d9ca5d9bf8f1bb640de4d73a837ab/JhScrollActionSheetView/Assets.xcassets/share/friends.imageset/friends@2x.png -------------------------------------------------------------------------------- /JhScrollActionSheetView/Assets.xcassets/share/friends.imageset/friends@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iotjin/JhScrollActionSheetView/074153497b9d9ca5d9bf8f1bb640de4d73a837ab/JhScrollActionSheetView/Assets.xcassets/share/friends.imageset/friends@3x.png -------------------------------------------------------------------------------- /JhScrollActionSheetView/Assets.xcassets/share/kongjian.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "kongjian@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "kongjian@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /JhScrollActionSheetView/Assets.xcassets/share/kongjian.imageset/kongjian@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iotjin/JhScrollActionSheetView/074153497b9d9ca5d9bf8f1bb640de4d73a837ab/JhScrollActionSheetView/Assets.xcassets/share/kongjian.imageset/kongjian@2x.png -------------------------------------------------------------------------------- /JhScrollActionSheetView/Assets.xcassets/share/kongjian.imageset/kongjian@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iotjin/JhScrollActionSheetView/074153497b9d9ca5d9bf8f1bb640de4d73a837ab/JhScrollActionSheetView/Assets.xcassets/share/kongjian.imageset/kongjian@3x.png -------------------------------------------------------------------------------- /JhScrollActionSheetView/Assets.xcassets/share/qq.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "qq@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "qq@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /JhScrollActionSheetView/Assets.xcassets/share/qq.imageset/qq@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iotjin/JhScrollActionSheetView/074153497b9d9ca5d9bf8f1bb640de4d73a837ab/JhScrollActionSheetView/Assets.xcassets/share/qq.imageset/qq@2x.png -------------------------------------------------------------------------------- /JhScrollActionSheetView/Assets.xcassets/share/qq.imageset/qq@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iotjin/JhScrollActionSheetView/074153497b9d9ca5d9bf8f1bb640de4d73a837ab/JhScrollActionSheetView/Assets.xcassets/share/qq.imageset/qq@3x.png -------------------------------------------------------------------------------- /JhScrollActionSheetView/Assets.xcassets/share/sina.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "sina@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "sina@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /JhScrollActionSheetView/Assets.xcassets/share/sina.imageset/sina@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iotjin/JhScrollActionSheetView/074153497b9d9ca5d9bf8f1bb640de4d73a837ab/JhScrollActionSheetView/Assets.xcassets/share/sina.imageset/sina@2x.png -------------------------------------------------------------------------------- /JhScrollActionSheetView/Assets.xcassets/share/sina.imageset/sina@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iotjin/JhScrollActionSheetView/074153497b9d9ca5d9bf8f1bb640de4d73a837ab/JhScrollActionSheetView/Assets.xcassets/share/sina.imageset/sina@3x.png -------------------------------------------------------------------------------- /JhScrollActionSheetView/Assets.xcassets/share/weixing.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "weixing@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "weixing@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /JhScrollActionSheetView/Assets.xcassets/share/weixing.imageset/weixing@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iotjin/JhScrollActionSheetView/074153497b9d9ca5d9bf8f1bb640de4d73a837ab/JhScrollActionSheetView/Assets.xcassets/share/weixing.imageset/weixing@2x.png -------------------------------------------------------------------------------- /JhScrollActionSheetView/Assets.xcassets/share/weixing.imageset/weixing@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iotjin/JhScrollActionSheetView/074153497b9d9ca5d9bf8f1bb640de4d73a837ab/JhScrollActionSheetView/Assets.xcassets/share/weixing.imageset/weixing@3x.png -------------------------------------------------------------------------------- /JhScrollActionSheetView/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 | -------------------------------------------------------------------------------- /JhScrollActionSheetView/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 | -------------------------------------------------------------------------------- /JhScrollActionSheetView/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 | -------------------------------------------------------------------------------- /JhScrollActionSheetView/JhScrollActionSheet/JhPageItemCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // JhPageItemCell.h 3 | // JhPageItemView 4 | // 5 | // Created by Jh on 2018/11/15. 6 | // Copyright © 2018 Jh. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "JhPageItemModel.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @class JhPageItemModel; 15 | @interface JhPageItemCell : UICollectionViewCell 16 | 17 | @property (weak, nonatomic) IBOutlet UILabel *customTextLabel; 18 | @property (weak, nonatomic) IBOutlet UIImageView *imgView; 19 | 20 | @property (nonatomic, strong) JhPageItemModel *data; 21 | 22 | 23 | @end 24 | 25 | NS_ASSUME_NONNULL_END 26 | -------------------------------------------------------------------------------- /JhScrollActionSheetView/JhScrollActionSheet/JhPageItemCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // JhPageItemCell.m 3 | // JhPageItemView 4 | // 5 | // Created by Jh on 2018/11/15. 6 | // Copyright © 2018 Jh. All rights reserved. 7 | // 8 | 9 | #import "JhPageItemCell.h" 10 | 11 | @implementation JhPageItemCell 12 | 13 | - (void)awakeFromNib { 14 | [super awakeFromNib]; 15 | // Initialization code 16 | 17 | 18 | 19 | 20 | } 21 | 22 | 23 | -(void)setData:(JhPageItemModel *)data{ 24 | _data=data; 25 | 26 | self.customTextLabel.text = data.text; 27 | self.imgView.image = [UIImage imageNamed:data.img]; 28 | 29 | } 30 | 31 | 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /JhScrollActionSheetView/JhScrollActionSheet/JhPageItemCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /JhScrollActionSheetView/JhScrollActionSheet/JhPageItemModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // JhPageItemModel.h 3 | // JhPageItemView 4 | // 5 | // Created by Jh on 2018/11/16. 6 | // Copyright © 2018 Jh. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface JhPageItemModel : NSObject 14 | @property(nonatomic,copy) NSString *text; 15 | @property(nonatomic,copy) NSString *img; 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /JhScrollActionSheetView/JhScrollActionSheet/JhPageItemModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // JhPageItemModel.m 3 | // JhPageItemView 4 | // 5 | // Created by Jh on 2018/11/16. 6 | // Copyright © 2018 Jh. All rights reserved. 7 | // 8 | 9 | #import "JhPageItemModel.h" 10 | 11 | @implementation JhPageItemModel 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /JhScrollActionSheetView/JhScrollActionSheet/JhScrollActionSheetView.h: -------------------------------------------------------------------------------- 1 | // 2 | // JhScrollActionSheetView.h 3 | // JhScrollActionSheetView 4 | // 5 | // Created by Jh on 2018/11/26. 6 | // Copyright © 2018 Jh. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @class JhScrollActionSheetView; 14 | 15 | typedef void(^clickShareBlock)(JhScrollActionSheetView *actionSheet, NSInteger index); 16 | 17 | @interface JhScrollActionSheetView : UIView 18 | 19 | @property (nonatomic, copy) void (^clickShareBlock)(JhScrollActionSheetView *actionSheet, NSInteger index); 20 | @property (nonatomic, copy) void (^clickOtherBlock)(JhScrollActionSheetView *actionSheet, NSInteger index); 21 | 22 | 23 | /** 24 | 创建JhScrollActionSheetView对象 25 | 26 | @param title 标题 (传nil时隐藏) 27 | @param shareDataArray 第一行的数据 28 | @param otherDataArray 第二行的数据 (传nil时隐藏) 29 | @return JhScrollActionSheetView对象 30 | */ 31 | - (instancetype)initWithTitle:(NSString *)title 32 | shareDataArray:(NSArray *)shareDataArray 33 | otherDataArray:(NSArray *)otherDataArray; 34 | 35 | /** 36 | 弹出JhScrollActionSheetView视图(只有一行数据) 37 | 38 | @param title 标题 (传nil时隐藏) 39 | @param shareDataArray 第一行的数据 40 | @param clickShareBlock block回调 41 | */ 42 | + (void)showShareActionSheetWithTitle:(NSString *)title 43 | shareDataArray:(NSArray *)shareDataArray 44 | handler:(clickShareBlock)clickShareBlock; 45 | 46 | /** 47 | * 弹出视图 48 | */ 49 | - (void)show; 50 | 51 | 52 | @end 53 | 54 | 55 | NS_ASSUME_NONNULL_END 56 | -------------------------------------------------------------------------------- /JhScrollActionSheetView/JhScrollActionSheet/JhScrollActionSheetView.m: -------------------------------------------------------------------------------- 1 | // 2 | // JhScrollActionSheetView.m 3 | // JhScrollActionSheetView 4 | // 5 | // Created by Jh on 2018/11/26. 6 | // Copyright © 2018 Jh. All rights reserved. 7 | // 8 | 9 | #import "JhScrollActionSheetView.h" 10 | #import "JhPageItemCell.h" 11 | 12 | 13 | #define Kwidth [UIScreen mainScreen].bounds.size.width 14 | #define Kheight [UIScreen mainScreen].bounds.size.height 15 | 16 | #define JhColor(r, g, b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1.0] 17 | #define JhRandomColor JhColor(arc4random_uniform(255), arc4random_uniform(255), arc4random_uniform(255)) 18 | 19 | #define kBottomSafeHeight ([[UIApplication sharedApplication] statusBarFrame].size.height>20?34:0) 20 | 21 | /** title视图的总高度 */ 22 | #define kTitleViewFrameH (self.isHiddenTitleLabel == YES ? 0 : 50) 23 | /** 两个滚动视图的总高度 */ 24 | #define kScrollViewFrameH (self.isHiddenOtherCollectionView == YES ? 100 : 200) 25 | /** 整个视图的总高度 */ 26 | #define kViewFrameH (kTitleViewFrameH + kScrollViewFrameH + 50 + kBottomSafeHeight) 27 | 28 | #define itemHorizontalMargin 0 29 | #define kTopBottomMargin 0 30 | 31 | static const NSTimeInterval kAnimateDuration = 0.5f; 32 | 33 | @interface JhScrollActionSheetView() 34 | 35 | @property (nonatomic, strong) NSArray *shareArray; 36 | @property (nonatomic, strong) NSArray *otherArray; 37 | 38 | /** 弹出视图 */ 39 | @property (strong, nonatomic) UIView *actionSheetView; 40 | @property (nonatomic, strong) UICollectionView *shareCollectionView; 41 | @property (nonatomic, strong) UICollectionView *otherCollectionView; 42 | @property (nonatomic, strong) UIButton *cancelBtn; 43 | @property (nonatomic, strong) UILabel *titleLabel; 44 | 45 | @property (nonatomic, strong) NSString *titleStr; 46 | 47 | /** collectionView 高度 */ 48 | @property (nonatomic, assign) CGFloat collectionViewH; 49 | /** title传nil时,为YES */ 50 | @property (assign, nonatomic) BOOL isHiddenTitleLabel; 51 | /** 当设置为YES时, kScrollViewFrameH 高度为一半 */ 52 | @property (assign, nonatomic) BOOL isHiddenOtherCollectionView; 53 | 54 | /** 55 | * 收起视图 56 | */ 57 | - (void)dismiss; 58 | 59 | @end 60 | 61 | @implementation JhScrollActionSheetView 62 | 63 | static NSString * const reuseIdentifier = @"Cell"; 64 | 65 | 66 | - (void)dealloc { 67 | #ifdef DEBUG 68 | NSLog(@"JhScrollActionSheetView dealloc"); 69 | #endif 70 | } 71 | 72 | - (instancetype)initWithTitle:(NSString *)title 73 | shareDataArray:(NSArray *)shareDataArray 74 | otherDataArray:(NSArray *)otherDataArray { 75 | self = [super initWithFrame:CGRectZero]; 76 | if (self) { 77 | _titleStr = title; 78 | _shareArray = shareDataArray; 79 | _otherArray = otherDataArray; 80 | [self initSetUp]; 81 | // [self show]; 82 | } 83 | return self; 84 | } 85 | 86 | - (void)initSetUp { 87 | self.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.3f]; 88 | self.frame = CGRectMake(0, 0, Kwidth, Kheight); 89 | self.userInteractionEnabled = YES; 90 | //title不传时,隐藏title 91 | if (!_titleStr.length) { 92 | _isHiddenTitleLabel = YES; 93 | } else { 94 | _isHiddenTitleLabel = NO; 95 | } 96 | //当otherArray为空时,隐藏otherCollectionView 97 | if (!_otherArray.count) { 98 | _isHiddenOtherCollectionView = YES; 99 | _collectionViewH = kScrollViewFrameH + kTopBottomMargin*2; 100 | [self actionSheetView]; 101 | [self titleLabel]; 102 | [self shareCollectionView]; 103 | [self cancelBtn]; 104 | self.cancelBtn.frame = CGRectMake(0, CGRectGetMaxY(self.shareCollectionView.frame), Kwidth, 50); 105 | } else { 106 | //全部显示 107 | _isHiddenOtherCollectionView = NO; 108 | _collectionViewH = kScrollViewFrameH/2 + kTopBottomMargin*2; 109 | [self actionSheetView]; 110 | [self titleLabel]; 111 | [self shareCollectionView]; 112 | [self otherCollectionView]; 113 | [self cancelBtn]; 114 | self.cancelBtn.frame = CGRectMake(0, CGRectGetMaxY(self.otherCollectionView.frame), Kwidth, 50); 115 | } 116 | _shareCollectionView.backgroundColor = [UIColor clearColor]; 117 | _otherCollectionView.backgroundColor = [UIColor clearColor]; 118 | _actionSheetView.backgroundColor = JhColor(240, 240, 240); 119 | _cancelBtn.backgroundColor = [UIColor whiteColor]; 120 | } 121 | 122 | /** 123 | 弹出JhScrollActionSheetView视图(只有一行数据) 124 | 125 | @param title 标题 (传nil时隐藏) 126 | @param shareDataArray 第一行的数据 127 | @param clickShareBlock block回调 128 | */ 129 | + (void)showShareActionSheetWithTitle:(NSString *)title 130 | shareDataArray:(NSArray *)shareDataArray 131 | handler:(clickShareBlock)clickShareBlock{ 132 | 133 | JhScrollActionSheetView *actionSheetView = [[JhScrollActionSheetView alloc]initWithTitle:title shareDataArray:shareDataArray otherDataArray:@[]]; 134 | actionSheetView.clickShareBlock = clickShareBlock; 135 | [actionSheetView show]; 136 | } 137 | 138 | 139 | - (void)show { 140 | // 在主线程中处理,否则在viewDidLoad方法中直接调用,会先加本视图,后加控制器的视图到UIWindow上,导致本视图无法显示出来,这样处理后便会优先加控制器的视图到UIWindow上 141 | [[NSOperationQueue mainQueue] addOperationWithBlock:^{ 142 | NSEnumerator *frontToBackWindows = [UIApplication.sharedApplication.windows reverseObjectEnumerator]; 143 | for (UIWindow *window in frontToBackWindows) { 144 | BOOL windowOnMainScreen = window.screen == UIScreen.mainScreen; 145 | BOOL windowIsVisible = !window.hidden && window.alpha > 0; 146 | BOOL windowLevelNormal = window.windowLevel == UIWindowLevelNormal; 147 | if (windowOnMainScreen && windowIsVisible && windowLevelNormal) { 148 | [window addSubview:self]; 149 | break; 150 | } 151 | } 152 | [UIView animateWithDuration:kAnimateDuration delay:0.2 usingSpringWithDamping:0.7f initialSpringVelocity:0.7f options:UIViewAnimationOptionCurveEaseInOut animations:^{ 153 | CGRect frame = CGRectMake(0, Kheight-kViewFrameH, Kwidth,kViewFrameH); 154 | self.actionSheetView.frame = frame; 155 | } completion:nil]; 156 | }]; 157 | } 158 | 159 | - (void)dismiss { 160 | [UIView animateWithDuration:kAnimateDuration delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{ 161 | self.alpha = 0.0f; 162 | } completion:^(BOOL finished) { 163 | [self removeFromSuperview]; 164 | }]; 165 | } 166 | 167 | #pragma mark - 点击取消按钮 168 | - (void)clickCancelBtn { 169 | [self dismiss]; 170 | } 171 | 172 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 173 | [self dismiss]; 174 | } 175 | 176 | 177 | #pragma mark 178 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { 179 | if (collectionView == _shareCollectionView) { 180 | return self.shareArray.count; 181 | } else { 182 | return self.otherArray.count; 183 | } 184 | } 185 | 186 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { 187 | JhPageItemCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath]; 188 | cell.data = self.shareArray[indexPath.row]; 189 | if (collectionView == _shareCollectionView) { 190 | cell.data =self.shareArray[indexPath.row]; 191 | } else { 192 | cell.data =self.otherArray[indexPath.row]; 193 | } 194 | return cell; 195 | } 196 | 197 | #pragma mark - 点击事件 198 | -(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { 199 | // NSLog(@"点击cell --- indexPath --- %@",indexPath); 200 | // //获取UICollectionViewCell 的 cell的text 201 | // JhPageItemCell * cell2 = (JhPageItemCell *)[self collectionView:collectionView cellForItemAtIndexPath:indexPath]; 202 | // NSString *text = cell2.customTextLabel.text; 203 | // NSLog(@" 点击 cell2 的text %@ ",text); 204 | 205 | __weak typeof(self) weakSelf = self; 206 | if (collectionView == _shareCollectionView) { 207 | if (weakSelf.clickShareBlock) { 208 | weakSelf.clickShareBlock(self, indexPath.row); 209 | } 210 | } else { 211 | if (weakSelf.clickOtherBlock) { 212 | weakSelf.clickOtherBlock(self, indexPath.row); 213 | } 214 | } 215 | [self dismiss]; 216 | } 217 | 218 | 219 | #pragma mark - getters and setters 220 | 221 | - (UIView *)actionSheetView { 222 | if (!_actionSheetView) { 223 | UIView *actionSheetView = [[UIView alloc] init]; 224 | CGRect frame = CGRectMake(0, Kheight, self.frame.size.width, kViewFrameH); 225 | actionSheetView.frame = frame; 226 | _actionSheetView = actionSheetView; 227 | [self addSubview:_actionSheetView]; 228 | } 229 | return _actionSheetView; 230 | } 231 | 232 | - (UILabel *)titleLabel { 233 | if (!_titleLabel) { 234 | UILabel *titleLabel = [[UILabel alloc]init]; 235 | titleLabel.textColor = JhColor(170, 170, 170); 236 | titleLabel.font = [UIFont systemFontOfSize:16]; 237 | titleLabel.textAlignment = NSTextAlignmentCenter; 238 | titleLabel.text = _titleStr; 239 | titleLabel.frame = CGRectMake(0, 0, Kwidth, kTitleViewFrameH); 240 | _titleLabel = titleLabel; 241 | [self.actionSheetView addSubview:self.titleLabel]; 242 | } 243 | return _titleLabel; 244 | } 245 | 246 | - (UIButton *)cancelBtn { 247 | if (!_cancelBtn) { 248 | UIButton *cancelBtn = [[UIButton alloc]init]; 249 | [cancelBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; 250 | cancelBtn.titleLabel.font = [UIFont systemFontOfSize:18]; 251 | [cancelBtn addTarget:self action:@selector(clickCancelBtn) forControlEvents:UIControlEventTouchUpInside]; 252 | [cancelBtn setTitle:@"取消" forState:UIControlStateNormal]; 253 | _cancelBtn = cancelBtn; 254 | [self.actionSheetView addSubview:self.cancelBtn]; 255 | } 256 | return _cancelBtn; 257 | } 258 | 259 | - (UICollectionView *)shareCollectionView { 260 | if (!_shareCollectionView) { 261 | CGFloat viewWidth = Kwidth; 262 | CGFloat viewHeight = _collectionViewH; 263 | CGFloat maxColumn = 5; 264 | CGFloat maxRow = 1; 265 | CGFloat itemW = (viewWidth - (maxColumn - 1) -0.1f) / maxColumn; 266 | CGFloat itemH = (viewHeight - (maxRow - 1)- 0.1f) / maxRow; 267 | 268 | UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; 269 | //设置水平滚动 270 | layout.scrollDirection = UICollectionViewScrollDirectionHorizontal; 271 | //设置每个cell的尺寸 272 | layout.itemSize = CGSizeMake(itemW, itemH); 273 | //cell之间的水平间距 行间距 274 | layout.minimumLineSpacing = itemHorizontalMargin; 275 | //cell之间的垂直间距 cell间距 276 | layout.minimumInteritemSpacing = 0; 277 | //设置四周边距 278 | layout.sectionInset = UIEdgeInsetsMake(0, 0, 0, 0); 279 | 280 | CGRect Collectionframe =CGRectMake(0,CGRectGetMaxY(self.titleLabel.frame), viewWidth, viewHeight); 281 | _shareCollectionView = [[UICollectionView alloc] initWithFrame:Collectionframe collectionViewLayout:layout]; 282 | [_shareCollectionView registerNib:[UINib nibWithNibName:NSStringFromClass([JhPageItemCell class]) bundle:[NSBundle mainBundle]] forCellWithReuseIdentifier:reuseIdentifier]; 283 | _shareCollectionView.delegate = self; 284 | _shareCollectionView.dataSource = self; 285 | // 这句话的意思是为了 不管集合视图里面的值 多不多 都可以滚动 解决了值少了 集合视图不能滚动的问题 286 | // _shareCollectionView.alwaysBounceVertical = YES; 287 | // _shareCollectionView.showsHorizontalScrollIndicator = NO; 288 | [self.actionSheetView addSubview:self.shareCollectionView]; 289 | CGFloat lineHeight = 1.0; 290 | UIView *line=[[UIView alloc]initWithFrame:CGRectMake(0,CGRectGetMaxY(_shareCollectionView.frame)-lineHeight, Kwidth, lineHeight)]; 291 | line.backgroundColor=JhColor(230, 230, 230); 292 | [self.actionSheetView addSubview:line]; 293 | } 294 | return _shareCollectionView; 295 | } 296 | 297 | - (UICollectionView *)otherCollectionView { 298 | if (!_otherCollectionView) { 299 | CGFloat viewWidth = Kwidth; 300 | CGFloat viewHeight = _collectionViewH; 301 | CGFloat maxColumn = 5; 302 | CGFloat maxRow = 1; 303 | CGFloat itemW = (viewWidth - (maxColumn - 1) -0.1f) / maxColumn; 304 | CGFloat itemH = (viewHeight - (maxRow - 1)- 0.1f) / maxRow; 305 | 306 | UICollectionViewFlowLayout *layout =[[UICollectionViewFlowLayout alloc] init]; 307 | //设置水平滚动 308 | layout.scrollDirection = UICollectionViewScrollDirectionHorizontal; 309 | //设置每个cell的尺寸 310 | layout.itemSize = CGSizeMake(itemW, itemH); 311 | //cell之间的水平间距 行间距 312 | layout.minimumLineSpacing = itemHorizontalMargin; 313 | //cell之间的垂直间距 cell间距 314 | layout.minimumInteritemSpacing = 0; 315 | //设置四周边距 316 | layout.sectionInset = UIEdgeInsetsMake(0, 0, 0, 0); 317 | 318 | CGRect Collectionframe =CGRectMake(0, CGRectGetMaxY(self.shareCollectionView.frame), viewWidth, viewHeight); 319 | _otherCollectionView = [[UICollectionView alloc] initWithFrame:Collectionframe collectionViewLayout:layout]; 320 | [_otherCollectionView registerNib:[UINib nibWithNibName:NSStringFromClass([JhPageItemCell class]) bundle:[NSBundle mainBundle]] forCellWithReuseIdentifier:reuseIdentifier]; 321 | _otherCollectionView.delegate = self; 322 | _otherCollectionView.dataSource = self; 323 | // 这句话的意思是为了 不管集合视图里面的值 多不多 都可以滚动 解决了值少了 集合视图不能滚动的问题 324 | // _shareCollectionView.alwaysBounceVertical = YES; 325 | // _shareCollectionView.showsHorizontalScrollIndicator = NO; 326 | 327 | [self.actionSheetView addSubview:self.otherCollectionView]; 328 | } 329 | return _otherCollectionView; 330 | } 331 | 332 | @end 333 | -------------------------------------------------------------------------------- /JhScrollActionSheetView/MJExtension/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013-2015 MJExtension (https://github.com/CoderMJLee/MJExtension) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /JhScrollActionSheetView/MJExtension/MJExtension/MJExtension.h: -------------------------------------------------------------------------------- 1 | // 2 | // MJExtension.h 3 | // MJExtension 4 | // 5 | // Created by mj on 14-1-15. 6 | // Copyright (c) 2014年 小码哥. All rights reserved. 7 | // 代码地址:https://github.com/CoderMJLee/MJExtension 8 | // 代码地址:http://code4app.com/ios/%E5%AD%97%E5%85%B8-JSON-%E4%B8%8E%E6%A8%A1%E5%9E%8B%E7%9A%84%E8%BD%AC%E6%8D%A2/5339992a933bf062608b4c57 9 | 10 | #import "NSObject+MJCoding.h" 11 | #import "NSObject+MJProperty.h" 12 | #import "NSObject+MJClass.h" 13 | #import "NSObject+MJKeyValue.h" 14 | #import "NSString+MJExtension.h" 15 | #import "MJExtensionConst.h" -------------------------------------------------------------------------------- /JhScrollActionSheetView/MJExtension/MJExtension/MJExtensionConst.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __MJExtensionConst__H__ 3 | #define __MJExtensionConst__H__ 4 | 5 | #import 6 | 7 | // 信号量 8 | #define MJExtensionSemaphoreCreate \ 9 | static dispatch_semaphore_t signalSemaphore; \ 10 | static dispatch_once_t onceTokenSemaphore; \ 11 | dispatch_once(&onceTokenSemaphore, ^{ \ 12 | signalSemaphore = dispatch_semaphore_create(1); \ 13 | }); 14 | 15 | #define MJExtensionSemaphoreWait \ 16 | dispatch_semaphore_wait(signalSemaphore, DISPATCH_TIME_FOREVER); 17 | 18 | #define MJExtensionSemaphoreSignal \ 19 | dispatch_semaphore_signal(signalSemaphore); 20 | 21 | // 过期 22 | #define MJExtensionDeprecated(instead) NS_DEPRECATED(2_0, 2_0, 2_0, 2_0, instead) 23 | 24 | // 构建错误 25 | #define MJExtensionBuildError(clazz, msg) \ 26 | NSError *error = [NSError errorWithDomain:msg code:250 userInfo:nil]; \ 27 | [clazz setMj_error:error]; 28 | 29 | // 日志输出 30 | #ifdef DEBUG 31 | #define MJExtensionLog(...) NSLog(__VA_ARGS__) 32 | #else 33 | #define MJExtensionLog(...) 34 | #endif 35 | 36 | /** 37 | * 断言 38 | * @param condition 条件 39 | * @param returnValue 返回值 40 | */ 41 | #define MJExtensionAssertError(condition, returnValue, clazz, msg) \ 42 | [clazz setMj_error:nil]; \ 43 | if ((condition) == NO) { \ 44 | MJExtensionBuildError(clazz, msg); \ 45 | return returnValue;\ 46 | } 47 | 48 | #define MJExtensionAssert2(condition, returnValue) \ 49 | if ((condition) == NO) return returnValue; 50 | 51 | /** 52 | * 断言 53 | * @param condition 条件 54 | */ 55 | #define MJExtensionAssert(condition) MJExtensionAssert2(condition, ) 56 | 57 | /** 58 | * 断言 59 | * @param param 参数 60 | * @param returnValue 返回值 61 | */ 62 | #define MJExtensionAssertParamNotNil2(param, returnValue) \ 63 | MJExtensionAssert2((param) != nil, returnValue) 64 | 65 | /** 66 | * 断言 67 | * @param param 参数 68 | */ 69 | #define MJExtensionAssertParamNotNil(param) MJExtensionAssertParamNotNil2(param, ) 70 | 71 | /** 72 | * 打印所有的属性 73 | */ 74 | #define MJLogAllIvars \ 75 | -(NSString *)description \ 76 | { \ 77 | return [self mj_keyValues].description; \ 78 | } 79 | #define MJExtensionLogAllProperties MJLogAllIvars 80 | 81 | /** 82 | * 类型(属性类型) 83 | */ 84 | extern NSString *const MJPropertyTypeInt; 85 | extern NSString *const MJPropertyTypeShort; 86 | extern NSString *const MJPropertyTypeFloat; 87 | extern NSString *const MJPropertyTypeDouble; 88 | extern NSString *const MJPropertyTypeLong; 89 | extern NSString *const MJPropertyTypeLongLong; 90 | extern NSString *const MJPropertyTypeChar; 91 | extern NSString *const MJPropertyTypeBOOL1; 92 | extern NSString *const MJPropertyTypeBOOL2; 93 | extern NSString *const MJPropertyTypePointer; 94 | 95 | extern NSString *const MJPropertyTypeIvar; 96 | extern NSString *const MJPropertyTypeMethod; 97 | extern NSString *const MJPropertyTypeBlock; 98 | extern NSString *const MJPropertyTypeClass; 99 | extern NSString *const MJPropertyTypeSEL; 100 | extern NSString *const MJPropertyTypeId; 101 | 102 | #endif 103 | -------------------------------------------------------------------------------- /JhScrollActionSheetView/MJExtension/MJExtension/MJExtensionConst.m: -------------------------------------------------------------------------------- 1 | #ifndef __MJExtensionConst__M__ 2 | #define __MJExtensionConst__M__ 3 | 4 | #import 5 | 6 | /** 7 | * 成员变量类型(属性类型) 8 | */ 9 | NSString *const MJPropertyTypeInt = @"i"; 10 | NSString *const MJPropertyTypeShort = @"s"; 11 | NSString *const MJPropertyTypeFloat = @"f"; 12 | NSString *const MJPropertyTypeDouble = @"d"; 13 | NSString *const MJPropertyTypeLong = @"l"; 14 | NSString *const MJPropertyTypeLongLong = @"q"; 15 | NSString *const MJPropertyTypeChar = @"c"; 16 | NSString *const MJPropertyTypeBOOL1 = @"c"; 17 | NSString *const MJPropertyTypeBOOL2 = @"b"; 18 | NSString *const MJPropertyTypePointer = @"*"; 19 | 20 | NSString *const MJPropertyTypeIvar = @"^{objc_ivar=}"; 21 | NSString *const MJPropertyTypeMethod = @"^{objc_method=}"; 22 | NSString *const MJPropertyTypeBlock = @"@?"; 23 | NSString *const MJPropertyTypeClass = @"#"; 24 | NSString *const MJPropertyTypeSEL = @":"; 25 | NSString *const MJPropertyTypeId = @"@"; 26 | 27 | #endif -------------------------------------------------------------------------------- /JhScrollActionSheetView/MJExtension/MJExtension/MJFoundation.h: -------------------------------------------------------------------------------- 1 | // 2 | // MJFoundation.h 3 | // MJExtensionExample 4 | // 5 | // Created by MJ Lee on 14/7/16. 6 | // Copyright (c) 2014年 小码哥. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MJFoundation : NSObject 12 | + (BOOL)isClassFromFoundation:(Class)c; 13 | @end 14 | -------------------------------------------------------------------------------- /JhScrollActionSheetView/MJExtension/MJExtension/MJFoundation.m: -------------------------------------------------------------------------------- 1 | // 2 | // MJFoundation.m 3 | // MJExtensionExample 4 | // 5 | // Created by MJ Lee on 14/7/16. 6 | // Copyright (c) 2014年 小码哥. All rights reserved. 7 | // 8 | 9 | #import "MJFoundation.h" 10 | #import "MJExtensionConst.h" 11 | #import 12 | 13 | @implementation MJFoundation 14 | 15 | + (BOOL)isClassFromFoundation:(Class)c 16 | { 17 | if (c == [NSObject class] || c == [NSManagedObject class]) return YES; 18 | 19 | static NSSet *foundationClasses; 20 | static dispatch_once_t onceToken; 21 | dispatch_once(&onceToken, ^{ 22 | // 集合中没有NSObject,因为几乎所有的类都是继承自NSObject,具体是不是NSObject需要特殊判断 23 | foundationClasses = [NSSet setWithObjects: 24 | [NSURL class], 25 | [NSDate class], 26 | [NSValue class], 27 | [NSData class], 28 | [NSError class], 29 | [NSArray class], 30 | [NSDictionary class], 31 | [NSString class], 32 | [NSAttributedString class], nil]; 33 | }); 34 | 35 | __block BOOL result = NO; 36 | [foundationClasses enumerateObjectsUsingBlock:^(Class foundationClass, BOOL *stop) { 37 | if ([c isSubclassOfClass:foundationClass]) { 38 | result = YES; 39 | *stop = YES; 40 | } 41 | }]; 42 | return result; 43 | } 44 | @end 45 | -------------------------------------------------------------------------------- /JhScrollActionSheetView/MJExtension/MJExtension/MJProperty.h: -------------------------------------------------------------------------------- 1 | // 2 | // MJProperty.h 3 | // MJExtensionExample 4 | // 5 | // Created by MJ Lee on 15/4/17. 6 | // Copyright (c) 2015年 小码哥. All rights reserved. 7 | // 包装一个成员属性 8 | 9 | #import 10 | #import 11 | #import "MJPropertyType.h" 12 | #import "MJPropertyKey.h" 13 | 14 | /** 15 | * 包装一个成员 16 | */ 17 | @interface MJProperty : NSObject 18 | /** 成员属性 */ 19 | @property (nonatomic, assign) objc_property_t property; 20 | /** 成员属性的名字 */ 21 | @property (nonatomic, readonly) NSString *name; 22 | 23 | /** 成员属性的类型 */ 24 | @property (nonatomic, readonly) MJPropertyType *type; 25 | /** 成员属性来源于哪个类(可能是父类) */ 26 | @property (nonatomic, assign) Class srcClass; 27 | 28 | /**** 同一个成员属性 - 父类和子类的行为可能不一致(originKey、propertyKeys、objectClassInArray) ****/ 29 | /** 设置最原始的key */ 30 | - (void)setOriginKey:(id)originKey forClass:(Class)c; 31 | /** 对应着字典中的多级key(里面存放的数组,数组里面都是MJPropertyKey对象) */ 32 | - (NSArray *)propertyKeysForClass:(Class)c; 33 | 34 | /** 模型数组中的模型类型 */ 35 | - (void)setObjectClassInArray:(Class)objectClass forClass:(Class)c; 36 | - (Class)objectClassInArrayForClass:(Class)c; 37 | /**** 同一个成员变量 - 父类和子类的行为可能不一致(key、keys、objectClassInArray) ****/ 38 | 39 | /** 40 | * 设置object的成员变量值 41 | */ 42 | - (void)setValue:(id)value forObject:(id)object; 43 | /** 44 | * 得到object的成员属性值 45 | */ 46 | - (id)valueForObject:(id)object; 47 | 48 | /** 49 | * 初始化 50 | */ 51 | + (instancetype)cachedPropertyWithProperty:(objc_property_t)property; 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /JhScrollActionSheetView/MJExtension/MJExtension/MJProperty.m: -------------------------------------------------------------------------------- 1 | // 2 | // MJProperty.m 3 | // MJExtensionExample 4 | // 5 | // Created by MJ Lee on 15/4/17. 6 | // Copyright (c) 2015年 小码哥. All rights reserved. 7 | // 8 | 9 | #import "MJProperty.h" 10 | #import "MJFoundation.h" 11 | #import "MJExtensionConst.h" 12 | #import 13 | 14 | @interface MJProperty() 15 | @property (strong, nonatomic) NSMutableDictionary *propertyKeysDict; 16 | @property (strong, nonatomic) NSMutableDictionary *objectClassInArrayDict; 17 | @end 18 | 19 | @implementation MJProperty 20 | 21 | #pragma mark - 初始化 22 | - (instancetype)init 23 | { 24 | if (self = [super init]) { 25 | _propertyKeysDict = [NSMutableDictionary dictionary]; 26 | _objectClassInArrayDict = [NSMutableDictionary dictionary]; 27 | } 28 | return self; 29 | } 30 | 31 | #pragma mark - 缓存 32 | + (instancetype)cachedPropertyWithProperty:(objc_property_t)property 33 | { 34 | MJExtensionSemaphoreCreate 35 | MJExtensionSemaphoreWait 36 | MJProperty *propertyObj = objc_getAssociatedObject(self, property); 37 | if (propertyObj == nil) { 38 | propertyObj = [[self alloc] init]; 39 | propertyObj.property = property; 40 | objc_setAssociatedObject(self, property, propertyObj, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 41 | } 42 | MJExtensionSemaphoreSignal 43 | return propertyObj; 44 | } 45 | 46 | #pragma mark - 公共方法 47 | - (void)setProperty:(objc_property_t)property 48 | { 49 | _property = property; 50 | 51 | MJExtensionAssertParamNotNil(property); 52 | 53 | // 1.属性名 54 | _name = @(property_getName(property)); 55 | 56 | // 2.成员类型 57 | NSString *attrs = @(property_getAttributes(property)); 58 | NSUInteger dotLoc = [attrs rangeOfString:@","].location; 59 | NSString *code = nil; 60 | NSUInteger loc = 1; 61 | if (dotLoc == NSNotFound) { // 没有, 62 | code = [attrs substringFromIndex:loc]; 63 | } else { 64 | code = [attrs substringWithRange:NSMakeRange(loc, dotLoc - loc)]; 65 | } 66 | _type = [MJPropertyType cachedTypeWithCode:code]; 67 | } 68 | 69 | /** 70 | * 获得成员变量的值 71 | */ 72 | - (id)valueForObject:(id)object 73 | { 74 | if (self.type.KVCDisabled) return [NSNull null]; 75 | return [object valueForKey:self.name]; 76 | } 77 | 78 | /** 79 | * 设置成员变量的值 80 | */ 81 | - (void)setValue:(id)value forObject:(id)object 82 | { 83 | if (self.type.KVCDisabled || value == nil) return; 84 | [object setValue:value forKey:self.name]; 85 | } 86 | 87 | /** 88 | * 通过字符串key创建对应的keys 89 | */ 90 | - (NSArray *)propertyKeysWithStringKey:(NSString *)stringKey 91 | { 92 | if (stringKey.length == 0) return nil; 93 | 94 | NSMutableArray *propertyKeys = [NSMutableArray array]; 95 | // 如果有多级映射 96 | NSArray *oldKeys = [stringKey componentsSeparatedByString:@"."]; 97 | 98 | for (NSString *oldKey in oldKeys) { 99 | NSUInteger start = [oldKey rangeOfString:@"["].location; 100 | if (start != NSNotFound) { // 有索引的key 101 | NSString *prefixKey = [oldKey substringToIndex:start]; 102 | NSString *indexKey = prefixKey; 103 | if (prefixKey.length) { 104 | MJPropertyKey *propertyKey = [[MJPropertyKey alloc] init]; 105 | propertyKey.name = prefixKey; 106 | [propertyKeys addObject:propertyKey]; 107 | 108 | indexKey = [oldKey stringByReplacingOccurrencesOfString:prefixKey withString:@""]; 109 | } 110 | 111 | /** 解析索引 **/ 112 | // 元素 113 | NSArray *cmps = [[indexKey stringByReplacingOccurrencesOfString:@"[" withString:@""] componentsSeparatedByString:@"]"]; 114 | for (NSInteger i = 0; i 10 | 11 | typedef enum { 12 | MJPropertyKeyTypeDictionary = 0, // 字典的key 13 | MJPropertyKeyTypeArray // 数组的key 14 | } MJPropertyKeyType; 15 | 16 | /** 17 | * 属性的key 18 | */ 19 | @interface MJPropertyKey : NSObject 20 | /** key的名字 */ 21 | @property (copy, nonatomic) NSString *name; 22 | /** key的种类,可能是@"10",可能是@"age" */ 23 | @property (assign, nonatomic) MJPropertyKeyType type; 24 | 25 | /** 26 | * 根据当前的key,也就是name,从object(字典或者数组)中取值 27 | */ 28 | - (id)valueInObject:(id)object; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /JhScrollActionSheetView/MJExtension/MJExtension/MJPropertyKey.m: -------------------------------------------------------------------------------- 1 | // 2 | // MJPropertyKey.m 3 | // MJExtensionExample 4 | // 5 | // Created by MJ Lee on 15/8/11. 6 | // Copyright (c) 2015年 小码哥. All rights reserved. 7 | // 8 | 9 | #import "MJPropertyKey.h" 10 | 11 | @implementation MJPropertyKey 12 | 13 | - (id)valueInObject:(id)object 14 | { 15 | if ([object isKindOfClass:[NSDictionary class]] && self.type == MJPropertyKeyTypeDictionary) { 16 | return object[self.name]; 17 | } else if ([object isKindOfClass:[NSArray class]] && self.type == MJPropertyKeyTypeArray) { 18 | NSArray *array = object; 19 | NSUInteger index = self.name.intValue; 20 | if (index < array.count) return array[index]; 21 | return nil; 22 | } 23 | return nil; 24 | } 25 | @end 26 | -------------------------------------------------------------------------------- /JhScrollActionSheetView/MJExtension/MJExtension/MJPropertyType.h: -------------------------------------------------------------------------------- 1 | // 2 | // MJPropertyType.h 3 | // MJExtension 4 | // 5 | // Created by mj on 14-1-15. 6 | // Copyright (c) 2014年 小码哥. All rights reserved. 7 | // 包装一种类型 8 | 9 | #import 10 | 11 | /** 12 | * 包装一种类型 13 | */ 14 | @interface MJPropertyType : NSObject 15 | /** 类型标识符 */ 16 | @property (nonatomic, copy) NSString *code; 17 | 18 | /** 是否为id类型 */ 19 | @property (nonatomic, readonly, getter=isIdType) BOOL idType; 20 | 21 | /** 是否为基本数字类型:int、float等 */ 22 | @property (nonatomic, readonly, getter=isNumberType) BOOL numberType; 23 | 24 | /** 是否为BOOL类型 */ 25 | @property (nonatomic, readonly, getter=isBoolType) BOOL boolType; 26 | 27 | /** 对象类型(如果是基本数据类型,此值为nil) */ 28 | @property (nonatomic, readonly) Class typeClass; 29 | 30 | /** 类型是否来自于Foundation框架,比如NSString、NSArray */ 31 | @property (nonatomic, readonly, getter = isFromFoundation) BOOL fromFoundation; 32 | /** 类型是否不支持KVC */ 33 | @property (nonatomic, readonly, getter = isKVCDisabled) BOOL KVCDisabled; 34 | 35 | /** 36 | * 获得缓存的类型对象 37 | */ 38 | + (instancetype)cachedTypeWithCode:(NSString *)code; 39 | @end -------------------------------------------------------------------------------- /JhScrollActionSheetView/MJExtension/MJExtension/MJPropertyType.m: -------------------------------------------------------------------------------- 1 | // 2 | // MJPropertyType.m 3 | // MJExtension 4 | // 5 | // Created by mj on 14-1-15. 6 | // Copyright (c) 2014年 小码哥. All rights reserved. 7 | // 8 | 9 | #import "MJPropertyType.h" 10 | #import "MJExtension.h" 11 | #import "MJFoundation.h" 12 | #import "MJExtensionConst.h" 13 | 14 | @implementation MJPropertyType 15 | 16 | + (instancetype)cachedTypeWithCode:(NSString *)code 17 | { 18 | MJExtensionAssertParamNotNil2(code, nil); 19 | 20 | static NSMutableDictionary *types; 21 | static dispatch_once_t onceToken; 22 | dispatch_once(&onceToken, ^{ 23 | types = [NSMutableDictionary dictionary]; 24 | }); 25 | 26 | MJExtensionSemaphoreCreate 27 | MJExtensionSemaphoreWait 28 | MJPropertyType *type = types[code]; 29 | if (type == nil) { 30 | type = [[self alloc] init]; 31 | type.code = code; 32 | types[code] = type; 33 | } 34 | MJExtensionSemaphoreSignal 35 | return type; 36 | } 37 | 38 | #pragma mark - 公共方法 39 | - (void)setCode:(NSString *)code 40 | { 41 | _code = code; 42 | 43 | MJExtensionAssertParamNotNil(code); 44 | 45 | if ([code isEqualToString:MJPropertyTypeId]) { 46 | _idType = YES; 47 | } else if (code.length == 0) { 48 | _KVCDisabled = YES; 49 | } else if (code.length > 3 && [code hasPrefix:@"@\""]) { 50 | // 去掉@"和",截取中间的类型名称 51 | _code = [code substringWithRange:NSMakeRange(2, code.length - 3)]; 52 | _typeClass = NSClassFromString(_code); 53 | _fromFoundation = [MJFoundation isClassFromFoundation:_typeClass]; 54 | _numberType = [_typeClass isSubclassOfClass:[NSNumber class]]; 55 | 56 | } else if ([code isEqualToString:MJPropertyTypeSEL] || 57 | [code isEqualToString:MJPropertyTypeIvar] || 58 | [code isEqualToString:MJPropertyTypeMethod]) { 59 | _KVCDisabled = YES; 60 | } 61 | 62 | // 是否为数字类型 63 | NSString *lowerCode = _code.lowercaseString; 64 | NSArray *numberTypes = @[MJPropertyTypeInt, MJPropertyTypeShort, MJPropertyTypeBOOL1, MJPropertyTypeBOOL2, MJPropertyTypeFloat, MJPropertyTypeDouble, MJPropertyTypeLong, MJPropertyTypeLongLong, MJPropertyTypeChar]; 65 | if ([numberTypes containsObject:lowerCode]) { 66 | _numberType = YES; 67 | 68 | if ([lowerCode isEqualToString:MJPropertyTypeBOOL1] 69 | || [lowerCode isEqualToString:MJPropertyTypeBOOL2]) { 70 | _boolType = YES; 71 | } 72 | } 73 | } 74 | @end 75 | -------------------------------------------------------------------------------- /JhScrollActionSheetView/MJExtension/MJExtension/NSObject+MJClass.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+MJClass.h 3 | // MJExtensionExample 4 | // 5 | // Created by MJ Lee on 15/8/11. 6 | // Copyright (c) 2015年 小码哥. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | /** 12 | * 遍历所有类的block(父类) 13 | */ 14 | typedef void (^MJClassesEnumeration)(Class c, BOOL *stop); 15 | 16 | /** 这个数组中的属性名才会进行字典和模型的转换 */ 17 | typedef NSArray * (^MJAllowedPropertyNames)(void); 18 | /** 这个数组中的属性名才会进行归档 */ 19 | typedef NSArray * (^MJAllowedCodingPropertyNames)(void); 20 | 21 | /** 这个数组中的属性名将会被忽略:不进行字典和模型的转换 */ 22 | typedef NSArray * (^MJIgnoredPropertyNames)(void); 23 | /** 这个数组中的属性名将会被忽略:不进行归档 */ 24 | typedef NSArray * (^MJIgnoredCodingPropertyNames)(void); 25 | 26 | /** 27 | * 类相关的扩展 28 | */ 29 | @interface NSObject (MJClass) 30 | /** 31 | * 遍历所有的类 32 | */ 33 | + (void)mj_enumerateClasses:(MJClassesEnumeration)enumeration; 34 | + (void)mj_enumerateAllClasses:(MJClassesEnumeration)enumeration; 35 | 36 | #pragma mark - 属性白名单配置 37 | /** 38 | * 这个数组中的属性名才会进行字典和模型的转换 39 | * 40 | * @param allowedPropertyNames 这个数组中的属性名才会进行字典和模型的转换 41 | */ 42 | + (void)mj_setupAllowedPropertyNames:(MJAllowedPropertyNames)allowedPropertyNames; 43 | 44 | /** 45 | * 这个数组中的属性名才会进行字典和模型的转换 46 | */ 47 | + (NSMutableArray *)mj_totalAllowedPropertyNames; 48 | 49 | #pragma mark - 属性黑名单配置 50 | /** 51 | * 这个数组中的属性名将会被忽略:不进行字典和模型的转换 52 | * 53 | * @param ignoredPropertyNames 这个数组中的属性名将会被忽略:不进行字典和模型的转换 54 | */ 55 | + (void)mj_setupIgnoredPropertyNames:(MJIgnoredPropertyNames)ignoredPropertyNames; 56 | 57 | /** 58 | * 这个数组中的属性名将会被忽略:不进行字典和模型的转换 59 | */ 60 | + (NSMutableArray *)mj_totalIgnoredPropertyNames; 61 | 62 | #pragma mark - 归档属性白名单配置 63 | /** 64 | * 这个数组中的属性名才会进行归档 65 | * 66 | * @param allowedCodingPropertyNames 这个数组中的属性名才会进行归档 67 | */ 68 | + (void)mj_setupAllowedCodingPropertyNames:(MJAllowedCodingPropertyNames)allowedCodingPropertyNames; 69 | 70 | /** 71 | * 这个数组中的属性名才会进行字典和模型的转换 72 | */ 73 | + (NSMutableArray *)mj_totalAllowedCodingPropertyNames; 74 | 75 | #pragma mark - 归档属性黑名单配置 76 | /** 77 | * 这个数组中的属性名将会被忽略:不进行归档 78 | * 79 | * @param ignoredCodingPropertyNames 这个数组中的属性名将会被忽略:不进行归档 80 | */ 81 | + (void)mj_setupIgnoredCodingPropertyNames:(MJIgnoredCodingPropertyNames)ignoredCodingPropertyNames; 82 | 83 | /** 84 | * 这个数组中的属性名将会被忽略:不进行归档 85 | */ 86 | + (NSMutableArray *)mj_totalIgnoredCodingPropertyNames; 87 | 88 | #pragma mark - 内部使用 89 | + (void)mj_setupBlockReturnValue:(id (^)(void))block key:(const char *)key; 90 | @end 91 | -------------------------------------------------------------------------------- /JhScrollActionSheetView/MJExtension/MJExtension/NSObject+MJClass.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+MJClass.m 3 | // MJExtensionExample 4 | // 5 | // Created by MJ Lee on 15/8/11. 6 | // Copyright (c) 2015年 小码哥. All rights reserved. 7 | // 8 | 9 | #import "NSObject+MJClass.h" 10 | #import "NSObject+MJCoding.h" 11 | #import "NSObject+MJKeyValue.h" 12 | #import "MJFoundation.h" 13 | #import 14 | 15 | static const char MJAllowedPropertyNamesKey = '\0'; 16 | static const char MJIgnoredPropertyNamesKey = '\0'; 17 | static const char MJAllowedCodingPropertyNamesKey = '\0'; 18 | static const char MJIgnoredCodingPropertyNamesKey = '\0'; 19 | 20 | @implementation NSObject (MJClass) 21 | 22 | + (NSMutableDictionary *)classDictForKey:(const void *)key 23 | { 24 | static NSMutableDictionary *allowedPropertyNamesDict; 25 | static NSMutableDictionary *ignoredPropertyNamesDict; 26 | static NSMutableDictionary *allowedCodingPropertyNamesDict; 27 | static NSMutableDictionary *ignoredCodingPropertyNamesDict; 28 | 29 | static dispatch_once_t onceToken; 30 | dispatch_once(&onceToken, ^{ 31 | allowedPropertyNamesDict = [NSMutableDictionary dictionary]; 32 | ignoredPropertyNamesDict = [NSMutableDictionary dictionary]; 33 | allowedCodingPropertyNamesDict = [NSMutableDictionary dictionary]; 34 | ignoredCodingPropertyNamesDict = [NSMutableDictionary dictionary]; 35 | }); 36 | 37 | if (key == &MJAllowedPropertyNamesKey) return allowedPropertyNamesDict; 38 | if (key == &MJIgnoredPropertyNamesKey) return ignoredPropertyNamesDict; 39 | if (key == &MJAllowedCodingPropertyNamesKey) return allowedCodingPropertyNamesDict; 40 | if (key == &MJIgnoredCodingPropertyNamesKey) return ignoredCodingPropertyNamesDict; 41 | return nil; 42 | } 43 | 44 | + (void)mj_enumerateClasses:(MJClassesEnumeration)enumeration 45 | { 46 | // 1.没有block就直接返回 47 | if (enumeration == nil) return; 48 | 49 | // 2.停止遍历的标记 50 | BOOL stop = NO; 51 | 52 | // 3.当前正在遍历的类 53 | Class c = self; 54 | 55 | // 4.开始遍历每一个类 56 | while (c && !stop) { 57 | // 4.1.执行操作 58 | enumeration(c, &stop); 59 | 60 | // 4.2.获得父类 61 | c = class_getSuperclass(c); 62 | 63 | if ([MJFoundation isClassFromFoundation:c]) break; 64 | } 65 | } 66 | 67 | + (void)mj_enumerateAllClasses:(MJClassesEnumeration)enumeration 68 | { 69 | // 1.没有block就直接返回 70 | if (enumeration == nil) return; 71 | 72 | // 2.停止遍历的标记 73 | BOOL stop = NO; 74 | 75 | // 3.当前正在遍历的类 76 | Class c = self; 77 | 78 | // 4.开始遍历每一个类 79 | while (c && !stop) { 80 | // 4.1.执行操作 81 | enumeration(c, &stop); 82 | 83 | // 4.2.获得父类 84 | c = class_getSuperclass(c); 85 | } 86 | } 87 | 88 | #pragma mark - 属性黑名单配置 89 | + (void)mj_setupIgnoredPropertyNames:(MJIgnoredPropertyNames)ignoredPropertyNames 90 | { 91 | [self mj_setupBlockReturnValue:ignoredPropertyNames key:&MJIgnoredPropertyNamesKey]; 92 | } 93 | 94 | + (NSMutableArray *)mj_totalIgnoredPropertyNames 95 | { 96 | return [self mj_totalObjectsWithSelector:@selector(mj_ignoredPropertyNames) key:&MJIgnoredPropertyNamesKey]; 97 | } 98 | 99 | #pragma mark - 归档属性黑名单配置 100 | + (void)mj_setupIgnoredCodingPropertyNames:(MJIgnoredCodingPropertyNames)ignoredCodingPropertyNames 101 | { 102 | [self mj_setupBlockReturnValue:ignoredCodingPropertyNames key:&MJIgnoredCodingPropertyNamesKey]; 103 | } 104 | 105 | + (NSMutableArray *)mj_totalIgnoredCodingPropertyNames 106 | { 107 | return [self mj_totalObjectsWithSelector:@selector(mj_ignoredCodingPropertyNames) key:&MJIgnoredCodingPropertyNamesKey]; 108 | } 109 | 110 | #pragma mark - 属性白名单配置 111 | + (void)mj_setupAllowedPropertyNames:(MJAllowedPropertyNames)allowedPropertyNames; 112 | { 113 | [self mj_setupBlockReturnValue:allowedPropertyNames key:&MJAllowedPropertyNamesKey]; 114 | } 115 | 116 | + (NSMutableArray *)mj_totalAllowedPropertyNames 117 | { 118 | return [self mj_totalObjectsWithSelector:@selector(mj_allowedPropertyNames) key:&MJAllowedPropertyNamesKey]; 119 | } 120 | 121 | #pragma mark - 归档属性白名单配置 122 | + (void)mj_setupAllowedCodingPropertyNames:(MJAllowedCodingPropertyNames)allowedCodingPropertyNames 123 | { 124 | [self mj_setupBlockReturnValue:allowedCodingPropertyNames key:&MJAllowedCodingPropertyNamesKey]; 125 | } 126 | 127 | + (NSMutableArray *)mj_totalAllowedCodingPropertyNames 128 | { 129 | return [self mj_totalObjectsWithSelector:@selector(mj_allowedCodingPropertyNames) key:&MJAllowedCodingPropertyNamesKey]; 130 | } 131 | 132 | #pragma mark - block和方法处理:存储block的返回值 133 | + (void)mj_setupBlockReturnValue:(id (^)(void))block key:(const char *)key 134 | { 135 | if (block) { 136 | objc_setAssociatedObject(self, key, block(), OBJC_ASSOCIATION_RETAIN_NONATOMIC); 137 | } else { 138 | objc_setAssociatedObject(self, key, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 139 | } 140 | 141 | // 清空数据 142 | MJExtensionSemaphoreCreate 143 | MJExtensionSemaphoreWait 144 | [[self classDictForKey:key] removeAllObjects]; 145 | MJExtensionSemaphoreSignal 146 | } 147 | 148 | + (NSMutableArray *)mj_totalObjectsWithSelector:(SEL)selector key:(const char *)key 149 | { 150 | MJExtensionSemaphoreCreate 151 | MJExtensionSemaphoreWait 152 | 153 | NSMutableArray *array = [self classDictForKey:key][NSStringFromClass(self)]; 154 | if (array == nil) { 155 | // 创建、存储 156 | [self classDictForKey:key][NSStringFromClass(self)] = array = [NSMutableArray array]; 157 | 158 | if ([self respondsToSelector:selector]) { 159 | #pragma clang diagnostic push 160 | #pragma clang diagnostic ignored "-Warc-performSelector-leaks" 161 | NSArray *subArray = [self performSelector:selector]; 162 | #pragma clang diagnostic pop 163 | if (subArray) { 164 | [array addObjectsFromArray:subArray]; 165 | } 166 | } 167 | 168 | [self mj_enumerateAllClasses:^(__unsafe_unretained Class c, BOOL *stop) { 169 | NSArray *subArray = objc_getAssociatedObject(c, key); 170 | [array addObjectsFromArray:subArray]; 171 | }]; 172 | } 173 | 174 | MJExtensionSemaphoreSignal 175 | 176 | return array; 177 | } 178 | @end 179 | -------------------------------------------------------------------------------- /JhScrollActionSheetView/MJExtension/MJExtension/NSObject+MJCoding.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+MJCoding.h 3 | // MJExtension 4 | // 5 | // Created by mj on 14-1-15. 6 | // Copyright (c) 2014年 小码哥. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MJExtensionConst.h" 11 | 12 | /** 13 | * Codeing协议 14 | */ 15 | @protocol MJCoding 16 | @optional 17 | /** 18 | * 这个数组中的属性名才会进行归档 19 | */ 20 | + (NSArray *)mj_allowedCodingPropertyNames; 21 | /** 22 | * 这个数组中的属性名将会被忽略:不进行归档 23 | */ 24 | + (NSArray *)mj_ignoredCodingPropertyNames; 25 | @end 26 | 27 | @interface NSObject (MJCoding) 28 | /** 29 | * 解码(从文件中解析对象) 30 | */ 31 | - (void)mj_decode:(NSCoder *)decoder; 32 | /** 33 | * 编码(将对象写入文件中) 34 | */ 35 | - (void)mj_encode:(NSCoder *)encoder; 36 | @end 37 | 38 | /** 39 | 归档的实现 40 | */ 41 | #define MJCodingImplementation \ 42 | - (id)initWithCoder:(NSCoder *)decoder \ 43 | { \ 44 | if (self = [super init]) { \ 45 | [self mj_decode:decoder]; \ 46 | } \ 47 | return self; \ 48 | } \ 49 | \ 50 | - (void)encodeWithCoder:(NSCoder *)encoder \ 51 | { \ 52 | [self mj_encode:encoder]; \ 53 | } 54 | 55 | #define MJExtensionCodingImplementation MJCodingImplementation -------------------------------------------------------------------------------- /JhScrollActionSheetView/MJExtension/MJExtension/NSObject+MJCoding.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+MJCoding.m 3 | // MJExtension 4 | // 5 | // Created by mj on 14-1-15. 6 | // Copyright (c) 2014年 小码哥. All rights reserved. 7 | // 8 | 9 | #import "NSObject+MJCoding.h" 10 | #import "NSObject+MJClass.h" 11 | #import "NSObject+MJProperty.h" 12 | #import "MJProperty.h" 13 | 14 | @implementation NSObject (MJCoding) 15 | 16 | - (void)mj_encode:(NSCoder *)encoder 17 | { 18 | Class clazz = [self class]; 19 | 20 | NSArray *allowedCodingPropertyNames = [clazz mj_totalAllowedCodingPropertyNames]; 21 | NSArray *ignoredCodingPropertyNames = [clazz mj_totalIgnoredCodingPropertyNames]; 22 | 23 | [clazz mj_enumerateProperties:^(MJProperty *property, BOOL *stop) { 24 | // 检测是否被忽略 25 | if (allowedCodingPropertyNames.count && ![allowedCodingPropertyNames containsObject:property.name]) return; 26 | if ([ignoredCodingPropertyNames containsObject:property.name]) return; 27 | 28 | id value = [property valueForObject:self]; 29 | if (value == nil) return; 30 | [encoder encodeObject:value forKey:property.name]; 31 | }]; 32 | } 33 | 34 | - (void)mj_decode:(NSCoder *)decoder 35 | { 36 | Class clazz = [self class]; 37 | 38 | NSArray *allowedCodingPropertyNames = [clazz mj_totalAllowedCodingPropertyNames]; 39 | NSArray *ignoredCodingPropertyNames = [clazz mj_totalIgnoredCodingPropertyNames]; 40 | 41 | [clazz mj_enumerateProperties:^(MJProperty *property, BOOL *stop) { 42 | // 检测是否被忽略 43 | if (allowedCodingPropertyNames.count && ![allowedCodingPropertyNames containsObject:property.name]) return; 44 | if ([ignoredCodingPropertyNames containsObject:property.name]) return; 45 | 46 | id value = [decoder decodeObjectForKey:property.name]; 47 | if (value == nil) { // 兼容以前的MJExtension版本 48 | value = [decoder decodeObjectForKey:[@"_" stringByAppendingString:property.name]]; 49 | } 50 | if (value == nil) return; 51 | [property setValue:value forObject:self]; 52 | }]; 53 | } 54 | @end 55 | -------------------------------------------------------------------------------- /JhScrollActionSheetView/MJExtension/MJExtension/NSObject+MJKeyValue.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+MJKeyValue.h 3 | // MJExtension 4 | // 5 | // Created by mj on 13-8-24. 6 | // Copyright (c) 2013年 小码哥. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MJExtensionConst.h" 11 | #import 12 | #import "MJProperty.h" 13 | 14 | /** 15 | * KeyValue协议 16 | */ 17 | @protocol MJKeyValue 18 | @optional 19 | /** 20 | * 只有这个数组中的属性名才允许进行字典和模型的转换 21 | */ 22 | + (NSArray *)mj_allowedPropertyNames; 23 | 24 | /** 25 | * 这个数组中的属性名将会被忽略:不进行字典和模型的转换 26 | */ 27 | + (NSArray *)mj_ignoredPropertyNames; 28 | 29 | /** 30 | * 将属性名换为其他key去字典中取值 31 | * 32 | * @return 字典中的key是属性名,value是从字典中取值用的key 33 | */ 34 | + (NSDictionary *)mj_replacedKeyFromPropertyName; 35 | 36 | /** 37 | * 将属性名换为其他key去字典中取值 38 | * 39 | * @return 从字典中取值用的key 40 | */ 41 | + (id)mj_replacedKeyFromPropertyName121:(NSString *)propertyName; 42 | 43 | /** 44 | * 数组中需要转换的模型类 45 | * 46 | * @return 字典中的key是数组属性名,value是数组中存放模型的Class(Class类型或者NSString类型) 47 | */ 48 | + (NSDictionary *)mj_objectClassInArray; 49 | 50 | /** 51 | * 旧值换新值,用于过滤字典中的值 52 | * 53 | * @param oldValue 旧值 54 | * 55 | * @return 新值 56 | */ 57 | - (id)mj_newValueFromOldValue:(id)oldValue property:(MJProperty *)property; 58 | 59 | /** 60 | * 当字典转模型完毕时调用 61 | */ 62 | - (void)mj_keyValuesDidFinishConvertingToObject; 63 | 64 | /** 65 | * 当模型转字典完毕时调用 66 | */ 67 | - (void)mj_objectDidFinishConvertingToKeyValues; 68 | @end 69 | 70 | @interface NSObject (MJKeyValue) 71 | #pragma mark - 类方法 72 | /** 73 | * 字典转模型过程中遇到的错误 74 | */ 75 | + (NSError *)mj_error; 76 | 77 | /** 78 | * 模型转字典时,字典的key是否参考replacedKeyFromPropertyName等方法(父类设置了,子类也会继承下来) 79 | */ 80 | + (void)mj_referenceReplacedKeyWhenCreatingKeyValues:(BOOL)reference; 81 | 82 | #pragma mark - 对象方法 83 | /** 84 | * 将字典的键值对转成模型属性 85 | * @param keyValues 字典(可以是NSDictionary、NSData、NSString) 86 | */ 87 | - (instancetype)mj_setKeyValues:(id)keyValues; 88 | 89 | /** 90 | * 将字典的键值对转成模型属性 91 | * @param keyValues 字典(可以是NSDictionary、NSData、NSString) 92 | * @param context CoreData上下文 93 | */ 94 | - (instancetype)mj_setKeyValues:(id)keyValues context:(NSManagedObjectContext *)context; 95 | 96 | /** 97 | * 将模型转成字典 98 | * @return 字典 99 | */ 100 | - (NSMutableDictionary *)mj_keyValues; 101 | - (NSMutableDictionary *)mj_keyValuesWithKeys:(NSArray *)keys; 102 | - (NSMutableDictionary *)mj_keyValuesWithIgnoredKeys:(NSArray *)ignoredKeys; 103 | 104 | /** 105 | * 通过模型数组来创建一个字典数组 106 | * @param objectArray 模型数组 107 | * @return 字典数组 108 | */ 109 | + (NSMutableArray *)mj_keyValuesArrayWithObjectArray:(NSArray *)objectArray; 110 | + (NSMutableArray *)mj_keyValuesArrayWithObjectArray:(NSArray *)objectArray keys:(NSArray *)keys; 111 | + (NSMutableArray *)mj_keyValuesArrayWithObjectArray:(NSArray *)objectArray ignoredKeys:(NSArray *)ignoredKeys; 112 | 113 | #pragma mark - 字典转模型 114 | /** 115 | * 通过字典来创建一个模型 116 | * @param keyValues 字典(可以是NSDictionary、NSData、NSString) 117 | * @return 新建的对象 118 | */ 119 | + (instancetype)mj_objectWithKeyValues:(id)keyValues; 120 | 121 | /** 122 | * 通过字典来创建一个CoreData模型 123 | * @param keyValues 字典(可以是NSDictionary、NSData、NSString) 124 | * @param context CoreData上下文 125 | * @return 新建的对象 126 | */ 127 | + (instancetype)mj_objectWithKeyValues:(id)keyValues context:(NSManagedObjectContext *)context; 128 | 129 | /** 130 | * 通过plist来创建一个模型 131 | * @param filename 文件名(仅限于mainBundle中的文件) 132 | * @return 新建的对象 133 | */ 134 | + (instancetype)mj_objectWithFilename:(NSString *)filename; 135 | 136 | /** 137 | * 通过plist来创建一个模型 138 | * @param file 文件全路径 139 | * @return 新建的对象 140 | */ 141 | + (instancetype)mj_objectWithFile:(NSString *)file; 142 | 143 | #pragma mark - 字典数组转模型数组 144 | /** 145 | * 通过字典数组来创建一个模型数组 146 | * @param keyValuesArray 字典数组(可以是NSDictionary、NSData、NSString) 147 | * @return 模型数组 148 | */ 149 | + (NSMutableArray *)mj_objectArrayWithKeyValuesArray:(id)keyValuesArray; 150 | 151 | /** 152 | * 通过字典数组来创建一个模型数组 153 | * @param keyValuesArray 字典数组(可以是NSDictionary、NSData、NSString) 154 | * @param context CoreData上下文 155 | * @return 模型数组 156 | */ 157 | + (NSMutableArray *)mj_objectArrayWithKeyValuesArray:(id)keyValuesArray context:(NSManagedObjectContext *)context; 158 | 159 | /** 160 | * 通过plist来创建一个模型数组 161 | * @param filename 文件名(仅限于mainBundle中的文件) 162 | * @return 模型数组 163 | */ 164 | + (NSMutableArray *)mj_objectArrayWithFilename:(NSString *)filename; 165 | 166 | /** 167 | * 通过plist来创建一个模型数组 168 | * @param file 文件全路径 169 | * @return 模型数组 170 | */ 171 | + (NSMutableArray *)mj_objectArrayWithFile:(NSString *)file; 172 | 173 | #pragma mark - 转换为JSON 174 | /** 175 | * 转换为JSON Data 176 | */ 177 | - (NSData *)mj_JSONData; 178 | /** 179 | * 转换为字典或者数组 180 | */ 181 | - (id)mj_JSONObject; 182 | /** 183 | * 转换为JSON 字符串 184 | */ 185 | - (NSString *)mj_JSONString; 186 | @end 187 | 188 | @interface NSObject (MJKeyValueDeprecated_v_2_5_16) 189 | - (instancetype)setKeyValues:(id)keyValue MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 190 | - (instancetype)setKeyValues:(id)keyValues error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 191 | - (instancetype)setKeyValues:(id)keyValues context:(NSManagedObjectContext *)context MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 192 | - (instancetype)setKeyValues:(id)keyValues context:(NSManagedObjectContext *)context error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 193 | + (void)referenceReplacedKeyWhenCreatingKeyValues:(BOOL)reference MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 194 | - (NSMutableDictionary *)keyValues MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 195 | - (NSMutableDictionary *)keyValuesWithError:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 196 | - (NSMutableDictionary *)keyValuesWithKeys:(NSArray *)keys MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 197 | - (NSMutableDictionary *)keyValuesWithKeys:(NSArray *)keys error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 198 | - (NSMutableDictionary *)keyValuesWithIgnoredKeys:(NSArray *)ignoredKeys MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 199 | - (NSMutableDictionary *)keyValuesWithIgnoredKeys:(NSArray *)ignoredKeys error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 200 | + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 201 | + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 202 | + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray keys:(NSArray *)keys MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 203 | + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray keys:(NSArray *)keys error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 204 | + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray ignoredKeys:(NSArray *)ignoredKeys MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 205 | + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray ignoredKeys:(NSArray *)ignoredKeys error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 206 | + (instancetype)objectWithKeyValues:(id)keyValues MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 207 | + (instancetype)objectWithKeyValues:(id)keyValues error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 208 | + (instancetype)objectWithKeyValues:(id)keyValues context:(NSManagedObjectContext *)context MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 209 | + (instancetype)objectWithKeyValues:(id)keyValues context:(NSManagedObjectContext *)context error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 210 | + (instancetype)objectWithFilename:(NSString *)filename MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 211 | + (instancetype)objectWithFilename:(NSString *)filename error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 212 | + (instancetype)objectWithFile:(NSString *)file MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 213 | + (instancetype)objectWithFile:(NSString *)file error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 214 | + (NSMutableArray *)objectArrayWithKeyValuesArray:(id)keyValuesArray MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 215 | + (NSMutableArray *)objectArrayWithKeyValuesArray:(id)keyValuesArray error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 216 | + (NSMutableArray *)objectArrayWithKeyValuesArray:(id)keyValuesArray context:(NSManagedObjectContext *)context MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 217 | + (NSMutableArray *)objectArrayWithKeyValuesArray:(id)keyValuesArray context:(NSManagedObjectContext *)context error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 218 | + (NSMutableArray *)objectArrayWithFilename:(NSString *)filename MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 219 | + (NSMutableArray *)objectArrayWithFilename:(NSString *)filename error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 220 | + (NSMutableArray *)objectArrayWithFile:(NSString *)file MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 221 | + (NSMutableArray *)objectArrayWithFile:(NSString *)file error:(NSError **)error MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 222 | - (NSData *)JSONData MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 223 | - (id)JSONObject MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 224 | - (NSString *)JSONString MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 225 | @end 226 | -------------------------------------------------------------------------------- /JhScrollActionSheetView/MJExtension/MJExtension/NSObject+MJKeyValue.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+MJKeyValue.m 3 | // MJExtension 4 | // 5 | // Created by mj on 13-8-24. 6 | // Copyright (c) 2013年 小码哥. All rights reserved. 7 | // 8 | 9 | #import "NSObject+MJKeyValue.h" 10 | #import "NSObject+MJProperty.h" 11 | #import "NSString+MJExtension.h" 12 | #import "MJProperty.h" 13 | #import "MJPropertyType.h" 14 | #import "MJExtensionConst.h" 15 | #import "MJFoundation.h" 16 | #import "NSString+MJExtension.h" 17 | #import "NSObject+MJClass.h" 18 | 19 | @implementation NSObject (MJKeyValue) 20 | 21 | #pragma mark - 错误 22 | static const char MJErrorKey = '\0'; 23 | + (NSError *)mj_error 24 | { 25 | return objc_getAssociatedObject(self, &MJErrorKey); 26 | } 27 | 28 | + (void)setMj_error:(NSError *)error 29 | { 30 | objc_setAssociatedObject(self, &MJErrorKey, error, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 31 | } 32 | 33 | #pragma mark - 模型 -> 字典时的参考 34 | /** 模型转字典时,字典的key是否参考replacedKeyFromPropertyName等方法(父类设置了,子类也会继承下来) */ 35 | static const char MJReferenceReplacedKeyWhenCreatingKeyValuesKey = '\0'; 36 | 37 | + (void)mj_referenceReplacedKeyWhenCreatingKeyValues:(BOOL)reference 38 | { 39 | objc_setAssociatedObject(self, &MJReferenceReplacedKeyWhenCreatingKeyValuesKey, @(reference), OBJC_ASSOCIATION_ASSIGN); 40 | } 41 | 42 | + (BOOL)mj_isReferenceReplacedKeyWhenCreatingKeyValues 43 | { 44 | __block id value = objc_getAssociatedObject(self, &MJReferenceReplacedKeyWhenCreatingKeyValuesKey); 45 | if (!value) { 46 | [self mj_enumerateAllClasses:^(__unsafe_unretained Class c, BOOL *stop) { 47 | value = objc_getAssociatedObject(c, &MJReferenceReplacedKeyWhenCreatingKeyValuesKey); 48 | 49 | if (value) *stop = YES; 50 | }]; 51 | } 52 | return [value boolValue]; 53 | } 54 | 55 | #pragma mark - --常用的对象-- 56 | static NSNumberFormatter *numberFormatter_; 57 | + (void)load 58 | { 59 | numberFormatter_ = [[NSNumberFormatter alloc] init]; 60 | 61 | // 默认设置 62 | [self mj_referenceReplacedKeyWhenCreatingKeyValues:YES]; 63 | } 64 | 65 | #pragma mark - --公共方法-- 66 | #pragma mark - 字典 -> 模型 67 | - (instancetype)mj_setKeyValues:(id)keyValues 68 | { 69 | return [self mj_setKeyValues:keyValues context:nil]; 70 | } 71 | 72 | /** 73 | 核心代码: 74 | */ 75 | - (instancetype)mj_setKeyValues:(id)keyValues context:(NSManagedObjectContext *)context 76 | { 77 | // 获得JSON对象 78 | keyValues = [keyValues mj_JSONObject]; 79 | 80 | MJExtensionAssertError([keyValues isKindOfClass:[NSDictionary class]], self, [self class], @"keyValues参数不是一个字典"); 81 | 82 | Class clazz = [self class]; 83 | NSArray *allowedPropertyNames = [clazz mj_totalAllowedPropertyNames]; 84 | NSArray *ignoredPropertyNames = [clazz mj_totalIgnoredPropertyNames]; 85 | 86 | //通过封装的方法回调一个通过运行时编写的,用于返回属性列表的方法。 87 | [clazz mj_enumerateProperties:^(MJProperty *property, BOOL *stop) { 88 | @try { 89 | // 0.检测是否被忽略 90 | if (allowedPropertyNames.count && ![allowedPropertyNames containsObject:property.name]) return; 91 | if ([ignoredPropertyNames containsObject:property.name]) return; 92 | 93 | // 1.取出属性值 94 | id value; 95 | NSArray *propertyKeyses = [property propertyKeysForClass:clazz]; 96 | for (NSArray *propertyKeys in propertyKeyses) { 97 | value = keyValues; 98 | for (MJPropertyKey *propertyKey in propertyKeys) { 99 | value = [propertyKey valueInObject:value]; 100 | } 101 | if (value) break; 102 | } 103 | 104 | // 值的过滤 105 | id newValue = [clazz mj_getNewValueFromObject:self oldValue:value property:property]; 106 | if (newValue != value) { // 有过滤后的新值 107 | [property setValue:newValue forObject:self]; 108 | return; 109 | } 110 | 111 | // 如果没有值,就直接返回 112 | if (!value || value == [NSNull null]) return; 113 | 114 | // 2.复杂处理 115 | MJPropertyType *type = property.type; 116 | Class propertyClass = type.typeClass; 117 | Class objectClass = [property objectClassInArrayForClass:[self class]]; 118 | 119 | // 不可变 -> 可变处理 120 | if (propertyClass == [NSMutableArray class] && [value isKindOfClass:[NSArray class]]) { 121 | value = [NSMutableArray arrayWithArray:value]; 122 | } else if (propertyClass == [NSMutableDictionary class] && [value isKindOfClass:[NSDictionary class]]) { 123 | value = [NSMutableDictionary dictionaryWithDictionary:value]; 124 | } else if (propertyClass == [NSMutableString class] && [value isKindOfClass:[NSString class]]) { 125 | value = [NSMutableString stringWithString:value]; 126 | } else if (propertyClass == [NSMutableData class] && [value isKindOfClass:[NSData class]]) { 127 | value = [NSMutableData dataWithData:value]; 128 | } 129 | 130 | if (!type.isFromFoundation && propertyClass) { // 模型属性 131 | value = [propertyClass mj_objectWithKeyValues:value context:context]; 132 | } else if (objectClass) { 133 | if (objectClass == [NSURL class] && [value isKindOfClass:[NSArray class]]) { 134 | // string array -> url array 135 | NSMutableArray *urlArray = [NSMutableArray array]; 136 | for (NSString *string in value) { 137 | if (![string isKindOfClass:[NSString class]]) continue; 138 | [urlArray addObject:string.mj_url]; 139 | } 140 | value = urlArray; 141 | } else { // 字典数组-->模型数组 142 | value = [objectClass mj_objectArrayWithKeyValuesArray:value context:context]; 143 | } 144 | } else { 145 | if (propertyClass == [NSString class]) { 146 | if ([value isKindOfClass:[NSNumber class]]) { 147 | // NSNumber -> NSString 148 | value = [value description]; 149 | } else if ([value isKindOfClass:[NSURL class]]) { 150 | // NSURL -> NSString 151 | value = [value absoluteString]; 152 | } 153 | } else if ([value isKindOfClass:[NSString class]]) { 154 | if (propertyClass == [NSURL class]) { 155 | // NSString -> NSURL 156 | // 字符串转码 157 | value = [value mj_url]; 158 | } else if (type.isNumberType) { 159 | NSString *oldValue = value; 160 | 161 | // NSString -> NSNumber 162 | if (type.typeClass == [NSDecimalNumber class]) { 163 | value = [NSDecimalNumber decimalNumberWithString:oldValue]; 164 | } else { 165 | value = [numberFormatter_ numberFromString:oldValue]; 166 | } 167 | 168 | // 如果是BOOL 169 | if (type.isBoolType) { 170 | // 字符串转BOOL(字符串没有charValue方法) 171 | // 系统会调用字符串的charValue转为BOOL类型 172 | NSString *lower = [oldValue lowercaseString]; 173 | if ([lower isEqualToString:@"yes"] || [lower isEqualToString:@"true"]) { 174 | value = @YES; 175 | } else if ([lower isEqualToString:@"no"] || [lower isEqualToString:@"false"]) { 176 | value = @NO; 177 | } 178 | } 179 | } 180 | } 181 | 182 | // value和property类型不匹配 183 | if (propertyClass && ![value isKindOfClass:propertyClass]) { 184 | value = nil; 185 | } 186 | } 187 | 188 | // 3.赋值 189 | [property setValue:value forObject:self]; 190 | } @catch (NSException *exception) { 191 | MJExtensionBuildError([self class], exception.reason); 192 | MJExtensionLog(@"%@", exception); 193 | } 194 | }]; 195 | 196 | // 转换完毕 197 | if ([self respondsToSelector:@selector(mj_keyValuesDidFinishConvertingToObject)]) { 198 | [self mj_keyValuesDidFinishConvertingToObject]; 199 | } 200 | return self; 201 | } 202 | 203 | + (instancetype)mj_objectWithKeyValues:(id)keyValues 204 | { 205 | return [self mj_objectWithKeyValues:keyValues context:nil]; 206 | } 207 | 208 | + (instancetype)mj_objectWithKeyValues:(id)keyValues context:(NSManagedObjectContext *)context 209 | { 210 | // 获得JSON对象 211 | keyValues = [keyValues mj_JSONObject]; 212 | MJExtensionAssertError([keyValues isKindOfClass:[NSDictionary class]], nil, [self class], @"keyValues参数不是一个字典"); 213 | 214 | if ([self isSubclassOfClass:[NSManagedObject class]] && context) { 215 | NSString *entityName = [NSStringFromClass(self) componentsSeparatedByString:@"."].lastObject; 216 | return [[NSEntityDescription insertNewObjectForEntityForName:entityName inManagedObjectContext:context] mj_setKeyValues:keyValues context:context]; 217 | } 218 | return [[[self alloc] init] mj_setKeyValues:keyValues]; 219 | } 220 | 221 | + (instancetype)mj_objectWithFilename:(NSString *)filename 222 | { 223 | MJExtensionAssertError(filename != nil, nil, [self class], @"filename参数为nil"); 224 | 225 | return [self mj_objectWithFile:[[NSBundle mainBundle] pathForResource:filename ofType:nil]]; 226 | } 227 | 228 | + (instancetype)mj_objectWithFile:(NSString *)file 229 | { 230 | MJExtensionAssertError(file != nil, nil, [self class], @"file参数为nil"); 231 | 232 | return [self mj_objectWithKeyValues:[NSDictionary dictionaryWithContentsOfFile:file]]; 233 | } 234 | 235 | #pragma mark - 字典数组 -> 模型数组 236 | + (NSMutableArray *)mj_objectArrayWithKeyValuesArray:(NSArray *)keyValuesArray 237 | { 238 | return [self mj_objectArrayWithKeyValuesArray:keyValuesArray context:nil]; 239 | } 240 | 241 | + (NSMutableArray *)mj_objectArrayWithKeyValuesArray:(id)keyValuesArray context:(NSManagedObjectContext *)context 242 | { 243 | // 如果是JSON字符串 244 | keyValuesArray = [keyValuesArray mj_JSONObject]; 245 | 246 | // 1.判断真实性 247 | MJExtensionAssertError([keyValuesArray isKindOfClass:[NSArray class]], nil, [self class], @"keyValuesArray参数不是一个数组"); 248 | 249 | // 如果数组里面放的是NSString、NSNumber等数据 250 | if ([MJFoundation isClassFromFoundation:self]) return [NSMutableArray arrayWithArray:keyValuesArray]; 251 | 252 | 253 | // 2.创建数组 254 | NSMutableArray *modelArray = [NSMutableArray array]; 255 | 256 | // 3.遍历 257 | for (NSDictionary *keyValues in keyValuesArray) { 258 | if ([keyValues isKindOfClass:[NSArray class]]){ 259 | [modelArray addObject:[self mj_objectArrayWithKeyValuesArray:keyValues context:context]]; 260 | } else { 261 | id model = [self mj_objectWithKeyValues:keyValues context:context]; 262 | if (model) [modelArray addObject:model]; 263 | } 264 | } 265 | 266 | return modelArray; 267 | } 268 | 269 | + (NSMutableArray *)mj_objectArrayWithFilename:(NSString *)filename 270 | { 271 | MJExtensionAssertError(filename != nil, nil, [self class], @"filename参数为nil"); 272 | 273 | return [self mj_objectArrayWithFile:[[NSBundle mainBundle] pathForResource:filename ofType:nil]]; 274 | } 275 | 276 | + (NSMutableArray *)mj_objectArrayWithFile:(NSString *)file 277 | { 278 | MJExtensionAssertError(file != nil, nil, [self class], @"file参数为nil"); 279 | 280 | return [self mj_objectArrayWithKeyValuesArray:[NSArray arrayWithContentsOfFile:file]]; 281 | } 282 | 283 | #pragma mark - 模型 -> 字典 284 | - (NSMutableDictionary *)mj_keyValues 285 | { 286 | return [self mj_keyValuesWithKeys:nil ignoredKeys:nil]; 287 | } 288 | 289 | - (NSMutableDictionary *)mj_keyValuesWithKeys:(NSArray *)keys 290 | { 291 | return [self mj_keyValuesWithKeys:keys ignoredKeys:nil]; 292 | } 293 | 294 | - (NSMutableDictionary *)mj_keyValuesWithIgnoredKeys:(NSArray *)ignoredKeys 295 | { 296 | return [self mj_keyValuesWithKeys:nil ignoredKeys:ignoredKeys]; 297 | } 298 | 299 | - (NSMutableDictionary *)mj_keyValuesWithKeys:(NSArray *)keys ignoredKeys:(NSArray *)ignoredKeys 300 | { 301 | // 如果自己不是模型类, 那就返回自己 302 | MJExtensionAssertError(![MJFoundation isClassFromFoundation:[self class]], (NSMutableDictionary *)self, [self class], @"不是自定义的模型类") 303 | 304 | id keyValues = [NSMutableDictionary dictionary]; 305 | 306 | Class clazz = [self class]; 307 | NSArray *allowedPropertyNames = [clazz mj_totalAllowedPropertyNames]; 308 | NSArray *ignoredPropertyNames = [clazz mj_totalIgnoredPropertyNames]; 309 | 310 | [clazz mj_enumerateProperties:^(MJProperty *property, BOOL *stop) { 311 | @try { 312 | // 0.检测是否被忽略 313 | if (allowedPropertyNames.count && ![allowedPropertyNames containsObject:property.name]) return; 314 | if ([ignoredPropertyNames containsObject:property.name]) return; 315 | if (keys.count && ![keys containsObject:property.name]) return; 316 | if ([ignoredKeys containsObject:property.name]) return; 317 | 318 | // 1.取出属性值 319 | id value = [property valueForObject:self]; 320 | if (!value) return; 321 | 322 | // 2.如果是模型属性 323 | MJPropertyType *type = property.type; 324 | Class propertyClass = type.typeClass; 325 | if (!type.isFromFoundation && propertyClass) { 326 | value = [value mj_keyValues]; 327 | } else if ([value isKindOfClass:[NSArray class]]) { 328 | // 3.处理数组里面有模型的情况 329 | value = [NSObject mj_keyValuesArrayWithObjectArray:value]; 330 | } else if (propertyClass == [NSURL class]) { 331 | value = [value absoluteString]; 332 | } 333 | 334 | // 4.赋值 335 | if ([clazz mj_isReferenceReplacedKeyWhenCreatingKeyValues]) { 336 | NSArray *propertyKeys = [[property propertyKeysForClass:clazz] firstObject]; 337 | NSUInteger keyCount = propertyKeys.count; 338 | // 创建字典 339 | __block id innerContainer = keyValues; 340 | [propertyKeys enumerateObjectsUsingBlock:^(MJPropertyKey *propertyKey, NSUInteger idx, BOOL *stop) { 341 | // 下一个属性 342 | MJPropertyKey *nextPropertyKey = nil; 343 | if (idx != keyCount - 1) { 344 | nextPropertyKey = propertyKeys[idx + 1]; 345 | } 346 | 347 | if (nextPropertyKey) { // 不是最后一个key 348 | // 当前propertyKey对应的字典或者数组 349 | id tempInnerContainer = [propertyKey valueInObject:innerContainer]; 350 | if (tempInnerContainer == nil || [tempInnerContainer isKindOfClass:[NSNull class]]) { 351 | if (nextPropertyKey.type == MJPropertyKeyTypeDictionary) { 352 | tempInnerContainer = [NSMutableDictionary dictionary]; 353 | } else { 354 | tempInnerContainer = [NSMutableArray array]; 355 | } 356 | if (propertyKey.type == MJPropertyKeyTypeDictionary) { 357 | innerContainer[propertyKey.name] = tempInnerContainer; 358 | } else { 359 | innerContainer[propertyKey.name.intValue] = tempInnerContainer; 360 | } 361 | } 362 | 363 | if ([tempInnerContainer isKindOfClass:[NSMutableArray class]]) { 364 | NSMutableArray *tempInnerContainerArray = tempInnerContainer; 365 | int index = nextPropertyKey.name.intValue; 366 | while (tempInnerContainerArray.count < index + 1) { 367 | [tempInnerContainerArray addObject:[NSNull null]]; 368 | } 369 | } 370 | 371 | innerContainer = tempInnerContainer; 372 | } else { // 最后一个key 373 | if (propertyKey.type == MJPropertyKeyTypeDictionary) { 374 | innerContainer[propertyKey.name] = value; 375 | } else { 376 | innerContainer[propertyKey.name.intValue] = value; 377 | } 378 | } 379 | }]; 380 | } else { 381 | keyValues[property.name] = value; 382 | } 383 | } @catch (NSException *exception) { 384 | MJExtensionBuildError([self class], exception.reason); 385 | MJExtensionLog(@"%@", exception); 386 | } 387 | }]; 388 | 389 | // 转换完毕 390 | if ([self respondsToSelector:@selector(mj_objectDidFinishConvertingToKeyValues)]) { 391 | [self mj_objectDidFinishConvertingToKeyValues]; 392 | } 393 | 394 | return keyValues; 395 | } 396 | #pragma mark - 模型数组 -> 字典数组 397 | + (NSMutableArray *)mj_keyValuesArrayWithObjectArray:(NSArray *)objectArray 398 | { 399 | return [self mj_keyValuesArrayWithObjectArray:objectArray keys:nil ignoredKeys:nil]; 400 | } 401 | 402 | + (NSMutableArray *)mj_keyValuesArrayWithObjectArray:(NSArray *)objectArray keys:(NSArray *)keys 403 | { 404 | return [self mj_keyValuesArrayWithObjectArray:objectArray keys:keys ignoredKeys:nil]; 405 | } 406 | 407 | + (NSMutableArray *)mj_keyValuesArrayWithObjectArray:(NSArray *)objectArray ignoredKeys:(NSArray *)ignoredKeys 408 | { 409 | return [self mj_keyValuesArrayWithObjectArray:objectArray keys:nil ignoredKeys:ignoredKeys]; 410 | } 411 | 412 | + (NSMutableArray *)mj_keyValuesArrayWithObjectArray:(NSArray *)objectArray keys:(NSArray *)keys ignoredKeys:(NSArray *)ignoredKeys 413 | { 414 | // 0.判断真实性 415 | MJExtensionAssertError([objectArray isKindOfClass:[NSArray class]], nil, [self class], @"objectArray参数不是一个数组"); 416 | 417 | // 1.创建数组 418 | NSMutableArray *keyValuesArray = [NSMutableArray array]; 419 | for (id object in objectArray) { 420 | if (keys) { 421 | [keyValuesArray addObject:[object mj_keyValuesWithKeys:keys]]; 422 | } else { 423 | [keyValuesArray addObject:[object mj_keyValuesWithIgnoredKeys:ignoredKeys]]; 424 | } 425 | } 426 | return keyValuesArray; 427 | } 428 | 429 | #pragma mark - 转换为JSON 430 | - (NSData *)mj_JSONData 431 | { 432 | if ([self isKindOfClass:[NSString class]]) { 433 | return [((NSString *)self) dataUsingEncoding:NSUTF8StringEncoding]; 434 | } else if ([self isKindOfClass:[NSData class]]) { 435 | return (NSData *)self; 436 | } 437 | 438 | return [NSJSONSerialization dataWithJSONObject:[self mj_JSONObject] options:kNilOptions error:nil]; 439 | } 440 | 441 | - (id)mj_JSONObject 442 | { 443 | if ([self isKindOfClass:[NSString class]]) { 444 | return [NSJSONSerialization JSONObjectWithData:[((NSString *)self) dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:nil]; 445 | } else if ([self isKindOfClass:[NSData class]]) { 446 | return [NSJSONSerialization JSONObjectWithData:(NSData *)self options:kNilOptions error:nil]; 447 | } 448 | 449 | return self.mj_keyValues; 450 | } 451 | 452 | - (NSString *)mj_JSONString 453 | { 454 | if ([self isKindOfClass:[NSString class]]) { 455 | return (NSString *)self; 456 | } else if ([self isKindOfClass:[NSData class]]) { 457 | return [[NSString alloc] initWithData:(NSData *)self encoding:NSUTF8StringEncoding]; 458 | } 459 | 460 | return [[NSString alloc] initWithData:[self mj_JSONData] encoding:NSUTF8StringEncoding]; 461 | } 462 | @end 463 | 464 | @implementation NSObject (MJKeyValueDeprecated_v_2_5_16) 465 | - (instancetype)setKeyValues:(id)keyValues 466 | { 467 | return [self mj_setKeyValues:keyValues]; 468 | } 469 | 470 | - (instancetype)setKeyValues:(id)keyValues error:(NSError **)error 471 | { 472 | id value = [self mj_setKeyValues:keyValues]; 473 | if (error != NULL) { 474 | *error = [self.class mj_error]; 475 | } 476 | return value; 477 | 478 | } 479 | 480 | - (instancetype)setKeyValues:(id)keyValues context:(NSManagedObjectContext *)context 481 | { 482 | return [self mj_setKeyValues:keyValues context:context]; 483 | } 484 | 485 | - (instancetype)setKeyValues:(id)keyValues context:(NSManagedObjectContext *)context error:(NSError **)error 486 | { 487 | id value = [self mj_setKeyValues:keyValues context:context]; 488 | if (error != NULL) { 489 | *error = [self.class mj_error]; 490 | } 491 | return value; 492 | } 493 | 494 | + (void)referenceReplacedKeyWhenCreatingKeyValues:(BOOL)reference 495 | { 496 | [self mj_referenceReplacedKeyWhenCreatingKeyValues:reference]; 497 | } 498 | 499 | - (NSMutableDictionary *)keyValues 500 | { 501 | return [self mj_keyValues]; 502 | } 503 | 504 | - (NSMutableDictionary *)keyValuesWithError:(NSError **)error 505 | { 506 | id value = [self mj_keyValues]; 507 | if (error != NULL) { 508 | *error = [self.class mj_error]; 509 | } 510 | return value; 511 | } 512 | 513 | - (NSMutableDictionary *)keyValuesWithKeys:(NSArray *)keys 514 | { 515 | return [self mj_keyValuesWithKeys:keys]; 516 | } 517 | 518 | - (NSMutableDictionary *)keyValuesWithKeys:(NSArray *)keys error:(NSError **)error 519 | { 520 | id value = [self mj_keyValuesWithKeys:keys]; 521 | if (error != NULL) { 522 | *error = [self.class mj_error]; 523 | } 524 | return value; 525 | } 526 | 527 | - (NSMutableDictionary *)keyValuesWithIgnoredKeys:(NSArray *)ignoredKeys 528 | { 529 | return [self mj_keyValuesWithIgnoredKeys:ignoredKeys]; 530 | } 531 | 532 | - (NSMutableDictionary *)keyValuesWithIgnoredKeys:(NSArray *)ignoredKeys error:(NSError **)error 533 | { 534 | id value = [self mj_keyValuesWithIgnoredKeys:ignoredKeys]; 535 | if (error != NULL) { 536 | *error = [self.class mj_error]; 537 | } 538 | return value; 539 | } 540 | 541 | + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray 542 | { 543 | return [self mj_keyValuesArrayWithObjectArray:objectArray]; 544 | } 545 | 546 | + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray error:(NSError **)error 547 | { 548 | id value = [self mj_keyValuesArrayWithObjectArray:objectArray]; 549 | if (error != NULL) { 550 | *error = [self mj_error]; 551 | } 552 | return value; 553 | } 554 | 555 | + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray keys:(NSArray *)keys 556 | { 557 | return [self mj_keyValuesArrayWithObjectArray:objectArray keys:keys]; 558 | } 559 | 560 | + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray keys:(NSArray *)keys error:(NSError **)error 561 | { 562 | id value = [self mj_keyValuesArrayWithObjectArray:objectArray keys:keys]; 563 | if (error != NULL) { 564 | *error = [self mj_error]; 565 | } 566 | return value; 567 | } 568 | 569 | + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray ignoredKeys:(NSArray *)ignoredKeys 570 | { 571 | return [self mj_keyValuesArrayWithObjectArray:objectArray ignoredKeys:ignoredKeys]; 572 | } 573 | 574 | + (NSMutableArray *)keyValuesArrayWithObjectArray:(NSArray *)objectArray ignoredKeys:(NSArray *)ignoredKeys error:(NSError **)error 575 | { 576 | id value = [self mj_keyValuesArrayWithObjectArray:objectArray ignoredKeys:ignoredKeys]; 577 | if (error != NULL) { 578 | *error = [self mj_error]; 579 | } 580 | return value; 581 | } 582 | 583 | + (instancetype)objectWithKeyValues:(id)keyValues 584 | { 585 | return [self mj_objectWithKeyValues:keyValues]; 586 | } 587 | 588 | + (instancetype)objectWithKeyValues:(id)keyValues error:(NSError **)error 589 | { 590 | id value = [self mj_objectWithKeyValues:keyValues]; 591 | if (error != NULL) { 592 | *error = [self mj_error]; 593 | } 594 | return value; 595 | } 596 | 597 | + (instancetype)objectWithKeyValues:(id)keyValues context:(NSManagedObjectContext *)context 598 | { 599 | return [self mj_objectWithKeyValues:keyValues context:context]; 600 | } 601 | 602 | + (instancetype)objectWithKeyValues:(id)keyValues context:(NSManagedObjectContext *)context error:(NSError **)error 603 | { 604 | id value = [self mj_objectWithKeyValues:keyValues context:context]; 605 | if (error != NULL) { 606 | *error = [self mj_error]; 607 | } 608 | return value; 609 | } 610 | 611 | + (instancetype)objectWithFilename:(NSString *)filename 612 | { 613 | return [self mj_objectWithFilename:filename]; 614 | } 615 | 616 | + (instancetype)objectWithFilename:(NSString *)filename error:(NSError **)error 617 | { 618 | id value = [self mj_objectWithFilename:filename]; 619 | if (error != NULL) { 620 | *error = [self mj_error]; 621 | } 622 | return value; 623 | } 624 | 625 | + (instancetype)objectWithFile:(NSString *)file 626 | { 627 | return [self mj_objectWithFile:file]; 628 | } 629 | 630 | + (instancetype)objectWithFile:(NSString *)file error:(NSError **)error 631 | { 632 | id value = [self mj_objectWithFile:file]; 633 | if (error != NULL) { 634 | *error = [self mj_error]; 635 | } 636 | return value; 637 | } 638 | 639 | + (NSMutableArray *)objectArrayWithKeyValuesArray:(id)keyValuesArray 640 | { 641 | return [self mj_objectArrayWithKeyValuesArray:keyValuesArray]; 642 | } 643 | 644 | + (NSMutableArray *)objectArrayWithKeyValuesArray:(id)keyValuesArray error:(NSError **)error 645 | { 646 | id value = [self mj_objectArrayWithKeyValuesArray:keyValuesArray]; 647 | if (error != NULL) { 648 | *error = [self mj_error]; 649 | } 650 | return value; 651 | } 652 | 653 | + (NSMutableArray *)objectArrayWithKeyValuesArray:(id)keyValuesArray context:(NSManagedObjectContext *)context 654 | { 655 | return [self mj_objectArrayWithKeyValuesArray:keyValuesArray context:context]; 656 | } 657 | 658 | + (NSMutableArray *)objectArrayWithKeyValuesArray:(id)keyValuesArray context:(NSManagedObjectContext *)context error:(NSError **)error 659 | { 660 | id value = [self mj_objectArrayWithKeyValuesArray:keyValuesArray context:context]; 661 | if (error != NULL) { 662 | *error = [self mj_error]; 663 | } 664 | return value; 665 | } 666 | 667 | + (NSMutableArray *)objectArrayWithFilename:(NSString *)filename 668 | { 669 | return [self mj_objectArrayWithFilename:filename]; 670 | } 671 | 672 | + (NSMutableArray *)objectArrayWithFilename:(NSString *)filename error:(NSError **)error 673 | { 674 | id value = [self mj_objectArrayWithFilename:filename]; 675 | if (error != NULL) { 676 | *error = [self mj_error]; 677 | } 678 | return value; 679 | } 680 | 681 | + (NSMutableArray *)objectArrayWithFile:(NSString *)file 682 | { 683 | return [self mj_objectArrayWithFile:file]; 684 | } 685 | 686 | + (NSMutableArray *)objectArrayWithFile:(NSString *)file error:(NSError **)error 687 | { 688 | id value = [self mj_objectArrayWithFile:file]; 689 | if (error != NULL) { 690 | *error = [self mj_error]; 691 | } 692 | return value; 693 | } 694 | 695 | - (NSData *)JSONData 696 | { 697 | return [self mj_JSONData]; 698 | } 699 | 700 | - (id)JSONObject 701 | { 702 | return [self mj_JSONObject]; 703 | } 704 | 705 | - (NSString *)JSONString 706 | { 707 | return [self mj_JSONString]; 708 | } 709 | @end -------------------------------------------------------------------------------- /JhScrollActionSheetView/MJExtension/MJExtension/NSObject+MJProperty.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+MJProperty.h 3 | // MJExtensionExample 4 | // 5 | // Created by MJ Lee on 15/4/17. 6 | // Copyright (c) 2015年 小码哥. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MJExtensionConst.h" 11 | 12 | @class MJProperty; 13 | 14 | /** 15 | * 遍历成员变量用的block 16 | * 17 | * @param property 成员的包装对象 18 | * @param stop YES代表停止遍历,NO代表继续遍历 19 | */ 20 | typedef void (^MJPropertiesEnumeration)(MJProperty *property, BOOL *stop); 21 | 22 | /** 将属性名换为其他key去字典中取值 */ 23 | typedef NSDictionary * (^MJReplacedKeyFromPropertyName)(void); 24 | typedef id (^MJReplacedKeyFromPropertyName121)(NSString *propertyName); 25 | /** 数组中需要转换的模型类 */ 26 | typedef NSDictionary * (^MJObjectClassInArray)(void); 27 | /** 用于过滤字典中的值 */ 28 | typedef id (^MJNewValueFromOldValue)(id object, id oldValue, MJProperty *property); 29 | 30 | /** 31 | * 成员属性相关的扩展 32 | */ 33 | @interface NSObject (MJProperty) 34 | #pragma mark - 遍历 35 | /** 36 | * 遍历所有的成员 37 | */ 38 | + (void)mj_enumerateProperties:(MJPropertiesEnumeration)enumeration; 39 | 40 | #pragma mark - 新值配置 41 | /** 42 | * 用于过滤字典中的值 43 | * 44 | * @param newValueFormOldValue 用于过滤字典中的值 45 | */ 46 | + (void)mj_setupNewValueFromOldValue:(MJNewValueFromOldValue)newValueFormOldValue; 47 | + (id)mj_getNewValueFromObject:(__unsafe_unretained id)object oldValue:(__unsafe_unretained id)oldValue property:(__unsafe_unretained MJProperty *)property; 48 | 49 | #pragma mark - key配置 50 | /** 51 | * 将属性名换为其他key去字典中取值 52 | * 53 | * @param replacedKeyFromPropertyName 将属性名换为其他key去字典中取值 54 | */ 55 | + (void)mj_setupReplacedKeyFromPropertyName:(MJReplacedKeyFromPropertyName)replacedKeyFromPropertyName; 56 | /** 57 | * 将属性名换为其他key去字典中取值 58 | * 59 | * @param replacedKeyFromPropertyName121 将属性名换为其他key去字典中取值 60 | */ 61 | + (void)mj_setupReplacedKeyFromPropertyName121:(MJReplacedKeyFromPropertyName121)replacedKeyFromPropertyName121; 62 | 63 | #pragma mark - array model class配置 64 | /** 65 | * 数组中需要转换的模型类 66 | * 67 | * @param objectClassInArray 数组中需要转换的模型类 68 | */ 69 | + (void)mj_setupObjectClassInArray:(MJObjectClassInArray)objectClassInArray; 70 | @end 71 | 72 | @interface NSObject (MJPropertyDeprecated_v_2_5_16) 73 | + (void)enumerateProperties:(MJPropertiesEnumeration)enumeration MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 74 | + (void)setupNewValueFromOldValue:(MJNewValueFromOldValue)newValueFormOldValue MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 75 | + (id)getNewValueFromObject:(__unsafe_unretained id)object oldValue:(__unsafe_unretained id)oldValue property:(__unsafe_unretained MJProperty *)property MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 76 | + (void)setupReplacedKeyFromPropertyName:(MJReplacedKeyFromPropertyName)replacedKeyFromPropertyName MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 77 | + (void)setupReplacedKeyFromPropertyName121:(MJReplacedKeyFromPropertyName121)replacedKeyFromPropertyName121 MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 78 | + (void)setupObjectClassInArray:(MJObjectClassInArray)objectClassInArray MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 79 | @end 80 | -------------------------------------------------------------------------------- /JhScrollActionSheetView/MJExtension/MJExtension/NSObject+MJProperty.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+MJProperty.m 3 | // MJExtensionExample 4 | // 5 | // Created by MJ Lee on 15/4/17. 6 | // Copyright (c) 2015年 小码哥. All rights reserved. 7 | // 8 | 9 | #import "NSObject+MJProperty.h" 10 | #import "NSObject+MJKeyValue.h" 11 | #import "NSObject+MJCoding.h" 12 | #import "NSObject+MJClass.h" 13 | #import "MJProperty.h" 14 | #import "MJFoundation.h" 15 | #import 16 | 17 | #pragma clang diagnostic push 18 | #pragma clang diagnostic ignored "-Wundeclared-selector" 19 | #pragma clang diagnostic ignored "-Warc-performSelector-leaks" 20 | 21 | static const char MJReplacedKeyFromPropertyNameKey = '\0'; 22 | static const char MJReplacedKeyFromPropertyName121Key = '\0'; 23 | static const char MJNewValueFromOldValueKey = '\0'; 24 | static const char MJObjectClassInArrayKey = '\0'; 25 | 26 | static const char MJCachedPropertiesKey = '\0'; 27 | 28 | @implementation NSObject (Property) 29 | 30 | + (NSMutableDictionary *)propertyDictForKey:(const void *)key 31 | { 32 | static NSMutableDictionary *replacedKeyFromPropertyNameDict; 33 | static NSMutableDictionary *replacedKeyFromPropertyName121Dict; 34 | static NSMutableDictionary *newValueFromOldValueDict; 35 | static NSMutableDictionary *objectClassInArrayDict; 36 | static NSMutableDictionary *cachedPropertiesDict; 37 | 38 | static dispatch_once_t onceToken; 39 | dispatch_once(&onceToken, ^{ 40 | replacedKeyFromPropertyNameDict = [NSMutableDictionary dictionary]; 41 | replacedKeyFromPropertyName121Dict = [NSMutableDictionary dictionary]; 42 | newValueFromOldValueDict = [NSMutableDictionary dictionary]; 43 | objectClassInArrayDict = [NSMutableDictionary dictionary]; 44 | cachedPropertiesDict = [NSMutableDictionary dictionary]; 45 | }); 46 | 47 | if (key == &MJReplacedKeyFromPropertyNameKey) return replacedKeyFromPropertyNameDict; 48 | if (key == &MJReplacedKeyFromPropertyName121Key) return replacedKeyFromPropertyName121Dict; 49 | if (key == &MJNewValueFromOldValueKey) return newValueFromOldValueDict; 50 | if (key == &MJObjectClassInArrayKey) return objectClassInArrayDict; 51 | if (key == &MJCachedPropertiesKey) return cachedPropertiesDict; 52 | return nil; 53 | } 54 | 55 | #pragma mark - --私有方法-- 56 | + (id)propertyKey:(NSString *)propertyName 57 | { 58 | MJExtensionAssertParamNotNil2(propertyName, nil); 59 | 60 | __block id key = nil; 61 | // 查看有没有需要替换的key 62 | if ([self respondsToSelector:@selector(mj_replacedKeyFromPropertyName121:)]) { 63 | key = [self mj_replacedKeyFromPropertyName121:propertyName]; 64 | } 65 | // 兼容旧版本 66 | if ([self respondsToSelector:@selector(replacedKeyFromPropertyName121:)]) { 67 | key = [self performSelector:@selector(replacedKeyFromPropertyName121) withObject:propertyName]; 68 | } 69 | 70 | // 调用block 71 | if (!key) { 72 | [self mj_enumerateAllClasses:^(__unsafe_unretained Class c, BOOL *stop) { 73 | MJReplacedKeyFromPropertyName121 block = objc_getAssociatedObject(c, &MJReplacedKeyFromPropertyName121Key); 74 | if (block) { 75 | key = block(propertyName); 76 | } 77 | if (key) *stop = YES; 78 | }]; 79 | } 80 | 81 | // 查看有没有需要替换的key 82 | if ((!key || [key isEqual:propertyName]) && [self respondsToSelector:@selector(mj_replacedKeyFromPropertyName)]) { 83 | key = [self mj_replacedKeyFromPropertyName][propertyName]; 84 | } 85 | // 兼容旧版本 86 | if ((!key || [key isEqual:propertyName]) && [self respondsToSelector:@selector(replacedKeyFromPropertyName)]) { 87 | key = [self performSelector:@selector(replacedKeyFromPropertyName)][propertyName]; 88 | } 89 | 90 | if (!key || [key isEqual:propertyName]) { 91 | [self mj_enumerateAllClasses:^(__unsafe_unretained Class c, BOOL *stop) { 92 | NSDictionary *dict = objc_getAssociatedObject(c, &MJReplacedKeyFromPropertyNameKey); 93 | if (dict) { 94 | key = dict[propertyName]; 95 | } 96 | if (key && ![key isEqual:propertyName]) *stop = YES; 97 | }]; 98 | } 99 | 100 | // 2.用属性名作为key 101 | if (!key) key = propertyName; 102 | 103 | return key; 104 | } 105 | 106 | + (Class)propertyObjectClassInArray:(NSString *)propertyName 107 | { 108 | __block id clazz = nil; 109 | if ([self respondsToSelector:@selector(mj_objectClassInArray)]) { 110 | clazz = [self mj_objectClassInArray][propertyName]; 111 | } 112 | // 兼容旧版本 113 | if ([self respondsToSelector:@selector(objectClassInArray)]) { 114 | clazz = [self performSelector:@selector(objectClassInArray)][propertyName]; 115 | } 116 | 117 | if (!clazz) { 118 | [self mj_enumerateAllClasses:^(__unsafe_unretained Class c, BOOL *stop) { 119 | NSDictionary *dict = objc_getAssociatedObject(c, &MJObjectClassInArrayKey); 120 | if (dict) { 121 | clazz = dict[propertyName]; 122 | } 123 | if (clazz) *stop = YES; 124 | }]; 125 | } 126 | 127 | // 如果是NSString类型 128 | if ([clazz isKindOfClass:[NSString class]]) { 129 | clazz = NSClassFromString(clazz); 130 | } 131 | return clazz; 132 | } 133 | 134 | #pragma mark - --公共方法-- 135 | + (void)mj_enumerateProperties:(MJPropertiesEnumeration)enumeration 136 | { 137 | // 获得成员变量 138 | NSArray *cachedProperties = [self properties]; 139 | 140 | // 遍历成员变量 141 | BOOL stop = NO; 142 | for (MJProperty *property in cachedProperties) { 143 | enumeration(property, &stop); 144 | if (stop) break; 145 | } 146 | } 147 | 148 | #pragma mark - 公共方法 149 | + (NSMutableArray *)properties 150 | { 151 | NSMutableArray *cachedProperties = [self propertyDictForKey:&MJCachedPropertiesKey][NSStringFromClass(self)]; 152 | 153 | if (cachedProperties == nil) { 154 | MJExtensionSemaphoreCreate 155 | MJExtensionSemaphoreWait 156 | 157 | if (cachedProperties == nil) { 158 | cachedProperties = [NSMutableArray array]; 159 | 160 | [self mj_enumerateClasses:^(__unsafe_unretained Class c, BOOL *stop) { 161 | // 1.获得所有的成员变量 162 | unsigned int outCount = 0; 163 | objc_property_t *properties = class_copyPropertyList(c, &outCount); 164 | 165 | // 2.遍历每一个成员变量 166 | for (unsigned int i = 0; i 10 | #import "MJExtensionConst.h" 11 | 12 | @interface NSString (MJExtension) 13 | /** 14 | * 驼峰转下划线(loveYou -> love_you) 15 | */ 16 | - (NSString *)mj_underlineFromCamel; 17 | /** 18 | * 下划线转驼峰(love_you -> loveYou) 19 | */ 20 | - (NSString *)mj_camelFromUnderline; 21 | /** 22 | * 首字母变大写 23 | */ 24 | - (NSString *)mj_firstCharUpper; 25 | /** 26 | * 首字母变小写 27 | */ 28 | - (NSString *)mj_firstCharLower; 29 | 30 | - (BOOL)mj_isPureInt; 31 | 32 | - (NSURL *)mj_url; 33 | @end 34 | 35 | @interface NSString (MJExtensionDeprecated_v_2_5_16) 36 | - (NSString *)underlineFromCamel MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 37 | - (NSString *)camelFromUnderline MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 38 | - (NSString *)firstCharUpper MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 39 | - (NSString *)firstCharLower MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 40 | - (BOOL)isPureInt MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 41 | - (NSURL *)url MJExtensionDeprecated("请在方法名前面加上mj_前缀,使用mj_***"); 42 | @end 43 | -------------------------------------------------------------------------------- /JhScrollActionSheetView/MJExtension/MJExtension/NSString+MJExtension.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+MJExtension.m 3 | // MJExtensionExample 4 | // 5 | // Created by MJ Lee on 15/6/7. 6 | // Copyright (c) 2015年 小码哥. All rights reserved. 7 | // 8 | 9 | #import "NSString+MJExtension.h" 10 | 11 | @implementation NSString (MJExtension) 12 | - (NSString *)mj_underlineFromCamel 13 | { 14 | if (self.length == 0) return self; 15 | NSMutableString *string = [NSMutableString string]; 16 | for (NSUInteger i = 0; i= 2) [string appendString:[cmp substringFromIndex:1]]; 40 | } else { 41 | [string appendString:cmp]; 42 | } 43 | } 44 | return string; 45 | } 46 | 47 | - (NSString *)mj_firstCharLower 48 | { 49 | if (self.length == 0) return self; 50 | NSMutableString *string = [NSMutableString string]; 51 | [string appendString:[NSString stringWithFormat:@"%c", [self characterAtIndex:0]].lowercaseString]; 52 | if (self.length >= 2) [string appendString:[self substringFromIndex:1]]; 53 | return string; 54 | } 55 | 56 | - (NSString *)mj_firstCharUpper 57 | { 58 | if (self.length == 0) return self; 59 | NSMutableString *string = [NSMutableString string]; 60 | [string appendString:[NSString stringWithFormat:@"%c", [self characterAtIndex:0]].uppercaseString]; 61 | if (self.length >= 2) [string appendString:[self substringFromIndex:1]]; 62 | return string; 63 | } 64 | 65 | - (BOOL)mj_isPureInt 66 | { 67 | NSScanner *scan = [NSScanner scannerWithString:self]; 68 | int val; 69 | return [scan scanInt:&val] && [scan isAtEnd]; 70 | } 71 | 72 | - (NSURL *)mj_url 73 | { 74 | // [self stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet characterSetWithCharactersInString:@"!$&'()*+,-./:;=?@_~%#[]"]]; 75 | #pragma clang diagnostic push 76 | #pragma clang diagnostic ignored"-Wdeprecated-declarations" 77 | return [NSURL URLWithString:(NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)self, (CFStringRef)@"!$&'()*+,-./:;=?@_~%#[]", NULL,kCFStringEncodingUTF8))]; 78 | #pragma clang diagnostic pop 79 | } 80 | @end 81 | 82 | @implementation NSString (MJExtensionDeprecated_v_2_5_16) 83 | - (NSString *)underlineFromCamel 84 | { 85 | return self.mj_underlineFromCamel; 86 | } 87 | 88 | - (NSString *)camelFromUnderline 89 | { 90 | return self.mj_camelFromUnderline; 91 | } 92 | 93 | - (NSString *)firstCharLower 94 | { 95 | return self.mj_firstCharLower; 96 | } 97 | 98 | - (NSString *)firstCharUpper 99 | { 100 | return self.mj_firstCharUpper; 101 | } 102 | 103 | - (BOOL)isPureInt 104 | { 105 | return self.mj_isPureInt; 106 | } 107 | 108 | - (NSURL *)url 109 | { 110 | return self.mj_url; 111 | } 112 | @end 113 | -------------------------------------------------------------------------------- /JhScrollActionSheetView/MJExtension/README.md: -------------------------------------------------------------------------------- 1 | 2 | ![Logo](http://images.cnitblog.com/blog2015/497279/201505/051004316736641.png) 3 | MJExtension 4 | === 5 | - A fast, convenient and nonintrusive conversion framework between JSON and model. 6 | - 转换速度快、使用简单方便的字典转模型框架 7 | 8 | GitHub:[CoderMJLee](https://github.com/CoderMJLee) | Blog:[mjios(Chinese)](http://www.cnblogs.com/mjios) | PR is welcome,or [feedback](mailto:richermj123go@vip.qq.com) 9 | 10 | 11 | ## Contents 12 | * [Getting Started 【开始使用】](#Getting_Started) 13 | * [Features 【能做什么】](#Features) 14 | * [Installation 【安装】](#Installation) 15 | * [Examples 【示例】](#Examples) 16 | * [JSON -> Model](#JSON_Model) 17 | * [JSONString -> Model](#JSONString_Model) 18 | * [Model contains model](#Model_contains_model) 19 | * [Model contains model-array](#Model_contains_model_array) 20 | * [Model name - JSON key mapping](#Model_name_JSON_key_mapping) 21 | * [JSON array -> model array](#JSON_array_model_array) 22 | * [Model -> JSON](#Model_JSON) 23 | * [Model array -> JSON array](#Model_array_JSON_array) 24 | * [Core Data](#Core_Data) 25 | * [Coding](#Coding) 26 | * [Camel -> underline](#Camel_underline) 27 | * [NSString -> NSDate, nil -> @""](#NSString_NSDate) 28 | * [More use cases](#More_use_cases) 29 | 30 | --- 31 | 32 | # Getting Started【开始使用】 33 | 34 | ## Features【能做什么】 35 | - MJExtension是一套字典和模型之间互相转换的超轻量级框架 36 | * `JSON` --> `Model`、`Core Data Model` 37 | * `JSONString` --> `Model`、`Core Data Model` 38 | * `Model`、`Core Data Model` --> `JSON` 39 | * `JSON Array` --> `Model Array`、`Core Data Model Array` 40 | * `JSONString` --> `Model Array`、`Core Data Model Array` 41 | * `Model Array`、`Core Data Model Array` --> `JSON Array` 42 | * Coding all properties of a model with only one line of code. 43 | * 只需要一行代码,就能实现模型的所有属性进行Coding(归档和解档) 44 | 45 | ## Installation【安装】 46 | 47 | ### From CocoaPods【使用CocoaPods】 48 | 49 | ```ruby 50 | pod 'MJExtension' 51 | ``` 52 | 53 | ### Manually【手动导入】 54 | - Drag all source files under folder `MJExtension` to your project.【将`MJExtension`文件夹中的所有源代码拽入项目中】 55 | - Import the main header file:`#import "MJExtension.h"`【导入主头文件:`#import "MJExtension.h"`】 56 | 57 | ```objc 58 | MJExtension.h 59 | MJConst.h MJConst.m 60 | MJFoundation.h MJFoundation.m 61 | MJProperty.h MJProperty.m 62 | MJType.h MJType.m 63 | NSObject+MJCoding.h NSObject+MJCoding.m 64 | NSObject+MJProperty.h NSObject+MJProperty.m 65 | NSObject+MJKeyValue.h NSObject+MJKeyValue.m 66 | ``` 67 | 68 | # Examples【示例】 69 | 70 | ### The most simple JSON -> Model【最简单的字典转模型】 71 | 72 | ```objc 73 | typedef enum { 74 | SexMale, 75 | SexFemale 76 | } Sex; 77 | 78 | @interface User : NSObject 79 | @property (copy, nonatomic) NSString *name; 80 | @property (copy, nonatomic) NSString *icon; 81 | @property (assign, nonatomic) unsigned int age; 82 | @property (copy, nonatomic) NSString *height; 83 | @property (strong, nonatomic) NSNumber *money; 84 | @property (assign, nonatomic) Sex sex; 85 | @property (assign, nonatomic, getter=isGay) BOOL gay; 86 | @end 87 | 88 | /***********************************************/ 89 | 90 | NSDictionary *dict = @{ 91 | @"name" : @"Jack", 92 | @"icon" : @"lufy.png", 93 | @"age" : @20, 94 | @"height" : @"1.55", 95 | @"money" : @100.9, 96 | @"sex" : @(SexFemale), 97 | @"gay" : @"true" 98 | // @"gay" : @"1" 99 | // @"gay" : @"NO" 100 | }; 101 | 102 | // JSON -> User 103 | User *user = [User mj_objectWithKeyValues:dict]; 104 | 105 | NSLog(@"name=%@, icon=%@, age=%zd, height=%@, money=%@, sex=%d, gay=%d", user.name, user.icon, user.age, user.height, user.money, user.sex, user.gay); 106 | // name=Jack, icon=lufy.png, age=20, height=1.550000, money=100.9, sex=1 107 | ``` 108 | 109 | ### JSONString -> Model【JSON字符串转模型】 110 | 111 | ```objc 112 | // 1.Define a JSONString 113 | NSString *jsonString = @"{\"name\":\"Jack\", \"icon\":\"lufy.png\", \"age\":20}"; 114 | 115 | // 2.JSONString -> User 116 | User *user = [User mj_objectWithKeyValues:jsonString]; 117 | 118 | // 3.Print user's properties 119 | NSLog(@"name=%@, icon=%@, age=%d", user.name, user.icon, user.age); 120 | // name=Jack, icon=lufy.png, age=20 121 | ``` 122 | 123 | ### Model contains model【模型中嵌套模型】 124 | 125 | ```objc 126 | @interface Status : NSObject 127 | @property (copy, nonatomic) NSString *text; 128 | @property (strong, nonatomic) User *user; 129 | @property (strong, nonatomic) Status *retweetedStatus; 130 | @end 131 | 132 | /***********************************************/ 133 | 134 | NSDictionary *dict = @{ 135 | @"text" : @"Agree!Nice weather!", 136 | @"user" : @{ 137 | @"name" : @"Jack", 138 | @"icon" : @"lufy.png" 139 | }, 140 | @"retweetedStatus" : @{ 141 | @"text" : @"Nice weather!", 142 | @"user" : @{ 143 | @"name" : @"Rose", 144 | @"icon" : @"nami.png" 145 | } 146 | } 147 | }; 148 | 149 | // JSON -> Status 150 | Status *status = [Status mj_objectWithKeyValues:dict]; 151 | 152 | NSString *text = status.text; 153 | NSString *name = status.user.name; 154 | NSString *icon = status.user.icon; 155 | NSLog(@"text=%@, name=%@, icon=%@", text, name, icon); 156 | // text=Agree!Nice weather!, name=Jack, icon=lufy.png 157 | 158 | NSString *text2 = status.retweetedStatus.text; 159 | NSString *name2 = status.retweetedStatus.user.name; 160 | NSString *icon2 = status.retweetedStatus.user.icon; 161 | NSLog(@"text2=%@, name2=%@, icon2=%@", text2, name2, icon2); 162 | // text2=Nice weather!, name2=Rose, icon2=nami.png 163 | ``` 164 | 165 | ### Model contains model-array【模型中有个数组属性,数组里面又要装着其他模型】 166 | 167 | ```objc 168 | @interface Ad : NSObject 169 | @property (copy, nonatomic) NSString *image; 170 | @property (copy, nonatomic) NSString *url; 171 | @end 172 | 173 | @interface StatusResult : NSObject 174 | /** Contatins status model */ 175 | @property (strong, nonatomic) NSMutableArray *statuses; 176 | /** Contatins ad model */ 177 | @property (strong, nonatomic) NSArray *ads; 178 | @property (strong, nonatomic) NSNumber *totalNumber; 179 | @end 180 | 181 | /***********************************************/ 182 | 183 | // Tell MJExtension what type of model will be contained in statuses and ads. 184 | [StatusResult mj_setupObjectClassInArray:^NSDictionary *{ 185 | return @{ 186 | @"statuses" : @"Status", 187 | // @"statuses" : [Status class], 188 | @"ads" : @"Ad" 189 | // @"ads" : [Ad class] 190 | }; 191 | }]; 192 | // Equals: StatusResult.m implements +mj_objectClassInArray method. 193 | 194 | NSDictionary *dict = @{ 195 | @"statuses" : @[ 196 | @{ 197 | @"text" : @"Nice weather!", 198 | @"user" : @{ 199 | @"name" : @"Rose", 200 | @"icon" : @"nami.png" 201 | } 202 | }, 203 | @{ 204 | @"text" : @"Go camping tomorrow!", 205 | @"user" : @{ 206 | @"name" : @"Jack", 207 | @"icon" : @"lufy.png" 208 | } 209 | } 210 | ], 211 | @"ads" : @[ 212 | @{ 213 | @"image" : @"ad01.png", 214 | @"url" : @"http://www.ad01.com" 215 | }, 216 | @{ 217 | @"image" : @"ad02.png", 218 | @"url" : @"http://www.ad02.com" 219 | } 220 | ], 221 | @"totalNumber" : @"2014" 222 | }; 223 | 224 | // JSON -> StatusResult 225 | StatusResult *result = [StatusResult mj_objectWithKeyValues:dict]; 226 | 227 | NSLog(@"totalNumber=%@", result.totalNumber); 228 | // totalNumber=2014 229 | 230 | // Printing 231 | for (Status *status in result.statuses) { 232 | NSString *text = status.text; 233 | NSString *name = status.user.name; 234 | NSString *icon = status.user.icon; 235 | NSLog(@"text=%@, name=%@, icon=%@", text, name, icon); 236 | } 237 | // text=Nice weather!, name=Rose, icon=nami.png 238 | // text=Go camping tomorrow!, name=Jack, icon=lufy.png 239 | 240 | // Printing 241 | for (Ad *ad in result.ads) { 242 | NSLog(@"image=%@, url=%@", ad.image, ad.url); 243 | } 244 | // image=ad01.png, url=http://www.ad01.com 245 | // image=ad02.png, url=http://www.ad02.com 246 | ``` 247 | 248 | ### Model name - JSON key mapping【模型中的属性名和字典中的key不相同(或者需要多级映射)】 249 | 250 | ```objc 251 | @interface Bag : NSObject 252 | @property (copy, nonatomic) NSString *name; 253 | @property (assign, nonatomic) double price; 254 | @end 255 | 256 | @interface Student : NSObject 257 | @property (copy, nonatomic) NSString *ID; 258 | @property (copy, nonatomic) NSString *desc; 259 | @property (copy, nonatomic) NSString *nowName; 260 | @property (copy, nonatomic) NSString *oldName; 261 | @property (copy, nonatomic) NSString *nameChangedTime; 262 | @property (strong, nonatomic) Bag *bag; 263 | @end 264 | 265 | /***********************************************/ 266 | 267 | // How to map 268 | [Student mj_setupReplacedKeyFromPropertyName:^NSDictionary *{ 269 | return @{ 270 | @"ID" : @"id", 271 | @"desc" : @"description", 272 | @"oldName" : @"name.oldName", 273 | @"nowName" : @"name.newName", 274 | @"nameChangedTime" : @"name.info[1].nameChangedTime", 275 | @"bag" : @"other.bag" 276 | }; 277 | }]; 278 | // Equals: Student.m implements +mj_replacedKeyFromPropertyName method. 279 | 280 | NSDictionary *dict = @{ 281 | @"id" : @"20", 282 | @"description" : @"kids", 283 | @"name" : @{ 284 | @"newName" : @"lufy", 285 | @"oldName" : @"kitty", 286 | @"info" : @[ 287 | @"test-data", 288 | @{ 289 | @"nameChangedTime" : @"2013-08" 290 | } 291 | ] 292 | }, 293 | @"other" : @{ 294 | @"bag" : @{ 295 | @"name" : @"a red bag", 296 | @"price" : @100.7 297 | } 298 | } 299 | }; 300 | 301 | // JSON -> Student 302 | Student *stu = [Student mj_objectWithKeyValues:dict]; 303 | 304 | // Printing 305 | NSLog(@"ID=%@, desc=%@, oldName=%@, nowName=%@, nameChangedTime=%@", 306 | stu.ID, stu.desc, stu.oldName, stu.nowName, stu.nameChangedTime); 307 | // ID=20, desc=kids, oldName=kitty, nowName=lufy, nameChangedTime=2013-08 308 | NSLog(@"bagName=%@, bagPrice=%f", stu.bag.name, stu.bag.price); 309 | // bagName=a red bag, bagPrice=100.700000 310 | ``` 311 | 312 | 313 | ### JSON array -> model array【将一个字典数组转成模型数组】 314 | 315 | ```objc 316 | NSArray *dictArray = @[ 317 | @{ 318 | @"name" : @"Jack", 319 | @"icon" : @"lufy.png" 320 | }, 321 | @{ 322 | @"name" : @"Rose", 323 | @"icon" : @"nami.png" 324 | } 325 | ]; 326 | 327 | // JSON array -> User array 328 | NSArray *userArray = [User mj_objectArrayWithKeyValuesArray:dictArray]; 329 | 330 | // Printing 331 | for (User *user in userArray) { 332 | NSLog(@"name=%@, icon=%@", user.name, user.icon); 333 | } 334 | // name=Jack, icon=lufy.png 335 | // name=Rose, icon=nami.png 336 | ``` 337 | 338 | ### Model -> JSON【将一个模型转成字典】 339 | ```objc 340 | // New model 341 | User *user = [[User alloc] init]; 342 | user.name = @"Jack"; 343 | user.icon = @"lufy.png"; 344 | 345 | Status *status = [[Status alloc] init]; 346 | status.user = user; 347 | status.text = @"Nice mood!"; 348 | 349 | // Status -> JSON 350 | NSDictionary *statusDict = status.mj_keyValues; 351 | NSLog(@"%@", statusDict); 352 | /* 353 | { 354 | text = "Nice mood!"; 355 | user = { 356 | icon = "lufy.png"; 357 | name = Jack; 358 | }; 359 | } 360 | */ 361 | 362 | // More complex situation 363 | Student *stu = [[Student alloc] init]; 364 | stu.ID = @"123"; 365 | stu.oldName = @"rose"; 366 | stu.nowName = @"jack"; 367 | stu.desc = @"handsome"; 368 | stu.nameChangedTime = @"2018-09-08"; 369 | 370 | Bag *bag = [[Bag alloc] init]; 371 | bag.name = @"a red bag"; 372 | bag.price = 205; 373 | stu.bag = bag; 374 | 375 | NSDictionary *stuDict = stu.mj_keyValues; 376 | NSLog(@"%@", stuDict); 377 | /* 378 | { 379 | ID = 123; 380 | bag = { 381 | name = "\U5c0f\U4e66\U5305"; 382 | price = 205; 383 | }; 384 | desc = handsome; 385 | nameChangedTime = "2018-09-08"; 386 | nowName = jack; 387 | oldName = rose; 388 | } 389 | */ 390 | ``` 391 | 392 | ### Model array -> JSON array【将一个模型数组转成字典数组】 393 | 394 | ```objc 395 | // New model array 396 | User *user1 = [[User alloc] init]; 397 | user1.name = @"Jack"; 398 | user1.icon = @"lufy.png"; 399 | 400 | User *user2 = [[User alloc] init]; 401 | user2.name = @"Rose"; 402 | user2.icon = @"nami.png"; 403 | 404 | NSArray *userArray = @[user1, user2]; 405 | 406 | // Model array -> JSON array 407 | NSArray *dictArray = [User mj_keyValuesArrayWithObjectArray:userArray]; 408 | NSLog(@"%@", dictArray); 409 | /* 410 | ( 411 | { 412 | icon = "lufy.png"; 413 | name = Jack; 414 | }, 415 | { 416 | icon = "nami.png"; 417 | name = Rose; 418 | } 419 | ) 420 | */ 421 | ``` 422 | 423 | ### Core Data 424 | 425 | ```objc 426 | NSDictionary *dict = @{ 427 | @"name" : @"Jack", 428 | @"icon" : @"lufy.png", 429 | @"age" : @20, 430 | @"height" : @1.55, 431 | @"money" : @"100.9", 432 | @"sex" : @(SexFemale), 433 | @"gay" : @"true" 434 | }; 435 | 436 | // This demo just provide simple steps 437 | NSManagedObjectContext *context = nil; 438 | User *user = [User mj_objectWithKeyValues:dict context:context]; 439 | 440 | [context save:nil]; 441 | ``` 442 | 443 | ### Coding 444 | 445 | ```objc 446 | #import "MJExtension.h" 447 | 448 | @implementation Bag 449 | // NSCoding Implementation 450 | MJExtensionCodingImplementation 451 | @end 452 | 453 | /***********************************************/ 454 | 455 | // what properties not to be coded 456 | [Bag mj_setupIgnoredCodingPropertyNames:^NSArray *{ 457 | return @[@"name"]; 458 | }]; 459 | // Equals: Bag.m implements +mj_ignoredCodingPropertyNames method. 460 | 461 | // Create model 462 | Bag *bag = [[Bag alloc] init]; 463 | bag.name = @"Red bag"; 464 | bag.price = 200.8; 465 | 466 | NSString *file = [NSHomeDirectory() stringByAppendingPathComponent:@"Desktop/bag.data"]; 467 | // Encoding 468 | [NSKeyedArchiver archiveRootObject:bag toFile:file]; 469 | 470 | // Decoding 471 | Bag *decodedBag = [NSKeyedUnarchiver unarchiveObjectWithFile:file]; 472 | NSLog(@"name=%@, price=%f", decodedBag.name, decodedBag.price); 473 | // name=(null), price=200.800000 474 | ``` 475 | 476 | ### Camel -> underline【统一转换属性名(比如驼峰转下划线)】 477 | ```objc 478 | // Dog 479 | #import "MJExtension.h" 480 | 481 | @implementation Dog 482 | + (NSString *)mj_replacedKeyFromPropertyName121:(NSString *)propertyName 483 | { 484 | // nickName -> nick_name 485 | return [propertyName mj_underlineFromCamel]; 486 | } 487 | @end 488 | 489 | // NSDictionary 490 | NSDictionary *dict = @{ 491 | @"nick_name" : @"旺财", 492 | @"sale_price" : @"10.5", 493 | @"run_speed" : @"100.9" 494 | }; 495 | // NSDictionary -> Dog 496 | Dog *dog = [Dog mj_objectWithKeyValues:dict]; 497 | 498 | // printing 499 | NSLog(@"nickName=%@, scalePrice=%f runSpeed=%f", dog.nickName, dog.salePrice, dog.runSpeed); 500 | ``` 501 | 502 | ### NSString -> NSDate, nil -> @""【过滤字典的值(比如字符串日期处理为NSDate、字符串nil处理为@"")】 503 | ```objc 504 | // Book 505 | #import "MJExtension.h" 506 | 507 | @implementation Book 508 | - (id)mj_newValueFromOldValue:(id)oldValue property:(MJProperty *)property 509 | { 510 | if ([property.name isEqualToString:@"publisher"]) { 511 | if (oldValue == nil) return @""; 512 | } else if (property.type.typeClass == [NSDate class]) { 513 | NSDateFormatter *fmt = [[NSDateFormatter alloc] init]; 514 | fmt.dateFormat = @"yyyy-MM-dd"; 515 | return [fmt dateFromString:oldValue]; 516 | } 517 | 518 | return oldValue; 519 | } 520 | @end 521 | 522 | // NSDictionary 523 | NSDictionary *dict = @{ 524 | @"name" : @"5分钟突破iOS开发", 525 | @"publishedTime" : @"2011-09-10" 526 | }; 527 | // NSDictionary -> Book 528 | Book *book = [Book mj_objectWithKeyValues:dict]; 529 | 530 | // printing 531 | NSLog(@"name=%@, publisher=%@, publishedTime=%@", book.name, book.publisher, book.publishedTime); 532 | ``` 533 | 534 | ### More use cases【更多用法】 535 | - Please reference to `NSObject+MJKeyValue.h` and `NSObject+MJCoding.h` 536 | 537 | 538 | ## 期待 539 | * 如果在使用过程中遇到BUG,希望你能Issues我,谢谢(或者尝试下载最新的框架代码看看BUG修复没有) 540 | * 如果在使用过程中发现功能不够用,希望你能Issues我,我非常想为这个框架增加更多好用的功能,谢谢 541 | * 如果你想为MJExtension输出代码,请拼命Pull Requests我 542 | -------------------------------------------------------------------------------- /JhScrollActionSheetView/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // JhScrollActionSheetView 4 | // 5 | // Created by Jh on 2018/11/26. 6 | // Copyright © 2018 Jh. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /JhScrollActionSheetView/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // JhScrollActionSheetView 4 | // 5 | // Created by Jh on 2018/11/26. 6 | // Copyright © 2018 Jh. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "MJExtension.h" 11 | #import "JhPageItemModel.h" 12 | 13 | #import "JhScrollActionSheetView.h" 14 | 15 | 16 | @interface ViewController () 17 | 18 | /** item数组 */ 19 | @property (nonatomic, strong) NSMutableArray *shareArray; 20 | @property (nonatomic, strong) NSMutableArray *otherArray; 21 | 22 | @end 23 | 24 | @implementation ViewController 25 | 26 | 27 | - (void)viewDidLoad { 28 | [super viewDidLoad]; 29 | 30 | [self setUI]; 31 | } 32 | 33 | - (void)setUI { 34 | UIButton *shareBtn = [UIButton buttonWithType:UIButtonTypeCustom]; 35 | shareBtn.frame = CGRectMake(100, 100, 50, 50); 36 | shareBtn.backgroundColor = [UIColor orangeColor]; 37 | [shareBtn setTitle:@"样式1" forState:UIControlStateNormal]; 38 | [shareBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; 39 | [shareBtn addTarget:self action:@selector(click:) forControlEvents:UIControlEventTouchUpInside]; 40 | shareBtn.tag = 11; 41 | [self.view addSubview:shareBtn]; 42 | 43 | UIButton *shareBtn2 = [UIButton buttonWithType:UIButtonTypeCustom]; 44 | shareBtn2.frame = CGRectMake(100, 200, 50, 50); 45 | shareBtn2.backgroundColor = [UIColor orangeColor]; 46 | [shareBtn2 setTitle:@"样式2" forState:UIControlStateNormal]; 47 | [shareBtn2 setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; 48 | [shareBtn2 addTarget:self action:@selector(click:) forControlEvents:UIControlEventTouchUpInside]; 49 | shareBtn2.tag = 12; 50 | [self.view addSubview:shareBtn2]; 51 | 52 | 53 | UIButton *shareBtn3 = [UIButton buttonWithType:UIButtonTypeCustom]; 54 | shareBtn3.frame = CGRectMake(100, 500, 50, 50); 55 | shareBtn3.backgroundColor = [UIColor orangeColor]; 56 | [shareBtn3 setTitle:@"样式3" forState:UIControlStateNormal]; 57 | [shareBtn3 setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; 58 | [shareBtn3 addTarget:self action:@selector(click:) forControlEvents:UIControlEventTouchUpInside]; 59 | shareBtn3.tag = 13; 60 | [self.view addSubview:shareBtn3]; 61 | } 62 | 63 | - (void)click:(UIButton *)btn { 64 | if (btn.tag == 11 ) { 65 | JhScrollActionSheetView *actionSheet = [[JhScrollActionSheetView alloc]initWithTitle:@"分享到" shareDataArray:self.shareArray otherDataArray:self.otherArray]; 66 | actionSheet.clickShareBlock = ^(JhScrollActionSheetView *actionSheet, NSInteger index) { 67 | NSLog(@" 点击分享 index %ld ",(long)index); 68 | }; 69 | actionSheet.clickOtherBlock = ^(JhScrollActionSheetView *actionSheet, NSInteger index) { 70 | NSLog(@" 点击其他 index %ld ",(long)index); 71 | }; 72 | [actionSheet show]; 73 | } 74 | if (btn.tag == 12 ) { 75 | [JhScrollActionSheetView showShareActionSheetWithTitle:@"分享" shareDataArray:self.shareArray handler:^(JhScrollActionSheetView *actionSheet, NSInteger index) { 76 | NSLog(@" 点击分享 index %ld ",(long)index); 77 | }]; 78 | } 79 | if (btn.tag == 13 ) { 80 | [JhScrollActionSheetView showShareActionSheetWithTitle:@"" shareDataArray:self.shareArray handler:^(JhScrollActionSheetView *actionSheet, NSInteger index) { 81 | NSLog(@"点击分享 index %ld ",(long)index); 82 | }]; 83 | } 84 | } 85 | 86 | - (NSMutableArray *)shareArray { 87 | if (!_shareArray) { 88 | _shareArray = [NSMutableArray new]; 89 | NSArray *data = @[ 90 | @{ 91 | @"text" : @"微信", 92 | @"img" : @"weixing", 93 | }, 94 | @{ 95 | @"text" : @"朋友圈", 96 | @"img" : @"friends", 97 | }, 98 | @{ 99 | @"text" : @"微博", 100 | @"img" : @"sina", 101 | }, 102 | @{ 103 | @"text" : @"QQ", 104 | @"img" : @"qq", 105 | }, 106 | @{ 107 | @"text" : @"QQ空间", 108 | @"img" : @"kongjian", 109 | }, 110 | 111 | 112 | @{ 113 | @"text" : @"微信", 114 | @"img" : @"weixing", 115 | }, 116 | @{ 117 | @"text" : @"朋友圈", 118 | @"img" : @"friends", 119 | }, 120 | @{ 121 | @"text" : @"微博", 122 | @"img" : @"sina", 123 | }, 124 | @{ 125 | @"text" : @"QQ", 126 | @"img" : @"qq", 127 | }, 128 | @{ 129 | @"text" : @"QQ空间", 130 | @"img" : @"kongjian", 131 | }, 132 | ]; 133 | self.shareArray = [JhPageItemModel mj_objectArrayWithKeyValuesArray:data]; 134 | } 135 | return _shareArray; 136 | } 137 | 138 | - (NSMutableArray *)otherArray { 139 | if (!_otherArray) { 140 | _otherArray = [NSMutableArray new]; 141 | NSArray *data = @[ 142 | @{ 143 | @"text" : @"字体设置", 144 | @"img" : @"fontsize", 145 | }, 146 | @{ 147 | @"text" : @"复制链接", 148 | @"img" : @"copylink", 149 | }, 150 | @{ 151 | @"text" : @"字体设置", 152 | @"img" : @"fontsize", 153 | }, 154 | @{ 155 | @"text" : @"复制链接", 156 | @"img" : @"copylink", 157 | }, 158 | 159 | @{ 160 | @"text" : @"字体设置", 161 | @"img" : @"fontsize", 162 | }, 163 | @{ 164 | @"text" : @"复制链接", 165 | @"img" : @"copylink", 166 | }, 167 | 168 | @{ 169 | @"text" : @"字体设置", 170 | @"img" : @"fontsize", 171 | }, 172 | ]; 173 | self.otherArray = [JhPageItemModel mj_objectArrayWithKeyValuesArray:data]; 174 | } 175 | return _otherArray; 176 | } 177 | 178 | 179 | 180 | 181 | 182 | @end 183 | -------------------------------------------------------------------------------- /JhScrollActionSheetView/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // JhScrollActionSheetView 4 | // 5 | // Created by Jh on 2018/11/26. 6 | // Copyright © 2018 Jh. 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 | -------------------------------------------------------------------------------- /JhScrollActionSheetView/screenshots/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iotjin/JhScrollActionSheetView/074153497b9d9ca5d9bf8f1bb640de4d73a837ab/JhScrollActionSheetView/screenshots/.DS_Store -------------------------------------------------------------------------------- /JhScrollActionSheetView/screenshots/0.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iotjin/JhScrollActionSheetView/074153497b9d9ca5d9bf8f1bb640de4d73a837ab/JhScrollActionSheetView/screenshots/0.gif -------------------------------------------------------------------------------- /JhScrollActionSheetView/screenshots/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iotjin/JhScrollActionSheetView/074153497b9d9ca5d9bf8f1bb640de4d73a837ab/JhScrollActionSheetView/screenshots/1.png -------------------------------------------------------------------------------- /JhScrollActionSheetView/screenshots/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iotjin/JhScrollActionSheetView/074153497b9d9ca5d9bf8f1bb640de4d73a837ab/JhScrollActionSheetView/screenshots/2.png -------------------------------------------------------------------------------- /JhScrollActionSheetView/screenshots/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iotjin/JhScrollActionSheetView/074153497b9d9ca5d9bf8f1bb640de4d73a837ab/JhScrollActionSheetView/screenshots/3.png -------------------------------------------------------------------------------- /JhScrollActionSheetViewTests/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 | -------------------------------------------------------------------------------- /JhScrollActionSheetViewTests/JhScrollActionSheetViewTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // JhScrollActionSheetViewTests.m 3 | // JhScrollActionSheetViewTests 4 | // 5 | // Created by Jh on 2018/11/26. 6 | // Copyright © 2018 Jh. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface JhScrollActionSheetViewTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation JhScrollActionSheetViewTests 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 | -------------------------------------------------------------------------------- /JhScrollActionSheetViewUITests/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 | -------------------------------------------------------------------------------- /JhScrollActionSheetViewUITests/JhScrollActionSheetViewUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // JhScrollActionSheetViewUITests.m 3 | // JhScrollActionSheetViewUITests 4 | // 5 | // Created by Jh on 2018/11/26. 6 | // Copyright © 2018 Jh. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface JhScrollActionSheetViewUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation JhScrollActionSheetViewUITests 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 | // In UI tests it is usually best to stop immediately when a failure occurs. 21 | self.continueAfterFailure = NO; 22 | 23 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 24 | [[[XCUIApplication alloc] init] launch]; 25 | 26 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 27 | } 28 | 29 | - (void)tearDown { 30 | // Put teardown code here. This method is called after the invocation of each test method in the class. 31 | } 32 | 33 | - (void)testExample { 34 | // Use recording to get started writing UI tests. 35 | // Use XCTAssert and related functions to verify your tests produce the correct results. 36 | } 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JhScrollActionSheetView 2 | 3 | JhScrollActionSheetView - UIcollectionView横向滚动,类似微博新版的详情页分享界面
4 | 可设置单排或双排显示,title不设置不显示title
5 | 如果想实现发送站内用户的功能,自己可以改一下代码 6 | 7 | ![](https://raw.githubusercontent.com/iotjin/JhScrollActionSheetView/master/JhScrollActionSheetView/screenshots/0.gif) 8 | 9 | ![](https://raw.githubusercontent.com/iotjin/JhScrollActionSheetView/master/JhScrollActionSheetView/screenshots/1.png)
10 | 11 | ![](https://raw.githubusercontent.com/iotjin/JhScrollActionSheetView/master/JhScrollActionSheetView/screenshots/2.png)
12 | 13 | ![](https://raw.githubusercontent.com/iotjin/JhScrollActionSheetView/master/JhScrollActionSheetView/screenshots/3.png)
14 | 15 | ## Examples 16 | 17 | * Demo1 18 | ```objc 19 | //带标题,双排 20 | JhScrollActionSheetView *actionSheet = [[JhScrollActionSheetView alloc]initWithTitle:@"分享到" shareDataArray:self.shareArray otherDataArray:self.otherArray]; 21 | actionSheet.clickShareBlock = ^(JhScrollActionSheetView *actionSheet, NSInteger index) { 22 | NSLog(@" 点击分享 index %ld ",(long)index); 23 | }; 24 | actionSheet.clickOtherBlock = ^(JhScrollActionSheetView *actionSheet, NSInteger index) { 25 | NSLog(@" 点击其他 index %ld ",(long)index); 26 | }; 27 | 28 | [actionSheet show]; 29 | ``` 30 | 31 | * Demo2 32 | ```objc 33 | //带标题,单排 34 | [JhScrollActionSheetView showShareActionSheetWithTitle:@"分享" shareDataArray:self.shareArray handler:^(JhScrollActionSheetView *actionSheet, NSInteger index) { 35 | NSLog(@" 点击分享 index %ld ",(long)index); 36 | }]; 37 | ``` 38 | 39 | * Demo3 40 | ```objc 41 | //不带标题,单排 42 | [JhScrollActionSheetView showShareActionSheetWithTitle:@"" shareDataArray:self.shareArray handler:^(JhScrollActionSheetView *actionSheet, NSInteger index) { 43 | NSLog(@"点击分享 index %ld ",(long)index); 44 | }]; 45 | ``` 46 | --------------------------------------------------------------------------------