diff --git a/DXFeedFrameworkTests/EndpointTest.swift b/DXFeedFrameworkTests/EndpointTest.swift index 97b225e9d..a8951b5b6 100644 --- a/DXFeedFrameworkTests/EndpointTest.swift +++ b/DXFeedFrameworkTests/EndpointTest.swift @@ -111,5 +111,5 @@ final class EndpointTest: XCTestCase { DXEndpoint.Role.fromNative(nativeRole) }, roles) } - + } diff --git a/Samples/DXFeedCandleChart/DXFeedCandleChartApp.swift b/Samples/DXFeedCandleChart/DXFeedCandleChartApp.swift index 33a166dbd..76b50f66a 100644 --- a/Samples/DXFeedCandleChart/DXFeedCandleChartApp.swift +++ b/Samples/DXFeedCandleChart/DXFeedCandleChartApp.swift @@ -15,7 +15,3 @@ struct DXFeedCandleChartApp: App { } } } - - - - diff --git a/Samples/DXFeedCandleChartMac/CandleStickChart.swift b/Samples/DXFeedCandleChartMac/CandleStickChart.swift index e4457f912..011d2a039 100644 --- a/Samples/DXFeedCandleChartMac/CandleStickChart.swift +++ b/Samples/DXFeedCandleChartMac/CandleStickChart.swift @@ -44,9 +44,9 @@ Low: \(self.low.formatted(currency: currency)) } extension Array { - mutating func safeReplace(_ newElement: Element, at:Int) { - if at >= 0 && at < self.count { - self[at] = newElement + mutating func safeReplace(_ newElement: Element, at index: Int) { + if index >= 0 && index < self.count { + self[index] = newElement } else { print("error during replace") } @@ -88,7 +88,6 @@ struct StockPrice: Identifiable { } } - class CandleList: ObservableObject, SnapshotDelegate { func receiveEvents(_ events: [DXFeedFramework.MarketEvent], isSnapshot: Bool) { @@ -150,7 +149,8 @@ class CandleList: ObservableObject, SnapshotDelegate { func fetchInfo() { DispatchQueue.global(qos: .background).async { let reader = DXInstrumentProfileReader() - let result = try? reader.readFromFile(address: "https://demo:demo@tools.dxfeed.com/ipf?SYMBOL=\(self.symbol)") + let address = "https://demo:demo@tools.dxfeed.com/ipf?SYMBOL=\(self.symbol)" + let result = try? reader.readFromFile(address: address) guard let result = result else { return } @@ -263,7 +263,9 @@ struct CandleStickChart: View { low: .value("Low", price.low), close: .value("Close", price.close) ) - .accessibilityLabel("\(price.timestamp.formatted(date: .complete, time: .omitted)): \(price.accessibilityTrendSummary)") + .accessibilityLabel(""" +\(price.timestamp.formatted(date: .complete, time: .omitted)): \(price.accessibilityTrendSummary) +""") .accessibilityValue(price.accessibilityDescription) .accessibilityHidden(false) .foregroundStyle( price.isClosingHigher ? .green : .red) @@ -300,7 +302,9 @@ struct CandleStickChart: View { .exclusively( before: DragGesture() .onChanged { value in - selectedPrice = findElement(location: value.location, proxy: proxy, geometry: geo) + selectedPrice = findElement(location: value.location, + proxy: proxy, + geometry: geo) } ) ) @@ -355,7 +359,7 @@ struct CandleStickChart: View { if let date = proxy.value(atX: relativeXPosition) as Date? { // Find the closest date element. var minDistance: TimeInterval = .infinity - var index: Int? = nil + var index: Int? for dataIndex in list.candles.indices { let nthSalesDataDistance = list.candles[dataIndex].timestamp.distance(to: date) if abs(nthSalesDataDistance) < minDistance { @@ -400,50 +404,49 @@ struct CandleStickMark: ChartContent { // MARK: - Accessibility extension CandleStickChart: AXChartDescriptorRepresentable { - func makeChartDescriptor() -> AXChartDescriptor { + func createLowest() -> ((KeyPath) -> (Double)) { + { path in + return list.candles.map { $0[keyPath: path]} .min()?.asDouble ?? 0 + } + } + func createHighest() -> ((KeyPath) -> (Double)) { + { path in + return list.candles.map { $0[keyPath: path]} .max()?.asDouble ?? 0 + } + } + func makeChartDescriptor() -> AXChartDescriptor { let dateStringConverter: ((Date) -> (String)) = { date in date.formatted(date: .abbreviated, time: .omitted) } - // These closures help find the min/max for each axis - let lowestValue: ((KeyPath) -> (Double)) = { path in - return list.candles.map { $0[keyPath: path]} .min()?.asDouble ?? 0 - } - let highestValue: ((KeyPath) -> (Double)) = { path in - return list.candles.map { $0[keyPath: path]} .max()?.asDouble ?? 0 - } - + let lowestValue = createLowest() + let highestValue = createHighest() let xAxis = AXCategoricalDataAxisDescriptor( title: "Date", categoryOrder: list.candles.map { dateStringConverter($0.timestamp) } ) - // Add axes for each data point captured in the candlestick let closeAxis = AXNumericDataAxisDescriptor( title: "Closing Price", range: 0...highestValue(\.close), gridlinePositions: [] ) { value in "Closing: \(value.formatted(currency: list.currency)))" } - let openAxis = AXNumericDataAxisDescriptor( title: "Opening Price", range: lowestValue(\.open)...highestValue(\.open), gridlinePositions: [] ) { value in "Opening: \(value.formatted(currency: list.currency))" } - let highAxis = AXNumericDataAxisDescriptor( title: "Highest Price", range: lowestValue(\.high)...highestValue(\.high), gridlinePositions: [] ) { value in "High: \(value.formatted(currency: list.currency))" } - let lowAxis = AXNumericDataAxisDescriptor( title: "Lowest Price", range: lowestValue(\.low)...highestValue(\.low), gridlinePositions: [] ) { value in "Low: \(value.formatted(currency: list.currency))" } - let series = AXDataSeriesDescriptor( name: list.descriptionString, isContinuous: false, @@ -458,7 +461,6 @@ extension CandleStickChart: AXChartDescriptorRepresentable { return AXChartDescriptor( title: list.descriptionString, - summary: nil, xAxis: xAxis, yAxis: closeAxis, additionalAxes: [openAxis, highAxis, lowAxis], @@ -482,12 +484,24 @@ struct CandleInfoView: View { VStack(alignment: .center, spacing: 4) { Text(price.timestamp.formatted(date: .abbreviated, time: .omitted)) HStack(spacing: 10) { - Text("Open: \(price.open.formatted(.currency(code: currency)))" ).foregroundColor(.secondary).frame(minWidth: 0, maxWidth: .infinity, alignment: .leading).minimumScaleFactor(0.01) - Text("Close: \(price.close.formatted(.currency(code: currency)))").foregroundColor(.secondary).frame(minWidth: 0, maxWidth: .infinity, alignment: .leading).minimumScaleFactor(0.01) + Text("Open: \(price.open.formatted(.currency(code: currency)))") + .foregroundColor(.secondary) + .frame(minWidth: 0, maxWidth: .infinity, alignment: .leading) + .minimumScaleFactor(0.01) + Text("Close: \(price.close.formatted(.currency(code: currency)))") + .foregroundColor(.secondary) + .frame(minWidth: 0, maxWidth: .infinity, alignment: .leading) + .minimumScaleFactor(0.01) } HStack(spacing: 10) { - Text("High: \(price.high.formatted(.currency(code: currency)))").foregroundColor(.secondary).frame(minWidth: 0, maxWidth: .infinity, alignment: .leading).minimumScaleFactor(0.01) - Text("Low: \(price.low.formatted(.currency(code: currency)))").foregroundColor(.secondary).frame(minWidth: 0, maxWidth: .infinity, alignment: .leading).minimumScaleFactor(0.01) + Text("High: \(price.high.formatted(.currency(code: currency)))") + .foregroundColor(.secondary) + .frame(minWidth: 0, maxWidth: .infinity, alignment: .leading) + .minimumScaleFactor(0.01) + Text("Low: \(price.low.formatted(.currency(code: currency)))") + .foregroundColor(.secondary) + .frame(minWidth: 0, maxWidth: .infinity, alignment: .leading) + .minimumScaleFactor(0.01) } } .lineLimit(1) diff --git a/Samples/DXFeedCandleChartMac/DXFeedCandleChartMacApp.swift b/Samples/DXFeedCandleChartMac/DXFeedCandleChartMacApp.swift index 468996a6b..3e140cc15 100644 --- a/Samples/DXFeedCandleChartMac/DXFeedCandleChartMacApp.swift +++ b/Samples/DXFeedCandleChartMac/DXFeedCandleChartMacApp.swift @@ -12,7 +12,7 @@ struct DXFeedCandleChartMacApp: App { let symbol = "AAPL" var body: some Scene { WindowGroup { - CandleStickChart(symbol: symbol, + CandleStickChart(symbol: symbol, type: .week, date: Calendar.current.date(byAdding: .year, value: -4, to: Date()), endpoint: nil) diff --git a/Samples/Playgrounds/LastEventsConsole.playground/Contents.swift b/Samples/Playgrounds/LastEventsConsole.playground/Contents.swift index 52d5c42d6..fb2bb9280 100644 --- a/Samples/Playgrounds/LastEventsConsole.playground/Contents.swift +++ b/Samples/Playgrounds/LastEventsConsole.playground/Contents.swift @@ -2,15 +2,13 @@ import PlaygroundSupport import UIKit import DXFeedFramework -/** - * This sample demonstrates a way to subscribe to the big world of symbols with dxFeed API, so that the events are - * updated and cached in memory of this process, and then take snapshots of those events from memory whenever - * they are needed. This example repeatedly reads symbol name from the console and prints a snapshot of its last - * quote, trade, summary, and profile events. - */ - -// Just UI for symbol input +/// This sample demonstrates a way to subscribe to the big world of symbols with dxFeed API, so that the events are +/// updated and cached in memory of this process, and then take snapshots of those events from memory whenever +/// they are needed. This example repeatedly reads symbol name from the console and prints a snapshot of its last +/// quote, trade, summary, and profile events. + class InputViewController: UIViewController { + // Just UI for symbol input var textField = UITextField() var resultLabel = UILabel() @@ -109,16 +107,14 @@ func fetchData(feed: DXFeed, symbol: String) throws -> String { * available for any reason and the wait above had timed out. This sample just prints all results. * "null" is printed when the event is not available. */ - try promises.forEach { pr in - result += (try pr.getResult()?.toString() ?? "Null result for \(pr)") + "\n" + try promises.forEach { promise in + result += (try promise.getResult()?.toString() ?? "Null result for \(promise)") + "\n" } print(result) print("end fetching for \(symbol)") return result } - - let viewController = InputViewController() viewController.feed = feed viewController.view.frame = CGRect(x: 0, y: 0, width: 400, height: 300) diff --git a/Samples/QuoteTableApp/QuoteTableViewController.swift b/Samples/QuoteTableApp/QuoteTableViewController.swift index 068a62c97..d291ed1d8 100644 --- a/Samples/QuoteTableApp/QuoteTableViewController.swift +++ b/Samples/QuoteTableApp/QuoteTableViewController.swift @@ -30,7 +30,7 @@ class QuoteTableViewController: UIViewController { self.quoteTableView.backgroundColor = .clear quoteTableView.separatorStyle = .none - + noticeButton.setTitle("Learn more about dxFeed APIs", for: .normal) noticeButton.titleEdgeInsets = UIEdgeInsets(top: 0, left: 8, bottom: 0, right: 0) @@ -155,7 +155,7 @@ extension QuoteTableViewController: UITableViewDelegate { func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { let symbol = symbols[indexPath.row] - let candleChartViewController = MyUIHostingController(rootView: CandleStickChart(symbol: symbol, + let candleChartViewController = MyUIHostingController(rootView: CandleStickChart(symbol: symbol, type: .week, endpoint: endpoint)) candleChartViewController.title = symbol @@ -170,7 +170,7 @@ extension QuoteTableViewController: UIGestureRecognizerDelegate { } } -class MyUIHostingController: UIHostingController where Content : View { +class MyUIHostingController: UIHostingController where Content: View { override func viewDidLoad() { super.viewDidLoad() // fix for datepicker selected color