質問編集履歴

2

修正・追加

2017/02/23 00:29

投稿

Nefytus
Nefytus

スコア12

test CHANGED
File without changes
test CHANGED
@@ -80,6 +80,340 @@
80
80
 
81
81
 
82
82
 
83
+ 教えていただいたように一番下の部分に追加したところ、19個用意した音声ファイルが複数回選択され、全部で189個のキューが自動で設定されるようになりました。
84
+
85
+ これについては、for文の部分で回数の設定などを行うことで19個のキューにすることができるのでしょうか?
86
+
87
+
88
+
89
+ ```Swift
90
+
91
+ class PlayerViewController: UIViewController, UICollectionViewDataSource {
92
+
93
+ static let assetKeysRequiredToPlay = [
94
+
95
+ "playable",
96
+
97
+ "hasProtectedContent"
98
+
99
+ ]
100
+
101
+
102
+
103
+ let player = AVQueuePlayer()
104
+
105
+
106
+
107
+ var currentTime: Double {
108
+
109
+ get {
110
+
111
+ return CMTimeGetSeconds(player.currentTime())
112
+
113
+ }
114
+
115
+
116
+
117
+ set {
118
+
119
+ let newTime = CMTimeMakeWithSeconds(newValue, 1)
120
+
121
+ player.seek(to: newTime, toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero)
122
+
123
+ }
124
+
125
+ }
126
+
127
+
128
+
129
+ var duration: Double {
130
+
131
+ guard let currentItem = player.currentItem else { return 0.0 }
132
+
133
+
134
+
135
+ return CMTimeGetSeconds(currentItem.duration)
136
+
137
+ }
138
+
139
+
140
+
141
+ var rate: Float {
142
+
143
+ get {
144
+
145
+ return player.rate
146
+
147
+ }
148
+
149
+
150
+
151
+ set {
152
+
153
+ player.rate = newValue
154
+
155
+ }
156
+
157
+ }
158
+
159
+
160
+
161
+ var playerLayer: AVPlayerLayer? {
162
+
163
+ return playerView.playerLayer
164
+
165
+ }
166
+
167
+
168
+
169
+ /*
170
+
171
+ A formatter for individual date components used to provide an appropriate
172
+
173
+ value for the `startTimeLabel` and `durationLabel`.
174
+
175
+ */
176
+
177
+ let timeRemainingFormatter: DateComponentsFormatter = {
178
+
179
+ let formatter = DateComponentsFormatter()
180
+
181
+ formatter.zeroFormattingBehavior = .pad
182
+
183
+ formatter.allowedUnits = [.minute, .second]
184
+
185
+
186
+
187
+ return formatter
188
+
189
+ }()
190
+
191
+
192
+
193
+ var timeObserverToken: Any?
194
+
195
+
196
+
197
+ var assetTitlesAndThumbnails: [URL: (title: String, thumbnail: UIImage)] = [:]
198
+
199
+
200
+
201
+ var loadedAssets = [String: AVURLAsset]()
202
+
203
+
204
+
205
+ @IBOutlet weak var timeSlider: UISlider!
206
+
207
+ @IBOutlet weak var startTimeLabel: UILabel!
208
+
209
+ @IBOutlet weak var durationLabel: UILabel!
210
+
211
+ @IBOutlet weak var rewindButton: UIButton!
212
+
213
+ @IBOutlet weak var playPauseButton: UIButton!
214
+
215
+ @IBOutlet weak var fastForwardButton: UIButton!
216
+
217
+ @IBOutlet weak var clearButton: UIButton!
218
+
219
+ @IBOutlet weak var collectionView: UICollectionView!
220
+
221
+ @IBOutlet weak var queueLabel: UILabel!
222
+
223
+ @IBOutlet weak var playerView: PlayerView!
224
+
225
+
226
+
227
+ override func viewWillAppear(_ animated: Bool) {
228
+
229
+ super.viewWillAppear(animated)
230
+
231
+
232
+
233
+
234
+
235
+ addObserver(self, forKeyPath: #keyPath(PlayerViewController.player.currentItem.duration), options: [.new, .initial], context: &playerViewControllerKVOContext)
236
+
237
+ addObserver(self, forKeyPath: #keyPath(PlayerViewController.player.rate), options: [.new, .initial], context: &playerViewControllerKVOContext)
238
+
239
+ addObserver(self, forKeyPath: #keyPath(PlayerViewController.player.currentItem.status), options: [.new, .initial], context: &playerViewControllerKVOContext)
240
+
241
+ addObserver(self, forKeyPath: #keyPath(PlayerViewController.player.currentItem), options: [.new, .initial], context: &playerViewControllerKVOContext)
242
+
243
+
244
+
245
+ playerView.playerLayer.player = player
246
+
247
+
248
+
249
+ let manifestURL = Bundle.main.url(forResource: "MediaManifest", withExtension: "json")!
250
+
251
+ asynchronouslyLoadURLAssetsWithManifestURL(jsonURL: manifestURL)
252
+
253
+
254
+
255
+ let interval = CMTimeMake(1, 1)
256
+
257
+ timeObserverToken = player.addPeriodicTimeObserver(forInterval: interval, queue: DispatchQueue.main) { [unowned self] time in
258
+
259
+ let timeElapsed = Float(CMTimeGetSeconds(time))
260
+
261
+
262
+
263
+ self.timeSlider.value = Float(timeElapsed)
264
+
265
+ self.startTimeLabel.text = self.createTimeString(time: timeElapsed)
266
+
267
+ }
268
+
269
+
270
+
271
+ }
272
+
273
+
274
+
275
+ override func viewDidDisappear(_ animated: Bool) {
276
+
277
+ super.viewDidDisappear(animated)
278
+
279
+
280
+
281
+ if let timeObserverToken = timeObserverToken {
282
+
283
+ player.removeTimeObserver(timeObserverToken)
284
+
285
+ self.timeObserverToken = nil
286
+
287
+ }
288
+
289
+
290
+
291
+ player.pause()
292
+
293
+
294
+
295
+ removeObserver(self, forKeyPath: #keyPath(PlayerViewController.player.currentItem.duration), context: &playerViewControllerKVOContext)
296
+
297
+ removeObserver(self, forKeyPath: #keyPath(PlayerViewController.player.rate), context: &playerViewControllerKVOContext)
298
+
299
+ removeObserver(self, forKeyPath: #keyPath(PlayerViewController.player.currentItem.status), context: &playerViewControllerKVOContext)
300
+
301
+ removeObserver(self, forKeyPath: #keyPath(PlayerViewController.player.currentItem), context: &playerViewControllerKVOContext)
302
+
303
+ }
304
+
305
+
306
+
307
+ func asynchronouslyLoadURLAsset(asset: AVURLAsset, title: String, thumbnailResourceName: String) {
308
+
309
+
310
+
311
+ asset.loadValuesAsynchronously(forKeys: PlayerViewController.assetKeysRequiredToPlay) {
312
+
313
+
314
+
315
+
316
+
317
+ DispatchQueue.main.async() {
318
+
319
+
320
+
321
+
322
+
323
+
324
+
325
+ for key in PlayerViewController.assetKeysRequiredToPlay {
326
+
327
+ var error: NSError?
328
+
329
+
330
+
331
+ if asset.statusOfValue(forKey: key, error: &error) == .failed {
332
+
333
+ let stringFormat = NSLocalizedString("error.asset_%@_key_%@_failed.description", comment: "Can't use this AVAsset because one of it's keys failed to load")
334
+
335
+
336
+
337
+ let message = String.localizedStringWithFormat(stringFormat, title, key)
338
+
339
+
340
+
341
+ self.handleError(with: message, error: error)
342
+
343
+
344
+
345
+ return
346
+
347
+ }
348
+
349
+ }
350
+
351
+
352
+
353
+
354
+
355
+ if !asset.isPlayable || asset.hasProtectedContent {
356
+
357
+ let stringFormat = NSLocalizedString("error.asset_%@_not_playable.description", comment: "Can't use this AVAsset because it isn't playable or has protected content")
358
+
359
+
360
+
361
+ let message = String.localizedStringWithFormat(stringFormat, title)
362
+
363
+
364
+
365
+ self.handleError(with: message)
366
+
367
+
368
+
369
+ return
370
+
371
+ }
372
+
373
+
374
+
375
+
376
+
377
+ self.loadedAssets[title] = asset
378
+
379
+
380
+
381
+ let name = (thumbnailResourceName as NSString).deletingPathExtension
382
+
383
+ let type = (thumbnailResourceName as NSString).pathExtension
384
+
385
+ let path = Bundle.main.path(forResource: name, ofType: type)!
386
+
387
+
388
+
389
+ let thumbnail = UIImage(contentsOfFile: path)!
390
+
391
+
392
+
393
+ self.assetTitlesAndThumbnails[asset.url] = (title, thumbnail)
394
+
395
+
396
+
397
+ for (loadedAssetTitle, loadedAsset) in self.loadedAssets {
398
+
399
+ let newPlayerItem = AVPlayerItem(asset: loadedAsset)
400
+
401
+ self.player.insert(newPlayerItem, after: nil)
402
+
403
+ }
404
+
405
+
406
+
407
+ }
408
+
409
+ }
410
+
411
+ }
412
+
413
+ ```
414
+
415
+
416
+
83
417
 
