@@ -1,7 +1,7 @@ |
||
1 | 1 |
github "Yalantis/PullToRefresh" |
2 |
-github "ReactiveX/RxSwift" ~> 4.3 |
|
2 |
+github "ReactiveX/RxSwift" |
|
3 | 3 |
github "onevcat/Kingfisher" ~> 5.0 |
4 |
-github "Alamofire/Alamofire" "5.0.0.beta.1" |
|
4 |
+github "Alamofire/Alamofire" "5.0.0-beta.3" |
|
5 | 5 |
github "stephencelis/SQLite.swift" ~> 0.11.5 |
6 | 6 |
github "tristanhimmelman/ObjectMapper" ~> 3.4 |
7 | 7 |
github "RxSwiftCommunity/RxDataSources" ~> 3.0 |
@@ -1,7 +1,7 @@ |
||
1 |
-github "Alamofire/Alamofire" "5.0.0.beta.1" |
|
1 |
+github "Alamofire/Alamofire" "5.0.0-beta.3" |
|
2 | 2 |
github "ReactiveX/RxSwift" "4.4.2" |
3 | 3 |
github "RxSwiftCommunity/RxDataSources" "3.1.0" |
4 | 4 |
github "Yalantis/PullToRefresh" "3.1" |
5 |
-github "onevcat/Kingfisher" "5.2.0" |
|
5 |
+github "onevcat/Kingfisher" "5.3.1" |
|
6 | 6 |
github "stephencelis/SQLite.swift" "0.11.5" |
7 | 7 |
github "tristanhimmelman/ObjectMapper" "3.4.2" |
@@ -507,7 +507,7 @@ |
||
507 | 507 |
A69FFA9E1E7004700006FEE0 /* PhotoDetailCommentCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhotoDetailCommentCell.swift; sourceTree = "<group>"; }; |
508 | 508 |
A69FFAA31E7004700006FEE0 /* PhotoDetailViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhotoDetailViewController.swift; sourceTree = "<group>"; }; |
509 | 509 |
A69FFAA41E7004700006FEE0 /* PhotoDetailViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhotoDetailViewModel.swift; sourceTree = "<group>"; }; |
510 |
- A69FFAA61E7004700006FEE0 /* ImageCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageCell.swift; sourceTree = "<group>"; wrapsLines = 0; }; |
|
510 |
+ A69FFAA61E7004700006FEE0 /* ImageCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageCell.swift; sourceTree = "<group>"; usesTabs = 0; wrapsLines = 1; }; |
|
511 | 511 |
A69FFAA81E7004700006FEE0 /* ShareController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShareController.swift; sourceTree = "<group>"; }; |
512 | 512 |
A69FFAA91E7004700006FEE0 /* PhotoPreviewViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhotoPreviewViewController.swift; sourceTree = "<group>"; }; |
513 | 513 |
A69FFAAB1E7004700006FEE0 /* GroupViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GroupViewController.swift; sourceTree = "<group>"; }; |
@@ -1489,6 +1489,7 @@ |
||
1489 | 1489 |
developmentRegion = English; |
1490 | 1490 |
hasScannedForEncodings = 0; |
1491 | 1491 |
knownRegions = ( |
1492 |
+ English, |
|
1492 | 1493 |
en, |
1493 | 1494 |
Base, |
1494 | 1495 |
global, |
@@ -158,15 +158,15 @@ class NetworkApi { |
||
158 | 158 |
} |
159 | 159 |
|
160 | 160 |
//extension request retrier |
161 |
-extension NetworkApi { |
|
162 |
- public struct OAuthHandler: RequestRetrier { |
|
163 |
- init() {} |
|
164 |
- public func should(_ manager: Session, retry request: Request, with error: Error, completion: @escaping RequestRetryCompletion) { |
|
165 |
- if let response = request.response, response.statusCode == 401 { |
|
166 |
- completion(true, 1.0) // 1秒后重试 |
|
167 |
- } else { |
|
168 |
- completion(false, 0.0) // 不重连 |
|
169 |
- } |
|
170 |
- } |
|
171 |
- } |
|
172 |
-} |
|
161 |
+//extension NetworkApi { |
|
162 |
+// public struct OAuthHandler: RequestRetrier { |
|
163 |
+// init() {} |
|
164 |
+// public func should(_ manager: Session, retry request: Request, with error: Error, completion: @escaping RequestRetryCompletion) { |
|
165 |
+// if let response = request.response, response.statusCode == 401 { |
|
166 |
+// completion(true, 1.0) // 1秒后重试 |
|
167 |
+// } else { |
|
168 |
+// completion(false, 0.0) // 不重连 |
|
169 |
+// } |
|
170 |
+// } |
|
171 |
+// } |
|
172 |
+//} |
@@ -13,6 +13,11 @@ import PaiaiUIKit |
||
13 | 13 |
final class ImageCell: UICollectionViewCell, UIScrollViewDelegate { |
14 | 14 |
@IBOutlet weak var scrollView: UIScrollView! |
15 | 15 |
var photoImage = UIImageView() |
16 |
+ |
|
17 |
+ private var angle: CGFloat = 0 |
|
18 |
+ private var scale: CGFloat = 1 |
|
19 |
+ private var scaleRatio: CGFloat = 1 |
|
20 |
+ private var aspectFitSize = CGSize.zero |
|
16 | 21 |
|
17 | 22 |
func setModel(url: String) { |
18 | 23 |
photoImage.frame = CGRect(x: 0, y: 0, width: width, height: height) |
@@ -57,9 +62,44 @@ final class ImageCell: UICollectionViewCell, UIScrollViewDelegate { |
||
57 | 62 |
scrollView.zoom(to: zoomRect, animated: true) |
58 | 63 |
} |
59 | 64 |
} |
60 |
- |
|
65 |
+ |
|
61 | 66 |
override func prepareForReuse() { |
62 | 67 |
super.prepareForReuse() |
63 | 68 |
scrollView.zoomScale = 1 |
69 |
+ clearRotation() |
|
70 |
+ } |
|
71 |
+ |
|
72 |
+ func rotate() { |
|
73 |
+ if let imageSize = photoImage.image?.size, |
|
74 |
+ aspectFitSize == CGSize.zero { |
|
75 |
+ let ratio = size.width / imageSize.width |
|
76 |
+ aspectFitSize = CGSize(width: size.width, height: ratio * imageSize.height) |
|
77 |
+ scaleRatio = size.width / aspectFitSize.height |
|
78 |
+ } |
|
79 |
+ |
|
80 |
+ let animation1 = CABasicAnimation(keyPath: "transform.rotation.z") |
|
81 |
+ animation1.fromValue = angle |
|
82 |
+ animation1.toValue = angle + CGFloat.pi * 0.5 |
|
83 |
+ |
|
84 |
+ let animation2 = CABasicAnimation(keyPath: "transform.scale") |
|
85 |
+ let (toScale, fromScale) = scale == 1 ? (scaleRatio, 1) : (1, scaleRatio) |
|
86 |
+ animation2.fromValue = CGPoint(x: fromScale, y: fromScale) |
|
87 |
+ animation2.toValue = CGPoint(x: toScale, y: toScale) |
|
88 |
+ |
|
89 |
+ |
|
90 |
+ let animationGroup = CAAnimationGroup() |
|
91 |
+ animationGroup.animations = [animation1, animation2] |
|
92 |
+ animationGroup.duration = 0.5 |
|
93 |
+ animationGroup.fillMode = .forwards |
|
94 |
+ animationGroup.isRemovedOnCompletion = false |
|
95 |
+ photoImage.layer.add(animationGroup, forKey: "") |
|
96 |
+ |
|
97 |
+ angle += CGFloat.pi * 0.5 |
|
98 |
+ scale = toScale |
|
99 |
+ } |
|
100 |
+ |
|
101 |
+ func clearRotation() { |
|
102 |
+ angle = 0 |
|
103 |
+ scale = 1 |
|
64 | 104 |
} |
65 | 105 |
} |
@@ -54,6 +54,7 @@ final class PhotoPreviewViewController: UIViewController { |
||
54 | 54 |
Toast.show(message: "已保存照片到相册中", image: UIImage(named: "icon-success")) |
55 | 55 |
} |
56 | 56 |
} |
57 |
+ var angle: CGFloat = 0 |
|
57 | 58 |
} |
58 | 59 |
|
59 | 60 |
/// binding |
@@ -100,22 +101,7 @@ extension PhotoPreviewViewController { |
||
100 | 101 |
guard let cell = collectionView.cellForItem(at: IndexPath(item: viewModel.currIndex, section: 0)) as? ImageCell else { |
101 | 102 |
return |
102 | 103 |
} |
103 |
- UIView.beginAnimations("image.rotate", context: nil) |
|
104 |
- UIView.animate(withDuration: 0.5) { |
|
105 |
- let image = cell.photoImage.image |
|
106 |
- switch image?.imageOrientation.rawValue { |
|
107 |
- case .some(0): |
|
108 |
- cell.photoImage.image = UIImage(cgImage: (image?.cgImage)!, scale: UIScreen.main.scale, orientation: UIImage.Orientation.right) |
|
109 |
- case .some(1): |
|
110 |
- cell.photoImage.image = UIImage(cgImage: (image?.cgImage)!, scale: UIScreen.main.scale, orientation: UIImage.Orientation.left) |
|
111 |
- case .some(2): |
|
112 |
- cell.photoImage.image = UIImage(cgImage: (image?.cgImage)!, scale: UIScreen.main.scale, orientation: UIImage.Orientation.up) |
|
113 |
- case .some(3): |
|
114 |
- cell.photoImage.image = UIImage(cgImage: (image?.cgImage)!, scale: UIScreen.main.scale, orientation: UIImage.Orientation.down) |
|
115 |
- default: |
|
116 |
- break |
|
117 |
- } |
|
118 |
- } |
|
104 |
+ cell.rotate() |
|
119 | 105 |
} |
120 | 106 |
|
121 | 107 |
@IBAction func download(_ sender: UIButton) { |