Swift Cannot find variable in scope - swift

Swift giving error that var is not in scope. "Cannot find 'midiManager' in scope" I am not sure how to fix issue
menu.swift
struct MainMenuBar: MenuBar {
public var body: StandardMenuBar {
StandardMenu(title: "Midi Devices") {
midiManager.endpoints.outputs.forEach { device in
TextMenuItem(title: device.name) { _ in
print(device.uniqueID)
}
}
}
}
}
midi.swift
#objc(ReactNativeMidiModule)
class ReactNativeMidiModule: RCTEventEmitter, NSApplicationDelegate {
// Create midi manager
public let midiManager = MIDI.IO.Manager(
clientName: "MIDIEventLogger",
model: "ELMC Midi Monitor",
manufacturer: "ELMC")
// other code
}

midiManager is not present inside your MainMenueBar. So midiManager can not be found. You must need to add midiManager inside your MainMenueBar structure. Like this -
struct MainMenuBar: MenuBar
{
public let midiManager = MIDI.IO.Manager(clientName: "MIDIEventLogger", model: "ELMC Midi Monitor", manufacturer: "ELMC")
public var body: StandardMenuBar
{
StandardMenu(title: "Midi Devices")
{
midiManager.endpoints.outputs.forEach { device in
TextMenuItem(title: device.name) { _ in
print(device.uniqueID)
}
}
}
}
}
or
By creating a common class as-
class MidiManager {
static let midiManager = MIDI.IO.Manager(clientName: "MIDIEventLogger", model: "ELMC Midi Monitor", manufacturer: "ELMC")
}
And then use it in both MainMenuBar and ReactNativeMidiModule as-
struct MainMenuBar: MenuBar {
public let midiManager = MidiManager.midiManager
public var body: StandardMenuBar {
StandardMenu(title: "Midi Devices") {
midiManager.endpoints.outputs.forEach { device in
TextMenuItem(title: device.name) { _ in
print(device.uniqueID)
}
}
}
}
}
#objc(ReactNativeMidiModule)
class ReactNativeMidiModule: RCTEventEmitter, NSApplicationDelegate {
// Create midi manager
public let midiManager = MidiManager.midiManager
// other code
}

Related

Using Child SwitchStore Views within a Parent's ForEachStore View

