bug fixes & download improvement
This commit is contained in:
@@ -10,96 +10,216 @@ import Network
|
||||
import AVFoundation
|
||||
import UIKit
|
||||
|
||||
class IDStr : Identifiable {
|
||||
var s : String = ""
|
||||
var art : Image?
|
||||
var m : AVPlayerItem?
|
||||
init () {self.m = nil}
|
||||
class TrackInfo : NSObject, Identifiable, ObservableObject {
|
||||
@Published var s : String = ""
|
||||
@Published var art : Image? = nil
|
||||
@Published var m : AVPlayerItem? = nil
|
||||
@Published var changed = false
|
||||
var cv : ContentView? = nil
|
||||
override init() {
|
||||
super.init()
|
||||
}
|
||||
init (str : String, music : AVPlayerItem) {
|
||||
self.s = str
|
||||
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 {
|
||||
|
||||
@Published var music = Array<IDStr>()
|
||||
|
||||
@Published var music = Array<TrackInfo>()
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
class PlaybackViewProxy {
|
||||
var pbv : PlaybackView
|
||||
init(v : PlaybackView) {
|
||||
var tabpbv : PlaybackView
|
||||
init() {
|
||||
pbv = PlaybackView()
|
||||
tabpbv = PlaybackView()
|
||||
}
|
||||
init(v : PlaybackView, tabpbv: PlaybackView) {
|
||||
self.pbv = v
|
||||
self.tabpbv = tabpbv
|
||||
}
|
||||
}
|
||||
|
||||
struct ContentView: View {
|
||||
@ObservedObject var music = ListViewModel()
|
||||
@ObservedObject var nowplaying : TrackInfo
|
||||
@State var pushState = false
|
||||
@State var geo :CGSize = .zero
|
||||
@State var _curr_sel_music : IDStr = IDStr()
|
||||
let pbv : PlaybackViewProxy
|
||||
var body: some View {
|
||||
GeometryReader { geometry in
|
||||
NavigationView(){
|
||||
List() {
|
||||
ForEach(music.music) { m in
|
||||
VStack(){
|
||||
Button(m.s, action: {
|
||||
let idx = music.music.firstIndex { s in
|
||||
s.s == m.s
|
||||
}
|
||||
if (idx != nil) {
|
||||
if (idx != 0) {
|
||||
music.music = Array(music.music[idx! ... (music.music.endIndex - 1)] + music.music[0...idx! - 1])
|
||||
self.player?.removeAllItems()
|
||||
for i in music.music {
|
||||
i.m!.seek(to: .zero)
|
||||
player?.insert(i.m!, after: nil)
|
||||
}
|
||||
}
|
||||
else {
|
||||
m.m!.seek(to: .zero)
|
||||
}
|
||||
}
|
||||
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()
|
||||
}
|
||||
}
|
||||
}
|
||||
Label("\(music.music.count) Files. ", systemImage: "heart.fill").background(.clear).labelStyle(.titleAndIcon).frame(width: geometry.size.width, alignment: .center)
|
||||
}
|
||||
}.onAppear {
|
||||
geo = geometry.size
|
||||
self.pbv.pbv.parent = self
|
||||
@State var geo:CGSize = .zero
|
||||
@State var active = false
|
||||
//@State var _curr_sel_music : TrackInfo = TrackInfo()
|
||||
var pbv : PlaybackViewProxy
|
||||
var dir: String
|
||||
|
||||
func update_pbv(idx: Int) {
|
||||
let m = music.music[idx]
|
||||
if (idx != 0) {
|
||||
music.music = Array(music.music[idx ... (music.music.endIndex - 1)] + music.music[0...idx - 1])
|
||||
self.player.removeAllItems()
|
||||
for i in music.music {
|
||||
i.m!.seek(to: .zero)
|
||||
player.insert(i.m!, after: nil)
|
||||
}
|
||||
}
|
||||
else {
|
||||
m.m!.seek(to: CMTime(value: 1, timescale: 10000))
|
||||
}
|
||||
|
||||
var player : AVQueuePlayer? = nil
|
||||
|
||||
//if !m.equals_to(other: self.nowplaying) {
|
||||
if (self.active) {
|
||||
self.pbv.tabpbv.update(music: m)
|
||||
}
|
||||
else {
|
||||
self.pbv.pbv.update(music: m)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
.navigationTitle("Songs")
|
||||
.navigationBarBackButtonHidden(false)
|
||||
.onAppear {
|
||||
self.active = true
|
||||
geo = geometry.size
|
||||
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
|
||||
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() {
|
||||
self.pbv = PlaybackViewProxy(v: PlaybackView())
|
||||
self.pbv = PlaybackViewProxy()
|
||||
let base = "https://billsun.dev/webdav/music-test"
|
||||
let url = URL(string: base)
|
||||
let request: URLRequest = URLRequest(url: url!)
|
||||
var request: URLRequest = URLRequest(url: url!)
|
||||
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:
|
||||
{ (data, response, error) -> Void in
|
||||
{ [self] (data, response, error) -> Void in
|
||||
if (error != nil) { return }
|
||||
let reply = String(data: data!, encoding: String.Encoding.utf8)!
|
||||
|
||||
@@ -131,66 +251,58 @@ struct ContentView: View {
|
||||
check_file(filepath)
|
||||
check_file("\(dir)/Documents/\(_file)")
|
||||
if (download) {
|
||||
session.dataTask(with: URLRequest(url: URL(string: base + "/" + _file)!)) {
|
||||
(data, response, error) -> Void in
|
||||
var tries = 16
|
||||
/*
|
||||
func try_save_response (data: Data?, response: URLResponse?, error: Error?) -> Void {
|
||||
if (error == nil) {
|
||||
let fp = fopen(filepath, "wb")
|
||||
data!.withUnsafeBytes({ ptr in
|
||||
fwrite(ptr, 1, data!.count, fp)
|
||||
})
|
||||
fclose(fp)
|
||||
add_music(filename: file)
|
||||
}
|
||||
}.resume()
|
||||
else {
|
||||
if (tries > 0) {
|
||||
tries -= 1
|
||||
session.dataTask(with: URLRequest(url: URL(string: base + "/" + _file)!, timeoutInterval: TimeInterval(100000 * (5 - tries))), completionHandler: try_save_response).resume()
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
}
|
||||
session.downloadTask(with: req, completionHandler: try_download).resume()
|
||||
|
||||
|
||||
//session.dataTask(with: URLRequest(url: URL(string: base + "/" + _file)!, timeoutInterval: TimeInterval(65535)), completionHandler: try_save_response).resume()
|
||||
}
|
||||
}
|
||||
}catch{}
|
||||
}
|
||||
).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)
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let item = AVPlayerItem(url: file_url)
|
||||
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!)
|
||||
}
|
||||
else {
|
||||
self.player?.play()
|
||||
}
|
||||
})
|
||||
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 {
|
||||
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,110 +8,129 @@
|
||||
import SwiftUI
|
||||
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
|
||||
var music : IDStr? = nil
|
||||
//var music : TrackInfo? = nil
|
||||
var parent : ContentView? = nil
|
||||
//@ObservedObject var timeout = Timeout(timeout: 5)
|
||||
var title = ""
|
||||
@State var playing = true
|
||||
@State private var appearSelf = true
|
||||
|
||||
@State var playing = true
|
||||
@State private var appearSelf = 3
|
||||
|
||||
@ObservedObject var appearTimer = AppearTimer()
|
||||
@ObservedObject var trackInfo : TrackInfo = TrackInfo()
|
||||
|
||||
|
||||
var body: some View {
|
||||
if parent != nil {
|
||||
if trackInfo.m != nil {
|
||||
GeometryReader { geo in
|
||||
ZStack {
|
||||
if(placeholder == nil) {
|
||||
Image(systemName: "square")
|
||||
if(trackInfo.art == nil) {
|
||||
|
||||
Image(systemName: "music.note")
|
||||
.resizable()
|
||||
.scaledToFill()
|
||||
.foregroundColor(.black)
|
||||
.scaledToFit()
|
||||
.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 {
|
||||
placeholder!.resizable().scaledToFill()
|
||||
trackInfo.art!.resizable().scaledToFill()
|
||||
}
|
||||
if (appearSelf)
|
||||
if (appearTimer.appear)
|
||||
{
|
||||
NavigationView{
|
||||
VStack{
|
||||
HStack{
|
||||
Button {
|
||||
if ( parent!.player!.timeControlStatus == .playing ) {
|
||||
parent!.player!.pause()
|
||||
self.playing = false
|
||||
} else {
|
||||
parent!.player!.play()
|
||||
self.playing = true
|
||||
}
|
||||
} label: {
|
||||
(
|
||||
self.playing ?
|
||||
Image(systemName: "stop") :
|
||||
Image(systemName: "play")
|
||||
)
|
||||
VStack {
|
||||
HStack {
|
||||
Button {
|
||||
if ( parent!.player.timeControlStatus == .playing ) {
|
||||
parent!.player.pause()
|
||||
self.playing = false
|
||||
} else {
|
||||
parent!.player.play()
|
||||
self.playing = true
|
||||
}
|
||||
} label: {
|
||||
(
|
||||
self.playing ?
|
||||
Image(systemName: "stop") :
|
||||
Image(systemName: "play")
|
||||
)
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: geo.size.width/5.5)
|
||||
}.background(Color(red: 0,green: 0,blue: 0,opacity: 0.2))
|
||||
.frame(width: geo.size.width/2.5)
|
||||
.cornerRadius(90, antialiased: true)
|
||||
.foregroundColor(.white)
|
||||
.opacity(1)
|
||||
.buttonStyle(.plain)
|
||||
Button {
|
||||
let curr = parent!.player.currentItem
|
||||
parent!.player.advanceToNextItem()
|
||||
curr!.seek(to: .zero)
|
||||
parent!.player.play()
|
||||
self.playing = true
|
||||
} label : {
|
||||
Image(systemName: "chevron.forward")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: geo.size.width/5.5)
|
||||
}.background(Color(red: 0,green: 0,blue: 0,opacity: 0.2))
|
||||
.frame(width: geo.size.width/2.5)
|
||||
.cornerRadius(90, antialiased: true)
|
||||
.foregroundColor(.white)
|
||||
.opacity(1)
|
||||
.buttonStyle(.plain)
|
||||
Button {
|
||||
let curr = parent!.player!.currentItem
|
||||
parent!.player!.advanceToNextItem()
|
||||
curr!.seek(to: .zero)
|
||||
parent!.player!.play()
|
||||
self.playing = true
|
||||
} label : {
|
||||
Image(systemName: "chevron.forward")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: geo.size.width/7, height: geo.size.height/7)
|
||||
}.background(Color.clear)
|
||||
.clipShape(Circle())
|
||||
.foregroundColor(.white)
|
||||
.frame(width: geo.size.width/4, height: geo.size.height/4)
|
||||
.padding(0)
|
||||
.opacity(1)
|
||||
.buttonStyle(.plain)
|
||||
}
|
||||
}.onAppear(){
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 3, execute: {
|
||||
appearSelf = false
|
||||
})
|
||||
}.navigationTitle("\(self.title)")
|
||||
}.opacity(0.65).navigationBarBackButtonHidden(false)
|
||||
.frame(width: geo.size.width/7, height: geo.size.height/7)
|
||||
}.background(Color.clear)
|
||||
.clipShape(Circle())
|
||||
.foregroundColor(.white)
|
||||
.frame(width: geo.size.width/4, height: geo.size.height/4)
|
||||
.padding(0)
|
||||
.opacity(1)
|
||||
.buttonStyle(.plain)
|
||||
}
|
||||
}
|
||||
}
|
||||
}.onTapGesture {
|
||||
appearSelf = true
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 5, execute: {
|
||||
appearSelf = false
|
||||
})
|
||||
appearTimer.appear()
|
||||
}
|
||||
}.navigationBarBackButtonHidden(false)
|
||||
.toolbar(.visible, for: .navigationBar)
|
||||
.onAppear() {
|
||||
appearTimer.appear(time: 3, _appear: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init() { }
|
||||
init(parent:ContentView, music: IDStr? = nil) {
|
||||
init(parent:ContentView, music: TrackInfo? = nil) {
|
||||
if music != nil && music!.art != nil {
|
||||
self.placeholder = music!.art!
|
||||
self.music = music
|
||||
self.parent = parent
|
||||
self.playing = parent.player!.timeControlStatus == .playing
|
||||
self.playing = parent.player.timeControlStatus == .playing
|
||||
}
|
||||
}
|
||||
|
||||
mutating func update (music: IDStr) {
|
||||
self.placeholder = music.art
|
||||
self.music = music
|
||||
mutating func update (music: TrackInfo) {
|
||||
self.trackInfo.from(other: music)
|
||||
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
|
||||
- Optimize Detailed Control View
|
||||
- Use customized controls
|
||||
- Performance tuning, reuse one view object!
|
||||
- Performance tuning
|
||||
- Volume and Seekbar
|
||||
- UI Improvements
|
||||
- Playback functions Shuffle, Stop after next song, Repeat
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = A95C117329C531C000737618 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = A95C117E29C531C100737618;
|
||||
remoteGlobalTrackInfoing = A95C117E29C531C100737618;
|
||||
remoteInfo = "MusicPlayer Watch App";
|
||||
};
|
||||
/* 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>
|
||||
+10
-10
@@ -7,33 +7,33 @@
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
uuid = "97AD3DB1-A549-419A-B226-A00CBDB192CF"
|
||||
uuid = "F041D2A4-68A2-4A72-AF55-126A4671C51F"
|
||||
shouldBeEnabled = "Yes"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "MusicPlayer Watch App/ContentView.swift"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "135"
|
||||
endingLineNumber = "135"
|
||||
landmarkName = "init()"
|
||||
landmarkType = "7">
|
||||
startingLineNumber = "284"
|
||||
endingLineNumber = "284"
|
||||
landmarkName = "try_download(u:r:e:)"
|
||||
landmarkType = "9">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
<BreakpointProxy
|
||||
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
|
||||
<BreakpointContent
|
||||
uuid = "29E8B965-E6C3-4F3A-8245-7CDC6049251B"
|
||||
uuid = "49177A11-3378-488A-968C-D4D34C28279D"
|
||||
shouldBeEnabled = "Yes"
|
||||
ignoreCount = "0"
|
||||
continueAfterRunningActions = "No"
|
||||
filePath = "MusicPlayer Watch App/ContentView.swift"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "96"
|
||||
endingLineNumber = "96"
|
||||
landmarkName = "init()"
|
||||
landmarkType = "7">
|
||||
startingLineNumber = "287"
|
||||
endingLineNumber = "287"
|
||||
landmarkName = "try_download(u:r:e:)"
|
||||
landmarkType = "9">
|
||||
</BreakpointContent>
|
||||
</BreakpointProxy>
|
||||
</Breakpoints>
|
||||
|
||||
@@ -4,11 +4,21 @@
|
||||
<dict>
|
||||
<key>SchemeUserState</key>
|
||||
<dict>
|
||||
<key>MusicPlayer Watch App 1.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>2</integer>
|
||||
</dict>
|
||||
<key>MusicPlayer Watch App.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
<key>MusicPlayer.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>1</integer>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>SuppressBuildableAutocreation</key>
|
||||
<dict>
|
||||
|
||||
Reference in New Issue
Block a user