enum TaskPriority {
case high
case medium
case low
}
struct Task: Identifiable {
var id: String = UUID().uuidString
var title: String
var priority: TaskPriority
var completed: Bool
}
By contrast, Apple’s native EKReminder is a class that inherits from EKCalendarItem, which in turn inherits from EKObject. Its accessible properties:
And accessible properties inherited from EKCalendarItem:
The EKObject class’s properties, booleans hasChanges and isNew, relate to saving and restoring state.
¿Why two different priority properties?
¿Why simply completionDate and not completionDateComponents?
Not following a tutorial today, just going to see if I can wrangle control of EventKit.
On weekends I’m trying to get away from tutorials per se, although at this point in my developer journey I’ll still be stealing adapting a lot of other people’s code. I’ll do my best to credit anyone whose code I cite here on the blog, and of course I’ll observe licenses when it comes to publishing anything.
I’m interested in working with EventKit, Apple’s framework for accessing calendar and reminders data. Specifically, I want to build an app that works with reminders. So far I haven’t found much any sample code online that uses EventKit in a SwiftUI environment; Apple’s Calendars and Reminders Programming Guide doesn’t even use Swift but rather Objective-C. (If he sees this @chrislowiec will be saying “I told you so!”)
I’m going to try starting with Peter Friese’s Building a To-Do List App with SwiftUI, Combine, and Firebase, which seeks to replicate the built-in iOS Reminders app, but instead of rolling a clone of the system’s underlying Reminders data store in Firebase I’ll be connecting to the original one. Once the basic create/delete/edit functionality is in place I have some ideas for different ways to view and manipulate tasks that I think could be useful for myself and others. Oh, and I’ll be writing mine for macOS and possibly iPadOS, because I think the iPhone screen is going to be too cramped for what I have in mind.
Since I’m going to be switching out bits and pieces derived from sample code from different sources, I’m making this as modular as I can, with a separate file for each view. Other than that, a #if statement for the .navigationBarTitle modifier that’s not available for macOS, and a few naming changes to make it easier to replace various elements of Friese’s code later, I haven’t yet written anything today that’s not taken directly from there, so there’s not much point in posting any of the code here.
Not sure if I’ll return to this before next weekend. Tomorrow I’m going to pick up where I left off in Paul Hudson’s 100 Days of SwiftUI.
Alternative Christmas movies for people who hate holiday sentimentality:
OK, I’ll give you Die Hard!
Bad Santa
Eyes Wide Shut
… other suggestions?
https://developer.apple.com/tutorials/swiftui/creating-a-macos-app
“The pattern for defining focused values resembles the pattern for definining new Environment values: Use a private key to read and write a custom property on the system-defined FocusedValues structure.”
“definining” lol
I am lost. Time to read the Swift language reference?
private struct SelectedLandmarkKey: FocusedValueKey {
typealias Value = Binding<Landmark>
}
extension FocusedValues {
var selectedLandmark: Binding<Landmark>? {
get { self[SelectedLandmarkKey.self] }
set { self[SelectedLandmarkKey.self] = newValue }
}
}
FocusedValues
is a struct type defined in the SwiftUI framework, a “collection of state exported by the focused view and its ancestors”.
So, within the app, ¿FocusedValues
knows if a given Landmark
is selected/has focus?
[ ] Find a thorough explanation of the <AngleBrackets>
syntax
[ ] And ¿what the heck is self[SelectedLandmarkKey.self]
?
[ ] Also find documentation for SwiftUI .tag(x)
modifier
SelectedLandmarkKey
is a struct that I just defined.
So SelectedLandmarkKey.self
is… a reference to that struct type?
And, in the extension, the first self
is a reference to (an instance of?) FocusedValues
[ ] But FocusedValues is a struct, not an array or a dictionary, so ¿how does the square brackets syntax work with structs?
Completely lost on this coordinator stuff.
import SwiftUI
import UIKit
struct PageViewController<Page: View>: UIViewControllerRepresentable {
var pages: [Page]
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIViewController(context: Context) -> UIPageViewController {
let pageViewController = UIPageViewController(
transitionStyle: .scroll,
navigationOrientation: .horizontal
)
pageViewController.dataSource = context.coordinator
return pageViewController
}
func updateUIViewController(_ pageViewController: UIPageViewController, context: Context) {
pageViewController.setViewControllers([context.coordinator.controllers[0]], direction: .forward, animated: true)
}
class Coordinator: NSObject, UIPageViewControllerDataSource {
var parent: PageViewController
var controllers = [UIViewController]()
init(_ pageViewController: PageViewController) {
parent = pageViewController
controllers = parent.pages.map { UIHostingController(rootView: $0) }
}
func pageViewController(
_ pageViewController: UIPageViewController,
viewControllerBefore viewController: UIViewController
) -> UIViewController? {
guard let index = controllers.firstIndex(of: viewController) else {
return nil
}
if index == 0 {
return controllers.last
}
return controllers[index - 1]
}
func pageViewController(
_ pageViewController: UIPageViewController,
viewControllerAfter viewController: UIViewController
) -> UIViewController? {
guard let index = controllers.firstIndex(of: viewController) else {
return nil
}
if index + 1 == controllers.count {
return controllers.first
}
return controllers[index + 1]
}
}
}
What do y’all think: update MailSuite and stick with Mail.app for another year, or drop a few extra bucks and jump ship to @MailMateApp?
Yes, even on Thanksgiving. (I suppose I should write something about how grateful I am to have the wherewithal to learn code, etc., and honestly I am, but I’m allergic to the orchestrated sentimentality that accompanies the fall and winter holidays.)
/// A type that provides a collection of all of its values.
///
/// Types that conform to the `CaseIterable` protocol are typically
/// enumerations without associated values. When using a `CaseIterable` type,
/// you can access a collection of all of the type's cases by using the type's
/// `allCases` property.
///
/// The compiler can automatically provide an implementation of the
/// `CaseIterable` requirements for any enumeration without associated values
/// or `@available` attributes on its cases. The synthesized `allCases`
/// collection provides the cases in order of their declaration.
var categories: [String: [Landmark]] {
Dictionary(
grouping: landmarks,
by: { $0.category.rawValue }
)
}
Still in the Apple SwiftUI tutorial.
I don’t like that the tutorial is having me drag in downloaded view files rather than writing them myself. Even if the code consists of techniques that have already been covered, I’m not a grizzled veteran who’s been coding Swift everyday for years, and the reinforcement would have been useful. I mean, I guess I could retype it from the downloaded source files…
Should I track down the source of the “snag” or just go on with the tutorial? I don’t really see myself drawing a lot of paths in my own apps, and I haven’t coded since starting my new (non-technical, alas) job, so I’d like to get on with the stuff I’m more interested in mastering.
I started the Apple SwiftUI tutorial as a break from Paul Hudson’s brilliant 100 Days of SwiftUI because the former includes a macOS lesson… but it’s preceded by quite a bit of iOS-centric material, and I still haven’t gotten to the Mac stuff.
The accompanying text of the tutorial (not the code itself, of course), always uses the full word ‘structure’, never just ‘struct’.
¿OK, what does Hashable do again, precisely?
Other than manually disabling and later reenabling cross-posting, is there a way to post to micro.blog without cross-posting on a per-post basis?
Back to (micro-) blogging, in the spirit of Andy Matuschak’s concept of “Working with the garage door open”. Time will tell how long I stick with it this time around and how often I actually post.