I am trying to discover how to display my application’s calculated Solar Information values in a chart.
- My application identifies a selected location in MapKit.
- The application identifies the location’s longitude, latitude, and current time of day.
- The application calculates the selected location’s NOAA [SOLAR ELEVATION], and the [SOLAR AZIMUTH] for the time of day.
- The application calculates the data, then stores the calculated values as a [Plist] file within my application’s Document Directory.
For the moment, complete with repeated scouring of the Internet, I am not sure how to properly convert, transfer, or create a Structure, required by the chart to display the calculated values. I would like to create the chart once the calculations are complete, but I introduced a Plist to store the calculations for future use, too.
The calculated values coincide with the NOAA Solar Calculations, complete to the displayed [h : m : s], whereas I also designed the application to create the [Array of Dictionary Objects] to store the calculated values for each subsequent six minute interval, until the end of the selected location’s day. The calculated values are properly appended to the [Array of Dictionary Objects] after each completed calculation, with data transfer constants. There are 240 calculations per day from [00:06:00 to 23:54:00], presented as a [STRING], complete with the [Elevation] presented as a [DOUBLE].
For example :: The application generates the following [Calculated Array of Dictionary Objects], then recreates, and appends a new Plist in the Document Directory.
mySolarElevationDataArrayOfDictionaries :: [(theRequiredTimeOfDay: "00:06:00", theCalculatedElevation: -62.60301082991259), (theRequiredTimeOfDay: "00:12:00", theCalculatedElevation: -62.94818095051292), (theRequiredTimeOfDay: "00:18:00", theCalculatedElevation: -63.245198186807215), (theRequiredTimeOfDay: "00:24:00", theCalculatedElevation: -63.49236786176319), (theRequiredTimeOfDay: "00:30:00", theCalculatedElevation: -63.688223890934175), (theRequiredTimeOfDay: "00:36:00", theCalculatedElevation: -63.831564163806945), (theRequiredTimeOfDay: "00:42:00", theCalculatedElevation: -63.921486675739004), (theRequiredTimeOfDay: "00:48:00", theCalculatedElevation: -63.95741610687708), to the end of the data :: ===> (theRequiredTimeOfDay: "23:54:00", theCalculatedElevation: -60.69355458181633)]
The application presents the initial data as follows ::
Then presents a compass view to illustrate the results ::
I modified the Chart’s [MOCK DATA] from the calculated values to test the Chart’s display in a [SwiftUI Hosting Controller].
For example :: The following Chart Mock Data in a [HourlySunElevation_MockChartData.swift] file is called by the application’s [Content View].
import Foundation
struct Value {
let theRequiredTimeOfDay: String
let theCalculatedElevation: Double
static func theSunElevationMockData() -> [Value] {
return [Value(theRequiredTimeOfDay: "00:06:00", theCalculatedElevation: -62.60301082991259), Value(theRequiredTimeOfDay: "00:12:00", theCalculatedElevation: -62.94818095051292), Value(theRequiredTimeOfDay: "00:18:00", theCalculatedElevation: -63.245198186807215), Value(theRequiredTimeOfDay: "00:24:00", theCalculatedElevation: -63.49236786176319), Value(theRequiredTimeOfDay: "00:30:00", theCalculatedElevation: -63.688223890934175), Value(theRequiredTimeOfDay: "00:36:00", theCalculatedElevation: -63.831564163806945), Value(theRequiredTimeOfDay: "00:42:00", theCalculatedElevation: -63.921486675739004), Value(theRequiredTimeOfDay: "00:48:00", theCalculatedElevation: -63.95741610687708), to the end of the data :: ===> Value(theRequiredTimeOfDay: "23:54:00", theCalculatedElevation: -60.69355458181633)]
The Chart illustrates the Mock Data as follows ::
I also created a Struct within the [MySunElevationChart_ViewController] to try to append the calculated data, using the same logic with the Plist data transfer constants, as employed by the [Array of Dictionary Objects] ::
struct ChartSolarElevationValues {
var theRequiredTimeOfDay: String
var theCalculatedElevation: Double
// Structs have an implicit [init]. This is here for reference.
init(theRequiredTimeOfDay: String, theCalculatedElevation: Double) {
self.theRequiredTimeOfDay = theRequiredTimeOfDay
self.theCalculatedElevation = theCalculatedElevation
//mySolarElevationChartData.append(self)
} // End of [init(theRequiredTimeOfDay: String, theCalculatedElevation: Double)]
} // End of [struct ChartSolarElevationValues]
Unfortunately, the result did not append each subsequent calculation, but continued to create the same calculation as a new distinct object ::
NOTE :: I only called three calculations with the Struct test.
// NOTE :: To prevent an [ERROR] at [var mySolarElevationChartData = [ChartSolarElevationValues]] since it has an init.
// Therefore you must add () at the end of [var mySolarElevationChartData = [ChartSolarElevationValues]]
let theData = [ChartSolarElevationValues]()
//print("theData :: \(theData)\n")
let someData = ChartSolarElevationValues(theRequiredTimeOfDay: TheTimeForDaySunElevation.theTheTimeForDaySunElevation, theCalculatedElevation:VerifyCityLocationSearchRequestCorrectedSolarElevation.theVerifyCityLocationSearchRequestCorrectedSolarElevation)
var theData_New = theData
theData_New.append(someData)
print("theData_New :: \(theData_New)\n")
// Prints :: theData_New :: [My_Map.ChartSolarElevationValues(theRequiredTimeOfDay: "00:06:00", theCalculatedElevation: -61.11000735370401)]]
// Prints :: [theData_New :: [My_Map.ChartSolarElevationValues(theRequiredTimeOfDay: "00:12:00", theCalculatedElevation: -61.315092082911875)]]
// Prints :: [theData_New :: [My_Map.ChartSolarElevationValues(theRequiredTimeOfDay: "00:18:00", theCalculatedElevation: -61.47403413313205)]]
So, I am misintepreting the required coding structure to properly append the Elevation Chart, and the Azimuth Chart with the calculated data.
I know something is amiss, but for the moment, I do not know how to address this issue.
Your suggestions would be welcome ... :]
jim_k
I previously mentioned, my application creates a [Solar Elevation] and a [Solar Azimuth] for an identifiable map location, based upon the [NOAA] calculations. The results happen to be accurate to the [Hour:Minute:Second], compared to NOAA calculations. The [Compass] view illustrates that success, at the selected location with the requested [Time of Day], and [Location].
I focused on the [Solar Elevation] first to determine how I could translate the calculated data to be displayed in a SwiftUI Chart. My previous attempts to create an [Appended Struct] to display the calculated data in the [Chart] failed miserably, although I managed to correct my error to properly append the [Struct]. As noted, every SwiftUI Chart example I discovered always engaged the [Chart Data] with [Mock Data] to interact with the [Chart]. The examples did not solve my question, but the accumulated information generated ideas for me to try.
NOTE :: For the moment, I have not discovered a solution with the following method to display the chart’s calculated [Y-Axis] data with a [Loli-pop], but still exploring.
So to possibly resolve my issue, I did the following to display the calculated data in a SwiftUI Chart with my very obscure, but somewhat tedious effective method. Please read my comment as too many incremental steps, and possibly TL:TR … :]
I prepared the [Calculated Data] ::
1. The application’s [MySunElevationChart_ViewController] manually identified each six minute time interval.
2. Converted each six minute interval into a 24 hour fraction.
3. Converted the fraction into a formatted date string.
4. Appended each formatted date string to the [theTimeOfDayArray].
5. Assigned the [theTimeOfDayArray] to a [Struct] in the [Constants Folder].
6. The application’s [MySunElevationChart_ViewController] calculated the [Solar Elevation] with each six minute interval date fraction.
7. Appended each calculated [Solar Elevation] to the [theCalculatedSunElevationArray].
8. Assigned the [theCalculatedSunElevationArray] to a [Struct] in the [Constants Folder].
I decided to modify my application’s original static value [MOCK DATA STRUCT] with the embedded [Calculated Data] ::
1. The application’s [MySunElevationChart_ViewController] retrieved the [theTimeOfDayArray].
2. Isolated and extracted each [Formatted String] at a specified index.
3. Assigned each extracted string value to a [Struct] in the [Constants Folder].
4. The application’s [MySunElevationChart_ViewController] retrieved the [theCalculatedSunElevationArray].
5. Isolated and extracted each [Solar Elevation] at a specified index.
6. Assigned each extracted [Solar Elevation] value to a [Struct] in the [Constants Folder].
7. The application refactored the static value [Mock Chart Data] with each [Formatted String Struct Value], and each [Solar Elevation Struct Value].
8. The application transfered the [Refactored Mock Data] to the [Chart Content View].
NOTE :: I created several [Structs] to prepare the application to receive and transfer the [Calculated Solar Elevation Values] to the [SwiftUI Chart].
I created [Structs] for the [Solar Time Of Day] and the [Solar Elevation] in the [Constants Folder]. I created [Structs] for the [Solar Time Of Day Array] and the [Solar Elevation Array] in the [Constants Folder]. I created [Structs] for each extracted [Solar Elevation Time] and each extracted [Solar Elevation] in the [Constants Folder] for the refactored [MOCK DATA STRUCT].
// [For example the Time Structs]
struct SolarElevationTime_0 {
static var theSolarElevationTime_0: String = ""
} // End of [struct SolarElevationTime_0]
// to the end of the data …
struct SolarElevationTime_238 {
static var theSolarElevationTime_238: String = ""
} // End of [struct SolarElevationTime_238]
// [For example the Solar Elevation Structs]
struct SolarElevation_0 {
static var theSolarElevation_0: Double = 0
} // End of [struct SolarElevation_0]
// to the end of the data …
struct SolarElevation_238 {
static var theSolarElevation_238: Double = 0
} // End of [struct SolarElevation_238]
I created a separate function, within the [MySunElevationChart_ViewController] to isolate, and extract each [Time of Day] from the [theTimeOfDayArray] with the following code ::
// Identify the [TIME OF DAY ARRAY] from the [CONSTANTS FOLDER]
let someRequiredTimeOfDayArray = SolarElevationRequiredTimeOfDayDataArray.theSolarElevationRequiredTimeOfDayDataArray
let theTimeOfDayValueAtIndex_0 = (someRequiredTimeOfDayArray[0])
// Transfer the constant to the [Constants Folder Struct]
SolarElevationTime_0.theSolarElevationTime_0 = theTimeOfDayValueAtIndex_0
// to the end of the data …
let theTimeOfDayValueAtIndex_238 = (someRequiredTimeOfDayArray[238])
// Transfer the constant to the [Constants Folder Struct]
SolarElevationTime_238.theSolarElevationTime_238 = theTimeOfDayValueAtIndex_238
I created a separate function, within the [MySunElevationChart_ViewController] to isolate, and extract each [Solar Elevation] from the [theCalculatedSunElevationArray] with the following code ::
// Identify the [SOLAR ELEVATION ARRAY] from the [CONSTANTS FOLDER]
let someRequiredSolarElevationArray = SolarElevationRequiredDataArray.theSolarElevationRequiredDataArray
let theSolarElevationValueAtIndex_0 = (someRequiredSolarElevationArray[0])
// Transfer the constant to the [Constants Folder Struct]
SolarElevation_0.theSolarElevation_0 = theSolarElevationValueAtIndex_0
// to the end of the data …
let theSolarElevationValueAtIndex_238 = (someRequiredSolarElevationArray[238])
// Transfer the constant to the [Constants Folder Struct]
SolarElevation_0.theSolarElevation_238 = theSolarElevationValueAtIndex_238
The application transfers and inserts the [Calculated Chart Data] to the application’s [Mock Data Struct]. I refactored the application’s original static value [Mock Data Struct] in the [HourlySunElevation_MockChartData] Swift File to receive the calculated [Struct] constants.
struct Value: Identifiable, Equatable, Hashable {
let id = UUID()
let theRequiredTimeOfDay: String
let theCalculatedElevation: Double
static func theSunElevationMockData() -> [Value] {
return [Value(theRequiredTimeOfDay: SolarElevationTime_0.theSolarElevationTime_0, theCalculatedElevation: SolarElevation_0.theSolarElevation_0), Value(theRequiredTimeOfDay: SolarElevationTime_1.theSolarElevationTime_1, theCalculatedElevation: SolarElevation_1.theSolarElevation_1),
// :: To the end of the data ::
Value(theRequiredTimeOfDay: SolarElevationTime_238.theSolarElevationTime_238, theCalculatedElevation: SolarElevation_238.theSolarElevation_238)]
} // End of [static func theSunElevationMockData() -> [Value]]
} // End of [struct Value: Identifiable, Equatable, Hashable]
The application’s [Content View] receives and presents the calculated [Chart Data] ::
Continued ::