├── DraggingSort.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── Sekorm.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── Sekorm.xcuserdatad │ └── xcschemes │ ├── DraggingSort.xcscheme │ └── xcschememanagement.plist ├── DraggingSort ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── drag_delete.imageset │ │ ├── Contents.json │ │ ├── drag_delete@2x.png │ │ └── drag_delete@3x.png │ └── subscribe_close.imageset │ │ ├── Contents.json │ │ ├── subscribe_close@2x.png │ │ └── subscribe_close@3x.png ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Info.plist ├── Tool │ ├── YLDragSortTool.h │ └── YLDragSortTool.m ├── UIView+Frame.h ├── UIView+Frame.m ├── YLDargSortCell.h ├── YLDargSortCell.m ├── YLDargSortModel.h ├── YLDargSortModel.m ├── YLDragSortViewController.h ├── YLDragSortViewController.m └── main.m ├── DraggingSortTests ├── DraggingSortTests.m └── Info.plist ├── DraggingSortUITests ├── DraggingSortUITests.m └── Info.plist ├── README.md └── YLDefine.h /DraggingSort.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | B4AA9DE61DDBF62900626C93 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = B4AA9DE51DDBF62900626C93 /* main.m */; }; 11 | B4AA9DE91DDBF62900626C93 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = B4AA9DE81DDBF62900626C93 /* AppDelegate.m */; }; 12 | B4AA9DEF1DDBF62900626C93 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B4AA9DED1DDBF62900626C93 /* Main.storyboard */; }; 13 | B4AA9DF11DDBF62900626C93 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B4AA9DF01DDBF62900626C93 /* Assets.xcassets */; }; 14 | B4AA9DF41DDBF62900626C93 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B4AA9DF21DDBF62900626C93 /* LaunchScreen.storyboard */; }; 15 | B4AA9DFF1DDBF62900626C93 /* DraggingSortTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B4AA9DFE1DDBF62900626C93 /* DraggingSortTests.m */; }; 16 | B4AA9E0A1DDBF62900626C93 /* DraggingSortUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = B4AA9E091DDBF62900626C93 /* DraggingSortUITests.m */; }; 17 | B4D160371DF558480017C639 /* YLDragSortViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B4D160361DF558480017C639 /* YLDragSortViewController.m */; }; 18 | B4D1603A1DF558B10017C639 /* YLDargSortModel.m in Sources */ = {isa = PBXBuildFile; fileRef = B4D160391DF558B10017C639 /* YLDargSortModel.m */; }; 19 | B4D1603D1DF558CB0017C639 /* YLDargSortCell.m in Sources */ = {isa = PBXBuildFile; fileRef = B4D1603C1DF558CB0017C639 /* YLDargSortCell.m */; }; 20 | B4D160401DF559180017C639 /* UIView+Frame.m in Sources */ = {isa = PBXBuildFile; fileRef = B4D1603F1DF559180017C639 /* UIView+Frame.m */; }; 21 | B4D1604C1DF56AA20017C639 /* YLDragSortTool.m in Sources */ = {isa = PBXBuildFile; fileRef = B4D1604B1DF56AA20017C639 /* YLDragSortTool.m */; }; 22 | /* End PBXBuildFile section */ 23 | 24 | /* Begin PBXContainerItemProxy section */ 25 | B4AA9DFB1DDBF62900626C93 /* PBXContainerItemProxy */ = { 26 | isa = PBXContainerItemProxy; 27 | containerPortal = B4AA9DD91DDBF62900626C93 /* Project object */; 28 | proxyType = 1; 29 | remoteGlobalIDString = B4AA9DE01DDBF62900626C93; 30 | remoteInfo = DraggingSort; 31 | }; 32 | B4AA9E061DDBF62900626C93 /* PBXContainerItemProxy */ = { 33 | isa = PBXContainerItemProxy; 34 | containerPortal = B4AA9DD91DDBF62900626C93 /* Project object */; 35 | proxyType = 1; 36 | remoteGlobalIDString = B4AA9DE01DDBF62900626C93; 37 | remoteInfo = DraggingSort; 38 | }; 39 | /* End PBXContainerItemProxy section */ 40 | 41 | /* Begin PBXFileReference section */ 42 | B4AA9DE11DDBF62900626C93 /* DraggingSort.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DraggingSort.app; sourceTree = BUILT_PRODUCTS_DIR; }; 43 | B4AA9DE51DDBF62900626C93 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 44 | B4AA9DE71DDBF62900626C93 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 45 | B4AA9DE81DDBF62900626C93 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 46 | B4AA9DEE1DDBF62900626C93 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 47 | B4AA9DF01DDBF62900626C93 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 48 | B4AA9DF31DDBF62900626C93 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 49 | B4AA9DF51DDBF62900626C93 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 50 | B4AA9DFA1DDBF62900626C93 /* DraggingSortTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DraggingSortTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 51 | B4AA9DFE1DDBF62900626C93 /* DraggingSortTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DraggingSortTests.m; sourceTree = ""; }; 52 | B4AA9E001DDBF62900626C93 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 53 | B4AA9E051DDBF62900626C93 /* DraggingSortUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DraggingSortUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 54 | B4AA9E091DDBF62900626C93 /* DraggingSortUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DraggingSortUITests.m; sourceTree = ""; }; 55 | B4AA9E0B1DDBF62900626C93 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 56 | B4D160351DF558480017C639 /* YLDragSortViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YLDragSortViewController.h; sourceTree = ""; }; 57 | B4D160361DF558480017C639 /* YLDragSortViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YLDragSortViewController.m; sourceTree = ""; }; 58 | B4D160381DF558B10017C639 /* YLDargSortModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YLDargSortModel.h; sourceTree = ""; }; 59 | B4D160391DF558B10017C639 /* YLDargSortModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YLDargSortModel.m; sourceTree = ""; }; 60 | B4D1603B1DF558CB0017C639 /* YLDargSortCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YLDargSortCell.h; sourceTree = ""; }; 61 | B4D1603C1DF558CB0017C639 /* YLDargSortCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YLDargSortCell.m; sourceTree = ""; }; 62 | B4D1603E1DF559180017C639 /* UIView+Frame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+Frame.h"; sourceTree = ""; }; 63 | B4D1603F1DF559180017C639 /* UIView+Frame.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+Frame.m"; sourceTree = ""; }; 64 | B4D160441DF55A660017C639 /* YLDefine.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = YLDefine.h; path = ../YLDefine.h; sourceTree = ""; }; 65 | B4D1604A1DF56AA20017C639 /* YLDragSortTool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YLDragSortTool.h; sourceTree = ""; }; 66 | B4D1604B1DF56AA20017C639 /* YLDragSortTool.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YLDragSortTool.m; sourceTree = ""; }; 67 | /* End PBXFileReference section */ 68 | 69 | /* Begin PBXFrameworksBuildPhase section */ 70 | B4AA9DDE1DDBF62900626C93 /* Frameworks */ = { 71 | isa = PBXFrameworksBuildPhase; 72 | buildActionMask = 2147483647; 73 | files = ( 74 | ); 75 | runOnlyForDeploymentPostprocessing = 0; 76 | }; 77 | B4AA9DF71DDBF62900626C93 /* Frameworks */ = { 78 | isa = PBXFrameworksBuildPhase; 79 | buildActionMask = 2147483647; 80 | files = ( 81 | ); 82 | runOnlyForDeploymentPostprocessing = 0; 83 | }; 84 | B4AA9E021DDBF62900626C93 /* Frameworks */ = { 85 | isa = PBXFrameworksBuildPhase; 86 | buildActionMask = 2147483647; 87 | files = ( 88 | ); 89 | runOnlyForDeploymentPostprocessing = 0; 90 | }; 91 | /* End PBXFrameworksBuildPhase section */ 92 | 93 | /* Begin PBXGroup section */ 94 | B4AA9DD81DDBF62900626C93 = { 95 | isa = PBXGroup; 96 | children = ( 97 | B4AA9DE31DDBF62900626C93 /* DraggingSort */, 98 | B4AA9DFD1DDBF62900626C93 /* DraggingSortTests */, 99 | B4AA9E081DDBF62900626C93 /* DraggingSortUITests */, 100 | B4AA9DE21DDBF62900626C93 /* Products */, 101 | ); 102 | sourceTree = ""; 103 | }; 104 | B4AA9DE21DDBF62900626C93 /* Products */ = { 105 | isa = PBXGroup; 106 | children = ( 107 | B4AA9DE11DDBF62900626C93 /* DraggingSort.app */, 108 | B4AA9DFA1DDBF62900626C93 /* DraggingSortTests.xctest */, 109 | B4AA9E051DDBF62900626C93 /* DraggingSortUITests.xctest */, 110 | ); 111 | name = Products; 112 | sourceTree = ""; 113 | }; 114 | B4AA9DE31DDBF62900626C93 /* DraggingSort */ = { 115 | isa = PBXGroup; 116 | children = ( 117 | B4D160491DF56AA20017C639 /* Tool */, 118 | B4AA9E261DDBF6AE00626C93 /* View */, 119 | B4AA9E251DDBF68200626C93 /* Model */, 120 | B4AA9E271DDBF6B600626C93 /* Controller */, 121 | B4AA9DE71DDBF62900626C93 /* AppDelegate.h */, 122 | B4AA9DE81DDBF62900626C93 /* AppDelegate.m */, 123 | B4D1603E1DF559180017C639 /* UIView+Frame.h */, 124 | B4D1603F1DF559180017C639 /* UIView+Frame.m */, 125 | B4D160441DF55A660017C639 /* YLDefine.h */, 126 | B4AA9DED1DDBF62900626C93 /* Main.storyboard */, 127 | B4AA9DF01DDBF62900626C93 /* Assets.xcassets */, 128 | B4AA9DF21DDBF62900626C93 /* LaunchScreen.storyboard */, 129 | B4AA9DF51DDBF62900626C93 /* Info.plist */, 130 | B4AA9DE41DDBF62900626C93 /* Supporting Files */, 131 | ); 132 | path = DraggingSort; 133 | sourceTree = ""; 134 | }; 135 | B4AA9DE41DDBF62900626C93 /* Supporting Files */ = { 136 | isa = PBXGroup; 137 | children = ( 138 | B4AA9DE51DDBF62900626C93 /* main.m */, 139 | ); 140 | name = "Supporting Files"; 141 | sourceTree = ""; 142 | }; 143 | B4AA9DFD1DDBF62900626C93 /* DraggingSortTests */ = { 144 | isa = PBXGroup; 145 | children = ( 146 | B4AA9DFE1DDBF62900626C93 /* DraggingSortTests.m */, 147 | B4AA9E001DDBF62900626C93 /* Info.plist */, 148 | ); 149 | path = DraggingSortTests; 150 | sourceTree = ""; 151 | }; 152 | B4AA9E081DDBF62900626C93 /* DraggingSortUITests */ = { 153 | isa = PBXGroup; 154 | children = ( 155 | B4AA9E091DDBF62900626C93 /* DraggingSortUITests.m */, 156 | B4AA9E0B1DDBF62900626C93 /* Info.plist */, 157 | ); 158 | path = DraggingSortUITests; 159 | sourceTree = ""; 160 | }; 161 | B4AA9E251DDBF68200626C93 /* Model */ = { 162 | isa = PBXGroup; 163 | children = ( 164 | B4D160381DF558B10017C639 /* YLDargSortModel.h */, 165 | B4D160391DF558B10017C639 /* YLDargSortModel.m */, 166 | ); 167 | name = Model; 168 | sourceTree = ""; 169 | }; 170 | B4AA9E261DDBF6AE00626C93 /* View */ = { 171 | isa = PBXGroup; 172 | children = ( 173 | B4D1603B1DF558CB0017C639 /* YLDargSortCell.h */, 174 | B4D1603C1DF558CB0017C639 /* YLDargSortCell.m */, 175 | ); 176 | name = View; 177 | sourceTree = ""; 178 | }; 179 | B4AA9E271DDBF6B600626C93 /* Controller */ = { 180 | isa = PBXGroup; 181 | children = ( 182 | B4D160351DF558480017C639 /* YLDragSortViewController.h */, 183 | B4D160361DF558480017C639 /* YLDragSortViewController.m */, 184 | ); 185 | name = Controller; 186 | sourceTree = ""; 187 | }; 188 | B4D160491DF56AA20017C639 /* Tool */ = { 189 | isa = PBXGroup; 190 | children = ( 191 | B4D1604A1DF56AA20017C639 /* YLDragSortTool.h */, 192 | B4D1604B1DF56AA20017C639 /* YLDragSortTool.m */, 193 | ); 194 | path = Tool; 195 | sourceTree = ""; 196 | }; 197 | /* End PBXGroup section */ 198 | 199 | /* Begin PBXNativeTarget section */ 200 | B4AA9DE01DDBF62900626C93 /* DraggingSort */ = { 201 | isa = PBXNativeTarget; 202 | buildConfigurationList = B4AA9E0E1DDBF62900626C93 /* Build configuration list for PBXNativeTarget "DraggingSort" */; 203 | buildPhases = ( 204 | B4AA9DDD1DDBF62900626C93 /* Sources */, 205 | B4AA9DDE1DDBF62900626C93 /* Frameworks */, 206 | B4AA9DDF1DDBF62900626C93 /* Resources */, 207 | ); 208 | buildRules = ( 209 | ); 210 | dependencies = ( 211 | ); 212 | name = DraggingSort; 213 | productName = DraggingSort; 214 | productReference = B4AA9DE11DDBF62900626C93 /* DraggingSort.app */; 215 | productType = "com.apple.product-type.application"; 216 | }; 217 | B4AA9DF91DDBF62900626C93 /* DraggingSortTests */ = { 218 | isa = PBXNativeTarget; 219 | buildConfigurationList = B4AA9E111DDBF62900626C93 /* Build configuration list for PBXNativeTarget "DraggingSortTests" */; 220 | buildPhases = ( 221 | B4AA9DF61DDBF62900626C93 /* Sources */, 222 | B4AA9DF71DDBF62900626C93 /* Frameworks */, 223 | B4AA9DF81DDBF62900626C93 /* Resources */, 224 | ); 225 | buildRules = ( 226 | ); 227 | dependencies = ( 228 | B4AA9DFC1DDBF62900626C93 /* PBXTargetDependency */, 229 | ); 230 | name = DraggingSortTests; 231 | productName = DraggingSortTests; 232 | productReference = B4AA9DFA1DDBF62900626C93 /* DraggingSortTests.xctest */; 233 | productType = "com.apple.product-type.bundle.unit-test"; 234 | }; 235 | B4AA9E041DDBF62900626C93 /* DraggingSortUITests */ = { 236 | isa = PBXNativeTarget; 237 | buildConfigurationList = B4AA9E141DDBF62900626C93 /* Build configuration list for PBXNativeTarget "DraggingSortUITests" */; 238 | buildPhases = ( 239 | B4AA9E011DDBF62900626C93 /* Sources */, 240 | B4AA9E021DDBF62900626C93 /* Frameworks */, 241 | B4AA9E031DDBF62900626C93 /* Resources */, 242 | ); 243 | buildRules = ( 244 | ); 245 | dependencies = ( 246 | B4AA9E071DDBF62900626C93 /* PBXTargetDependency */, 247 | ); 248 | name = DraggingSortUITests; 249 | productName = DraggingSortUITests; 250 | productReference = B4AA9E051DDBF62900626C93 /* DraggingSortUITests.xctest */; 251 | productType = "com.apple.product-type.bundle.ui-testing"; 252 | }; 253 | /* End PBXNativeTarget section */ 254 | 255 | /* Begin PBXProject section */ 256 | B4AA9DD91DDBF62900626C93 /* Project object */ = { 257 | isa = PBXProject; 258 | attributes = { 259 | LastUpgradeCheck = 0720; 260 | ORGANIZATIONNAME = YL; 261 | TargetAttributes = { 262 | B4AA9DE01DDBF62900626C93 = { 263 | CreatedOnToolsVersion = 7.2; 264 | DevelopmentTeam = W55448EFBF; 265 | }; 266 | B4AA9DF91DDBF62900626C93 = { 267 | CreatedOnToolsVersion = 7.2; 268 | TestTargetID = B4AA9DE01DDBF62900626C93; 269 | }; 270 | B4AA9E041DDBF62900626C93 = { 271 | CreatedOnToolsVersion = 7.2; 272 | TestTargetID = B4AA9DE01DDBF62900626C93; 273 | }; 274 | }; 275 | }; 276 | buildConfigurationList = B4AA9DDC1DDBF62900626C93 /* Build configuration list for PBXProject "DraggingSort" */; 277 | compatibilityVersion = "Xcode 3.2"; 278 | developmentRegion = English; 279 | hasScannedForEncodings = 0; 280 | knownRegions = ( 281 | en, 282 | Base, 283 | ); 284 | mainGroup = B4AA9DD81DDBF62900626C93; 285 | productRefGroup = B4AA9DE21DDBF62900626C93 /* Products */; 286 | projectDirPath = ""; 287 | projectRoot = ""; 288 | targets = ( 289 | B4AA9DE01DDBF62900626C93 /* DraggingSort */, 290 | B4AA9DF91DDBF62900626C93 /* DraggingSortTests */, 291 | B4AA9E041DDBF62900626C93 /* DraggingSortUITests */, 292 | ); 293 | }; 294 | /* End PBXProject section */ 295 | 296 | /* Begin PBXResourcesBuildPhase section */ 297 | B4AA9DDF1DDBF62900626C93 /* Resources */ = { 298 | isa = PBXResourcesBuildPhase; 299 | buildActionMask = 2147483647; 300 | files = ( 301 | B4AA9DF41DDBF62900626C93 /* LaunchScreen.storyboard in Resources */, 302 | B4AA9DF11DDBF62900626C93 /* Assets.xcassets in Resources */, 303 | B4AA9DEF1DDBF62900626C93 /* Main.storyboard in Resources */, 304 | ); 305 | runOnlyForDeploymentPostprocessing = 0; 306 | }; 307 | B4AA9DF81DDBF62900626C93 /* Resources */ = { 308 | isa = PBXResourcesBuildPhase; 309 | buildActionMask = 2147483647; 310 | files = ( 311 | ); 312 | runOnlyForDeploymentPostprocessing = 0; 313 | }; 314 | B4AA9E031DDBF62900626C93 /* Resources */ = { 315 | isa = PBXResourcesBuildPhase; 316 | buildActionMask = 2147483647; 317 | files = ( 318 | ); 319 | runOnlyForDeploymentPostprocessing = 0; 320 | }; 321 | /* End PBXResourcesBuildPhase section */ 322 | 323 | /* Begin PBXSourcesBuildPhase section */ 324 | B4AA9DDD1DDBF62900626C93 /* Sources */ = { 325 | isa = PBXSourcesBuildPhase; 326 | buildActionMask = 2147483647; 327 | files = ( 328 | B4D160371DF558480017C639 /* YLDragSortViewController.m in Sources */, 329 | B4D1603D1DF558CB0017C639 /* YLDargSortCell.m in Sources */, 330 | B4D160401DF559180017C639 /* UIView+Frame.m in Sources */, 331 | B4D1603A1DF558B10017C639 /* YLDargSortModel.m in Sources */, 332 | B4AA9DE91DDBF62900626C93 /* AppDelegate.m in Sources */, 333 | B4AA9DE61DDBF62900626C93 /* main.m in Sources */, 334 | B4D1604C1DF56AA20017C639 /* YLDragSortTool.m in Sources */, 335 | ); 336 | runOnlyForDeploymentPostprocessing = 0; 337 | }; 338 | B4AA9DF61DDBF62900626C93 /* Sources */ = { 339 | isa = PBXSourcesBuildPhase; 340 | buildActionMask = 2147483647; 341 | files = ( 342 | B4AA9DFF1DDBF62900626C93 /* DraggingSortTests.m in Sources */, 343 | ); 344 | runOnlyForDeploymentPostprocessing = 0; 345 | }; 346 | B4AA9E011DDBF62900626C93 /* Sources */ = { 347 | isa = PBXSourcesBuildPhase; 348 | buildActionMask = 2147483647; 349 | files = ( 350 | B4AA9E0A1DDBF62900626C93 /* DraggingSortUITests.m in Sources */, 351 | ); 352 | runOnlyForDeploymentPostprocessing = 0; 353 | }; 354 | /* End PBXSourcesBuildPhase section */ 355 | 356 | /* Begin PBXTargetDependency section */ 357 | B4AA9DFC1DDBF62900626C93 /* PBXTargetDependency */ = { 358 | isa = PBXTargetDependency; 359 | target = B4AA9DE01DDBF62900626C93 /* DraggingSort */; 360 | targetProxy = B4AA9DFB1DDBF62900626C93 /* PBXContainerItemProxy */; 361 | }; 362 | B4AA9E071DDBF62900626C93 /* PBXTargetDependency */ = { 363 | isa = PBXTargetDependency; 364 | target = B4AA9DE01DDBF62900626C93 /* DraggingSort */; 365 | targetProxy = B4AA9E061DDBF62900626C93 /* PBXContainerItemProxy */; 366 | }; 367 | /* End PBXTargetDependency section */ 368 | 369 | /* Begin PBXVariantGroup section */ 370 | B4AA9DED1DDBF62900626C93 /* Main.storyboard */ = { 371 | isa = PBXVariantGroup; 372 | children = ( 373 | B4AA9DEE1DDBF62900626C93 /* Base */, 374 | ); 375 | name = Main.storyboard; 376 | sourceTree = ""; 377 | }; 378 | B4AA9DF21DDBF62900626C93 /* LaunchScreen.storyboard */ = { 379 | isa = PBXVariantGroup; 380 | children = ( 381 | B4AA9DF31DDBF62900626C93 /* Base */, 382 | ); 383 | name = LaunchScreen.storyboard; 384 | sourceTree = ""; 385 | }; 386 | /* End PBXVariantGroup section */ 387 | 388 | /* Begin XCBuildConfiguration section */ 389 | B4AA9E0C1DDBF62900626C93 /* Debug */ = { 390 | isa = XCBuildConfiguration; 391 | buildSettings = { 392 | ALWAYS_SEARCH_USER_PATHS = NO; 393 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 394 | CLANG_CXX_LIBRARY = "libc++"; 395 | CLANG_ENABLE_MODULES = YES; 396 | CLANG_ENABLE_OBJC_ARC = YES; 397 | CLANG_WARN_BOOL_CONVERSION = YES; 398 | CLANG_WARN_CONSTANT_CONVERSION = YES; 399 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 400 | CLANG_WARN_EMPTY_BODY = YES; 401 | CLANG_WARN_ENUM_CONVERSION = YES; 402 | CLANG_WARN_INT_CONVERSION = YES; 403 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 404 | CLANG_WARN_UNREACHABLE_CODE = YES; 405 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 406 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 407 | COPY_PHASE_STRIP = NO; 408 | DEBUG_INFORMATION_FORMAT = dwarf; 409 | ENABLE_STRICT_OBJC_MSGSEND = YES; 410 | ENABLE_TESTABILITY = YES; 411 | GCC_C_LANGUAGE_STANDARD = gnu99; 412 | GCC_DYNAMIC_NO_PIC = NO; 413 | GCC_NO_COMMON_BLOCKS = YES; 414 | GCC_OPTIMIZATION_LEVEL = 0; 415 | GCC_PREPROCESSOR_DEFINITIONS = ( 416 | "DEBUG=1", 417 | "$(inherited)", 418 | ); 419 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 420 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 421 | GCC_WARN_UNDECLARED_SELECTOR = YES; 422 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 423 | GCC_WARN_UNUSED_FUNCTION = YES; 424 | GCC_WARN_UNUSED_VARIABLE = YES; 425 | IPHONEOS_DEPLOYMENT_TARGET = 9.2; 426 | MTL_ENABLE_DEBUG_INFO = YES; 427 | ONLY_ACTIVE_ARCH = YES; 428 | SDKROOT = iphoneos; 429 | }; 430 | name = Debug; 431 | }; 432 | B4AA9E0D1DDBF62900626C93 /* Release */ = { 433 | isa = XCBuildConfiguration; 434 | buildSettings = { 435 | ALWAYS_SEARCH_USER_PATHS = NO; 436 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 437 | CLANG_CXX_LIBRARY = "libc++"; 438 | CLANG_ENABLE_MODULES = YES; 439 | CLANG_ENABLE_OBJC_ARC = YES; 440 | CLANG_WARN_BOOL_CONVERSION = YES; 441 | CLANG_WARN_CONSTANT_CONVERSION = YES; 442 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 443 | CLANG_WARN_EMPTY_BODY = YES; 444 | CLANG_WARN_ENUM_CONVERSION = YES; 445 | CLANG_WARN_INT_CONVERSION = YES; 446 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 447 | CLANG_WARN_UNREACHABLE_CODE = YES; 448 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 449 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 450 | COPY_PHASE_STRIP = NO; 451 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 452 | ENABLE_NS_ASSERTIONS = NO; 453 | ENABLE_STRICT_OBJC_MSGSEND = YES; 454 | GCC_C_LANGUAGE_STANDARD = gnu99; 455 | GCC_NO_COMMON_BLOCKS = YES; 456 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 457 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 458 | GCC_WARN_UNDECLARED_SELECTOR = YES; 459 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 460 | GCC_WARN_UNUSED_FUNCTION = YES; 461 | GCC_WARN_UNUSED_VARIABLE = YES; 462 | IPHONEOS_DEPLOYMENT_TARGET = 9.2; 463 | MTL_ENABLE_DEBUG_INFO = NO; 464 | SDKROOT = iphoneos; 465 | VALIDATE_PRODUCT = YES; 466 | }; 467 | name = Release; 468 | }; 469 | B4AA9E0F1DDBF62900626C93 /* Debug */ = { 470 | isa = XCBuildConfiguration; 471 | buildSettings = { 472 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 473 | DEVELOPMENT_TEAM = W55448EFBF; 474 | INFOPLIST_FILE = DraggingSort/Info.plist; 475 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 476 | PRODUCT_BUNDLE_IDENTIFIER = yeliang.YLSetting; 477 | PRODUCT_NAME = "$(TARGET_NAME)"; 478 | }; 479 | name = Debug; 480 | }; 481 | B4AA9E101DDBF62900626C93 /* Release */ = { 482 | isa = XCBuildConfiguration; 483 | buildSettings = { 484 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 485 | DEVELOPMENT_TEAM = W55448EFBF; 486 | INFOPLIST_FILE = DraggingSort/Info.plist; 487 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 488 | PRODUCT_BUNDLE_IDENTIFIER = yeliang.YLSetting; 489 | PRODUCT_NAME = "$(TARGET_NAME)"; 490 | }; 491 | name = Release; 492 | }; 493 | B4AA9E121DDBF62900626C93 /* Debug */ = { 494 | isa = XCBuildConfiguration; 495 | buildSettings = { 496 | BUNDLE_LOADER = "$(TEST_HOST)"; 497 | INFOPLIST_FILE = DraggingSortTests/Info.plist; 498 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 499 | PRODUCT_BUNDLE_IDENTIFIER = com.yeliang.DraggingSortTests; 500 | PRODUCT_NAME = "$(TARGET_NAME)"; 501 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/DraggingSort.app/DraggingSort"; 502 | }; 503 | name = Debug; 504 | }; 505 | B4AA9E131DDBF62900626C93 /* Release */ = { 506 | isa = XCBuildConfiguration; 507 | buildSettings = { 508 | BUNDLE_LOADER = "$(TEST_HOST)"; 509 | INFOPLIST_FILE = DraggingSortTests/Info.plist; 510 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 511 | PRODUCT_BUNDLE_IDENTIFIER = com.yeliang.DraggingSortTests; 512 | PRODUCT_NAME = "$(TARGET_NAME)"; 513 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/DraggingSort.app/DraggingSort"; 514 | }; 515 | name = Release; 516 | }; 517 | B4AA9E151DDBF62900626C93 /* Debug */ = { 518 | isa = XCBuildConfiguration; 519 | buildSettings = { 520 | INFOPLIST_FILE = DraggingSortUITests/Info.plist; 521 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 522 | PRODUCT_BUNDLE_IDENTIFIER = com.yeliang.DraggingSortUITests; 523 | PRODUCT_NAME = "$(TARGET_NAME)"; 524 | TEST_TARGET_NAME = DraggingSort; 525 | USES_XCTRUNNER = YES; 526 | }; 527 | name = Debug; 528 | }; 529 | B4AA9E161DDBF62900626C93 /* Release */ = { 530 | isa = XCBuildConfiguration; 531 | buildSettings = { 532 | INFOPLIST_FILE = DraggingSortUITests/Info.plist; 533 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 534 | PRODUCT_BUNDLE_IDENTIFIER = com.yeliang.DraggingSortUITests; 535 | PRODUCT_NAME = "$(TARGET_NAME)"; 536 | TEST_TARGET_NAME = DraggingSort; 537 | USES_XCTRUNNER = YES; 538 | }; 539 | name = Release; 540 | }; 541 | /* End XCBuildConfiguration section */ 542 | 543 | /* Begin XCConfigurationList section */ 544 | B4AA9DDC1DDBF62900626C93 /* Build configuration list for PBXProject "DraggingSort" */ = { 545 | isa = XCConfigurationList; 546 | buildConfigurations = ( 547 | B4AA9E0C1DDBF62900626C93 /* Debug */, 548 | B4AA9E0D1DDBF62900626C93 /* Release */, 549 | ); 550 | defaultConfigurationIsVisible = 0; 551 | defaultConfigurationName = Release; 552 | }; 553 | B4AA9E0E1DDBF62900626C93 /* Build configuration list for PBXNativeTarget "DraggingSort" */ = { 554 | isa = XCConfigurationList; 555 | buildConfigurations = ( 556 | B4AA9E0F1DDBF62900626C93 /* Debug */, 557 | B4AA9E101DDBF62900626C93 /* Release */, 558 | ); 559 | defaultConfigurationIsVisible = 0; 560 | defaultConfigurationName = Release; 561 | }; 562 | B4AA9E111DDBF62900626C93 /* Build configuration list for PBXNativeTarget "DraggingSortTests" */ = { 563 | isa = XCConfigurationList; 564 | buildConfigurations = ( 565 | B4AA9E121DDBF62900626C93 /* Debug */, 566 | B4AA9E131DDBF62900626C93 /* Release */, 567 | ); 568 | defaultConfigurationIsVisible = 0; 569 | defaultConfigurationName = Release; 570 | }; 571 | B4AA9E141DDBF62900626C93 /* Build configuration list for PBXNativeTarget "DraggingSortUITests" */ = { 572 | isa = XCConfigurationList; 573 | buildConfigurations = ( 574 | B4AA9E151DDBF62900626C93 /* Debug */, 575 | B4AA9E161DDBF62900626C93 /* Release */, 576 | ); 577 | defaultConfigurationIsVisible = 0; 578 | defaultConfigurationName = Release; 579 | }; 580 | /* End XCConfigurationList section */ 581 | }; 582 | rootObject = B4AA9DD91DDBF62900626C93 /* Project object */; 583 | } 584 | -------------------------------------------------------------------------------- /DraggingSort.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /DraggingSort.xcodeproj/project.xcworkspace/xcuserdata/Sekorm.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloYeah/DraggingSort/9b00c99badc4bed759458e08dbbbfc5d8feb58ee/DraggingSort.xcodeproj/project.xcworkspace/xcuserdata/Sekorm.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /DraggingSort.xcodeproj/xcuserdata/Sekorm.xcuserdatad/xcschemes/DraggingSort.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 43 | 49 | 50 | 51 | 52 | 53 | 59 | 60 | 61 | 62 | 63 | 64 | 74 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 95 | 101 | 102 | 103 | 104 | 106 | 107 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /DraggingSort.xcodeproj/xcuserdata/Sekorm.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | DraggingSort.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | B4AA9DE01DDBF62900626C93 16 | 17 | primary 18 | 19 | 20 | B4AA9DF91DDBF62900626C93 21 | 22 | primary 23 | 24 | 25 | B4AA9E041DDBF62900626C93 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /DraggingSort/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // DraggingSort 4 | // 5 | // Created by HelloYeah on 16/11/16. 6 | // Copyright © 2016年 YL. 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 | -------------------------------------------------------------------------------- /DraggingSort/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // DraggingSort 4 | // 5 | // Created by HelloYeah on 16/11/16. 6 | // Copyright © 2016年 YL. 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 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // 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. 25 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // 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. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // 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. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /DraggingSort/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 | "info" : { 45 | "version" : 1, 46 | "author" : "xcode" 47 | } 48 | } -------------------------------------------------------------------------------- /DraggingSort/Assets.xcassets/drag_delete.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "drag_delete@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "drag_delete@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /DraggingSort/Assets.xcassets/drag_delete.imageset/drag_delete@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloYeah/DraggingSort/9b00c99badc4bed759458e08dbbbfc5d8feb58ee/DraggingSort/Assets.xcassets/drag_delete.imageset/drag_delete@2x.png -------------------------------------------------------------------------------- /DraggingSort/Assets.xcassets/drag_delete.imageset/drag_delete@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloYeah/DraggingSort/9b00c99badc4bed759458e08dbbbfc5d8feb58ee/DraggingSort/Assets.xcassets/drag_delete.imageset/drag_delete@3x.png -------------------------------------------------------------------------------- /DraggingSort/Assets.xcassets/subscribe_close.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "subscribe_close@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "subscribe_close@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /DraggingSort/Assets.xcassets/subscribe_close.imageset/subscribe_close@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloYeah/DraggingSort/9b00c99badc4bed759458e08dbbbfc5d8feb58ee/DraggingSort/Assets.xcassets/subscribe_close.imageset/subscribe_close@2x.png -------------------------------------------------------------------------------- /DraggingSort/Assets.xcassets/subscribe_close.imageset/subscribe_close@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HelloYeah/DraggingSort/9b00c99badc4bed759458e08dbbbfc5d8feb58ee/DraggingSort/Assets.xcassets/subscribe_close.imageset/subscribe_close@3x.png -------------------------------------------------------------------------------- /DraggingSort/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /DraggingSort/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 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /DraggingSort/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | 123 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UIRequiredDeviceCapabilities 32 | 33 | armv7 34 | 35 | UISupportedInterfaceOrientations 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationLandscapeLeft 39 | UIInterfaceOrientationLandscapeRight 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /DraggingSort/Tool/YLDragSortTool.h: -------------------------------------------------------------------------------- 1 | // 2 | // YLDragSortTool.h 3 | // 4 | // 5 | // Created by HelloYeah on 2016/11/30. 6 | // Copyright © 2016年 YeLiang. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface YLDragSortTool : NSObject 12 | @property (nonatomic,assign) BOOL isEditing; 13 | @property (nonatomic,strong) NSMutableArray * subscribeArray; 14 | + (instancetype)shareInstance; 15 | @end 16 | -------------------------------------------------------------------------------- /DraggingSort/Tool/YLDragSortTool.m: -------------------------------------------------------------------------------- 1 | // 2 | // SKDragSortTool.m 3 | // 4 | // 5 | // Created by HelloYeah on 2016/11/30. 6 | // Copyright © 2016年 YeLiang. All rights reserved. 7 | // 8 | 9 | #import "YLDragSortTool.h" 10 | 11 | @implementation YLDragSortTool 12 | static YLDragSortTool *DragSortTool = nil; 13 | 14 | + (instancetype)shareInstance 15 | { 16 | @synchronized (self) { 17 | if (DragSortTool == nil) { 18 | DragSortTool = [[self alloc] init]; 19 | } 20 | } 21 | 22 | return DragSortTool; 23 | } 24 | 25 | + (instancetype)allocWithZone:(struct _NSZone *)zone 26 | { 27 | @synchronized (self) { 28 | if (DragSortTool == nil) { 29 | DragSortTool = [super allocWithZone:zone]; 30 | } 31 | } 32 | return DragSortTool; 33 | } 34 | 35 | - (id)copy 36 | { 37 | return DragSortTool; 38 | } 39 | 40 | - (id)mutableCopy{ 41 | return DragSortTool; 42 | } 43 | 44 | - (NSMutableArray *)subscribeArray { 45 | 46 | if (!_subscribeArray) { 47 | 48 | _subscribeArray = [@[@"推荐",@"视频",@"军事",@"娱乐",@"问答",@"娱乐",@"汽车",@"段子",@"趣图",@"财经",@"热点",@"房产",@"社会",@"数码",@"美女",@"数码",@"文化",@"美文",@"星座",@"旅游",@"视频",@"军事",@"娱乐",@"问答",@"娱乐",@"汽车",@"段子",@"趣图",@"财经",@"热点",@"房产",@"社会",@"数码",@"美女",@"数码",@"文化",@"美文",@"星座",@"旅游"] mutableCopy]; 49 | } 50 | return _subscribeArray; 51 | } 52 | 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /DraggingSort/UIView+Frame.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+Frame.h 3 | // 4 | // 5 | // Created by xiaoyu on 16/6/29. 6 | // Copyright © 2016年 YaoZhong. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef enum : NSUInteger { 12 | SKOscillatoryAnimationToBigger, 13 | SKOscillatoryAnimationToSmaller, 14 | } SKOscillatoryAnimationType; 15 | 16 | @interface UIView (Frame) 17 | @property (nonatomic) CGFloat left; 18 | @property (nonatomic) CGFloat top; 19 | @property (nonatomic) CGFloat right; 20 | @property (nonatomic) CGFloat bottom; 21 | @property (nonatomic) CGFloat width; 22 | @property (nonatomic) CGFloat height; 23 | @property (nonatomic) CGFloat centerX; ///< Shortcut for center.x 24 | @property (nonatomic) CGFloat centerY; ///< Shortcut for center.y 25 | @property (nonatomic) CGPoint origin; 26 | @property (nonatomic) CGSize size; 27 | @property (nonatomic, readonly) CGFloat screenX; 28 | @property (nonatomic, readonly) CGFloat screenY; 29 | 30 | + (void)showOscillatoryAnimationWithLayer:(CALayer *)layer 31 | type:(SKOscillatoryAnimationType)type; 32 | @end 33 | -------------------------------------------------------------------------------- /DraggingSort/UIView+Frame.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+Frame.m 3 | // 4 | // 5 | // Created by xiaoyu on 16/6/29. 6 | // Copyright © 2016年 YaoZhong. All rights reserved. 7 | // 8 | 9 | #import "UIView+Frame.h" 10 | 11 | @implementation UIView (Frame) 12 | - (CGFloat)left 13 | { 14 | return self.frame.origin.x; 15 | } 16 | 17 | - (void)setLeft:(CGFloat)x 18 | { 19 | CGRect frame = self.frame; 20 | frame.origin.x = x; 21 | self.frame = frame; 22 | } 23 | 24 | - (CGFloat)top 25 | { 26 | return self.frame.origin.y; 27 | } 28 | 29 | - (void)setTop:(CGFloat)y 30 | { 31 | CGRect frame = self.frame; 32 | frame.origin.y = y; 33 | self.frame = frame; 34 | } 35 | 36 | - (CGFloat)right 37 | { 38 | return self.frame.origin.x + self.frame.size.width; 39 | } 40 | 41 | - (void)setRight:(CGFloat)right 42 | { 43 | CGRect frame = self.frame; 44 | frame.origin.x = right - frame.size.width; 45 | self.frame = frame; 46 | } 47 | 48 | - (CGFloat)bottom 49 | { 50 | return self.frame.origin.y + self.frame.size.height; 51 | } 52 | 53 | - (void)setBottom:(CGFloat)bottom 54 | { 55 | CGRect frame = self.frame; 56 | frame.origin.y = bottom - frame.size.height; 57 | self.frame = frame; 58 | } 59 | 60 | - (CGFloat)width 61 | { 62 | return self.frame.size.width; 63 | } 64 | 65 | - (void)setWidth:(CGFloat)width 66 | { 67 | CGRect frame = self.frame; 68 | frame.size.width = width; 69 | self.frame = frame; 70 | } 71 | 72 | - (CGFloat)height 73 | { 74 | return self.frame.size.height; 75 | } 76 | 77 | - (void)setHeight:(CGFloat)height 78 | { 79 | CGRect frame = self.frame; 80 | frame.size.height = height; 81 | self.frame = frame; 82 | } 83 | 84 | - (CGFloat)screenX 85 | { 86 | CGFloat x = 0; 87 | for (UIView* view = self; view; view = view.superview) { 88 | x += view.left; 89 | } 90 | return x; 91 | } 92 | 93 | - (CGFloat)screenY 94 | { 95 | CGFloat y = 0; 96 | for (UIView* view = self; view; view = view.superview) { 97 | y += view.top; 98 | } 99 | return y; 100 | } 101 | 102 | - (CGPoint)origin 103 | { 104 | return self.frame.origin; 105 | } 106 | 107 | - (void)setOrigin:(CGPoint)origin 108 | { 109 | CGRect frame = self.frame; 110 | frame.origin = origin; 111 | self.frame = frame; 112 | } 113 | 114 | - (CGFloat)centerX 115 | { 116 | return self.center.x; 117 | } 118 | 119 | - (void)setCenterX:(CGFloat)centerX 120 | { 121 | self.center = CGPointMake(centerX, self.center.y); 122 | } 123 | 124 | - (CGFloat)centerY 125 | { 126 | return self.center.y; 127 | } 128 | 129 | - (void)setCenterY:(CGFloat)centerY 130 | { 131 | self.center = CGPointMake(self.center.x, centerY); 132 | } 133 | 134 | - (CGSize)size 135 | { 136 | return self.frame.size; 137 | } 138 | 139 | - (void)setSize:(CGSize)size 140 | { 141 | CGRect frame = self.frame; 142 | frame.size = size; 143 | self.frame = frame; 144 | } 145 | 146 | + (void)showOscillatoryAnimationWithLayer:(CALayer *)layer type:(SKOscillatoryAnimationType)type{ 147 | NSNumber *animationScale1 = type == SKOscillatoryAnimationToBigger ? @(1.15) : @(0.5); 148 | NSNumber *animationScale2 = type == SKOscillatoryAnimationToBigger ? @(0.92) : @(1.15); 149 | 150 | [UIView animateWithDuration:0.15 delay:0 options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveEaseInOut animations:^{ 151 | [layer setValue:animationScale1 forKeyPath:@"transform.scale"]; 152 | } completion:^(BOOL finished) { 153 | [UIView animateWithDuration:0.15 delay:0 options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveEaseInOut animations:^{ 154 | [layer setValue:animationScale2 forKeyPath:@"transform.scale"]; 155 | } completion:^(BOOL finished) { 156 | [UIView animateWithDuration:0.1 delay:0 options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveEaseInOut animations:^{ 157 | [layer setValue:@(1.0) forKeyPath:@"transform.scale"]; 158 | } completion:nil]; 159 | }]; 160 | }]; 161 | } 162 | 163 | @end 164 | -------------------------------------------------------------------------------- /DraggingSort/YLDargSortCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // YLDargSortCell.h 3 | // 4 | // 5 | // Created by HelloYeah on 2016/11/30. 6 | // Copyright © 2016年 YeLiang. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @protocol SKDragSortDelegate 12 | 13 | - (void)YLDargSortCellGestureAction:(UIGestureRecognizer *)gestureRecognizer; 14 | 15 | - (void)YLDargSortCellCancelSubscribe:(NSString *)subscribe; 16 | 17 | @end 18 | 19 | @interface YLDargSortCell : UICollectionViewCell 20 | @property (nonatomic,strong) NSString * subscribe; 21 | @property (nonatomic,weak) id delegate; 22 | 23 | - (void)showDeleteBtn; 24 | @end 25 | -------------------------------------------------------------------------------- /DraggingSort/YLDargSortCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // YLDargSortCell.m 3 | // 4 | // 5 | // Created by HelloYeah on 2016/11/30. 6 | // Copyright © 2016年 YeLiang. All rights reserved. 7 | // 8 | 9 | #import "YLDargSortCell.h" 10 | #import "YLDragSortTool.h" 11 | #import "UIView+Frame.h" 12 | #import "YLDefine.h" 13 | 14 | #define kDeleteBtnWH 10 * SCREEN_WIDTH_RATIO 15 | @interface YLDargSortCell () 16 | @property (nonatomic,strong) UILabel *label; 17 | 18 | @property (nonatomic,strong) UIButton * deleteBtn; 19 | @end 20 | @implementation YLDargSortCell 21 | 22 | - (instancetype)initWithFrame:(CGRect)frame 23 | { 24 | self = [super initWithFrame:frame]; 25 | if (self) { 26 | [self setUp]; 27 | } 28 | return self; 29 | } 30 | 31 | - (void)setUp { 32 | 33 | 34 | //给每个cell添加一个长按手势 35 | UILongPressGestureRecognizer * longPress =[[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(gestureAction:)]; 36 | longPress.delegate = self; 37 | [self addGestureRecognizer:longPress]; 38 | 39 | UIPanGestureRecognizer * pan =[[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(gestureAction:)]; 40 | pan.delegate = self; 41 | [self addGestureRecognizer:pan]; 42 | 43 | _label = [[UILabel alloc] init]; 44 | [self.contentView addSubview:_label]; 45 | _label.font = kFont(15); 46 | _label.textColor = RGBColorMake(110, 110, 110, 1); 47 | _label.layer.cornerRadius = 4 * SCREEN_WIDTH_RATIO; 48 | _label.layer.masksToBounds = NO; 49 | _label.layer.borderColor = RGBColorMake(110, 110, 110, 1).CGColor; 50 | _label.layer.borderWidth = kLineHeight; 51 | _label.textAlignment = NSTextAlignmentCenter; 52 | 53 | _deleteBtn = [UIButton buttonWithType:UIButtonTypeCustom]; 54 | [_deleteBtn setImage:[UIImage imageNamed:@"drag_delete"] forState:UIControlStateNormal]; 55 | _deleteBtn.width = kDeleteBtnWH; 56 | _deleteBtn.height = kDeleteBtnWH; 57 | 58 | [_deleteBtn addTarget:self action:@selector(cancelSubscribe) forControlEvents:UIControlEventTouchUpInside]; 59 | [self.contentView addSubview:_deleteBtn]; 60 | } 61 | 62 | - (void)cancelSubscribe { 63 | 64 | if (self.delegate && [self.delegate respondsToSelector:@selector(YLDargSortCellCancelSubscribe:)]) { 65 | [self.delegate YLDargSortCellCancelSubscribe:self.subscribe]; 66 | } 67 | } 68 | 69 | - (void)showDeleteBtn { 70 | 71 | _deleteBtn.hidden = NO; 72 | } 73 | 74 | 75 | 76 | - (void)setSubscribe:(NSString *)subscribe { 77 | 78 | _subscribe = subscribe; 79 | _deleteBtn.hidden = ![YLDragSortTool shareInstance].isEditing; 80 | _label.text = subscribe; 81 | _label.width = self.width - kDeleteBtnWH; 82 | _label.height = self.height - kDeleteBtnWH; 83 | _label.center = CGPointMake(self.width * 0.5, self.height * 0.5); 84 | 85 | } 86 | 87 | - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer { 88 | 89 | if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] && ![YLDragSortTool shareInstance].isEditing) { 90 | return NO; 91 | } 92 | return YES; 93 | } 94 | 95 | 96 | - (void)gestureAction:(UIGestureRecognizer *)gestureRecognizer{ 97 | 98 | if (self.delegate && [self.delegate respondsToSelector:@selector(YLDargSortCellGestureAction:)]) { 99 | [self.delegate YLDargSortCellGestureAction:gestureRecognizer]; 100 | } 101 | } 102 | 103 | @end 104 | -------------------------------------------------------------------------------- /DraggingSort/YLDargSortModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // YLModel.h 3 | // 4 | // 5 | // Created by HelloYeah on 2016/12/2. 6 | // Copyright © 2016年 YeLiang. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface YLDargSortModel : NSObject 12 | 13 | @property (nonatomic,copy) NSString * name; 14 | @property (nonatomic,assign) BOOL selectedFlag; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /DraggingSort/YLDargSortModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // YLModel.m 3 | // 4 | // 5 | // Created by HelloYeah on 2016/12/2. 6 | // Copyright © 2016年 YeLiang. All rights reserved. 7 | // 8 | 9 | #import "YLDargSortModel.h" 10 | 11 | @implementation YLDargSortModel 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /DraggingSort/YLDragSortViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // YLDeleteSortVC.h 3 | // 4 | // 5 | // Created by HelloYeah on 2016/11/30. 6 | // Copyright © 2016年 YeLiang. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface YLDragSortViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /DraggingSort/YLDragSortViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // YLDragSortViewController.m 3 | // 4 | // 5 | // Created by HelloYeah on 2016/11/30. 6 | // Copyright © 2016年 YeLiang. All rights reserved. 7 | // 8 | #import "YLDragSortViewController.h" 9 | #import "YLDragSortTool.h" 10 | #import "YLDargSortCell.h" 11 | #import "UIView+Frame.h" 12 | #import "YLDefine.h" 13 | 14 | #define kSpaceBetweenSubscribe 4 * SCREEN_WIDTH_RATIO 15 | #define kVerticalSpaceBetweenSubscribe 2 * SCREEN_WIDTH_RATIO 16 | #define kSubscribeHeight 35 * SCREEN_WIDTH_RATIO 17 | #define kContentLeftAndRightSpace 20 * SCREEN_WIDTH_RATIO 18 | #define kTopViewHeight 80 * SCREEN_WIDTH_RATIO 19 | 20 | @interface YLDragSortViewController () 21 | 22 | @property (nonatomic,strong) UIView * topView; 23 | @property (nonatomic,strong) UICollectionView * dragSortView; 24 | @property (nonatomic,strong) UIView * snapshotView; //截屏得到的view 25 | @property (nonatomic,weak) YLDargSortCell * originalCell; 26 | @property (nonatomic,strong) NSIndexPath * indexPath; 27 | @property (nonatomic,strong) NSIndexPath * nextIndexPath; 28 | @property (nonatomic,strong) UIButton * sortDeleteBtn; 29 | 30 | @end 31 | 32 | @implementation YLDragSortViewController 33 | 34 | - (void)viewDidLoad { 35 | 36 | [super viewDidLoad]; 37 | [self.view addSubview:self.dragSortView]; 38 | [self.view addSubview:self.topView]; 39 | } 40 | 41 | - (BOOL)prefersStatusBarHidden { 42 | 43 | return YES; 44 | } 45 | 46 | 47 | #pragma mark - collectionView dataSouce 48 | 49 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{ 50 | return [YLDragSortTool shareInstance].subscribeArray.count; 51 | } 52 | 53 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{ 54 | 55 | YLDargSortCell * cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"YLDargSortCell" forIndexPath:indexPath]; 56 | cell.delegate = self; 57 | cell.subscribe = [YLDragSortTool shareInstance].subscribeArray[indexPath.row]; 58 | return cell; 59 | } 60 | 61 | #pragma mark - SKDragSortDelegate 62 | 63 | - (void)YLDargSortCellGestureAction:(UIGestureRecognizer *)gestureRecognizer{ 64 | 65 | //记录上一次手势的位置 66 | static CGPoint startPoint; 67 | //触发长按手势的cell 68 | YLDargSortCell * cell = (YLDargSortCell *)gestureRecognizer.view; 69 | 70 | if (gestureRecognizer.state == UIGestureRecognizerStateBegan) { 71 | 72 | //开始长按 73 | if ([gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]]) { 74 | 75 | [YLDragSortTool shareInstance].isEditing = YES; 76 | [_sortDeleteBtn setTitle:@"完成" forState:UIControlStateNormal]; 77 | self.dragSortView.scrollEnabled = NO; 78 | } 79 | 80 | if (![YLDragSortTool shareInstance].isEditing) { 81 | return; 82 | } 83 | 84 | NSArray *cells = [self.dragSortView visibleCells]; 85 | for (YLDargSortCell *cell in cells) { 86 | [cell showDeleteBtn]; 87 | } 88 | 89 | //获取cell的截图 90 | _snapshotView = [cell snapshotViewAfterScreenUpdates:YES]; 91 | _snapshotView.center = cell.center; 92 | [_dragSortView addSubview:_snapshotView]; 93 | _indexPath = [_dragSortView indexPathForCell:cell]; 94 | _originalCell = cell; 95 | _originalCell.hidden = YES; 96 | startPoint = [gestureRecognizer locationInView:_dragSortView]; 97 | 98 | //移动 99 | }else if (gestureRecognizer.state == UIGestureRecognizerStateChanged){ 100 | 101 | CGFloat tranX = [gestureRecognizer locationOfTouch:0 inView:_dragSortView].x - startPoint.x; 102 | CGFloat tranY = [gestureRecognizer locationOfTouch:0 inView:_dragSortView].y - startPoint.y; 103 | 104 | //设置截图视图位置 105 | _snapshotView.center = CGPointApplyAffineTransform(_snapshotView.center, CGAffineTransformMakeTranslation(tranX, tranY)); 106 | startPoint = [gestureRecognizer locationOfTouch:0 inView:_dragSortView]; 107 | //计算截图视图和哪个cell相交 108 | for (UICollectionViewCell *cell in [_dragSortView visibleCells]) { 109 | //跳过隐藏的cell 110 | if ([_dragSortView indexPathForCell:cell] == _indexPath) { 111 | continue; 112 | } 113 | //计算中心距 114 | CGFloat space = sqrtf(pow(_snapshotView.center.x - cell.center.x, 2) + powf(_snapshotView.center.y - cell.center.y, 2)); 115 | 116 | //如果相交一半且两个视图Y的绝对值小于高度的一半就移动 117 | if (space <= _snapshotView.bounds.size.width * 0.5 && (fabs(_snapshotView.center.y - cell.center.y) <= _snapshotView.bounds.size.height * 0.5)) { 118 | _nextIndexPath = [_dragSortView indexPathForCell:cell]; 119 | if (_nextIndexPath.item > _indexPath.item) { 120 | for (NSUInteger i = _indexPath.item; i < _nextIndexPath.item ; i ++) { 121 | [[YLDragSortTool shareInstance].subscribeArray exchangeObjectAtIndex:i withObjectAtIndex:i + 1]; 122 | } 123 | }else{ 124 | for (NSUInteger i = _indexPath.item; i > _nextIndexPath.item ; i --) { 125 | [[YLDragSortTool shareInstance].subscribeArray exchangeObjectAtIndex:i withObjectAtIndex:i - 1]; 126 | } 127 | } 128 | //移动 129 | [_dragSortView moveItemAtIndexPath:_indexPath toIndexPath:_nextIndexPath]; 130 | //设置移动后的起始indexPath 131 | _indexPath = _nextIndexPath; 132 | break; 133 | } 134 | } 135 | //停止 136 | }else if(gestureRecognizer.state == UIGestureRecognizerStateEnded) { 137 | 138 | [_snapshotView removeFromSuperview]; 139 | _originalCell.hidden = NO; 140 | } 141 | } 142 | 143 | - (void)YLDargSortCellCancelSubscribe:(NSString *)subscribe { 144 | 145 | UIAlertController * alertController = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:@"取消订阅%@",subscribe] message:nil preferredStyle:UIAlertControllerStyleAlert]; 146 | [self presentViewController:alertController animated:YES completion:^{ 147 | 148 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 149 | [alertController dismissViewControllerAnimated:YES completion:nil]; 150 | }); 151 | }]; 152 | } 153 | 154 | 155 | - (UIView *)topView { 156 | 157 | if (!_topView) { 158 | _topView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, kTopViewHeight)]; 159 | _topView.backgroundColor = [UIColor whiteColor]; 160 | 161 | UIButton * closeBtn = [UIButton buttonWithType:UIButtonTypeCustom]; 162 | [closeBtn setImage:[UIImage imageNamed:@"subscribe_close"] forState:UIControlStateNormal]; 163 | CGFloat btnWH = 35 * SCREEN_WIDTH_RATIO; 164 | CGFloat topMargin = 15 * SCREEN_WIDTH_RATIO; 165 | CGFloat rightMargin = 15 * SCREEN_WIDTH_RATIO; 166 | closeBtn.frame = CGRectMake(SCREEN_WIDTH - btnWH - rightMargin, topMargin, btnWH, btnWH); 167 | [closeBtn addTarget:self action:@selector(back) forControlEvents:UIControlEventTouchUpInside]; 168 | [_topView addSubview:closeBtn]; 169 | 170 | UILabel * titleLabel = [[UILabel alloc] init]; 171 | titleLabel.font = kFont(13); 172 | titleLabel.text = @"我的关注"; 173 | [titleLabel sizeToFit]; 174 | titleLabel.textColor = RGBColorMake(110, 110, 110, 1); 175 | [_topView addSubview:titleLabel]; 176 | titleLabel.centerY = (kTopViewHeight - closeBtn.bottom) * 0.5 + closeBtn.bottom; 177 | titleLabel.left = kContentLeftAndRightSpace; 178 | 179 | UIButton * finshBtn = [UIButton buttonWithType:UIButtonTypeCustom]; 180 | [_topView addSubview:finshBtn]; 181 | [finshBtn setTitle:@"排序删除" forState:UIControlStateNormal]; 182 | [finshBtn setTitleColor:[UIColor orangeColor] forState:UIControlStateNormal]; 183 | finshBtn.titleLabel.font = kFont(12); 184 | finshBtn.layer.borderColor = [UIColor orangeColor].CGColor; 185 | finshBtn.layer.borderWidth = kLineHeight; 186 | finshBtn.layer.cornerRadius = 4 * SCREEN_WIDTH_RATIO; 187 | finshBtn.layer.masksToBounds = YES; 188 | [finshBtn sizeToFit]; 189 | finshBtn.height = 21 * SCREEN_WIDTH_RATIO; 190 | finshBtn.width = finshBtn.width + 8 * SCREEN_WIDTH_RATIO; 191 | finshBtn.right = SCREEN_WIDTH - kContentLeftAndRightSpace; 192 | finshBtn.centerY = titleLabel.centerY; 193 | [finshBtn addTarget:self action:@selector(finshClick) forControlEvents:UIControlEventTouchUpInside]; 194 | _sortDeleteBtn = finshBtn; 195 | 196 | UIView * bottomLine = [[UIView alloc] initWithFrame:CGRectMake(20 * SCREEN_WIDTH_RATIO, _topView.height - kLineHeight, SCREEN_WIDTH, kLineHeight)]; 197 | bottomLine.backgroundColor = RGBColorMake(110, 110, 110, 1); 198 | [_topView addSubview:bottomLine]; 199 | } 200 | return _topView; 201 | } 202 | 203 | - (void)finshClick { 204 | 205 | [YLDragSortTool shareInstance].isEditing = ![YLDragSortTool shareInstance].isEditing; 206 | NSString * title = [YLDragSortTool shareInstance].isEditing ? @"完成":@"排序删除"; 207 | 208 | self.dragSortView.scrollEnabled = ![YLDragSortTool shareInstance].isEditing; 209 | [_sortDeleteBtn setTitle:title forState:UIControlStateNormal]; 210 | 211 | [self.dragSortView reloadData]; 212 | } 213 | 214 | - (void)back { 215 | 216 | [self dismissViewControllerAnimated:YES completion:nil]; 217 | } 218 | 219 | - (UICollectionView *)dragSortView { 220 | 221 | if (!_dragSortView) { 222 | UICollectionViewFlowLayout * layout = [[UICollectionViewFlowLayout alloc] init]; 223 | CGFloat width = (SCREEN_WIDTH - 3 * kSpaceBetweenSubscribe - 2 * kContentLeftAndRightSpace )/4 ; 224 | layout.itemSize = CGSizeMake(width, kSubscribeHeight + 10 * SCREEN_WIDTH_RATIO); 225 | layout.minimumLineSpacing = kSpaceBetweenSubscribe; 226 | layout.minimumInteritemSpacing = kVerticalSpaceBetweenSubscribe; 227 | layout.sectionInset = UIEdgeInsetsMake(kContentLeftAndRightSpace, kContentLeftAndRightSpace, kContentLeftAndRightSpace, kContentLeftAndRightSpace); 228 | _dragSortView = [[UICollectionView alloc] initWithFrame:CGRectMake(0,kTopViewHeight, SCREEN_WIDTH, SCREEN_HEIGHT - kTopViewHeight) collectionViewLayout:layout]; 229 | //注册cell 230 | [_dragSortView registerClass:[YLDargSortCell class] forCellWithReuseIdentifier:@"YLDargSortCell"]; 231 | _dragSortView.dataSource = self; 232 | _dragSortView.backgroundColor = [UIColor whiteColor]; 233 | } 234 | return _dragSortView; 235 | } 236 | 237 | @end 238 | -------------------------------------------------------------------------------- /DraggingSort/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // DraggingSort 4 | // 5 | // Created by HelloYeah on 16/11/16. 6 | // Copyright © 2016年 YL. 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 | -------------------------------------------------------------------------------- /DraggingSortTests/DraggingSortTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // DraggingSortTests.m 3 | // DraggingSortTests 4 | // 5 | // Created by HelloYeah on 16/11/16. 6 | // Copyright © 2016年 YL. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface DraggingSortTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation DraggingSortTests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | // Put setup code here. This method is called before the invocation of each test method in the class. 20 | } 21 | 22 | - (void)tearDown { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample { 28 | // This is an example of a functional test case. 29 | // Use XCTAssert and related functions to verify your tests produce the correct results. 30 | } 31 | 32 | - (void)testPerformanceExample { 33 | // This is an example of a performance test case. 34 | [self measureBlock:^{ 35 | // Put the code you want to measure the time of here. 36 | }]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /DraggingSortTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /DraggingSortUITests/DraggingSortUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // DraggingSortUITests.m 3 | // DraggingSortUITests 4 | // 5 | // Created by HelloYeah on 16/11/16. 6 | // Copyright © 2016年 YL. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface DraggingSortUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation DraggingSortUITests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | 22 | // In UI tests it is usually best to stop immediately when a failure occurs. 23 | self.continueAfterFailure = NO; 24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 25 | [[[XCUIApplication alloc] init] launch]; 26 | 27 | // 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. 28 | } 29 | 30 | - (void)tearDown { 31 | // Put teardown code here. This method is called after the invocation of each test method in the class. 32 | [super tearDown]; 33 | } 34 | 35 | - (void)testExample { 36 | // Use recording to get started writing UI tests. 37 | // Use XCTAssert and related functions to verify your tests produce the correct results. 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /DraggingSortUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DraggingSort 2 | 3 | ###导读 4 | >拖拽排序是新闻类的App可以说是必有的交互设计,如今日头条,网易新闻等。拖拽排序是一个交互体验非常好的设计,简单,方便。 5 | 6 | ####今日头条的拖拽排序界面 7 | ![今日头条的拖拽排序界面.png](http://upload-images.jianshu.io/upload_images/1338042-7d5fa67d9b03b5a9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 8 | 9 | 10 | ####我实现的长按拖拽排序效果 11 | ![长按拖拽排序.gif](http://upload-images.jianshu.io/upload_images/1338042-dd15e90dd9e752fc.gif?imageMogr2/auto-orient/strip) 12 | 13 | ####实现方案 14 | 15 | 1.给CollectionViewCell添加一个长按手势,通过协议把手势传递到collectionView所在的控制器中。 16 | - (void)awakeFromNib{ 17 | self.layer.cornerRadius = 3; 18 | self.layer.masksToBounds = YES; 19 | //给每个cell添加一个长按手势 20 | UILongPressGestureRecognizer * longPress =[[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(longPress:)]; 21 | longPress.delegate = self; 22 | [self addGestureRecognizer:longPress]; 23 | } 24 | 25 | - (void)longPress:(UILongPressGestureRecognizer *)longPress{ 26 | if (self.delegate && [self.delegate respondsToSelector:@selector(longPress:)]) { 27 | [self.delegate longPress:longPress]; 28 | } 29 | } 30 | 31 | 2.开始长按时对cell进行截图,并隐藏cell。 32 | 33 | - (void)longPress:(UILongPressGestureRecognizer *)longPress{ 34 | //记录上一次手势的位置 35 | static CGPoint startPoint; 36 | //触发长按手势的cell 37 | MovingCell * cell = (MovingCell *)longPress.view; 38 | //开始长按 39 | if (longPress.state == UIGestureRecognizerStateBegan) { 40 | [self shakeAllCell]; 41 | //获取cell的截图 42 | _snapshotView = [cell snapshotViewAfterScreenUpdates:YES]; 43 | _snapshotView.center = cell.center; 44 | [_collectionView addSubview:_snapshotView]; 45 | _indexPath= [_collectionView indexPathForCell:cell]; 46 | _originalCell = cell; 47 | _originalCell.hidden = YES; 48 | startPoint = [longPress locationInView:_collectionView]; 49 | } 50 | 51 | 3、在手势移动的时候,移动截图视图,用遍历的方法求出截图移动到哪个cell的位置,再调用系统的api交换这个cell和隐藏cell的位置,并且数据源中的数据也需要调整顺序 52 | 53 | //手势移动的时候 54 | else if (longPress.state == UIGestureRecognizerStateChanged){ 55 | CGFloat tranX = [longPress locationOfTouch:0 inView:_collectionView].x - startPoint.x; 56 | CGFloat tranY = [longPress locationOfTouch:0 inView:_collectionView].y - startPoint.y; 57 | //设置截图视图位置 58 | _snapshotView.center = CGPointApplyAffineTransform(_snapshotView.center, CGAffineTransformMakeTranslation(tranX, tranY)); 59 | startPoint = [longPress locationOfTouch:0 inView:_collectionView]; 60 | //计算截图视图和哪个cell相交 61 | for (UICollectionViewCell *cell in [_collectionView visibleCells]) { 62 | //跳过隐藏的cell 63 | if ([_collectionView indexPathForCell:cell] == _indexPath) { 64 | continue; 65 | } 66 | //计算中心距 67 | CGFloat space = sqrtf(pow(_snapshotView.center.x - cell.center.x, 2) + powf(_snapshotView.center.y - cell.center.y, 2)); 68 | 69 | //如果相交一半且两个视图Y的绝对值小于高度的一半就移动 70 | if (space <= _snapshotView.bounds.size.width * 0.5 && (fabs(_snapshotView.center.y - cell.center.y) <= _snapshotView.bounds.size.height * 0.5)) { 71 | _nextIndexPath = [_collectionView indexPathForCell:cell]; 72 | if (_nextIndexPath.item > _indexPath.item) { 73 | for (NSUInteger i = _indexPath.item; i < _nextIndexPath.item ; i ++) { 74 | [self.array exchangeObjectAtIndex:i withObjectAtIndex:i + 1]; 75 | } 76 | }else{ 77 | for (NSUInteger i = _indexPath.item; i > _nextIndexPath.item ; i --) { 78 | [self.array exchangeObjectAtIndex:i withObjectAtIndex:i - 1]; 79 | } 80 | } 81 | //移动 82 | [_collectionView moveItemAtIndexPath:_indexPath toIndexPath:_nextIndexPath]; 83 | //设置移动后的起始indexPath 84 | _indexPath = _nextIndexPath; 85 | break; 86 | } 87 | } 88 | 4.手势停止时,移除截图的view,显示隐藏cell 89 | 90 | //手势停止时 91 | }else if(longPress.state == UIGestureRecognizerStateEnded){ 92 | [self stopShake]; 93 | [_snapshotView removeFromSuperview]; 94 | _originalCell.hidden = NO; 95 | } 96 | 97 | ####其他 98 | 代码还可以进一步封装,写一个数据管理类dataTool,dataTool作为collectionView的数据源,所有的数据源方法都写到dataTool类中。手势的代理方法也在里面实现,这样控制器会简洁很多,控制器就不需要关注拖拽排序的具体逻辑了。大家有空可以自己写写看,也许你们有更好的处理方案,可以评论交流一下。 99 | github地址:https://github.com/HelloYeah/DraggingSort 100 | -------------------------------------------------------------------------------- /YLDefine.h: -------------------------------------------------------------------------------- 1 | // 2 | // YLDefine.h 3 | // DraggingSort 4 | // 5 | // Created by HelloYeah on 2016/12/5. 6 | // Copyright © 2016年 YL. All rights reserved. 7 | // 8 | 9 | #ifndef YLDefine_h 10 | #define YLDefine_h 11 | 12 | 13 | /*** 当前屏幕宽度 */ 14 | #define SCREEN_WIDTH [UIScreen mainScreen].bounds.size.width 15 | /*** 当前屏幕高度 */ 16 | #define SCREEN_HEIGHT [UIScreen mainScreen].bounds.size.height 17 | /*** 屏宽比例 */ 18 | #define SCREEN_WIDTH_RATIO (SCREEN_WIDTH / 375) 19 | #define kLineHeight (1 / [UIScreen mainScreen].scale) 20 | #pragma mark - 字体 21 | /*** 普通字体 */ 22 | #define kFont(size) [UIFont systemFontOfSize:((size) * SCREEN_WIDTH_RATIO + SCREEN_WIDTH_RATIO * (SCREEN_WIDTH_RATIO < 1 ? 1 : - 1 ))] 23 | 24 | //根据RGB值创建UIColor 25 | #define RGBColorMake(R,G,B,_alpha_) [UIColor colorWithRed:R/255.0 green:G/255.0 blue:B/255.0 alpha:_alpha_] 26 | 27 | #endif /* YLDefine_h */ 28 | --------------------------------------------------------------------------------