bug fixes & download improvement

master
Bill 2 years ago
parent 78760740a2
commit 740f63d0d6

@ -10,96 +10,216 @@ import Network
import AVFoundation import AVFoundation
import UIKit import UIKit
class IDStr : Identifiable { class TrackInfo : NSObject, Identifiable, ObservableObject {
var s : String = "" @Published var s : String = ""
var art : Image? @Published var art : Image? = nil
var m : AVPlayerItem? @Published var m : AVPlayerItem? = nil
init () {self.m = nil} @Published var changed = false
var cv : ContentView? = nil
override init() {
super.init()
}
init (str : String, music : AVPlayerItem) { init (str : String, music : AVPlayerItem) {
self.s = str self.s = str
self.m = music self.m = music
} }
func equals_to (other: TrackInfo) -> Bool {
return self.m == other.m
}
func from(other : TrackInfo) {
self.s = other.s
self.art = other.art
self.m = other.m
self.changed = !self.changed
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if (change![.newKey] is NSNull) {
self.changed = !self.changed
return
}
if let cv = self.cv {
if let idx = cv.music.music.firstIndex(where: { s in
change![.newKey] as? AVPlayerItem == s.m
}){
self.from(other: cv.music.music[idx])
cv.update_pbv(idx: idx)
}
}
}
} }
class ListViewModel: ObservableObject { class ListViewModel: ObservableObject {
@Published var music = Array<IDStr>() @Published var music = Array<TrackInfo>()
func addItem(i : String, m : AVPlayerItem) { func addItem(i : String, m : AVPlayerItem) {
music.append(IDStr(str: i, music: m)) music.append(TrackInfo(str: i, music: m))
} }
func addItem(str : IDStr) { func addItem(str : TrackInfo) {
music.append(str) music.append(str)
} }
} }
class PlaybackViewProxy { class PlaybackViewProxy {
var pbv : PlaybackView var pbv : PlaybackView
init(v : PlaybackView) { var tabpbv : PlaybackView
init() {
pbv = PlaybackView()
tabpbv = PlaybackView()
}
init(v : PlaybackView, tabpbv: PlaybackView) {
self.pbv = v self.pbv = v
self.tabpbv = tabpbv
} }
} }
struct ContentView: View { struct ContentView: View {
@ObservedObject var music = ListViewModel() @ObservedObject var music = ListViewModel()
@ObservedObject var nowplaying : TrackInfo
@State var pushState = false @State var pushState = false
@State var geo :CGSize = .zero @State var geo:CGSize = .zero
@State var _curr_sel_music : IDStr = IDStr() @State var active = false
let pbv : PlaybackViewProxy //@State var _curr_sel_music : TrackInfo = TrackInfo()
var body: some View { var pbv : PlaybackViewProxy
GeometryReader { geometry in var dir: String
NavigationView(){
List() { func update_pbv(idx: Int) {
ForEach(music.music) { m in let m = music.music[idx]
VStack(){
Button(m.s, action: {
let idx = music.music.firstIndex { s in
s.s == m.s
}
if (idx != nil) {
if (idx != 0) { if (idx != 0) {
music.music = Array(music.music[idx! ... (music.music.endIndex - 1)] + music.music[0...idx! - 1]) music.music = Array(music.music[idx ... (music.music.endIndex - 1)] + music.music[0...idx - 1])
self.player?.removeAllItems() self.player.removeAllItems()
for i in music.music { for i in music.music {
i.m!.seek(to: .zero) i.m!.seek(to: .zero)
player?.insert(i.m!, after: nil) player.insert(i.m!, after: nil)
} }
} }
else { else {
m.m!.seek(to: .zero) m.m!.seek(to: CMTime(value: 1, timescale: 10000))
} }
//if !m.equals_to(other: self.nowplaying) {
if (self.active) {
self.pbv.tabpbv.update(music: m)
}
else {
self.pbv.pbv.update(music: m)
} }
self._curr_sel_music = m
self.pbv.pbv.update(music: _curr_sel_music)
pushState = true
}).ignoresSafeArea(.all).cornerRadius(.zero).padding(.zero).frame(maxHeight: CGFloat(50)).foregroundColor(.white)
NavigationLink(destination: self.pbv.pbv, isActive: $pushState) {
EmptyView()
} }
func update_pbv(m: TrackInfo) {
if let idx = music.music.firstIndex(where: { s in s.s == m.s }){
self.update_pbv(idx: idx)
}
}
var body: some View {
NavigationStack {
TabView {
GeometryReader { geometry in
List() {
ForEach(music.music) { m in
VStack(){
NavigationLink(m.s, value: m)
.ignoresSafeArea(.all)
.cornerRadius(.zero)
.padding(.zero)
.frame(maxHeight: CGFloat(50))
.foregroundColor(.white)
} }
} }
Label("\(music.music.count) Files. ", systemImage: "heart.fill").background(.clear).labelStyle(.titleAndIcon).frame(width: geometry.size.width, alignment: .center) Label("\(music.music.count) Files. ", systemImage: "heart.fill").background(.clear).labelStyle(.titleAndIcon).frame(width: geometry.size.width, alignment: .center)
} }
}.onAppear { .navigationTitle("Songs")
.navigationBarBackButtonHidden(false)
.onAppear {
self.active = true
geo = geometry.size geo = geometry.size
self.pbv.pbv.parent = self self.pbv.tabpbv.update(music: self.nowplaying)
}
}.navigationDestination(for: TrackInfo.self) { m in
{
m -> PlaybackView in
if self.active {
self.active = false
update_pbv(m:m)
}
self.pbv.tabpbv.trackInfo.m = nil
return self.pbv.pbv
} (m)
}.navigationBarBackButtonHidden(false)
.toolbar(.visible, for: .navigationBar)
self.pbv.tabpbv
} }
} }
} }
var player : AVQueuePlayer? = nil var player : AVQueuePlayer
func add_music (filename: String) {
let file_url = URL(filePath: dir + "/Documents/" + filename)
let asset = AVAsset(url: file_url)
let track = TrackInfo()
asset.loadMetadata(for: .iTunesMetadata) {
items, b in
if (items == nil) { return }
for i in items! {
if(i.identifier == .iTunesMetadataCoverArt) {
Task{
let imageData = try await i.load(.dataValue)
track.art = Image(uiImage: UIImage(data: imageData!)!)
/*if (track.art != nil) {
track.art!.resizable().scaledToFill().frame(width: geo.width, height: geo.height)
}*/
}
}
}
}
let item = AVPlayerItem(url: file_url)
track.s = filename.prefix(filename.count - 4).removingPercentEncoding!
track.m = item
self.music.addItem(str: track)
//item.addObserver(self, forKeyPath: "status", context: nil)
self.player.insert(item, after: nil)
if (self.player.status == .failed) {
print(self.player.error!)
}
else {
//self.player.play()
}
}
init() { init() {
self.pbv = PlaybackViewProxy(v: PlaybackView()) self.pbv = PlaybackViewProxy()
let base = "https://billsun.dev/webdav/music-test" let base = "https://billsun.dev/webdav/music-test"
let url = URL(string: base) let url = URL(string: base)
let request: URLRequest = URLRequest(url: url!) var request: URLRequest = URLRequest(url: url!)
let session = URLSession(configuration: .default) let session = URLSession(configuration: .default)
let dir = NSHomeDirectory() self.dir = NSHomeDirectory()
let dir = self.dir
do {
let session = AVAudioSession.sharedInstance()
try session.setCategory(AVAudioSession.Category.playback)
} catch {
print(error)
}
self.player = AVQueuePlayer()
self.nowplaying = TrackInfo()
self.nowplaying.cv = self
self.pbv.pbv.parent = self
self.pbv.tabpbv.parent = self
self.player.audiovisualBackgroundPlaybackPolicy = .continuesIfPossible
self.player.addObserver(self.nowplaying, forKeyPath: "currentItem",options: [.old, .new], context: &self)
session.dataTask(with: request, completionHandler: session.dataTask(with: request, completionHandler:
{ (data, response, error) -> Void in { [self] (data, response, error) -> Void in
if (error != nil) { return } if (error != nil) { return }
let reply = String(data: data!, encoding: String.Encoding.utf8)! let reply = String(data: data!, encoding: String.Encoding.utf8)!
@ -131,66 +251,58 @@ struct ContentView: View {
check_file(filepath) check_file(filepath)
check_file("\(dir)/Documents/\(_file)") check_file("\(dir)/Documents/\(_file)")
if (download) { if (download) {
session.dataTask(with: URLRequest(url: URL(string: base + "/" + _file)!)) { var tries = 16
(data, response, error) -> Void in /*
func try_save_response (data: Data?, response: URLResponse?, error: Error?) -> Void {
if (error == nil) { if (error == nil) {
let fp = fopen(filepath, "wb") let fp = fopen(filepath, "wb")
data!.withUnsafeBytes({ ptr in data!.withUnsafeBytes({ ptr in
fwrite(ptr, 1, data!.count, fp) fwrite(ptr, 1, data!.count, fp)
}) })
fclose(fp) fclose(fp)
add_music(filename: file)
} }
}.resume() else {
} if (tries > 0) {
} tries -= 1
}catch{} session.dataTask(with: URLRequest(url: URL(string: base + "/" + _file)!, timeoutInterval: TimeInterval(100000 * (5 - tries))), completionHandler: try_save_response).resume()
}
).resume()
let enumerator = FileManager.default.enumerator(atPath: dir + "/Documents/")
enumerator!.forEach({ e in
if (self.player == nil) {
do {
let session = AVAudioSession.sharedInstance()
try session.setCategory(AVAudioSession.Category.playback)
} catch {
print(error)
} }
self.player = AVQueuePlayer()
} }
let filename = (e as! String)
let file_url = URL(filePath: dir + "/Documents/" + filename)
let asset = AVAsset(url: file_url)
let idstr = IDStr()
let geo = self.geo
asset.loadMetadata(for: .iTunesMetadata) {
items, b in
if (items == nil) { return }
for i in items! {
if(i.identifier == .iTunesMetadataCoverArt) {
Task{
let imageData = try await i.load(.dataValue)
idstr.art = Image(uiImage: UIImage(data: imageData!)!)
/*if (idstr.art != nil) {
idstr.art!.resizable().scaledToFill().frame(width: geo.width, height: geo.height)
}*/ }*/
var req = URLRequest(url: URL(string: base + "/" + _file)!, timeoutInterval: 65536)
func try_download (u: URL?, r: URLResponse?, e: Error?) -> Void { // use download to avoid memory overflow
if (e == nil) {
do {
try FileManager.default.moveItem(at: u!, to: URL(filePath: filepath))
} catch { print(error) }
add_music(filename: file)
} else if (tries > 0) {
tries -= 1
if let e = e as? NSError,
let data = e.userInfo[NSURLSessionDownloadTaskResumeData] as? Data {
session.downloadTask(withResumeData: data, completionHandler: try_download).resume()
} }
else {
session.downloadTask(with: req, completionHandler: try_download).resume()
} }
} }
} }
let item = AVPlayerItem(url: file_url) session.downloadTask(with: req, completionHandler: try_download).resume()
idstr.s = filename.prefix(filename.count - 4).removingPercentEncoding!
idstr.m = item
self.music.addItem(str: idstr)
//item.addObserver(self, forKeyPath: "status", context: nil)
self.player?.insert(item, after: nil)
if (self.player?.status == .failed) {
print(self.player!.error!) //session.dataTask(with: URLRequest(url: URL(string: base + "/" + _file)!, timeoutInterval: TimeInterval(65535)), completionHandler: try_save_response).resume()
} }
else {
self.player?.play()
} }
}) }catch{}
}
).resume()
let enumerator = FileManager.default.enumerator(atPath: dir + "/Documents/")
enumerator!.forEach({ e in add_music(filename: (e as! String))})
self.pbv.pbv.update(music: self.nowplaying)
self.pbv.tabpbv.update(music: self.nowplaying)
} }
} }

