I'm just learning Swift and SwiftUI.
I'm trying to write a segmented level indicator. Each segment is a separate view (RoundedRectangle) that draws itself with a 0.1 opacity for off or a 1.0 opacity for on. It draws in green, yellow or red depending on the level.
I haven't been able to figure out a way to create an array of @State variables, so there is a lot of otherwise redundant code
struct ContentView: View {
@State private var value = 0.0
@State private var segment0 = false
@State private var segment1 = false
@State private var segment2 = false
@State private var segment3 = false
@State private var segment4 = false
@State private var segment5 = false
@State private var segment6 = false
@State private var segment7 = false
@State private var segment8 = false
@State private var segment9 = false
var body: some View {
let valueBinding = Binding(
get: {return self.value},
set: {
self.value = $0
let intValue = Int(self.value)
for i in 0...9 {
let isOn = intValue > i
switch (i) {
case 0:
if isOn != segment0 {segment0 = isOn}
case 1:
if isOn != segment1 {segment1 = isOn}
case 2:
if isOn != segment2 {segment2 = isOn}
case 3:
if isOn != segment3 {segment3 = isOn}
case 4:
if isOn != segment4 {segment4 = isOn}
case 5:
if isOn != segment5 {segment5 = isOn}
case 6:
if isOn != segment6 {segment6 = isOn}
case 7:
if isOn != segment7 {segment7 = isOn}
case 8:
if isOn != segment8 {segment8 = isOn}
case 9:
if isOn != segment9 {segment9 = isOn}
default:
break
}
}
}
)
VStack {
HStack(
alignment: .top,
spacing: 1
) {
CellView(isOn: $segment0, color:Color.green)
CellView(isOn: $segment1, color:Color.green)
CellView(isOn: $segment2, color:Color.green)
CellView(isOn: $segment3, color:Color.green)
CellView(isOn: $segment4, color:Color.green)
CellView(isOn: $segment5, color:Color.yellow)
CellView(isOn: $segment6, color:Color.yellow)
CellView(isOn: $segment7, color:Color.yellow)
CellView(isOn: $segment8, color:Color.red)
CellView(isOn: $segment9, color:Color.red)
}
SliderView(value: valueBinding)
}
.padding()
}
}
struct SliderView: View {
@Binding var value: Double
var body: some View {
Slider(value: $value, in: 0...10)
.frame(width: 200)
}
}
struct CellView: View {
@Binding var isOn: Bool
let color: Color
let cornerSize: CGFloat = 4
let size:CGFloat = 20
var body: some View {
print ("cell")
return RoundedRectangle(cornerSize: CGSize(width: cornerSize, height: cornerSize))
.opacity(isOn ? 1.0 : 0.1)
.foregroundColor(color)
.frame(width:size, height:size)
}
}
My first attempt bound the value Double (directly from the Slider) to all of the RoundedRectangle views and each view determined whether is was on or off, and it worked, but SwiftUI redrew all the RoundedRectangle views each time value changed and that seemed inefficient. This way, only the views that actually need to change are redrawn.
Any ideas?
Thanks,
Mark
Post
Replies
Boosts
Views
Activity
Apple recently automatically upgraded me from Xcode 12 to Xcode 13. I've been building command line utilities. In Xcode 12, the output of the build showed up in the Project Navigator. I could drag that to an open terminal window and it would enter the full, convoluted, path to my executable ready to add command line parameters and run.
Now in Xcode 13, I don't see the build target in the Project Navigator. Is there an easy way to put the path in the terminal window?
I see in the release notes, where hiding the Products folder when it is in the default location is a now a "feature" in Xcode 13. While there is the "Show in Finder" option under the Product menu, that's not as easy as before. Is there a way to unhide the Products folder, even if it is in the default location? I suppose I could change the default location, but then I'd have to do it on every new project.
Is there a good tutorial and reference (preferably a book) for XCode 13? I'm looking for something of the caliber of the Swift manual. The Swift manual was free for the download, but I am willing to pay for a good XCode book.
I'm looking for more than the built in help.
Thanks,
Mark
I'm trying to preview the SwiftUI screens from my Mac app on the canvas in XCODE 13. In live operation, the model on my app connects to an external device via TCP over the network. I have a an initializer (init()) for my model that initializes the model without network access and I use this in the PreviewProvider in my view file. However, the preview fails to load unless the external device is available on the network. The preview says it is unable to connect to the main application, which makes sense as the main app won't run without the device present.
Why does XCODE have to run the app? and if so, what is the purpose of the PreviewProvider in the view file?
I am developing a Mac app using SwiftUI and XCODE 13. I have the preview displaying, and while the SwiftUI Inspector is available when I command click in the source code, it is not available in the preview pane. The icon for the inspector in the menu above the preview is grayed out as is the icon to duplicate and the inspector icon at the bottom of the window.
These icons are present in a similar app from which I adapted the views.
Mark
In XCODE 13, if I select a brace (parenthesis, bracket or brace), the matching brace briefly highlights. This is fine if the matching brace is on the screen, but the highlighting goes away before I can scroll to a matching brace if it is off the screen. Is there a way to find a matching brace that is many lines away? Is there an automatic was to highlight all the code between matching braces?
Secondly, does XCODE have the capability of collapsing code between braces?
Thanks,
Mark
Back in August, I started trying to learn Mac programming with the Xcode 12 from the App Store as Xcode 13 was still in beta. Apparently, once 13 was out of beta, Apple automatically upgraded me. It really throws a curve in your learning process when the tools change out from under you, but I have survived.
Xcode 12 had a feature where an image popped up to indicate success or failure of the build. See above.
I can't reproduce this in Xcode 13. I can set up a system notification, but that's not the same.
The definition of the protocol ViewModifer (SwiftUI.swift) includes the line "typealias Content." From what I read in the Swift docs, typealias requires a type. In fact, if I try to create a similar protocol by pasting the protocol code from SwuifUI.swift into my own file, Xcode gives the error "Type alias is missing an assigned type; use 'associatedtype' to define an associated type requirement."
FWIW, the ViewModifier protocol also has the line "associatedtype Body: View"
Can someone explain?
I'm developing an iOS app in Xcode 13.1. I set the scheme (I think that's what says "iPad Air 2" in the screenshot) to use a given simulator, but it I exit Xcode and restart, it sometimes changes to another simulator. Is there a way to get Xcode to remember the setting?
Thanks,
Mark
I'm developing an iPad app in Xcode 13.1. I'm using the iPad Air 2 simulator (that's the physical iPad I have). I've set the simulator to be in landscape mode with the home button to the right. When my app loads, it always loads in portrait mode. If I rotate the simulator to portrait and back to landscape, the app screen rotates as desired. Why isn't the app screen properly rotated when the app first launches in the simulator?
Thanks,
Mark
I have written a program in SwiftUI to display information from a database that includes the street address, but not the latitude and longitude. I've added a button that passes the street address to geocodeAddressString to get the lat & long and updates the map, but every time I click the button, even though the map appears to be displayed properly, I get a message in Xcode complaining "Modifying state during view update..."
My view has a @State variable that holds a MKCoordinateRegion() for the map to display. The closure on completion of the geocode lookup updates that @State.
@State private var mapRegion = MKCoordinateRegion()
private func updateAddress() {
let index = data.zipCode.index(data.zipCode.startIndex, offsetBy: 5)
geocoder.geocodeAddressString("\(data.streetAddress) \(data.zipCode[..<index])") { result, error in
DispatchQueue.main.async {
if let coordinate = result?.first?.location?.coordinate {
mapRegion = MKCoordinateRegion (
center: coordinate,
latitudinalMeters: 750,
longitudinalMeters: 750
)
place = IdentifiablePlace(lat: coordinate.latitude, long: coordinate.longitude)
// print ("updating address")
}
}
}
}
I am learning Swift/SwiftUI and working on my first substantial (for me) macOS application. Since I was following current tutorials and WWDC videos, I ended up using some features that are only available in OSX 12. Is there a way to maintain one code base that can be compiled for different target versions? I think I'm looking for something like C/C++'s #ifdef that would include different pieces of code depending on the target OS version.
Mark
I wrote a program that can download an updated data file publicly available from the US Government's FCC website. The file is updated weekly. This week, I went to download the file with my program and it failed to download. I looked at the HTTPURLResponse parameter to the completion callback and it shows a statusCode of 403 (forbidden). The program is the same program as last week when it worked. I copied the exact URL that the program was trying to download to both Safari and the command line curl and both were able to download the file without issue on the same computer. I changed the program to try and download a different file from a different server and it downloaded fine.
I tried running the same program on a different Mac and it failed also.
I tried several times for over an hour with the same result.
Browsing the web for a solution I see mention of clearing caches. How does one clear the caches for a SwiftUI program?
Thanks,
Mark
I wrote a SwiftUI app for the Mac that uses MapKit to display a map for a given address. It uses geocoding to convert a street address to latitude and longitude. I place a pin on the map at the actual latitude and longitude. I have noticed that the pin appears to move slightly back and forth or up and down while it is displayed. The program isn't doing any other calculations. I have noticed that if the map is not displayed, the Mac Activity Monitor shows that the application is not using any CPU resources, but when the map is displayed, Activity Monitor shows around 10%. I'm not sure what that 10% means because Activity Monitory says that the User is only using 1.5 - 2%.
What is the CPU doing? Is it waiting for the user to move or zoom the map? Is there a way to disable that and have just a static map display?
When a Swift program is executing a switch statement does it look at each case in turn to see which one to execute? Would it make sense to put the case's more likely to be chosen closer to the top of the statement?
With a switch statement on an enum with a large (over 100) number of cases would it make sense to replace the switch with a dictionary of closures?