I'm facing an issue implementing The Swift Composable Architecture in which I have a list of IdentifiedArray rows within my AppState that holds RowState which holds an EnumRowState as part of it's state, to allow me to SwitchStore on it within a RowView that is rendered within a ForEachStore on the AppView.
The problem I'm running into is that within a child reducer called liveReducer, there is an Effect.timer that is updating every one second, and should only be causing the LiveView to re-render.
However what's happening is that the AddView is also getting re-rendered every time too! The reason I know this is because I've manually added a Text("\(Date())") within the AddView and I see the date changing every one second regardless of the fact that it's not related in anyway to a change in state.
I've added .debug() to the appReducer and I see in the logs that the rows part of the sate shows ...(1 unchanged) which sounds right, so why then is every single row being re-rendered on every single Effect.timer effect?
Thank you in advance!
Below is how I've implemented this:
P.S. I've used a technique as describe here to pullback reducers on an enum property:
https://forums.swift.org/t/pullback-reducer-on-enum-property-switchstore/52628
Here is a video of the problem, in which you can see that once I've selected a name from the menu, ALL the views are getting updated, INCLUDING the navBarTitle!
https://youtube.com/shorts/rn_Yd57n1r8
struct AppState: Equatable {
var rows: IdentifiedArray<UUID, RowState> = []
}
enum AppAction: Equatable {
case row(id: UUID, action: RowAction)
}
public struct RowState: Equatable, Identifiable {
public var enumRowState: EnumRowState
public let id: UUID
}
public enum EnumRowState: Equatable {
case add(AddState)
case live(LiveState)
}
public enum RowAction: Equatable {
case live(AddAction)
case add(LiveAction)
}
public struct LiveState: Equatable {
public var secondsElapsed = 0
}
enum LiveAction: Equatable {
case onAppear
case onDisappear
case timerTicked
}
struct AppState: Equatable { }
enum AddAction: Equatable { }
public let liveReducer = Reducer<LiveState, LiveAction, LiveEnvironment>.init({
state, action, environment in
switch action {
case .onAppear:
return Effect
.timer(
id: state.baby.uid,
every: 1,
tolerance: .zero,
on: environment.mainQueue)
.map { _ in
LiveAction.timerTicked
})
case .timerTicked:
state.secondsElapsed += 1
return .none
case .onDisappear:
return .cancel(id: state.baby.uid)
}
})
public let addReducer = Reducer<AddState, AddAction, AddEnvironment>.init({
state, action, environment in
switch action {
})
}
///
/// Intermediate reducers to pull back to an Enum State which will be used within the `SwitchStore`
///
public var intermediateAddReducer: Reducer<EnumRowState, RowAction, RowEnvironment> {
return addReducer.pullback(
state: /EnumRowState.add,
action: /RowAction.add,
environment: { ... }
)
}
public var intermediateLiveReducer: Reducer<EnumRowState, RowAction, RowEnvironment > {
return liveReducer.pullback(
state: /EnumRowState.live,
action: /RowAction.live,
environment: { ... }
)
}
public let rowReducer: Reducer<RowState, RowAction, RowEnvironment> = .combine(
intermediateAddReducer.pullback(
state: \RowState.enumRowState,
action: /RowAction.self,
environment: { $0 }
),
intermediateLiveReducer.pullback(
state: \RowState.enumRowState,
action: /RowAction.self,
environment: { $0 }
)
)
let appReducer: Reducer<AppState, AppAction, AppEnvironment> = .combine(
rowReducer.forEach(
state: \.rows,
action: /AppAction.row(id:action:),
environment: { ... }
),
.init({ state, action, environment in
switch action {
case AppAction.onAppear:
state.rows = [
RowState(id: UUID(), enumRowState: .add(AddState()))
RowState(id: UUID(), enumRowState: .add(LiveState()))
]
return .none
default:
return .none
}
})
)
.debug()
public struct AppView: View {
let store: Store<AppState, AppAction>
public var body: some View {
WithViewStore(self.store) { viewStore in
List {
ForEachStore(
self.store.scope(
state: \AppState.rows,
action: AppAction.row(id:action:))
) { rowViewStore in
RowView(store: rowViewStore)
}
}
}
}
public struct RowView: View {
public let store: Store<RowState, RowAction>
public var body: some View {
WithViewStore(self.store) { viewStore in
SwitchStore(self.store.scope(state: \RowState.enumRowState)) {
CaseLet(state: /EnumRowState.add, action: RowAction.add) { store in
AddView(store: store)
}
CaseLet(state: /EnumRowState.live, action: RowAction.live) { store in
LiveView(store: store)
}
}
}
}
}
struct LiveView: View {
let store: Store<LiveState, LiveAction>
var body: some View {
WithViewStore(self.store) { viewStore in
Text(viewStore.secondsElapsed)
}
}
}
struct AddView: View {
let store: Store<AddState, AddAction>
var body: some View {
WithViewStore(self.store) { viewStore in
// This is getting re-rendered every time the `liveReducer`'s `secondsElapsed` state changes!?!
Text("\(Date())")
}
}
}

How to define extension for SectionedFetchResults with Key (String) and Result (NSFetchRequestResult)

I have SectionedFetchResults defined like this:
private var consumption: SectionedFetchResults<String?, MedicationConsumption>
MedicationConsumption have variable quantity. I need to write extension for consumption that, it will have function totalQuantity. I have tried various way on extending it, but without any luck.
How to write extension on SectionedFetchResults, that it will return totalQuantity??
1st extension which is not working:
extension SectionedFetchResults where Result == NSManagedObject {
var totalQuantity: Int { /* Code here */ }
}
2nd extension which is not compiling:
extension SectionedFetchResults<String, NSFetchRequestResult>.Element {
var totalQuantity: Int { /* Code here */ }
}
Source code:
static var fetchRequest: NSFetchRequest<MedicationConsumption> {
let result = MedicationConsumption.fetchRequest()
result.sortDescriptors = [NSSortDescriptor(keyPath: \MedicationConsumption.date, ascending: true)]
result.predicate = NSPredicate(format: "(medication.type == 1)")
return result
}
#SectionedFetchRequest(fetchRequest: Self.fetchRequest, sectionIdentifier: \MedicationConsumption.group)
private var consumption: SectionedFetchResults<String?, MedicationConsumption>
// Use case scenario
var body: some View {
List(waterConsumption) { section in
VStack {
Text("\(section.totalQuantity)")
}
}
}
MedicationConsumption: NSManagedObject
extension MedicationConsumption {
#nonobjc public class func fetchRequest() -> NSFetchRequest<MedicationConsumption> {
return NSFetchRequest<MedicationConsumption>(entityName: "MedicationConsumption")
}
#NSManaged public var date: Date?
#NSManaged public var group: String?
#NSManaged public var quantity: Double
#NSManaged public var medication: Medication?
}
I assume it can be like
for Grand Total for response:
extension SectionedFetchResults where Result == MedicationConsumption {
var totalQuantity: Double {
self.reduce(0) { sum, section in
section.reduce(into: sum) { $0 += $1.quantity }
}
}
}
for total in Section
extension SectionedFetchResults.Section where Result == MedicationConsumption {
var totalQuantity: Double {
self.reduce(0) { $0 + $1.quantity }
}
}
Tested module in project

MacOS: conditional CommandGroup

