-
Notifications
You must be signed in to change notification settings - Fork 1
/
CP3DTouchManager.m
136 lines (115 loc) · 4.52 KB
/
CP3DTouchManager.m
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
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
//
// CP3DTouchManager.m
// 3DTouchManagerDemo
//
// Created by Mrc.cc on 2017/7/3.
// Copyright © 2017年 Paul Chen. All rights reserved.
//
#import "CP3DTouchManager.h"
#import <objc/runtime.h>
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunguarded-availability"
@interface CP3DTouchManager()<UIViewControllerPreviewingDelegate>
@end
@implementation CP3DTouchManager
+ (instancetype)shared{
static CP3DTouchManager *util = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
util = [CP3DTouchManager new];
});
return util;
}
- (instancetype)init{
if ([UIDevice currentDevice].systemVersion.floatValue >= 9.0) {
self = [super init];
return self;
}
return nil;
}
+ (void)setupPreviewCommitHandler:(CPPreviewCommitHandler)commitHandler{
[CP3DTouchManager shared].commitHandler = commitHandler;
}
+ (void)makeViewController:(UIViewController *)vc support3DTouchForView:(UIView *)view{
[[CP3DTouchManager shared] makeViewController:vc support3DTouchForView:view];
}
+ (void)makeViewControllerSupport3DTouch:(UIViewController *)vc{
[self makeViewController:vc support3DTouchForView:vc.view];
}
- (void)makeViewController:(UIViewController *)vc support3DTouchForView:(UIView *)view{
if (vc.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable) {
CP3DTouchManager *util = [CP3DTouchManager shared];
[vc registerForPreviewingWithDelegate:util sourceView:view];
}
}
- (void)makeViewControllerSupport3DTouch:(UIViewController *)vc{
[self makeViewController:vc support3DTouchForView:vc.view];
}
#pragma mark 3D touch
- (UIViewController *)previewingContext:(id<UIViewControllerPreviewing>)previewingContext viewControllerForLocation:(CGPoint)location{
UIView *view = [previewingContext.sourceView viewAtTouchPoint:location];
if (view.viewControllerFor3DTouch) {
previewingContext.sourceRect = [view convertRect:view.bounds toView:previewingContext.sourceView];
return view.viewControllerFor3DTouch();
}
return nil;
}
- (void)previewingContext:(id<UIViewControllerPreviewing>)previewingContext commitViewController:(UIViewController *)viewControllerToCommit{
if (self.commitHandler) {
self.commitHandler(viewControllerToCommit);
}
}
@end
@implementation UIView (Touch3D)
- (void)setTouch3DPriority:(CPView3DTouchPriority)touch3DPriority{
objc_setAssociatedObject(self, @selector(touch3DPriority), [NSNumber numberWithInteger:touch3DPriority], OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (CPView3DTouchPriority)touch3DPriority{
NSNumber *value = objc_getAssociatedObject(self, _cmd);
if (value) {
return value.integerValue;
}
return 0;
}
- (void)setViewControllerFor3DTouch:(UIViewController *(^)(void))viewControllerFor3DTouch{
objc_setAssociatedObject(self, @selector(viewControllerFor3DTouch), viewControllerFor3DTouch, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (CPViewFor3DTouchHandler)viewControllerFor3DTouch{
return objc_getAssociatedObject(self, _cmd);
}
- (UIView *)viewAtTouchPoint:(CGPoint)point{
// Do nothing when hidden == YES.
if (self.hidden) {
return nil;
}
// Check whether the point was contained.
BOOL isInSelf = CGRectContainsPoint(self.bounds, point);
// Go through all subviews to find the appropriate view.
if (isInSelf) {
UIView *touchView = nil;
for (NSInteger i = self.subviews.count - 1; i >= 0; i --) {
// Find the view from front to back.
UIView *view = [self.subviews objectAtIndex:i];
// subview frame origin
CGPoint origin = view.frame.origin;
// subview bounds origin
CGPoint sorigin = view.bounds.origin;
// Convert the point to the subview's coordinate system.
CGPoint convertPoint = CGPointMake(point.x - origin.x + sorigin.x, point.y - origin.y + sorigin.y);
UIView *result = [view viewAtTouchPoint:convertPoint];
// Find the view.
if (result && result.viewControllerFor3DTouch) {
if (!touchView || touchView.touch3DPriority < result.touch3DPriority) {
touchView = result;
}
}
}
if (touchView) {
return touchView;
}
// If no view found, return self if self can response, otherwise return nil.
return self.viewControllerFor3DTouch ? self : nil;
}
return nil;
}
@end