84
418
 
85
419
  よろしくお願いいたします。

1

修正

2017/02/23 00:29

投稿

Nefytus
Nefytus

スコア12

test CHANGED
File without changes
test CHANGED
@@ -10,4 +10,76 @@
10
10
 
11
11
  アプリ起動後、再生ボタンを押すとセットされた音声ファイルが再生されるようにしたいです。
12
12
 
13
+
14
+
15
+ 以下にある、addItemのボタンの機能を参考にするのかと考えていますが、自動で全音声ファイルをキューに加える方法が分からず、質問させていただきました。
16
+
17
+ ```Swift
18
+
19
+ @IBAction func addItemToQueueButtonPressed(_ sender: UIButton) {
20
+
21
+ let alertTitle = NSLocalizedString("popover.title.addItem", comment: "Title of popover that adds items to the queue")
22
+
23
+
24
+
25
+ let alertMessage = NSLocalizedString("popover.message.addItem", comment: "Message on popover that adds items to the queue")
26
+
27
+
28
+
29
+ let alertController = UIAlertController(title: alertTitle, message: alertMessage, preferredStyle: .actionSheet)
30
+
31
+
32
+
33
+ // Populate the sheet with the titles of the assets we have loaded.
34
+
35
+ for (loadedAssetTitle, loadedAsset) in loadedAssets {
36
+
37
+ let alertAction = UIAlertAction(title:loadedAssetTitle, style: .default) { [unowned self] alertAction in
38
+
39
+ let oldItems = self.player.items()
40
+
41
+
42
+
43
+ let newPlayerItem = AVPlayerItem(asset: loadedAsset)
44
+
45
+
46
+
47
+ self.player.insert(newPlayerItem, after: nil)
48
+
49
+
50
+
51
+ self.queueDidChangeWithOldPlayerItems(oldPlayerItems: oldItems, newPlayerItems: self.player.items())
52
+
53
+ }
54
+
55
+
56
+
57
+ alertController.addAction(alertAction)
58
+
59
+ }
60
+
61
+
62
+
63
+ let cancelActionTitle = NSLocalizedString("popover.title.cancel", comment: "Title of popover cancel action")
64
+
65
+
66
+
67
+ let cancelAction = UIAlertAction(title: cancelActionTitle, style: .cancel, handler: nil)
68
+
69
+
70
+
71
+ alertController.addAction(cancelAction)
72
+
73
+
74
+
75
+ presentModalPopoverAlertController(alertController: alertController, sender: sender)
76
+
77
+ }
78
+
79
+ ```
80
+
81
+
82
+
83
+
84
+
13
85
  よろしくお願いいたします。