I have a custom CommandGroup (customPasteboardCommands - it replaces the built-in .pasteboard group) which I would like to render conditionally.
What is the correct syntax?
I tried two ways, none of them worked:
First
if viewModel.shouldUseCustomCommandGroup {
customPasteboardCommands
}
Error:
Closure containing control flow statement cannot be used with result
builder 'CommandsBuilder'
Second:
viewModel.shouldUseCustomCommandGroup ? customPasteboardCommands : EmptyCommands()
Error:
Result values in '? :' expression have mismatching types 'some
Commands' and 'EmptyCommands'
Full code:
App.swift
import SwiftUI
#main
struct macos_playgroundApp: App {
private let viewModel = ViewModel()
var body: some Scene {
WindowGroup {
Button("Toggle custom CommandGroup") {
viewModel.onToggleCustomCommandGroup()
}
}
.commands {
commands
}
}
#CommandsBuilder
var commands: some Commands {
emptyNewItemCommands
viewModel.shouldUseCustomCommandGroup ? customPasteboardCommands : EmptyCommands()
}
var emptyNewItemCommands: some Commands {
CommandGroup(replacing: .newItem) {}
}
var customPasteboardCommands: some Commands {
CommandGroup(replacing: .pasteboard) {
Button("Select All") {
print("Custom select all activated")
}
.keyboardShortcut("a", modifiers: [.command])
}
}
}
ViewModel.swift
import Foundation
class ViewModel: ObservableObject {
#Published var shouldUseCustomCommandGroup: Bool = false
func onToggleCustomCommandGroup() {
shouldUseCustomCommandGroup = !shouldUseCustomCommandGroup
}
}

Get rid off extra output in playground

I am currently learning swift, so I'm working in the swift playground with xcode.
I am working with classes but I get some extra output that it's just kind of distracting for me.
I don't know if I have modify xcode preference or there is something wrong with my code.
//: Playground - noun: a place where people can play
import UIKit
class Person {
var name = ""
}
class BlogPost {
var title:String?
var body = ""
var author:Person!
var numberOfComments = 0
}
let post = BlogPost()
if let actualTitle = post.title {
}
I just want to get rid off the __lldb_expr_114.
Use a protocol oriented approach:
import Foundation
import Swift
protocol PlaygroundFriendlyClass: CustomStringConvertible
{
}
extension PlaygroundFriendlyClass
{
var description: String
{
return String(describing: type(of: self)).components(separatedBy: ".").last!
}
}
class Foo: PlaygroundFriendlyClass
{
init()
{
}
}
class Bar: PlaygroundFriendlyClass
{
init()
{
}
}
Foo() // "Foo"
Bar() // "Bar"
Add the description property:
var description : String {
return "BlogPost \(author) - \(title)"
}

Command Pattern example confusion

I am going through the Head-First Design Pattern book when I came across the "Command Pattern" chapter. I have recreated the example in Playground:
protocol RemoteActions {
func turnOn()
}
protocol Product {
var description: String { get set }
}
struct Light: Product {
var description: String
// some other properties
}
struct Heater: Product {
var description: String
// some other properties
}
class LightOn: RemoteActions {
var light: Light
init(light: Light) {
self.light = light
}
func turnOn() {
print("\(light.description) on")
}
}
class HeaterOn: RemoteActions {
var heater: Heater
init(heater: Heater) {
self.heater = heater
}
func turnOn() {
print("\(heater.description) on")
}
}
class Remote {
func doAction(action: RemoteActions) {
action.turnOn()
}
}
let r = Remote()
let l = Light(description: "light1")
let h = Heater(description: "heater1")
let lo = LightOn(light: l)
let ho = HeaterOn(heater: h)
r.doAction(action: lo)
r.doAction(action: ho)
I mean what are the benefits of this pattern?? Yes, I can see that the remote will only know about its actions, but what if I wanted to create a new Product to be turned on and off? I will undoubtfully have to create a new "Command Class" right? Which makes this part in the book really silly:
Wouldn't it be better if we conformed the action into said Product? Like this:
protocol RemoteActions {
func turnOn()
}
protocol Product: RemoteActions {
var description: String { get set }
func turnOn()
}
struct Light: Product {
var description: String
// some other properties
func turnOn() {
print("\(description) on")
}
}
struct Heater: Product {
var description: String
// some other properties
func turnOn() {
print("\(description) on")
}
}
class Remote {
func doAction(product: Product) {
product.turnOn()
}
}
let r = Remote()
let l = Light(description: "light1")
let h = Heater(description: "heater1")
r.doAction(product: l)
r.doAction(product: h)
gof says: 'The Command pattern lets toolkit objects make requests of unspecified application objects by turning the request itself into an object. This object can be stored and passed around like other objects. The key to this pattern is an abstract Command class, which declares an interface for executing operations. In the simplest form this interface includes an abstract Execute operation. Concrete Command subclasses specify a receiver-action pair by storing the receiver as an instance variable and by implementing Execute to invoke the request. The receiver has the knowledge required to carry out the request.'