As a podcast audioence
I want the app to automatically load the lastest podcast epiosde
So I can always enjoy the newest feed of the channel
Given the audioence has connectivity
When the audioence requests to see the channel feed
Then the app should display the latest feed from remote
- URL
- Execute ‘func load’ and with data above.
- System download data with URL
- System validates downloading data
- System creates channel feed for validate data
- System deliver channel feed
System delivers invalidate data error
System delivers connectivity error
Property | Type |
---|---|
profileImage |
URL(optional) |
episodes |
[Episode] |
Property | Type |
---|---|
coverImage |
URL(optional) |
title |
String(optional) |
description |
String |
releaseDate |
String |
soundURL |
URL(optional) |
<channel>
<image>
<url>https://i1.sndcdn.com/avatars-000326154119-ogb1ma-original.jpg</url>
</image>
<item>
<guid isPermaLink="false">tag:soundcloud,2010:tracks/1000284829</guid>
<title>Ep. 135 流動的資金盛宴</title>
<pubDate>Sun, 07 Mar 2021 22:00:12 +0000</pubDate>
<description>現代金融理論加上現代科技,解放資本,將所有人捲入投資市場。人們有更多資訊、投資對象,以及比較的對象。就像手機讓人們滑臉書欲罷不能,閒不下來;科技也讓人們追逐投資報酬率,無法接受資本「閒置」。看似更有效率的市場背後,是更大的風險。
主題文章:博弈、科技與投資自己之必要
https://bit.ly/2MSu8Qk
首月一元訂閱,即可看網站全文
bit.ly/37Yi4D4</description>
<enclosure type="audio/mpeg" url="https://feeds.soundcloud.com/stream/1000284829-daodutech-podcast-a-liquid-feast-of-capital.mp3" length="60557439"/>
<itunes:image href="https://i1.sndcdn.com/artworks-Z7zJRFuDjv63KCHv-5W8whA-t3000x3000.jpg"/>
</item>
As a podcast audioence
I want to look into selected episode's description
So I can learn more about the topic and project
- array of
Episode
Int
1.Load episode
2.Kingfisher
load episode coverImage with URL
3.Render UI component with episode
System delivers invalid data error
Kingfisher
displays placeholder on UIImageView
Transfer to player page
As an audience who already peruse episode's summary
Finally decided to listen to the content
The app should be able to let me play the podcast
- URL
https://xxx.sound.mp3
1.AVPlayerItem load url, and the url is valid
2.AVPlayerItem is ready to play
3.AVPlayer play the audio
System doesn't play the audio
1.AVPlayerItem is ready to play
2.AVPlayer play the audio
System doesn't play the audio
- AVPlayerItem is ready to play
- AVPlayer pause the audio
- Input:
[Episode]
, Int - Output:
Result<( Episode, URL), Error>
- Execute ‘func loadEpisode’
- PlayerModel retrieve episode and URL for Controller
- Render interface with episode
- AudioPlayer load sound URL
- AVPlayerItem is read to play
- AVPlayer start to play
System delivers index out of range error
System delivers sound URL is missing error
- Double
public final class AVPlayerManager {
private var player:AVPlayer?
private var timeObserver: Any?
private var isSeekInProgress = false
private var chaseTime: CMTime = .zero
- AVPlayer currentItem's duration is not nil
- Convert slider value to total second
- Convert sldier value, the process is shown as below:
if let duration = player?.currentItem?.duration {
let totalSecond = CMTimeGetSeconds(duration)
let value = (sliderValue) * Float(totalSecond)
let seekTime = CMTime(value: CMTimeValue(value), timescale: 1)
}
- Execute
func stopPlayingAndSeekSmoothlyToTime(newChaseTime:)
- Pause AVPlayer
- Compare
currentChaseTime
withnewChaseTime
if CMTimeCompare(newChaseTime, chaseTime) != 0 {
chaseTime = newChaseTime
if !isSeekInProgress {
trySeekToChaseTime()
}
}
- Check statement
isSeekInProgress
if !isSeekInProgress {
trySeekToChaseTime()
}
- Check AVPlayer currentItem's status.
if status == .unknown {
// wait until item becomes ready
} else if status == .readyToPlay {
actuallySeekToTime()
}
isSeekInProgress = true
let seekTimeInProgress = chaseTime
- Execute
AVPlayer.seekseek(to: seekTimeInProgress, toleranceBefore: .zero, toleranceAfter: .zero, completion:)
- Execute
CMTimeCompare(seekTimeInProgress, self.chaseTime)
if CMTimeCompare(seekTimeInProgress, self.chaseTime) == 0 {
self.isSeekInProgress = false
} else {
self.trySeekToChaseTime()
}
- notify PlayerViewController to update