I got your code to work by:
changing DeviceModel so it doesn't inherit from anything
change setUpModel() to use the singleton
func setUpModel() {
BLEManager.shared.connectToDevice(to: index)
}
made BLEManager.init private
deleted the init from ContentView
in the App body, call ContentView() with no parameters
Post
Replies
Boosts
Views
Activity
I can reproduce your problem. Thank you for posting all your code, which made this possible.
BLEManager is supposed to a singleton, right? So you want exactly one of these in your program. To ensure this, you should make the initializer private and access the BLEManager only through shared. But in the ContentView, you create a BLEManager without going through shared, so now you have two - one created in the App's body, and one created by your ContentView.
If I make the BLEManager private, the compiler complains about the initializer for DeviceModel - "'super.init' isn't called on all paths before returning from initializer". Which is fair enough, but I'm not allowed to call super.init() - I made it private to ensure the all accesses to the singleton BLEManager go through its shared accessor.
I'm puzzled as to why a DeviceModel is a BLEManager. Just the names tell me that they are different objects; a Device may need access to a BLEManager, but it shouldn't be a BLEManager. Also, you expect an array of DeviceModels - how does that work if they are all the same object (BLEManager.shared?). It can work if they all use the same object.
Hi. I'm glad you asked this because I'm constantly tripping over SwiftUI syntax myself. There are a bunch of ways to express the contents of your NavigationSplitView.
Note that SwiftUI is not Swift. It looks like Swift, it is written in Swift, but it is a domain specific language for creating descriptions of user interfaces. It extends the Swift language.
If you look at the documentation for NavigationSplitView in Xcode's Documentation viewer, you'll find
struct NavigationSplitView<Sidebar, Content, Detail> where Sidebar : View, Content : View, Detail: View
and if you click on View, you'll find that it is a protocol.
The initializer you are using is the one which creates a two-column view, with no control over the visibility of the columns
public init(@ViewBuilder sidebar: () -> Sidebar, @ViewBuilder detail: () -> Detail) where Content == EmptyView
The parameters (labelled sidebar and detail here) are closures - functions returning structs conforming to the View protocol.
my SidebarView and DetailView are Views defined like this
struct SidebarView: View {
var body: some View {
Text("sidebar")
}
}
struct DetailView: View {
var body: some View {
Text("detail")
}
}
And here are functions which return these structs
func DetailViewFunc() -> DetailView {
return DetailView()
}
func SidebarViewFunc() -> SidebarView {
return SidebarView()
}
we can use these functions as parameter values:
struct ContentView: View {
var body: some View {
NavigationSplitView ( sidebar: SidebarViewFunc , detail: DetailViewFunc)
}
}
that's a bit verbose, but it does look like a regular function call with a parameter list.
More succinctly, you can just write the functions directly in the parameter list, without names. You can omit the return keyword because of the use of @ViewBuilder in the declaration of the NavigationSplitView initializer. You don't need SidebarViewFunc or DetailViewFunc any more. Usually, separate closures go on separate lines:
struct ContentView: View {
var body: some View {
NavigationSplitView (
sidebar: { SidebarView() },
detail: { DetailView() }
)
}
}
This works fine, but most code examples won't look like this. The Swift developers were very proud of how much typing you don't have to do. If the last parameter to a function is a closure, you can omit its name and move it outside the parentheses:
struct ContentView: View {
var body: some View {
NavigationSplitView (
sidebar: { SidebarView() } )
{ DetailView() }
}
}
this works too. However SwiftUI does quite a lot with closures, often views take multiple closure parameters, so some people thought it would be cool to extend this syntax to multiple trailing closures. See https://github.com/apple/swift-evolution/blob/main/proposals/0279-multiple-trailing-closures.md for more context. The rule here is that the first trailing closure can be unnamed, while the subsequent ones must be named. Which has the effect here of removing the visible "sidebar" label and reinstating the "detail" label. But because all the parameters are closures and were moved out of the parentheses, we can omit the parentheses, grounds for rejoicing in some circles. So now the ContentView can look like this:
struct ContentView: View {
var body: some View {
NavigationSplitView {
SidebarView() }
detail: {
DetailView() }
}
}
Xcode's code completion suggestions suggest the explicitly labelled parameter version, not the multiple trailing closure syntax version, which is unhelpful. And if you try to translate from Xcode's suggestion to trailing closure syntax, and forget to delete a comma, you'll see five compiler errors, none of which tell you that you have a comma which shouldn't be there.
struct ContentView: View {
var body: some View {
NavigationSplitView {
SidebarView() }, // added (and unnecessary) comma
detail: {
DetailView() }
}
}
if that bothers you, I'd encourage you to file a bug. Swift error reporting has improved since the beginning, but the language has also become more and more complex.
Stick at it. Eventually you'll get used to it, and know what to look for when Swift kicks out an error you cannot understand.
I'm using several (UVC) cameras on Sonoma 14.2 and they work okay. There's nothing generally broken about USB camera support on 14.2. This sounds like something you should report to Canon - as you say, the system report sees the camera but the EDSDK does not.
take a look at the AVCam sample code. It is for iOS, but most of it translates pretty well to macOS. You build a AVCaptureSession using your AVCaptureDevice, and set up a AVCapturePreviewLayer so you can see what it is producing.
There is also older sample code kicking around which is more Mac-oriented, and some third-party samples on GitHub. Try searching for "macOS AVCaptureSession sample"
it seems that HIDDriverKit isn't available on iPadOS. But you can write your own code to detect your custom device (using USBDriverKit) and your own routines to read and write reports, which are usually pretty simple control pipe writes and interrupt pipe reads. If your device isn't horrendously complicated, this is easier than using EA, and you don't need to deal with MFi licensing.
If you're trying to initialize an unsigned Swift integer from something that might be negative, Swift won't let you unless you're explicit.
let x:Int8 = -1
let y = UInt8(x)
fails because "negative value is not representable"
but this works
let y = UInt8(bitPattern: x)
y will be 255
/Applications/Xcode.app/Contents/Developer/Platforms/DriverKit.platform/Developer/SDKs/DriverKit.sdk/System/DriverKit/System/Library/Frameworks/USBDriverKit.framework
Yes, it is weird that you have to add it manually. Mine is saved relative to the Developer directory.
@cullenp you asked "how do I access the CMIO extension in the first place"
From an app, use the routines in CoreMediaIO/CMIOHardwareObject.h to iterate through the CMIO objects, starting at kCMIOObjectSystemObject until you find an object with kCMIODevicePropertyDeviceUID with a value equal to the value of the deviceID parameter used in your initializer of your CMIOExtensionDevice.
You also asked "Is it possible to supply the Extension provider source with my queue? "
I'm not sure what you're asking here. You find the sink stream's ID by querying the sink device you found using the code above. Using that sink stream ID, you can copy its queue using CMIOStreamCopyBufferQueue, and you use CMSimpleQueueEnqueue to put your samples onto the sink stream's queue.
have you read this thread? https://developer.apple.com/forums/thread/681053
You didn't post any code so I'm making an educated guess here.
Your ContentView contains a PreviewPane which is dependent on data from a LiDAR camera. You're developing on a Mac which doesn't have a LiDAR camera. The Preview runs on your Mac, not on the phone, so if it expects a LiDAR camera it isn't going to work.
Previews aren't magic, they are conveniences which enable you to see what your UI would look like under various circumstances. But if your UI is tied to dependencies which cannot be represented in the context of a preview, it is going to be difficult to preview. You're going to have to change your preview so that it isn't dependent on LiDAR. That probably means that your preview will just show a static image as a placeholder, and you're going to have to get the static image from somewhere and explicitly refer to it in your preview.
This is a problem I run into all the time because a lot of example code uses in-memory data structures for brevity, but the real world is much messier.
Neither forums.developer.apple.com nor discussions.apple.com are places where bugs are tracked or reported. Please report a bug using Feedback Assistant
You are not wrong, something did change - "The p and po command aliases have been redefined to the new dwim-print command."
More info here https://developer.apple.com/documentation/xcode-release-notes/xcode-15-release-notes
in the section "Debugging, New Features", or search for dwim-print, or scroll through the whole thing
You could take a look at this rather ancient sample code: https://developer.apple.com/library/archive/samplecode/TextEdit/Introduction/Intro.html, then see what has been deprecated and/or replaced since
Note that TextEdit performance is not great with large or complex files, and I have no idea if the currently-shipping TextEdit is still based on the code published in the link above or has been substantially updated.
If you want to look at newer code, try searching GitHub for "swift rich text".
see the function signatures in the Developer Documentation and follow those to some explanations of the use of the various types of buffers and buffer pointers.
func withUnsafeMutableBytes<R>((UnsafeMutableRawBufferPointer) throws -> R) rethrows -> R
and
func withUnsafeMutableBufferPointer<R>((inout UnsafeMutableBufferPointer<Element>) throws -> R) rethrows -> R
an UnsafeMutableRawBufferPointer is simply a pointer into untyped memory. It is just a bag of bytes.
an UnsafeMutableBufferPointer is a pointer into typed memory. Each element is of type Element. It is a bag of Elements.
You may need to use these APIs to interact with C APIs which take pointers to void *, char * or expect a contiguous array of Elements.