├── DragAndDrop.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── hiran.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── hiran.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ └── xcschememanagement.plist ├── README.md └── TableViewDragAndDrop ├── AppDelegate.swift ├── Assets.xcassets ├── Andaman.imageset │ ├── Andaman.jpg │ └── Contents.json ├── AppIcon.appiconset │ ├── Contents.json │ ├── Icon-App-20x20@1x.png │ ├── Icon-App-20x20@2x.png │ ├── Icon-App-20x20@3x.png │ ├── Icon-App-29x29@1x.png │ ├── Icon-App-29x29@2x.png │ ├── Icon-App-29x29@3x.png │ ├── Icon-App-40x40@1x.png │ ├── Icon-App-40x40@2x.png │ ├── Icon-App-40x40@3x.png │ ├── Icon-App-57x57@1x.png │ ├── Icon-App-57x57@2x.png │ ├── Icon-App-60x60@2x.png │ ├── Icon-App-60x60@3x.png │ ├── Icon-App-72x72@1x.png │ ├── Icon-App-72x72@2x.png │ ├── Icon-App-76x76@1x.png │ ├── Icon-App-76x76@2x.png │ ├── Icon-App-83.5x83.5@2x.png │ ├── Icon-Small-50x50@1x.png │ ├── Icon-Small-50x50@2x.png │ └── ItunesArtwork@2x.png ├── Assam.imageset │ ├── Assam.jpg │ └── Contents.json ├── Binsar.imageset │ ├── Binsar.jpg │ └── Contents.json ├── BirBilling.imageset │ ├── BirBilling.jpg │ └── Contents.json ├── Contents.json ├── Coorg.imageset │ ├── Contents.json │ └── Coorg.jpg ├── Goa.imageset │ ├── Contents.json │ └── Goa.jpg ├── Kanatal.imageset │ ├── Contents.json │ └── Kanatal.jpg ├── Kasol.imageset │ ├── Contents.json │ └── Kasol.jpg ├── Kerala.imageset │ ├── Contents.json │ └── Kerala.jpg ├── Kutch.imageset │ ├── Contents.json │ └── Kutch.jpg ├── Leh-Ladakh.imageset │ ├── Contents.json │ └── Leh-Ladakh.jpg ├── Mcleodganj.imageset │ ├── Contents.json │ └── Mcleodganj.jpg ├── Rishikesh.imageset │ ├── Contents.json │ └── Rishikesh.jpg ├── Shimla.imageset │ ├── Contents.json │ └── Shimla.jpg └── Srinagar.imageset │ ├── Contents.json │ └── Srinagar.jpg ├── Base.lproj ├── LaunchScreen.storyboard └── Main.storyboard ├── DataModel ├── DataModel+Dragging.swift └── DataModel.swift ├── DetailViewController ├── DetailViewController+Drag.swift ├── DetailViewController+Drop.swift └── DetailViewController.swift ├── Info.plist ├── Place └── Place.swift └── ViewController ├── ViewController+Data.swift ├── ViewController+Drag.swift ├── ViewController+Drop.swift └── ViewController.swift /DragAndDrop.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 9254DCFB2043C7230033E271 /* DetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9254DCFA2043C7230033E271 /* DetailViewController.swift */; }; 11 | 9254DCFD2043CC150033E271 /* Place.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9254DCFC2043CC150033E271 /* Place.swift */; }; 12 | 9254DCFF2043D0CA0033E271 /* DetailViewController+Drag.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9254DCFE2043D0CA0033E271 /* DetailViewController+Drag.swift */; }; 13 | 9254DD012043D0DF0033E271 /* DetailViewController+Drop.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9254DD002043D0DF0033E271 /* DetailViewController+Drop.swift */; }; 14 | 9254DD072043DF040033E271 /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = 9254DD062043DF040033E271 /* README.md */; }; 15 | 92767C4020401257003CF900 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92767C3F20401257003CF900 /* AppDelegate.swift */; }; 16 | 92767C4220401257003CF900 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92767C4120401257003CF900 /* ViewController.swift */; }; 17 | 92767C4520401257003CF900 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 92767C4320401257003CF900 /* Main.storyboard */; }; 18 | 92767C4720401257003CF900 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 92767C4620401257003CF900 /* Assets.xcassets */; }; 19 | 92767C4A20401257003CF900 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 92767C4820401257003CF900 /* LaunchScreen.storyboard */; }; 20 | 92767C52204013E2003CF900 /* ViewController+Drag.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92767C51204013E2003CF900 /* ViewController+Drag.swift */; }; 21 | 92767C5620401429003CF900 /* ViewController+Drop.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92767C5520401429003CF900 /* ViewController+Drop.swift */; }; 22 | 92767C5820401448003CF900 /* ViewController+Data.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92767C5720401448003CF900 /* ViewController+Data.swift */; }; 23 | 92767C5A20401479003CF900 /* DataModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92767C5920401479003CF900 /* DataModel.swift */; }; 24 | 92767C5C2040149B003CF900 /* DataModel+Dragging.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92767C5B2040149B003CF900 /* DataModel+Dragging.swift */; }; 25 | /* End PBXBuildFile section */ 26 | 27 | /* Begin PBXFileReference section */ 28 | 9254DCFA2043C7230033E271 /* DetailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailViewController.swift; sourceTree = ""; }; 29 | 9254DCFC2043CC150033E271 /* Place.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Place.swift; sourceTree = ""; }; 30 | 9254DCFE2043D0CA0033E271 /* DetailViewController+Drag.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DetailViewController+Drag.swift"; sourceTree = ""; }; 31 | 9254DD002043D0DF0033E271 /* DetailViewController+Drop.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DetailViewController+Drop.swift"; sourceTree = ""; }; 32 | 9254DD062043DF040033E271 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = SOURCE_ROOT; }; 33 | 92767C3C20401257003CF900 /* DragAndDrop.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DragAndDrop.app; sourceTree = BUILT_PRODUCTS_DIR; }; 34 | 92767C3F20401257003CF900 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 35 | 92767C4120401257003CF900 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 36 | 92767C4420401257003CF900 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 37 | 92767C4620401257003CF900 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 38 | 92767C4920401257003CF900 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 39 | 92767C4B20401257003CF900 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 40 | 92767C51204013E2003CF900 /* ViewController+Drag.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ViewController+Drag.swift"; sourceTree = ""; }; 41 | 92767C5520401429003CF900 /* ViewController+Drop.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ViewController+Drop.swift"; sourceTree = ""; }; 42 | 92767C5720401448003CF900 /* ViewController+Data.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ViewController+Data.swift"; sourceTree = ""; }; 43 | 92767C5920401479003CF900 /* DataModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataModel.swift; sourceTree = ""; }; 44 | 92767C5B2040149B003CF900 /* DataModel+Dragging.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DataModel+Dragging.swift"; sourceTree = ""; }; 45 | /* End PBXFileReference section */ 46 | 47 | /* Begin PBXFrameworksBuildPhase section */ 48 | 92767C3920401257003CF900 /* Frameworks */ = { 49 | isa = PBXFrameworksBuildPhase; 50 | buildActionMask = 2147483647; 51 | files = ( 52 | ); 53 | runOnlyForDeploymentPostprocessing = 0; 54 | }; 55 | /* End PBXFrameworksBuildPhase section */ 56 | 57 | /* Begin PBXGroup section */ 58 | 9254DD022043D32F0033E271 /* ViewController */ = { 59 | isa = PBXGroup; 60 | children = ( 61 | 92767C4120401257003CF900 /* ViewController.swift */, 62 | 92767C51204013E2003CF900 /* ViewController+Drag.swift */, 63 | 92767C5520401429003CF900 /* ViewController+Drop.swift */, 64 | 92767C5720401448003CF900 /* ViewController+Data.swift */, 65 | ); 66 | path = ViewController; 67 | sourceTree = ""; 68 | }; 69 | 9254DD032043D3450033E271 /* DetailViewController */ = { 70 | isa = PBXGroup; 71 | children = ( 72 | 9254DCFA2043C7230033E271 /* DetailViewController.swift */, 73 | 9254DCFE2043D0CA0033E271 /* DetailViewController+Drag.swift */, 74 | 9254DD002043D0DF0033E271 /* DetailViewController+Drop.swift */, 75 | ); 76 | path = DetailViewController; 77 | sourceTree = ""; 78 | }; 79 | 9254DD042043D35E0033E271 /* DataModel */ = { 80 | isa = PBXGroup; 81 | children = ( 82 | 92767C5920401479003CF900 /* DataModel.swift */, 83 | 92767C5B2040149B003CF900 /* DataModel+Dragging.swift */, 84 | ); 85 | path = DataModel; 86 | sourceTree = ""; 87 | }; 88 | 9254DD052043D3650033E271 /* Place */ = { 89 | isa = PBXGroup; 90 | children = ( 91 | 9254DCFC2043CC150033E271 /* Place.swift */, 92 | ); 93 | path = Place; 94 | sourceTree = ""; 95 | }; 96 | 92767C3320401257003CF900 = { 97 | isa = PBXGroup; 98 | children = ( 99 | 92767C3E20401257003CF900 /* TableViewDragAndDrop */, 100 | 92767C3D20401257003CF900 /* Products */, 101 | ); 102 | sourceTree = ""; 103 | }; 104 | 92767C3D20401257003CF900 /* Products */ = { 105 | isa = PBXGroup; 106 | children = ( 107 | 92767C3C20401257003CF900 /* DragAndDrop.app */, 108 | ); 109 | name = Products; 110 | sourceTree = ""; 111 | }; 112 | 92767C3E20401257003CF900 /* TableViewDragAndDrop */ = { 113 | isa = PBXGroup; 114 | children = ( 115 | 9254DD062043DF040033E271 /* README.md */, 116 | 92767C3F20401257003CF900 /* AppDelegate.swift */, 117 | 9254DD042043D35E0033E271 /* DataModel */, 118 | 9254DD052043D3650033E271 /* Place */, 119 | 9254DD022043D32F0033E271 /* ViewController */, 120 | 9254DD032043D3450033E271 /* DetailViewController */, 121 | 92767C4320401257003CF900 /* Main.storyboard */, 122 | 92767C4620401257003CF900 /* Assets.xcassets */, 123 | 92767C4820401257003CF900 /* LaunchScreen.storyboard */, 124 | 92767C4B20401257003CF900 /* Info.plist */, 125 | ); 126 | path = TableViewDragAndDrop; 127 | sourceTree = ""; 128 | }; 129 | /* End PBXGroup section */ 130 | 131 | /* Begin PBXNativeTarget section */ 132 | 92767C3B20401257003CF900 /* DragAndDrop */ = { 133 | isa = PBXNativeTarget; 134 | buildConfigurationList = 92767C4E20401257003CF900 /* Build configuration list for PBXNativeTarget "DragAndDrop" */; 135 | buildPhases = ( 136 | 92767C3820401257003CF900 /* Sources */, 137 | 92767C3920401257003CF900 /* Frameworks */, 138 | 92767C3A20401257003CF900 /* Resources */, 139 | ); 140 | buildRules = ( 141 | ); 142 | dependencies = ( 143 | ); 144 | name = DragAndDrop; 145 | productName = TableViewDragAndDrop; 146 | productReference = 92767C3C20401257003CF900 /* DragAndDrop.app */; 147 | productType = "com.apple.product-type.application"; 148 | }; 149 | /* End PBXNativeTarget section */ 150 | 151 | /* Begin PBXProject section */ 152 | 92767C3420401257003CF900 /* Project object */ = { 153 | isa = PBXProject; 154 | attributes = { 155 | LastSwiftUpdateCheck = 0920; 156 | LastUpgradeCheck = 0920; 157 | ORGANIZATIONNAME = "iLeaf Solutions pvt ltd"; 158 | TargetAttributes = { 159 | 92767C3B20401257003CF900 = { 160 | CreatedOnToolsVersion = 9.2; 161 | ProvisioningStyle = Automatic; 162 | }; 163 | }; 164 | }; 165 | buildConfigurationList = 92767C3720401257003CF900 /* Build configuration list for PBXProject "DragAndDrop" */; 166 | compatibilityVersion = "Xcode 8.0"; 167 | developmentRegion = en; 168 | hasScannedForEncodings = 0; 169 | knownRegions = ( 170 | en, 171 | Base, 172 | ); 173 | mainGroup = 92767C3320401257003CF900; 174 | productRefGroup = 92767C3D20401257003CF900 /* Products */; 175 | projectDirPath = ""; 176 | projectRoot = ""; 177 | targets = ( 178 | 92767C3B20401257003CF900 /* DragAndDrop */, 179 | ); 180 | }; 181 | /* End PBXProject section */ 182 | 183 | /* Begin PBXResourcesBuildPhase section */ 184 | 92767C3A20401257003CF900 /* Resources */ = { 185 | isa = PBXResourcesBuildPhase; 186 | buildActionMask = 2147483647; 187 | files = ( 188 | 92767C4A20401257003CF900 /* LaunchScreen.storyboard in Resources */, 189 | 92767C4720401257003CF900 /* Assets.xcassets in Resources */, 190 | 9254DD072043DF040033E271 /* README.md in Resources */, 191 | 92767C4520401257003CF900 /* Main.storyboard in Resources */, 192 | ); 193 | runOnlyForDeploymentPostprocessing = 0; 194 | }; 195 | /* End PBXResourcesBuildPhase section */ 196 | 197 | /* Begin PBXSourcesBuildPhase section */ 198 | 92767C3820401257003CF900 /* Sources */ = { 199 | isa = PBXSourcesBuildPhase; 200 | buildActionMask = 2147483647; 201 | files = ( 202 | 92767C4220401257003CF900 /* ViewController.swift in Sources */, 203 | 9254DCFF2043D0CA0033E271 /* DetailViewController+Drag.swift in Sources */, 204 | 92767C5820401448003CF900 /* ViewController+Data.swift in Sources */, 205 | 92767C52204013E2003CF900 /* ViewController+Drag.swift in Sources */, 206 | 92767C4020401257003CF900 /* AppDelegate.swift in Sources */, 207 | 92767C5C2040149B003CF900 /* DataModel+Dragging.swift in Sources */, 208 | 92767C5620401429003CF900 /* ViewController+Drop.swift in Sources */, 209 | 9254DCFD2043CC150033E271 /* Place.swift in Sources */, 210 | 92767C5A20401479003CF900 /* DataModel.swift in Sources */, 211 | 9254DCFB2043C7230033E271 /* DetailViewController.swift in Sources */, 212 | 9254DD012043D0DF0033E271 /* DetailViewController+Drop.swift in Sources */, 213 | ); 214 | runOnlyForDeploymentPostprocessing = 0; 215 | }; 216 | /* End PBXSourcesBuildPhase section */ 217 | 218 | /* Begin PBXVariantGroup section */ 219 | 92767C4320401257003CF900 /* Main.storyboard */ = { 220 | isa = PBXVariantGroup; 221 | children = ( 222 | 92767C4420401257003CF900 /* Base */, 223 | ); 224 | name = Main.storyboard; 225 | sourceTree = ""; 226 | }; 227 | 92767C4820401257003CF900 /* LaunchScreen.storyboard */ = { 228 | isa = PBXVariantGroup; 229 | children = ( 230 | 92767C4920401257003CF900 /* Base */, 231 | ); 232 | name = LaunchScreen.storyboard; 233 | sourceTree = ""; 234 | }; 235 | /* End PBXVariantGroup section */ 236 | 237 | /* Begin XCBuildConfiguration section */ 238 | 92767C4C20401257003CF900 /* Debug */ = { 239 | isa = XCBuildConfiguration; 240 | buildSettings = { 241 | ALWAYS_SEARCH_USER_PATHS = NO; 242 | CLANG_ANALYZER_NONNULL = YES; 243 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 244 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 245 | CLANG_CXX_LIBRARY = "libc++"; 246 | CLANG_ENABLE_MODULES = YES; 247 | CLANG_ENABLE_OBJC_ARC = YES; 248 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 249 | CLANG_WARN_BOOL_CONVERSION = YES; 250 | CLANG_WARN_COMMA = YES; 251 | CLANG_WARN_CONSTANT_CONVERSION = YES; 252 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 253 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 254 | CLANG_WARN_EMPTY_BODY = YES; 255 | CLANG_WARN_ENUM_CONVERSION = YES; 256 | CLANG_WARN_INFINITE_RECURSION = YES; 257 | CLANG_WARN_INT_CONVERSION = YES; 258 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 259 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 260 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 261 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 262 | CLANG_WARN_STRICT_PROTOTYPES = YES; 263 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 264 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 265 | CLANG_WARN_UNREACHABLE_CODE = YES; 266 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 267 | CODE_SIGN_IDENTITY = "iPhone Developer"; 268 | COPY_PHASE_STRIP = NO; 269 | DEBUG_INFORMATION_FORMAT = dwarf; 270 | ENABLE_STRICT_OBJC_MSGSEND = YES; 271 | ENABLE_TESTABILITY = YES; 272 | GCC_C_LANGUAGE_STANDARD = gnu11; 273 | GCC_DYNAMIC_NO_PIC = NO; 274 | GCC_NO_COMMON_BLOCKS = YES; 275 | GCC_OPTIMIZATION_LEVEL = 0; 276 | GCC_PREPROCESSOR_DEFINITIONS = ( 277 | "DEBUG=1", 278 | "$(inherited)", 279 | ); 280 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 281 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 282 | GCC_WARN_UNDECLARED_SELECTOR = YES; 283 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 284 | GCC_WARN_UNUSED_FUNCTION = YES; 285 | GCC_WARN_UNUSED_VARIABLE = YES; 286 | IPHONEOS_DEPLOYMENT_TARGET = 11.2; 287 | MTL_ENABLE_DEBUG_INFO = YES; 288 | ONLY_ACTIVE_ARCH = YES; 289 | SDKROOT = iphoneos; 290 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 291 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 292 | }; 293 | name = Debug; 294 | }; 295 | 92767C4D20401257003CF900 /* Release */ = { 296 | isa = XCBuildConfiguration; 297 | buildSettings = { 298 | ALWAYS_SEARCH_USER_PATHS = NO; 299 | CLANG_ANALYZER_NONNULL = YES; 300 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 301 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 302 | CLANG_CXX_LIBRARY = "libc++"; 303 | CLANG_ENABLE_MODULES = YES; 304 | CLANG_ENABLE_OBJC_ARC = YES; 305 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 306 | CLANG_WARN_BOOL_CONVERSION = YES; 307 | CLANG_WARN_COMMA = YES; 308 | CLANG_WARN_CONSTANT_CONVERSION = YES; 309 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 310 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 311 | CLANG_WARN_EMPTY_BODY = YES; 312 | CLANG_WARN_ENUM_CONVERSION = YES; 313 | CLANG_WARN_INFINITE_RECURSION = YES; 314 | CLANG_WARN_INT_CONVERSION = YES; 315 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 316 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 317 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 318 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 319 | CLANG_WARN_STRICT_PROTOTYPES = YES; 320 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 321 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 322 | CLANG_WARN_UNREACHABLE_CODE = YES; 323 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 324 | CODE_SIGN_IDENTITY = "iPhone Developer"; 325 | COPY_PHASE_STRIP = NO; 326 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 327 | ENABLE_NS_ASSERTIONS = NO; 328 | ENABLE_STRICT_OBJC_MSGSEND = YES; 329 | GCC_C_LANGUAGE_STANDARD = gnu11; 330 | GCC_NO_COMMON_BLOCKS = YES; 331 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 332 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 333 | GCC_WARN_UNDECLARED_SELECTOR = YES; 334 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 335 | GCC_WARN_UNUSED_FUNCTION = YES; 336 | GCC_WARN_UNUSED_VARIABLE = YES; 337 | IPHONEOS_DEPLOYMENT_TARGET = 11.2; 338 | MTL_ENABLE_DEBUG_INFO = NO; 339 | SDKROOT = iphoneos; 340 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 341 | VALIDATE_PRODUCT = YES; 342 | }; 343 | name = Release; 344 | }; 345 | 92767C4F20401257003CF900 /* Debug */ = { 346 | isa = XCBuildConfiguration; 347 | buildSettings = { 348 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 349 | CODE_SIGN_STYLE = Automatic; 350 | DEVELOPMENT_TEAM = Y6AK6TF2DS; 351 | INFOPLIST_FILE = TableViewDragAndDrop/Info.plist; 352 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 353 | PRODUCT_BUNDLE_IDENTIFIER = com.ileaf.TableViewDragAndDrop; 354 | PRODUCT_NAME = "$(TARGET_NAME)"; 355 | SWIFT_VERSION = 4.0; 356 | TARGETED_DEVICE_FAMILY = "1,2"; 357 | }; 358 | name = Debug; 359 | }; 360 | 92767C5020401257003CF900 /* Release */ = { 361 | isa = XCBuildConfiguration; 362 | buildSettings = { 363 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 364 | CODE_SIGN_STYLE = Automatic; 365 | DEVELOPMENT_TEAM = Y6AK6TF2DS; 366 | INFOPLIST_FILE = TableViewDragAndDrop/Info.plist; 367 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 368 | PRODUCT_BUNDLE_IDENTIFIER = com.ileaf.TableViewDragAndDrop; 369 | PRODUCT_NAME = "$(TARGET_NAME)"; 370 | SWIFT_VERSION = 4.0; 371 | TARGETED_DEVICE_FAMILY = "1,2"; 372 | }; 373 | name = Release; 374 | }; 375 | /* End XCBuildConfiguration section */ 376 | 377 | /* Begin XCConfigurationList section */ 378 | 92767C3720401257003CF900 /* Build configuration list for PBXProject "DragAndDrop" */ = { 379 | isa = XCConfigurationList; 380 | buildConfigurations = ( 381 | 92767C4C20401257003CF900 /* Debug */, 382 | 92767C4D20401257003CF900 /* Release */, 383 | ); 384 | defaultConfigurationIsVisible = 0; 385 | defaultConfigurationName = Release; 386 | }; 387 | 92767C4E20401257003CF900 /* Build configuration list for PBXNativeTarget "DragAndDrop" */ = { 388 | isa = XCConfigurationList; 389 | buildConfigurations = ( 390 | 92767C4F20401257003CF900 /* Debug */, 391 | 92767C5020401257003CF900 /* Release */, 392 | ); 393 | defaultConfigurationIsVisible = 0; 394 | defaultConfigurationName = Release; 395 | }; 396 | /* End XCConfigurationList section */ 397 | }; 398 | rootObject = 92767C3420401257003CF900 /* Project object */; 399 | } 400 | -------------------------------------------------------------------------------- /DragAndDrop.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /DragAndDrop.xcodeproj/project.xcworkspace/xcuserdata/hiran.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/DragAndDrop-iOS11/9ffd4510324901169e441edbffb63572d769cb42/DragAndDrop.xcodeproj/project.xcworkspace/xcuserdata/hiran.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /DragAndDrop.xcodeproj/xcuserdata/hiran.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /DragAndDrop.xcodeproj/xcuserdata/hiran.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | DragAndDrop.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | TableViewDragAndDrop.xcscheme 13 | 14 | orderHint 15 | 0 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Drag and Drop 2 | 3 | 4 | ### Preview 5 | 6 | ![Demo](https://user-images.githubusercontent.com/32927921/36656888-5169cf80-1af0-11e8-97d1-59787fa4fda8.gif) 7 | 8 | 9 | Drag and drop for a table view. 10 | 11 | To enable drag and drop, you specify the table view as its own drag delegate and drop delegate. To provide or consume data, you implement the drag and drop delegate methods. 12 | 13 | 14 | ### Enable Drag and Drop Interactions 15 | To enable dragging, dropping, or both, specify a table view as its own drag or drop delegate. 16 | This code enables both dragging and dropping: 17 | 18 | ``` swift 19 | override func viewDidLoad() { 20 | super.viewDidLoad() 21 | 22 | tableView.dragDelegate = self 23 | tableView.dropDelegate = self 24 | } 25 | ``` 26 | 27 | Unlike a custom view, a table view does not have an `interactions` property to which you add interactions. Instead, a table view uses a drag delegate and a drop delegate directly. 28 | 29 | ### Provide Data for a Drag Session 30 | To provide data for dragging from a table view, implement the [`tableView(_:itemsForBeginning:at:)`] method. 31 | 32 | ``` swift 33 | func tableView(_ tableView: UITableView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] { 34 | return model.dragItems(for: indexPath) 35 | } 36 | ``` 37 | 38 | The following helper function, used by the `tableView(_:itemsForBeginning:at:)` method, serves as an interface to the data model in this sample code project: 39 | 40 | ``` swift 41 | func dragItems(for indexPath: IndexPath) -> [UIDragItem] { 42 | let placeName = placeNames[indexPath.row] 43 | 44 | let data = placeName.data(using: .utf8) 45 | let itemProvider = NSItemProvider() 46 | 47 | itemProvider.registerDataRepresentation(forTypeIdentifier: kUTTypePlainText as String, visibility: .all) { completion in 48 | completion(data, nil) 49 | return nil 50 | } 51 | 52 | return [ 53 | UIDragItem(itemProvider: itemProvider) 54 | ] 55 | } 56 | ``` 57 | 58 | ### Consume Data from a Drop Session 59 | To consume data from a drop session in a table view, you implement three delegate methods. 60 | 61 | First, your app can refuse the drag items based on their class, the state of your app, or other requirements. 62 | 63 | ``` swift 64 | func tableView(_ tableView: UITableView, canHandle session: UIDropSession) -> Bool { 65 | return model.canHandle(session) 66 | } 67 | ``` 68 | 69 | The following helper function, used by the [`tableView(_:canHandle:)`] method, serves as the interface to the data model: 70 | 71 | ``` swift 72 | func canHandle(_ session: UIDropSession) -> Bool { 73 | return session.canLoadObjects(ofClass: NSString.self) 74 | } 75 | ``` 76 | 77 | Second, you must tell the system how you want to consume the data, which is typically by copying it. You specify this choice by way of a drop proposal: 78 | 79 | ``` swift 80 | func tableView(_ tableView: UITableView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UITableViewDropProposal { 81 | // The .move operation is available only for dragging within a single app. 82 | if tableView.hasActiveDrag { 83 | if session.items.count > 1 { 84 | return UITableViewDropProposal(operation: .cancel) 85 | } else { 86 | return UITableViewDropProposal(operation: .move, intent: .insertAtDestinationIndexPath) 87 | } 88 | } else { 89 | return UITableViewDropProposal(operation: .copy, intent: .insertAtDestinationIndexPath) 90 | } 91 | } 92 | ``` 93 | 94 | Finally, after the user lifts their finger from the screen, indicating their intent to drop the drag items, your table view has one opportunity to request particular data representations of the drag items: 95 | 96 | ``` swift 97 | /** 98 | This delegate method is the only opportunity for accessing and loading 99 | the data representations offered in the drag item. The drop coordinator 100 | supports accessing the dropped items, updating the table view, and specifying 101 | optional animations. Local drags with one item go through the existing 102 | `tableView(_:moveRowAt:to:)` method on the data source. 103 | */ 104 | func tableView(_ tableView: UITableView, performDropWith coordinator: UITableViewDropCoordinator) { 105 | let destinationIndexPath: IndexPath 106 | 107 | if let indexPath = coordinator.destinationIndexPath { 108 | destinationIndexPath = indexPath 109 | } else { 110 | // Get last index path of table view. 111 | let section = tableView.numberOfSections - 1 112 | let row = tableView.numberOfRows(inSection: section) 113 | destinationIndexPath = IndexPath(row: row, section: section) 114 | } 115 | 116 | coordinator.session.loadObjects(ofClass: NSString.self) { items in 117 | // Consume drag items. 118 | let stringItems = items as! [String] 119 | 120 | var indexPaths = [IndexPath]() 121 | for (index, item) in stringItems.enumerated() { 122 | let indexPath = IndexPath(row: destinationIndexPath.row + index, section: destinationIndexPath.section) 123 | self.model.addItem(item, at: indexPath.row) 124 | indexPaths.append(indexPath) 125 | } 126 | 127 | tableView.insertRows(at: indexPaths, with: .automatic) 128 | } 129 | } 130 | ``` 131 | 132 | 133 | ## Drag and drop for a `UIImageView` instance. 134 | 135 | 136 | This sample code project uses a [`UIImageView`]instance to show how any instance or subclass of the [`UIView`] class can act as a drag source or a drop destination. 137 | 138 | To enable drag and drop, you add one or more interaction objects to a view. To provide or consume data, you implement the protocol methods in the interaction delegates. 139 | 140 | 141 | ### Enable Drag and Drop Interactions 142 | To enable dragging, dropping, or both, attach interactions to views. 143 | 144 | Add the drag interaction: 145 | ``` swift 146 | let dragInteraction = UIDragInteraction(delegate: self) 147 | imageView.addInteraction(dragInteraction) 148 | ``` 149 | 150 | Add the drop interaction: 151 | ``` swift 152 | let dropInteraction = UIDropInteraction(delegate: self) 153 | view.addInteraction(dropInteraction) 154 | ``` 155 | 156 | Enabling drag and drop for an image view, requires an additional step. You must explicitly enable user interaction, like this: 157 | ``` swift 158 | imageView.isUserInteractionEnabled = true 159 | ``` 160 | 161 | 162 | ### Provide Data for a Drag Session 163 | The [`dragInteraction(_:itemsForBeginning:)`] method is the one essential method for allowing dragging from a view. 164 | 165 | ``` swift 166 | func dragInteraction(_ interaction: UIDragInteraction, itemsForBeginning session: UIDragSession) -> [UIDragItem] { 167 | guard let image = imageView.image else { return [] } 168 | 169 | let provider = NSItemProvider(object: image) 170 | let item = UIDragItem(itemProvider: provider) 171 | item.localObject = image 172 | 173 | /* 174 | Returning a non-empty array, as shown here, enables dragging. You 175 | can disable dragging by instead returning an empty array. 176 | */ 177 | return [item] 178 | } 179 | ``` 180 | 181 | The system calls this delegate method in response to the user gesture that initiates dragging. In your implementation, return an array of one or more drag items, each with one item provider. In each item provider, specify one or more data representations of the model object to be dragged. The model object must conform to the [`NSItemProviderWriting`] protocol. 182 | 183 | 184 | ### Consume Data from a Drop Session 185 | To enable a view to consume data from a drop session, you implement three delegate methods. 186 | 187 | First, your app can refuse the drag items based on their uniform type identifiers (UTIs), the state of your app, or other requirements. Here, the implementation allows a user to drop only a single item that conforms to the [`kUTTypeImage`] UTI: 188 | 189 | ``` swift 190 | func dropInteraction(_ interaction: UIDropInteraction, canHandle session: UIDropSession) -> Bool { 191 | return session.hasItemsConforming(toTypeIdentifiers: [kUTTypeImage as String]) && session.items.count == 1 192 | } 193 | ``` 194 | 195 | Second, you must tell the system how you want to consume the data, which is typically by copying it. You specify this choice by way of a drop proposal: 196 | 197 | ``` swift 198 | func dropInteraction(_ interaction: UIDropInteraction, sessionDidUpdate session: UIDropSession) -> UIDropProposal { 199 | let dropLocation = session.location(in: view) 200 | updateLayers(forDropLocation: dropLocation) 201 | 202 | let operation: UIDropOperation 203 | 204 | if imageView.frame.contains(dropLocation) { 205 | /* 206 | If you add in-app drag-and-drop support for the .move operation, 207 | you must write code to coordinate between the drag interaction 208 | delegate and the drop interaction delegate. 209 | */ 210 | operation = session.localDragSession == nil ? .copy : .move 211 | } else { 212 | // Do not allow dropping outside of the image view. 213 | operation = .cancel 214 | } 215 | 216 | return UIDropProposal(operation: operation) 217 | } 218 | ``` 219 | 220 | Finally, after the user lifts their finger from the screen, indicating their intent to drop the drag items, your view has one opportunity to request particular data representations of the drag items: 221 | 222 | ``` swift 223 | func dropInteraction(_ interaction: UIDropInteraction, performDrop session: UIDropSession) { 224 | // Consume drag items (in this example, of type UIImage). 225 | session.loadObjects(ofClass: UIImage.self) { imageItems in 226 | let images = imageItems as! [UIImage] 227 | 228 | /* 229 | If you do not employ the loadObjects(ofClass:completion:) convenience 230 | method of the UIDropSession class, which automatically employs 231 | the main thread, explicitly dispatch UI work to the main thread. 232 | For example, you can use `DispatchQueue.main.async` method. 233 | */ 234 | self.imageView.image = images.first 235 | } 236 | 237 | // Perform additional UI updates as needed. 238 | let dropLocation = session.location(in: view) 239 | updateLayers(forDropLocation: dropLocation) 240 | } 241 | ``` 242 | 243 | ## Author 244 | iLeaf Solutions 245 | [http://www.ileafsolutions.com](http://www.ileafsolutions.com) 246 | 247 | 248 | ## License 249 | 250 | MIT License 251 | 252 | Copyright (c) 2018 iLeaf Solutions Pvt. Ltd. 253 | 254 | Permission is hereby granted, free of charge, to any person obtaining a copy 255 | of this software and associated documentation files (the "Software"), to deal 256 | in the Software without restriction, including without limitation the rights 257 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 258 | copies of the Software, and to permit persons to whom the Software is 259 | furnished to do so, subject to the following conditions: 260 | 261 | The above copyright notice and this permission notice shall be included in all 262 | copies or substantial portions of the Software. 263 | 264 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 265 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 266 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 267 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 268 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 269 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 270 | SOFTWARE. 271 | 272 | 273 | 274 | 275 | -------------------------------------------------------------------------------- /TableViewDragAndDrop/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // TableViewDragAndDrop 4 | // 5 | // Created by Hiran on 2/23/18. 6 | // Copyright © 2018 iLeaf Solutions pvt ltd. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(_ application: UIApplication) { 23 | // 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. 24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(_ application: UIApplication) { 28 | // 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. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(_ application: UIApplication) { 33 | // 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. 34 | } 35 | 36 | func applicationDidBecomeActive(_ application: UIApplication) { 37 | // 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. 38 | } 39 | 40 | func applicationWillTerminate(_ application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/Andaman.imageset/Andaman.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/DragAndDrop-iOS11/9ffd4510324901169e441edbffb63572d769cb42/TableViewDragAndDrop/Assets.xcassets/Andaman.imageset/Andaman.jpg -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/Andaman.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Andaman.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "57x57", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-57x57@1x.png", 49 | "scale" : "1x" 50 | }, 51 | { 52 | "size" : "57x57", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-57x57@2x.png", 55 | "scale" : "2x" 56 | }, 57 | { 58 | "size" : "60x60", 59 | "idiom" : "iphone", 60 | "filename" : "Icon-App-60x60@2x.png", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "size" : "60x60", 65 | "idiom" : "iphone", 66 | "filename" : "Icon-App-60x60@3x.png", 67 | "scale" : "3x" 68 | }, 69 | { 70 | "size" : "20x20", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-20x20@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "20x20", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-20x20@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "29x29", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-29x29@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "29x29", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-29x29@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "40x40", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-40x40@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "40x40", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-40x40@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "50x50", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-Small-50x50@1x.png", 109 | "scale" : "1x" 110 | }, 111 | { 112 | "size" : "50x50", 113 | "idiom" : "ipad", 114 | "filename" : "Icon-Small-50x50@2x.png", 115 | "scale" : "2x" 116 | }, 117 | { 118 | "size" : "72x72", 119 | "idiom" : "ipad", 120 | "filename" : "Icon-App-72x72@1x.png", 121 | "scale" : "1x" 122 | }, 123 | { 124 | "size" : "72x72", 125 | "idiom" : "ipad", 126 | "filename" : "Icon-App-72x72@2x.png", 127 | "scale" : "2x" 128 | }, 129 | { 130 | "size" : "76x76", 131 | "idiom" : "ipad", 132 | "filename" : "Icon-App-76x76@1x.png", 133 | "scale" : "1x" 134 | }, 135 | { 136 | "size" : "76x76", 137 | "idiom" : "ipad", 138 | "filename" : "Icon-App-76x76@2x.png", 139 | "scale" : "2x" 140 | }, 141 | { 142 | "size" : "83.5x83.5", 143 | "idiom" : "ipad", 144 | "filename" : "Icon-App-83.5x83.5@2x.png", 145 | "scale" : "2x" 146 | }, 147 | { 148 | "size" : "1024x1024", 149 | "idiom" : "ios-marketing", 150 | "filename" : "ItunesArtwork@2x.png", 151 | "scale" : "1x" 152 | } 153 | ], 154 | "info" : { 155 | "version" : 1, 156 | "author" : "xcode" 157 | } 158 | } -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/DragAndDrop-iOS11/9ffd4510324901169e441edbffb63572d769cb42/TableViewDragAndDrop/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/DragAndDrop-iOS11/9ffd4510324901169e441edbffb63572d769cb42/TableViewDragAndDrop/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/DragAndDrop-iOS11/9ffd4510324901169e441edbffb63572d769cb42/TableViewDragAndDrop/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/DragAndDrop-iOS11/9ffd4510324901169e441edbffb63572d769cb42/TableViewDragAndDrop/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/DragAndDrop-iOS11/9ffd4510324901169e441edbffb63572d769cb42/TableViewDragAndDrop/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/DragAndDrop-iOS11/9ffd4510324901169e441edbffb63572d769cb42/TableViewDragAndDrop/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/DragAndDrop-iOS11/9ffd4510324901169e441edbffb63572d769cb42/TableViewDragAndDrop/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/DragAndDrop-iOS11/9ffd4510324901169e441edbffb63572d769cb42/TableViewDragAndDrop/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/DragAndDrop-iOS11/9ffd4510324901169e441edbffb63572d769cb42/TableViewDragAndDrop/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/DragAndDrop-iOS11/9ffd4510324901169e441edbffb63572d769cb42/TableViewDragAndDrop/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/DragAndDrop-iOS11/9ffd4510324901169e441edbffb63572d769cb42/TableViewDragAndDrop/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/DragAndDrop-iOS11/9ffd4510324901169e441edbffb63572d769cb42/TableViewDragAndDrop/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/DragAndDrop-iOS11/9ffd4510324901169e441edbffb63572d769cb42/TableViewDragAndDrop/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/DragAndDrop-iOS11/9ffd4510324901169e441edbffb63572d769cb42/TableViewDragAndDrop/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/DragAndDrop-iOS11/9ffd4510324901169e441edbffb63572d769cb42/TableViewDragAndDrop/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/DragAndDrop-iOS11/9ffd4510324901169e441edbffb63572d769cb42/TableViewDragAndDrop/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/DragAndDrop-iOS11/9ffd4510324901169e441edbffb63572d769cb42/TableViewDragAndDrop/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/DragAndDrop-iOS11/9ffd4510324901169e441edbffb63572d769cb42/TableViewDragAndDrop/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/AppIcon.appiconset/Icon-Small-50x50@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/DragAndDrop-iOS11/9ffd4510324901169e441edbffb63572d769cb42/TableViewDragAndDrop/Assets.xcassets/AppIcon.appiconset/Icon-Small-50x50@1x.png -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/AppIcon.appiconset/Icon-Small-50x50@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/DragAndDrop-iOS11/9ffd4510324901169e441edbffb63572d769cb42/TableViewDragAndDrop/Assets.xcassets/AppIcon.appiconset/Icon-Small-50x50@2x.png -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/DragAndDrop-iOS11/9ffd4510324901169e441edbffb63572d769cb42/TableViewDragAndDrop/Assets.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/Assam.imageset/Assam.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/DragAndDrop-iOS11/9ffd4510324901169e441edbffb63572d769cb42/TableViewDragAndDrop/Assets.xcassets/Assam.imageset/Assam.jpg -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/Assam.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Assam.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/Binsar.imageset/Binsar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/DragAndDrop-iOS11/9ffd4510324901169e441edbffb63572d769cb42/TableViewDragAndDrop/Assets.xcassets/Binsar.imageset/Binsar.jpg -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/Binsar.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Binsar.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/BirBilling.imageset/BirBilling.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/DragAndDrop-iOS11/9ffd4510324901169e441edbffb63572d769cb42/TableViewDragAndDrop/Assets.xcassets/BirBilling.imageset/BirBilling.jpg -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/BirBilling.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "BirBilling.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/Coorg.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Coorg.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/Coorg.imageset/Coorg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/DragAndDrop-iOS11/9ffd4510324901169e441edbffb63572d769cb42/TableViewDragAndDrop/Assets.xcassets/Coorg.imageset/Coorg.jpg -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/Goa.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Goa.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/Goa.imageset/Goa.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/DragAndDrop-iOS11/9ffd4510324901169e441edbffb63572d769cb42/TableViewDragAndDrop/Assets.xcassets/Goa.imageset/Goa.jpg -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/Kanatal.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Kanatal.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/Kanatal.imageset/Kanatal.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/DragAndDrop-iOS11/9ffd4510324901169e441edbffb63572d769cb42/TableViewDragAndDrop/Assets.xcassets/Kanatal.imageset/Kanatal.jpg -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/Kasol.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Kasol.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/Kasol.imageset/Kasol.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/DragAndDrop-iOS11/9ffd4510324901169e441edbffb63572d769cb42/TableViewDragAndDrop/Assets.xcassets/Kasol.imageset/Kasol.jpg -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/Kerala.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Kerala.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/Kerala.imageset/Kerala.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/DragAndDrop-iOS11/9ffd4510324901169e441edbffb63572d769cb42/TableViewDragAndDrop/Assets.xcassets/Kerala.imageset/Kerala.jpg -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/Kutch.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Kutch.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/Kutch.imageset/Kutch.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/DragAndDrop-iOS11/9ffd4510324901169e441edbffb63572d769cb42/TableViewDragAndDrop/Assets.xcassets/Kutch.imageset/Kutch.jpg -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/Leh-Ladakh.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Leh-Ladakh.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/Leh-Ladakh.imageset/Leh-Ladakh.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/DragAndDrop-iOS11/9ffd4510324901169e441edbffb63572d769cb42/TableViewDragAndDrop/Assets.xcassets/Leh-Ladakh.imageset/Leh-Ladakh.jpg -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/Mcleodganj.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Mcleodganj.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/Mcleodganj.imageset/Mcleodganj.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/DragAndDrop-iOS11/9ffd4510324901169e441edbffb63572d769cb42/TableViewDragAndDrop/Assets.xcassets/Mcleodganj.imageset/Mcleodganj.jpg -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/Rishikesh.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Rishikesh.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/Rishikesh.imageset/Rishikesh.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/DragAndDrop-iOS11/9ffd4510324901169e441edbffb63572d769cb42/TableViewDragAndDrop/Assets.xcassets/Rishikesh.imageset/Rishikesh.jpg -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/Shimla.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Shimla.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/Shimla.imageset/Shimla.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/DragAndDrop-iOS11/9ffd4510324901169e441edbffb63572d769cb42/TableViewDragAndDrop/Assets.xcassets/Shimla.imageset/Shimla.jpg -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/Srinagar.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Srinagar.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /TableViewDragAndDrop/Assets.xcassets/Srinagar.imageset/Srinagar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iLeafSolutionsPvtLtd/DragAndDrop-iOS11/9ffd4510324901169e441edbffb63572d769cb42/TableViewDragAndDrop/Assets.xcassets/Srinagar.imageset/Srinagar.jpg -------------------------------------------------------------------------------- /TableViewDragAndDrop/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 | -------------------------------------------------------------------------------- /TableViewDragAndDrop/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 36 | 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 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /TableViewDragAndDrop/DataModel/DataModel+Dragging.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DataModel+Dragging.swift 3 | // TableViewDragAndDrop 4 | // 5 | // Created by Hiran on 2/23/18. 6 | // Copyright © 2018 iLeaf Solutions pvt ltd. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import MobileCoreServices 11 | 12 | extension DataModel { 13 | /** 14 | A helper function that serves as an interface to the data model, 15 | called by the implementation of the `tableView(_ canHandle:)` method. 16 | */ 17 | func canHandle(_ session: UIDropSession) -> Bool { 18 | return session.canLoadObjects(ofClass: NSString.self) 19 | } 20 | 21 | /** 22 | A helper function that serves as an interface to the data mode, called 23 | by the `tableView(_:itemsForBeginning:at:)` method. 24 | */ 25 | func dragItems(for indexPath: IndexPath) -> [UIDragItem] { 26 | let placeName = placeNames[indexPath.row] 27 | let placeDescription = placeDescriptions[indexPath.row] 28 | let place = placeName+placeDescription 29 | let data = place.data(using: .utf8) 30 | 31 | let itemProvider = NSItemProvider() 32 | 33 | 34 | itemProvider.registerDataRepresentation(forTypeIdentifier: kUTTypePlainText as String, visibility: .all) { completion in 35 | completion(data, nil) 36 | return nil 37 | } 38 | 39 | 40 | 41 | return [ 42 | UIDragItem(itemProvider: itemProvider) 43 | ] 44 | } 45 | } 46 | 47 | -------------------------------------------------------------------------------- /TableViewDragAndDrop/DataModel/DataModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DataModel.swift 3 | // TableViewDragAndDrop 4 | // 5 | // Created by Hiran on 2/23/18. 6 | // Copyright © 2018 iLeaf Solutions pvt ltd. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | /// The data model used to populate the table view on app launch. 11 | struct DataModel { 12 | 13 | private(set) var placeNames = [ 14 | "1. Goa – The Official Party Hub\n\n", 15 | "2. Mcleodganj – Heaven Amidst The Hills\n\n", 16 | "3. Srinagar – The Gem of Kashmir\n\n", 17 | "4. Andaman – The Beach Haven\n\n", 18 | "5. Leh-Ladakh – The Biker’s Paradise\n\n", 19 | "6. Binsar – Explore The Realms Of Wildlife\n\n", 20 | "7. Coorg – Walk Amidst The Coffee Plantations Of South Indian Scotland\n\n", 21 | "8. Kerala – The Magical God’s Own Country\n\n", 22 | "9. Kanatal – For The Best Camping Experiences\n\n", 23 | "10. Kasol – The Trekker’s Paradise\n\n", 24 | "11. Kutch – The Most Beautiful Stretch Of White Desert\n\n", 25 | "12. Bir Billing – The Paragliding Hub Of India\n\n", 26 | "13. Assam – Home Of One Horned Rhinos\n\n", 27 | "14. Rishikesh – The Adventure Capital Of India\n\n", 28 | "15. Shimla – The Queen Of Northern Hills\n\n", 29 | ] 30 | 31 | private(set) var placeImages = [ 32 | "Goa", 33 | "Mcleodganj", 34 | "Srinagar", 35 | "Andaman", 36 | "Leh-Ladakh", 37 | "Binsar", 38 | "Coorg", 39 | "Kerala", 40 | "Kanatal", 41 | "Kasol", 42 | "Kutch", 43 | "BirBilling", 44 | "Assam", 45 | "Rishikesh", 46 | "Shimla", 47 | ] 48 | 49 | private(set) var placeDescriptions = [ 50 | "Unarguably, Goa has to be the amongst the first few places to visit in India in your twenties. Young and energetic! Amazing nightlife, variety of booze, beach shacks and dirt cheap prices – Goa is one of the best holiday destinations in India that makes your trip memorable.\n\nBest time to visit: November to February\n\nHow to reach\n\nBy air: Dabolim International Airport is the major airport in Goa.\n\nBy rail: Madgaon Railway Station and Thivim Railway Station are the main railway heads of Goa.\n\nBy road: Margao Bus Terminal, Kadamba Bus Terminal, and Mapusa Bus Terminal are best connected bus terminals in Goa. However, many people prefer taking a car/bike ride from Mumbai and Pune.\n\nAttractions: Beaches like Vagator, Calangute, Anjuna, Colva, & Benaulim, Fort Aguada, Church of Mae De Deus, Basilica of Bom Jesus, Temple of Bodgeshwar, Dudhsagar Waterfalls, St Xavier’s Church, Grand Island (for watersports), and clubs like Cafe Mambos,Titos, LPK (Love Passion Karma), SinQ, & Club Cubana", 51 | "The majestic mountains can call tourists to experience the best of what nature has to offer at Mcleodganj – one of the most beautiful places in India. Triund offers the spectacular view of the Dhauladhar ranges. Experience bliss while camping under billions of stars with your friends in Triund. This is among loveliest Indian destinations for camping, regardless of which season you’re coming in.\n\nBest time to visit: September to June\n\nHow to reach\n\nBy air: Gaggal Airport (18 km away) is the nearest airport.\n\nBy rail: The nearest rail head is Pathankot Railway Station (89 km away)\n\nBy road: Numerous state government & private buses ply between Mcleodganj and various cities of north India like Delhi, Chandigarh, Dharamshala etc. on a regular basis. Passengers can take a bus till Mcleodganj bus stand and then hire a taxi.\n\nAttractions: Kangra Fort, Bhagsunath Temple, Bhagsu Falls, Namgyal Monastery, Dalai Lama Temple complex, HPCA Stadium, tea plantations of Kangra valley, and Triund trek", 52 | "If you’re in your twenties, it’s time to add Kashmir to your list of best places to visit in India. If there is heaven on earth, this it is! Experience its charismatic charm before the natural hits & turmoil spoils it all. And when would be a better time to explore a flood-hit, terror-stricken heaven on earth if not now?!\n\nBest time to visit: April to October\n\nHow to reach\n\nBy air: Srinagar has its own airport.\n\nBy rail: The Srinagar Railway Station is under construction. Till then, passengers can take a train to Udhampur Railway Station(229 km from Srinagar)\n\nBy road: Unless you are traveling from a city of Jammu & Kashmir, road is not a preferred way to reach Srinagar.\n\nAttractions: Dal Lake (boating in shikaras & nightstays in houseboats), Nishat Bagh, Shalimar Bagh, Tomb of Zin-ul-Abidin, Jama Masjid, Hazratbal Mosque, and Shankaracharya Hill", 53 | "Scared of water? Never swam? Maybe it’s time to beat the fear out of you and dive in to the deep sea and overcome the fear of water and depths, ZNMD Style. Trust us, you’d be delighted at the sites underwater and it will keep you coming back for more. And woah, for aqua lovers, it is famous tourist places in India which feels no less than a paradise!\n\nBest time to visit: November to mid-May\n\nHow to reach\n\nBy air: Vir Savarkar Airport in Port Blair is the archipelago’s major airport.\n\nBy sea: Ships ply between Haddo Wharf Port in Port Blair and cities of Chennai, Kolkata, & Visakhapatnam.\n\nAttractions: Cellular Jail National Memorial, Radhanagar Beach, Rajiv Gandhi Water Sports Complex in Port Blair, Mahatma Gandhi Marine National Park, Chidiya Tapu, and watersports like scuba-diving, snorkeling, & parasailing", 54 | "Undoubtedly, Leh – Ladakh is on every travel enthusiasts list of places to visit in India before they turn 30. Ride on the crazy winding roads, get stuck in the middle of nowhere, sleep with the locals and learn to be independent on the desert mountains as you undertake this adventurous journey.\n\nBest time to visit: April to mid-May and mid-September to mid-October\n\nHow to reach\n\nBy air: Kushok Bakula Rimpochee Airport in Leh is the airport connecting the region to other places by air.\n\nBy rail: Jammu Tawi Railway Station (700 km from Ladakh) is the nearest rail head. From here, one can hire a cab or board a JKSRTC bus to Ladakh.\n\nBy road: The most popular means of reach Ladakh remains to be road. Travelers can go on a bike/jeep ride to the destination. Bike trips from Delhi, Chandigarh, and Manali are most popular.\n\nAttractions: Zanskar Valley, Pangong Tso Lake, Khardung-La Pass, Spituk Gompa, and Hemis National Park", 55 | "Peace. Jungles. Heights. Chills. Wildlife. All you wildlife enthusiasts out there, head to Binsar – one of the rising tourist destinations in India located in the heart of Kumaoni region of Almora for an incredible trip of your lifetime.\n\nBest time to visit: October to November\n\nHow to reach\n\nBy air: There’s a domestic airport in Pantnagar, 152 km from Binsar.\n\nBy rail: Kathgodam Railway Station, 119 km from Binsar, is the nearest railway head.\n\nBy road: Buses connect the town with all major neighboring areas.\n\nAttractions: Zero Point, Pariyadeva Pashan, Mary Budden Estate, Binsar Wildlife Sanctuary, Bineshwar Mahadev Temple, and more.", 56 | "Coorg simply cannot be skipped from the list of best places to visit in India. A quick getaway for many from Bangalore, this mesmerizing hill station in Karnataka is breathtakingly beautiful. A visit here sure would heal you and energize you!\n\nBest time to visit: October to March\n\nHow to reach\n\nBy air: The nearest domestic airport is in Mangalore, 156 km away. The nearest international airport is the Kempegowda International Airport in Bengaluru, 285 kilometres away.\n\nBy rail: Mysore Junction, 106 km away, is the nearest rail head.\n\nBy road: The 238 km long road trip from Bangalore (Bengaluru) takes 5 hours 30 minutes.\n\nAttractions: Abbey Falls, Nalknad Palace, Barapole River, Brahmagiri Peak, Iruppu Falls, Namdroling Monastery, Nagarhole National Park, Microlight flight at Chelavara, ziplining, and angling in River Kaveri", 57 | "To all the nature lover’s out there. A trip to God’s own country is a must in your twenties for its enchanting wilderness. Luscious green trees, pristine water, crazy wildlife experience – visit Kerala for more such wonderful delights.\n\nBest time to visit: November to January and June to August\n\nHow to reach\n\nBy air: Kerala has three main airports – Calicut International Airport, Cochin International Airport, and Trivandrum International Airport. These airports connect Kerala with different cities across the world, such as Delhi, Mumbai, Chennai, Muscat, and Dubai.\n\nBy rail: Thiruvananthapuram Central railway station, Ernakulam Junction railway station, and Kollam Junction railway station are three major rail heads of Kerala. These stations connect the state with cities and towns across India.\n\nAttractions\n\nAlleppey: Alappuzha Beach, Krishnapuram Palace, Kumarakom bird sanctuary, Marari Beach, Revi Karunakaran Museum, Marari Beach, Punnamada Lake, Pathiramanal, and Sri Krishna Temple in Ambalappuzha\n\nMunnar: TATA Tea Museum, Meesapulimala, Blossom Park, Pothamedu ViewPoint, Attukal Waterfalls, Cheeyappara Waterfalls, Kundala Lake, Mattupetty Dam, Anamudi, and Eravikulam National Park\n\nKumarakom: Kumarakom Bird Sanctuary, Kumarakom Backwaters, Aruvikkuzhi waterfall, Thirunakkara Mahadeva Temple, Vembanad Lake, Kumarakom Beach, and Pathiramanal Island\n\nWayanad: Meenmutty Waterfalls, Chembra Peak, 9 Hairpin Curves, Muthanga Wildlife Sanctuary, Ekkadal Caves, Bathery Jain Temple, Neelimala View Point, and Pookot Lake\n\nThekkady: Periyar Wildlife Sanctuary, Mangla Devi Temple, Abraham’s Spice Garden, Murikkady, Kadathanadan Kalari Centre, Chellarkovil, Kumily, and Deepa World Spice & Ayurvedic Garden\n\nKovalam: Lighthouse Beach, Samudra Beach, Thiruvallam Parasurama Temple, Vizhinjam Marine Aquarium, Halcyon Castle, Akkulam Lake, Jama Masjid, Vellayani Lake, Karamana River, and Rock Cut Caves\n\nBekal: Bekal Fort, Ananthapura Temple, Valiyaparamba Backwaters, Bekal Beach, Mallikarjuna Temple, Chandragiri Fort, Kappil Beach, Nileswaram, Bekal Hole Aqua Park, and Pallikere Beach\n\nKozhikode: Mananchira, Conolly Canal, Hilite Mall, Kallayi, Tali Temple, Kappad Beach, Kozhikode Beach, Thusharagiri Waterfalls, Sargaalaya, Payyoli Beach, Kozhippara Falls, and Matri Dei Cathedral\n\nVarakala: Varkala Beach, Janardhan Temple, Sivagiri Muth, Kappil Lake, Papanasam Beach, Janardan Swami Temple, Vishnu Temple, Anjengo Fort, Sarkara Devi Temple, Varkala Tunnel, and Kaduvayil Thangal Dargah", 58 | "With this rising adventure spot that offers endless opportunities to enjoy thrilling activities clubbed with one of the best camping experiences, weekends will no more be boring at escapes like Kanatal. Considered to be one of the best holiday destinations in India for all travelers, camping in Kanatal is one experience that no one should miss out on.\n\nBest time to visit: April to June\n\nHow to reach\n\nBy air: Located at a distance of 92 kms, Jolly Grant Airport is the nearest airstrip to Kanatal.\n\nBy rail: Located at a distance of 75 kms, Rishikesh railway station is the nearest railhead to Kanatal.\n\nAttractions: Kodia Jungle, Tehri Lake, Surkanda Devi temple, New Tehri Dam, and more.", 59 | "Here’s why every man should travel solo at least once in your life – Not only will you discover a new you and find a direction for yourself, but you’d return with experiences of a lifetime. And there’s no better place than Kasol, one of the top 10 tourist places in India.\n\nBest time to visit: October to June\n\nHow to reach\n\nBy air: Bhuntar Domestic Airport (31 km away) is the nearest flight connect.\n\nBy rail: Pathankot (296 km away) is the nearest rail head.\n\nBy road: HRTC (Himachal Road Transport Corporation) runs regular buses from Delhi, Haryana, & Punjab and other Himachal cities like Pathankot, Shimla, Kangra, Solan, & Dharamsala.\n\nAttractions: Kheerganga peak, Malana village, Parvati river, Manikaran Sahib gurudwara, Jari, Bhuntar, and more.", 60 | "Kutch is a must visit place in India before you turn 30. Travel to the no man’s land, the seasonal salt marsh amidst the famous Thar Desert during the kite festival where the sky comes alive with vibrant and oversized kites at one of the top tourist places in India.\n\nBest time to visit: November to February\n\nHow to reach\n\nBy air: Bhuj Airport, 69 km away, is the nearest air connect.\n\nBy rail: Bhuj Railway Station is 50 km away from Kutch.\n\nAttractions: Prag Mahal, Kalo Dungar, Kutch Museum, Archaeological Museum, Mandvi Beach, White Desert, Aina Mahal, and more.", 61 | "Rising to fame post hosting the first ever paragliding world cup, Bir Billing soon caught the attention of adventure enthusiasts across the country. Comprising of more than ten paragliding spots, Bir Billing is one of those tourist places that has truly lived upto its name of paragliding capital of India.\n\nBest time to visit: April to June\n\nHow to reach\n\nBy air: Kangra airport in Gaggal happens to be the nearest airport located at a distance of about 67 kilometers from Bir.\n\nBy rail: Pathankot is the nearest railway station to Bir Billing located at a distance of about 140 kilometers.\n\nBy road: Located in the heart of Himachal, Bir Billing is accessible by road as many state-run and private buses run from the nearby cities of Delhi, Chandigarh, Manali, Shimla, and more.\n\nAttractions: Baijnath Shiv Temple, Billing Valley, Chamunda Devi Temple, Shiva Shrine, Ahju Fort, and more.", 62 | "Stay set to be overwhelmed by the sceneries, flora, and fauna of the Dibru Saikhowa National Park. And this wildlife expedition is not the same as any jeep safari. Instead, activities like jungle walk and boat ride are conducted during the months of November to April. Cruise along the Brahmaputra river to witness the animals in their most natural habitats.\n\nBest time to visit: October to April\n\nHow to reach\n\nBy air: Mohanbari in Dibrugarh, 40 km away, is the nearest domestic airport. Lokpriya Gopinath Bordoloi International Airport at Guwahati is 510 km away.\n\nBy rail: New Tinsukia Railway Station is 12 km away.\n\nAttractions: Kaziranga National Park, Manas National Park, Kamakhya Temple, Srimanta Sankardev Kalakshetra, Assam State Museum, and more.", 63 | "With bursting energy and enthusiasm, twenties is the best time to enjoy thrill and adventure, especially with your friends. Travel to the adventure capital of India, Rishikesh and ride on the mystical but fierce fast flowing waters of Ganges. Rishikesh is a must visit place in India if you haven’t yet crossed the age bar.\n\nBest time to visit: September to November and February to June\n\nHow to reach\n\nBy air: Jolly Grant Airport in Dehradun, 20 km from Rishikesh, is the nearest air connect.\n\nBy rail: Haridwar Junction, 21 km from Rishikesh, is the nearest rail head.\n\nBy road: It is well-connected by road to major cities, including Haridwar (21 km away) and Delhi (229 km away).\n\nAttractions: Rajaji National Park, Lakshman Jhula, Neelkanth Mahadev Temple, Parmarth Niketan, Ram Jhula, Shivpuri River Rafting Point, and more.", 64 | "Revisit childhood by hopping on the colorful toy train from Kalka to Shimla as it makes way through the pine forests and verdant valleys. Experiencing this exceptionally elating toy train experience is a must for everyone on their trip to this best tourist place in India at least once in a lifetime.\n\nBest time to visit: March to June\n\nHow to reach\n\nBy air: Located at a distance of 25 kms, Jubbarhatti is the nearest airport from Shimla.\n\nBy rail: The toy train from Kalka to Shimla is the most convenient railway line that connects Shimla to other nearby towns.\n\nBy road: Many state-run and private buses run from the nearby cities of Delhi, Chandigarh, Manali, and Kullu that are well connected to Shimla via road.\n\nAttractions: Kufri, Mall Road, Chadwick Falls, Jakhu Temple, Annandale, Christ Church, Scandal Point, and more." 65 | ] 66 | 67 | /// The traditional method for rearranging rows in a table view. 68 | mutating func moveItem(at sourceIndex: Int, to destinationIndex: Int) { 69 | guard sourceIndex != destinationIndex else { return } 70 | 71 | let place = placeNames[sourceIndex] 72 | placeNames.remove(at: sourceIndex) 73 | placeNames.insert(place, at: destinationIndex) 74 | } 75 | 76 | /// The method for adding a new item to the table view's data model. 77 | mutating func addItem(_ place: String, at index: Int) { 78 | placeNames.insert(place, at: index) 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /TableViewDragAndDrop/DetailViewController/DetailViewController+Drag.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DetailViewController+Drag.swift 3 | // TableViewDragAndDrop 4 | // 5 | // Created by Hiran on 2/26/18. 6 | // Copyright © 2018 iLeaf Solutions pvt ltd. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension DetailViewController: UIDragInteractionDelegate { 12 | // MARK: - UIDragInteractionDelegate 13 | 14 | /* 15 | The `dragInteraction(_:itemsForBeginning:)` method is the essential method 16 | to implement for allowing dragging from a view. 17 | */ 18 | func dragInteraction(_ interaction: UIDragInteraction, itemsForBeginning session: UIDragSession) -> [UIDragItem] { 19 | guard let image = imageView?.image else { return [] } 20 | 21 | let provider = NSItemProvider(object: image) 22 | let item = UIDragItem(itemProvider: provider) 23 | item.localObject = image 24 | 25 | /* 26 | Returning a non-empty array, as shown here, enables dragging. You 27 | can disable dragging by instead returning an empty array. 28 | */ 29 | return [item] 30 | } 31 | 32 | /* 33 | Code below here adds visual enhancements but is not required for minimal 34 | dragging support. If you do not implement this method, the system uses 35 | the default lift animation. 36 | */ 37 | func dragInteraction(_ interaction: UIDragInteraction, previewForLifting item: UIDragItem, session: UIDragSession) -> UITargetedDragPreview? { 38 | guard let image = item.localObject as? UIImage else { return nil } 39 | 40 | // Scale the preview image view frame to the image's size. 41 | let frame: CGRect 42 | if image.size.width > image.size.height { 43 | let multiplier = (imageView?.frame.width)! / image.size.width 44 | frame = CGRect(x: 0, y: 0, width: (imageView?.frame.width)!, height: image.size.height * multiplier) 45 | } else { 46 | let multiplier = (imageView?.frame.height)! / image.size.height 47 | frame = CGRect(x: 0, y: 0, width: image.size.width * multiplier, height: (imageView?.frame.height)!) 48 | } 49 | 50 | // Create a new view to display the image as a drag preview. 51 | let previewImageView = UIImageView(image: image) 52 | previewImageView.contentMode = .scaleAspectFit 53 | previewImageView.frame = frame 54 | 55 | /* 56 | Provide a custom targeted drag preview that lifts from the center 57 | of imageView. The center is calculated because it needs to be in 58 | the coordinate system of imageView. Using imageView.center returns 59 | a point that is in the coordinate system of imageView's superview, 60 | which is not what is needed here. 61 | */ 62 | let center = CGPoint(x: (imageView?.bounds.midX)!, y: (imageView?.bounds.midY)!) 63 | let target = UIDragPreviewTarget(container: imageView!, center: center) 64 | return UITargetedDragPreview(view: previewImageView, parameters: UIDragPreviewParameters(), target: target) 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /TableViewDragAndDrop/DetailViewController/DetailViewController+Drop.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DetailViewController+Drop.swift 3 | // TableViewDragAndDrop 4 | // 5 | // Created by Hiran on 2/26/18. 6 | // Copyright © 2018 iLeaf Solutions pvt ltd. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import Foundation 11 | import MobileCoreServices 12 | 13 | extension DetailViewController: UIDropInteractionDelegate { 14 | // MARK: - UIDropInteractionDelegate 15 | 16 | /** 17 | Ensure that the drop session contains a drag item with a data representation 18 | that the view can consume. 19 | */ 20 | func dropInteraction(_ interaction: UIDropInteraction, canHandle session: UIDropSession) -> Bool { 21 | return session.hasItemsConforming(toTypeIdentifiers: [kUTTypeImage as String]) && session.items.count == 1 22 | } 23 | 24 | // Update UI, as needed, when touch point of drag session enters view. 25 | func dropInteraction(_ interaction: UIDropInteraction, sessionDidEnter session: UIDropSession) { 26 | let dropLocation = session.location(in: view) 27 | updateLayers(forDropLocation: dropLocation) 28 | } 29 | 30 | /** 31 | Required delegate method: return a drop proposal, indicating how the 32 | view is to handle the dropped items. 33 | */ 34 | func dropInteraction(_ interaction: UIDropInteraction, sessionDidUpdate session: UIDropSession) -> UIDropProposal { 35 | let dropLocation = session.location(in: view) 36 | updateLayers(forDropLocation: dropLocation) 37 | 38 | let operation: UIDropOperation 39 | 40 | if (imageView?.frame.contains(dropLocation))! { 41 | /* 42 | If you add in-app drag-and-drop support for the .move operation, 43 | you must write code to coordinate between the drag interaction 44 | delegate and the drop interaction delegate. 45 | */ 46 | operation = session.localDragSession == nil ? .copy : .move 47 | } else { 48 | // Do not allow dropping outside of the image view. 49 | operation = .cancel 50 | } 51 | 52 | return UIDropProposal(operation: operation) 53 | } 54 | 55 | /** 56 | This delegate method is the only opportunity for accessing and loading 57 | the data representations offered in the drag item. 58 | */ 59 | func dropInteraction(_ interaction: UIDropInteraction, performDrop session: UIDropSession) { 60 | // Consume drag items (in this example, of type UIImage). 61 | session.loadObjects(ofClass: UIImage.self) { imageItems in 62 | let images = imageItems as! [UIImage] 63 | 64 | /* 65 | If you do not employ the loadObjects(ofClass:completion:) convenience 66 | method of the UIDropSession class, which automatically employs 67 | the main thread, explicitly dispatch UI work to the main thread. 68 | For example, you can use `DispatchQueue.main.async` method. 69 | */ 70 | self.imageView?.image = images.first 71 | } 72 | 73 | // Perform additional UI updates as needed. 74 | let dropLocation = session.location(in: view) 75 | updateLayers(forDropLocation: dropLocation) 76 | } 77 | 78 | // Update UI, as needed, when touch point of drag session leaves view. 79 | func dropInteraction(_ interaction: UIDropInteraction, sessionDidExit session: UIDropSession) { 80 | let dropLocation = session.location(in: view) 81 | updateLayers(forDropLocation: dropLocation) 82 | } 83 | 84 | // Update UI and model, as needed, when drop session ends. 85 | func dropInteraction(_ interaction: UIDropInteraction, sessionDidEnd session: UIDropSession) { 86 | let dropLocation = session.location(in: view) 87 | updateLayers(forDropLocation: dropLocation) 88 | } 89 | 90 | // MARK: - Helpers 91 | 92 | func updateLayers(forDropLocation dropLocation: CGPoint) { 93 | if (imageView?.frame.contains(dropLocation))! { 94 | view.layer.borderWidth = 0.0 95 | imageView?.layer.borderWidth = 2.0 96 | } else if view.frame.contains(dropLocation) { 97 | view.layer.borderWidth = 5.0 98 | imageView?.layer.borderWidth = 0.0 99 | } else { 100 | view.layer.borderWidth = 0.0 101 | imageView?.layer.borderWidth = 0.0 102 | } 103 | } 104 | } 105 | 106 | 107 | -------------------------------------------------------------------------------- /TableViewDragAndDrop/DetailViewController/DetailViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DetailViewController.swift 3 | // TableViewDragAndDrop 4 | // 5 | // Created by Hiran on 2/26/18. 6 | // Copyright © 2018 iLeaf Solutions pvt ltd. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class DetailViewController: UIViewController { 12 | 13 | @IBOutlet weak var imageView: UIImageView?{ 14 | didSet { 15 | imageView?.layer.borderColor = UIColor.green.cgColor 16 | imageView?.layer.borderWidth = 0.0 17 | } 18 | } 19 | @IBOutlet weak var lblTitle: UILabel? 20 | @IBOutlet weak var txtDescription: UITextView? 21 | 22 | var place = Place() 23 | 24 | override func viewDidLoad() { 25 | super.viewDidLoad() 26 | 27 | // Do any additional setup after loading the view. 28 | 29 | // Enable dragging from the image view (see ViewController+Drag.swift). 30 | let dragInteraction = UIDragInteraction(delegate: self as UIDragInteractionDelegate) 31 | imageView?.addInteraction(dragInteraction) 32 | 33 | // Enable dropping onto the image view (see ViewController+Drop.swift). 34 | let dropInteraction = UIDropInteraction(delegate: self as UIDropInteractionDelegate) 35 | view.addInteraction(dropInteraction) 36 | 37 | 38 | self.imageView?.image = UIImage.init(named: place.image!) 39 | self.lblTitle?.text = place.title 40 | self.txtDescription?.text = place.placeDescription 41 | 42 | } 43 | 44 | override func didReceiveMemoryWarning() { 45 | super.didReceiveMemoryWarning() 46 | // Dispose of any resources that can be recreated. 47 | } 48 | 49 | 50 | /* 51 | // MARK: - Navigation 52 | 53 | // In a storyboard-based application, you will often want to do a little preparation before navigation 54 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 55 | // Get the new view controller using segue.destinationViewController. 56 | // Pass the selected object to the new view controller. 57 | } 58 | */ 59 | 60 | } 61 | -------------------------------------------------------------------------------- /TableViewDragAndDrop/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 | -------------------------------------------------------------------------------- /TableViewDragAndDrop/Place/Place.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Place.swift 3 | // TableViewDragAndDrop 4 | // 5 | // Created by Hiran on 2/26/18. 6 | // Copyright © 2018 iLeaf Solutions pvt ltd. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class Place: NSObject { 12 | var image: String? 13 | var title: String? 14 | var placeDescription: String? 15 | } 16 | -------------------------------------------------------------------------------- /TableViewDragAndDrop/ViewController/ViewController+Data.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController+Data.swift 3 | // TableViewDragAndDrop 4 | // 5 | // Created by Hiran on 2/23/18. 6 | // Copyright © 2018 iLeaf Solutions pvt ltd. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | // Logic that connects `TableViewController`'s data model with its user interface. 12 | extension ViewController { 13 | // MARK: - UITableViewDataSource 14 | 15 | override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 16 | return model.placeNames.count 17 | } 18 | 19 | override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 20 | let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) 21 | cell.textLabel?.text = model.placeNames[indexPath.row] 22 | cell.detailTextLabel?.text = model.placeDescriptions[indexPath.row] 23 | return cell 24 | } 25 | 26 | // MARK: - UITableViewDelegate 27 | 28 | override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool { 29 | return true 30 | } 31 | 32 | override func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) { 33 | model.moveItem(at: sourceIndexPath.row, to: destinationIndexPath.row) 34 | } 35 | 36 | override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 37 | performSegue(withIdentifier: "Detail", sender: self) 38 | } 39 | 40 | } 41 | 42 | -------------------------------------------------------------------------------- /TableViewDragAndDrop/ViewController/ViewController+Drag.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController+Drag.swift 3 | // TableViewDragAndDrop 4 | // 5 | // Created by Hiran on 2/23/18. 6 | // Copyright © 2018 iLeaf Solutions pvt ltd. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension ViewController: UITableViewDragDelegate { 12 | // MARK: - UITableViewDragDelegate 13 | 14 | /** 15 | The `tableView(_:itemsForBeginning:at:)` method is the essential method 16 | to implement for allowing dragging from a table. 17 | */ 18 | func tableView(_ tableView: UITableView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] { 19 | return model.dragItems(for: indexPath) 20 | } 21 | } 22 | 23 | -------------------------------------------------------------------------------- /TableViewDragAndDrop/ViewController/ViewController+Drop.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController+Drop.swift 3 | // TableViewDragAndDrop 4 | // 5 | // Created by Hiran on 2/23/18. 6 | // Copyright © 2018 iLeaf Solutions pvt ltd. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension ViewController: UITableViewDropDelegate { 12 | // MARK: - UITableViewDropDelegate 13 | 14 | /** 15 | Ensure that the drop session contains a drag item with a data representation 16 | that the view can consume. 17 | */ 18 | func tableView(_ tableView: UITableView, canHandle session: UIDropSession) -> Bool { 19 | return model.canHandle(session) 20 | } 21 | 22 | /** 23 | A drop proposal from a table view includes two items: a drop operation, 24 | typically .move or .copy; and an intent, which declares the action the 25 | table view will take upon receiving the items. (A drop proposal from a 26 | custom view does includes only a drop operation, not an intent.) 27 | */ 28 | func tableView(_ tableView: UITableView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UITableViewDropProposal { 29 | // The .move operation is available only for dragging within a single app. 30 | if tableView.hasActiveDrag { 31 | if session.items.count > 1 { 32 | return UITableViewDropProposal(operation: .cancel) 33 | } else { 34 | return UITableViewDropProposal(operation: .move, intent: .insertAtDestinationIndexPath) 35 | } 36 | } else { 37 | return UITableViewDropProposal(operation: .copy, intent: .insertAtDestinationIndexPath) 38 | } 39 | } 40 | 41 | /** 42 | This delegate method is the only opportunity for accessing and loading 43 | the data representations offered in the drag item. The drop coordinator 44 | supports accessing the dropped items, updating the table view, and specifying 45 | optional animations. Local drags with one item go through the existing 46 | `tableView(_:moveRowAt:to:)` method on the data source. 47 | */ 48 | func tableView(_ tableView: UITableView, performDropWith coordinator: UITableViewDropCoordinator) { 49 | let destinationIndexPath: IndexPath 50 | 51 | if let indexPath = coordinator.destinationIndexPath { 52 | destinationIndexPath = indexPath 53 | } else { 54 | // Get last index path of table view. 55 | let section = tableView.numberOfSections - 1 56 | let row = tableView.numberOfRows(inSection: section) 57 | destinationIndexPath = IndexPath(row: row, section: section) 58 | } 59 | 60 | coordinator.session.loadObjects(ofClass: NSString.self) { items in 61 | // Consume drag items. 62 | let stringItems = items as! [String] 63 | 64 | var indexPaths = [IndexPath]() 65 | for (index, item) in stringItems.enumerated() { 66 | let indexPath = IndexPath(row: destinationIndexPath.row + index, section: destinationIndexPath.section) 67 | self.model.addItem(item, at: indexPath.row) 68 | indexPaths.append(indexPath) 69 | } 70 | 71 | tableView.insertRows(at: indexPaths, with: .automatic) 72 | } 73 | } 74 | } 75 | 76 | -------------------------------------------------------------------------------- /TableViewDragAndDrop/ViewController/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // TableViewDragAndDrop 4 | // 5 | // Created by Hiran on 2/23/18. 6 | // Copyright © 2018 iLeaf Solutions pvt ltd. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UITableViewController { 12 | 13 | // MARK: - Properties 14 | 15 | var model = DataModel() 16 | 17 | // MARK: - View Life Cycle 18 | 19 | // Specify the table as its own drag source and drop delegate. 20 | override func viewDidLoad() { 21 | super.viewDidLoad() 22 | 23 | tableView.dragDelegate = self 24 | tableView.dropDelegate = self 25 | } 26 | 27 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 28 | if segue.destination is DetailViewController { 29 | if let indexPath = self.tableView.indexPathForSelectedRow { 30 | let place = Place() 31 | place.image = model.placeImages[indexPath.row] 32 | place.title = model.placeNames[indexPath.row] 33 | place.placeDescription = model.placeDescriptions[indexPath.row] 34 | let vc = segue.destination as! DetailViewController 35 | vc.place = place; 36 | 37 | 38 | } 39 | } 40 | } 41 | 42 | } 43 | 44 | --------------------------------------------------------------------------------