@ -13,7 +13,14 @@ struct MusicPlayer_Watch_AppApp: App {
var body: some Scene { var body: some Scene {
WindowGroup { WindowGroup {
ContentView().cornerRadius(.zero).padding(.zero) ContentView().cornerRadius(.zero)
.padding(.zero)
.frame(
width: WKInterfaceDevice.current().screenBounds.width,
height: WKInterfaceDevice.current().screenBounds.height
).tabItem {
Image(systemName: "circle.fill")
}
} }
} }

@ -8,42 +8,68 @@
import SwiftUI import SwiftUI
import UIKit import UIKit
class AppearTimer : ObservableObject {
@Published var appear = false
var timeout = 0
let lock : NSLock = NSLock()
func appear(time: Int = 5, _appear: Bool = false) {
self.lock.lock()
self.timeout = self.timeout + time
self.appear = timeout > 0
DispatchQueue.main.asyncAfter(deadline: .now().advanced(by: .seconds(time)),
execute: {
self.lock.lock()
self.timeout -= time
self.appear = self.timeout > 0
self.lock.unlock()
}
)
self.lock.unlock()
}
}
struct PlaybackView: View {
var placeholder: Image? = nil struct PlaybackView: View {
var music : IDStr? = nil //var music : TrackInfo? = nil
var parent : ContentView? = nil var parent : ContentView? = nil
//@ObservedObject var timeout = Timeout(timeout: 5) //@ObservedObject var timeout = Timeout(timeout: 5)
var title = "" var title = ""
@State var playing = true @State var playing = true
@State private var appearSelf = true @State private var appearSelf = 3
@ObservedObject var appearTimer = AppearTimer()
@ObservedObject var trackInfo : TrackInfo = TrackInfo()
var body: some View { var body: some View {
if parent != nil { if trackInfo.m != nil {
GeometryReader { geo in GeometryReader { geo in
ZStack { ZStack {
if(placeholder == nil) { if(trackInfo.art == nil) {
Image(systemName: "square")
Image(systemName: "music.note")
.resizable() .resizable()
.scaledToFill() .scaledToFit()
.foregroundColor(.black) .foregroundColor(.white)
.frame(width: geo.size.width*0.84, height: geo.size.height*0.84)
.padding(.leading, geo.size.width*0.08)
.padding(.top, geo.size.height*0.08)
} }
else { else {
placeholder!.resizable().scaledToFill() trackInfo.art!.resizable().scaledToFill()
} }
if (appearSelf) if (appearTimer.appear)
{ {
NavigationView{ VStack {
VStack{ HStack {
HStack{
Button { Button {
if ( parent!.player!.timeControlStatus == .playing ) { if ( parent!.player.timeControlStatus == .playing ) {
parent!.player!.pause() parent!.player.pause()
self.playing = false self.playing = false
} else { } else {
parent!.player!.play() parent!.player.play()
self.playing = true self.playing = true
} }
} label: { } label: {
@ -62,10 +88,10 @@ struct PlaybackView: View {
.opacity(1) .opacity(1)
.buttonStyle(.plain) .buttonStyle(.plain)
Button { Button {
let curr = parent!.player!.currentItem let curr = parent!.player.currentItem
parent!.player!.advanceToNextItem() parent!.player.advanceToNextItem()
curr!.seek(to: .zero) curr!.seek(to: .zero)
parent!.player!.play() parent!.player.play()
self.playing = true self.playing = true
} label : { } label : {
Image(systemName: "chevron.forward") Image(systemName: "chevron.forward")
@ -80,38 +106,31 @@ struct PlaybackView: View {
.opacity(1) .opacity(1)
.buttonStyle(.plain) .buttonStyle(.plain)
} }
}.onAppear(){ }
DispatchQueue.main.asyncAfter(deadline: .now() + 3, execute: {
appearSelf = false
})
}.navigationTitle("\(self.title)")
}.opacity(0.65).navigationBarBackButtonHidden(false)
} }
}.onTapGesture { }.onTapGesture {
appearSelf = true appearTimer.appear()
DispatchQueue.main.asyncAfter(deadline: .now() + 5, execute: {
appearSelf = false
})
} }
}.navigationBarBackButtonHidden(false)
.toolbar(.visible, for: .navigationBar)
.onAppear() {
appearTimer.appear(time: 3, _appear: true)
} }
} }
} }
init() { } init() { }
init(parent:ContentView, music: IDStr? = nil) { init(parent:ContentView, music: TrackInfo? = nil) {
if music != nil && music!.art != nil { if music != nil && music!.art != nil {
self.placeholder = music!.art!
self.music = music
self.parent = parent self.parent = parent
self.playing = parent.player!.timeControlStatus == .playing self.playing = parent.player.timeControlStatus == .playing
} }
} }
mutating func update (music: IDStr) { mutating func update (music: TrackInfo) {
self.placeholder = music.art self.trackInfo.from(other: music)
self.music = music
self.title = music.s self.title = music.s
self.playing = self.parent!.player!.timeControlStatus == .playing self.playing = self.parent!.player.timeControlStatus == .playing
} }
} }

@ -10,7 +10,7 @@
- Download progress bar, pause/cancel/resume - Download progress bar, pause/cancel/resume
- Optimize Detailed Control View - Optimize Detailed Control View
- Use customized controls - Use customized controls
- Performance tuning, reuse one view object! - Performance tuning
- Volume and Seekbar - Volume and Seekbar
- UI Improvements - UI Improvements
- Playback functions Shuffle, Stop after next song, Repeat - Playback functions Shuffle, Stop after next song, Repeat

@ -20,7 +20,7 @@
isa = PBXContainerItemProxy; isa = PBXContainerItemProxy;
containerPortal = A95C117329C531C000737618 /* Project object */; containerPortal = A95C117329C531C000737618 /* Project object */;
proxyType = 1; proxyType = 1;
remoteGlobalIDString = A95C117E29C531C100737618; remoteGlobalTrackInfoing = A95C117E29C531C100737618;
remoteInfo = "MusicPlayer Watch App"; remoteInfo = "MusicPlayer Watch App";
}; };
/* End PBXContainerItemProxy section */ /* End PBXContainerItemProxy section */

@ -0,0 +1,96 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1430"
version = "2.0">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A95C117E29C531C100737618"
BuildableName = "MusicPlayer Watch App.app"
BlueprintName = "MusicPlayer Watch App"
ReferencedContainer = "container:MusicPlayer.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A95C117829C531C100737618"
BuildableName = "MusicPlayer.app"
BlueprintName = "MusicPlayer"
ReferencedContainer = "container:MusicPlayer.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
</TestAction>
<LaunchAction
buildConfiguration = "Release"
selectedDebuggerIdentifier = ""
selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
disableMainThreadChecker = "YES"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugXPCServices = "NO"
debugServiceExtension = "internal"
enableGPUValidationMode = "1"
allowLocationSimulation = "YES"
viewDebuggingEnabled = "No"
queueDebuggingEnabled = "No">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A95C117E29C531C100737618"
BuildableName = "MusicPlayer Watch App.app"
BlueprintName = "MusicPlayer Watch App"
ReferencedContainer = "container:MusicPlayer.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A95C117E29C531C100737618"
BuildableName = "MusicPlayer Watch App.app"
BlueprintName = "MusicPlayer Watch App"
ReferencedContainer = "container:MusicPlayer.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1430"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A95C117829C531C100737618"
BuildableName = "MusicPlayer.app"
BlueprintName = "MusicPlayer"
ReferencedContainer = "container:MusicPlayer.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A95C117829C531C100737618"
BuildableName = "MusicPlayer.app"
BlueprintName = "MusicPlayer"
ReferencedContainer = "container:MusicPlayer.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A95C117829C531C100737618"
BuildableName = "MusicPlayer.app"
BlueprintName = "MusicPlayer"
ReferencedContainer = "container:MusicPlayer.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

@ -7,33 +7,33 @@
<BreakpointProxy <BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint"> BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent <BreakpointContent
uuid = "97AD3DB1-A549-419A-B226-A00CBDB192CF" uuid = "F041D2A4-68A2-4A72-AF55-126A4671C51F"
shouldBeEnabled = "Yes" shouldBeEnabled = "Yes"
ignoreCount = "0" ignoreCount = "0"
continueAfterRunningActions = "No" continueAfterRunningActions = "No"
filePath = "MusicPlayer Watch App/ContentView.swift" filePath = "MusicPlayer Watch App/ContentView.swift"
startingColumnNumber = "9223372036854775807" startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807"
startingLineNumber = "135" startingLineNumber = "284"
endingLineNumber = "135" endingLineNumber = "284"
landmarkName = "init()" landmarkName = "try_download(u:r:e:)"
landmarkType = "7"> landmarkType = "9">
</BreakpointContent> </BreakpointContent>
</BreakpointProxy> </BreakpointProxy>
<BreakpointProxy <BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint"> BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent <BreakpointContent
uuid = "29E8B965-E6C3-4F3A-8245-7CDC6049251B" uuid = "49177A11-3378-488A-968C-D4D34C28279D"
shouldBeEnabled = "Yes" shouldBeEnabled = "Yes"
ignoreCount = "0" ignoreCount = "0"
continueAfterRunningActions = "No" continueAfterRunningActions = "No"
filePath = "MusicPlayer Watch App/ContentView.swift" filePath = "MusicPlayer Watch App/ContentView.swift"
startingColumnNumber = "9223372036854775807" startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807"
startingLineNumber = "96" startingLineNumber = "287"
endingLineNumber = "96" endingLineNumber = "287"
landmarkName = "init()" landmarkName = "try_download(u:r:e:)"
landmarkType = "7"> landmarkType = "9">
</BreakpointContent> </BreakpointContent>
</BreakpointProxy> </BreakpointProxy>
</Breakpoints> </Breakpoints>

@ -4,11 +4,21 @@
<dict> <dict>
<key>SchemeUserState</key> <key>SchemeUserState</key>
<dict> <dict>
<key>MusicPlayer Watch App 1.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>2</integer>
</dict>
<key>MusicPlayer Watch App.xcscheme_^#shared#^_</key> <key>MusicPlayer Watch App.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>0</integer> <integer>0</integer>
</dict> </dict>
<key>MusicPlayer.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>1</integer>
</dict>
</dict> </dict>
<key>SuppressBuildableAutocreation</key> <key>SuppressBuildableAutocreation</key>
<dict> <dict>

Loading…
Cancel
Save