For security reasons I want to disable the new iOS 11 drag & drop feature within my whole app. More specifically the drag part.
In iOS 11 it\'s happening by defa
I'm not aware of any way to fully disable the dragging functionality, but there's a way to confine the drag session to your own app only. That should already be a big improvement in terms of security.
Take a look at sessionIsRestrictedToDraggingApplication.
dragInteraction(_:sessionIsRestrictedToDraggingApplication:)
Called to ask your app whether the drag session should be confined to the app in which it begins.
Drag & Drop is not enabled by default. You need to enable it by providing drag interaction delegate to your view. So you may not need to disable drag and drop, if you've not implemented it.
Note:
Text views and text fields automatically support drag and drop. But it is its default behavior to allow copy contents from one source to another source using UIMenuController. Drag & drop makes it easy to copy-paste your text contents for text input views. Drag & drop has no impact on data security concern, compared to current stable OS features for data sharing using UIMenuController.
Here is Apple's statement for the same.
Making a View into a Drag Source By implementing a drag interaction delegate (UIDragInteractionDelegate) for a view, you enable that view to function as a drag source in your app.
Enable a View as a Drag Source
Any instance or subclass of UIView can act as a drag source. Your first steps to make this happen are:
Here’s how to do this using a custom helper method, which you would typically call within a view controller’s viewDidLoad() method:
func customEnableDragging(on view: UIView, dragInteractionDelegate: UIDragInteractionDelegate) {
let dragInteraction = UIDragInteraction(delegate: dragInteractionDelegate)
view.addInteraction(dragInteraction)
}
Create a Drag Item
A drag item encapsulates a source app’s promises for providing a variety of data representations for one model object.
To create a drag item, implement the dragInteraction(_:itemsForBeginning:)
method in your drag interaction delegate, as shown here in a minimal form:
func dragInteraction(_ interaction: UIDragInteraction, itemsForBeginning session: UIDragSession) -> [UIDragItem] {
// Cast to NSString is required for NSItemProviderWriting support.
let stringItemProvider = NSItemProvider(object: "Hello World" as NSString)
return [
UIDragItem(itemProvider: stringItemProvider)
]
}
This implementation uses the init(object:) convenience initializer. When you instantiate a drag item, pass an object in your app’s native representation, or in the highest-fidelity representation you support. In general, ensure that the first element in the item provider’s registeredTypeIdentifiers
array represents the highest-fidelity data your drag interaction delegate can deliver.
To add more data representations to a drag item, as you typically would in your app, add them in fidelity order, from highest to lowest. When adding representations, you have choices:
NSItemProviderWriting
protocol in your model class. Using this protocol, you place the code for providing multiple data representations within the model class.registerObject(_:visibility:)
method, or related methods, from the NSItemProvider
class, to explicitly register data representations.Found a solution. It is to method swizzle the isEnabled method of UIDragInteraction to return NO in the situations your app may need. Note that normally it's not a good idea to method swizzle.
@implementation UIDragInteraction (TextLimitations)
+ (void)load
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class class = [self class];
SEL originalSelector = @selector(isEnabled);
SEL swizzledSelector = @selector(restrictIsEnabled);
Method originalMethod = class_getInstanceMethod(class, originalSelector);
Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
BOOL didAddMethod =
class_addMethod(class,
originalSelector,
method_getImplementation(swizzledMethod),
method_getTypeEncoding(swizzledMethod));
if (didAddMethod) {
class_replaceMethod(class,
swizzledSelector,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod));
} else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
});
}
-(BOOL)restrictIsEnabled
{
if (restrictedCondition)
{
return NO;
}
return [self restrictIsEnabled];
}