Post

Replies

Boosts

Views

Activity

Reply to Core Image drawing corruption
@FrankSchlegel wow thank you, I added the ROI callback (simply returning the images full extent) and the top image doesn't look corrupted anymore. I'm so confused as to why the default behavior is any different when an ROI callback is not specified, wow. Still not the end of the story though, when drawing large with interpolation disabled (NSImageInterpolationNone and kCAFilterNearest), the top image is doing something odd, new video here -> http://tclementdev.com/coreimage_metal_test2.mov
Topic: UI Frameworks SubTopic: AppKit Tags:
Jul ’23
Reply to Core Image drawing corruption
@FrankSchlegel here's a screen recording, top view is drawing the image in drawRect(), bottom view is assigning the image to the layer contents. The bottom view display what I expect. http://tclementdev.com/coreimage_metal_test.mov
Topic: UI Frameworks SubTopic: AppKit Tags:
Jul ’23
Reply to Core Image drawing corruption
I've done some further experiments: if I set the CGImage (obtained from the CIImage) directly onto the contents property of the layer of my view, then it works and display fine. But if I implement drawRect() and draw the CGImage into the CGContext using CGContextDrawImage() then it appears corrupted. How weird is that?
Topic: UI Frameworks SubTopic: AppKit Tags:
Jul ’23
Reply to NWConnection send buffer and when to send more data
Using a method like this to handle input is roughly the same as calling connection.receive(minimumIncompleteLength: 1, maximumLength: 1000), is there a reason you are not parsing out the length of your frame from the packet header? Hi Matt, in my app I do parse the length from the packet header. This is a reduced sample code, the simplest possible that demonstrates the problem. I added a protocol framer that basically does nothing (just passing the data along), and it changed the behavior of the writer, which seems wrong to me. About your code, you need to remove these three lines: if error == nil { startReceive(on: connection) } Because the whole point is to see what happens when the other side does not read (or rather does not read fast enough). If you remove these three lines, you will see that the sender keeps enqueuing indefinitely into memory explosion.
Sep ’21
Reply to NWConnection send buffer and when to send more data
Ok Quinn. I made further testing and the problem seems related to me using a protocol framer. Give it a try and let me know what you think. import Foundation import Network class MyProtocol: NWProtocolFramerImplementation { // Create a global definition of your game protocol to add to connections. static let definition = NWProtocolFramer.Definition(implementation: MyProtocol.self) // Set a name for your protocol for use in debugging. static var label: String { return "MyProtocol" } // Set the default behavior for most framing protocol functions. required init(framer: NWProtocolFramer.Instance) { } func start(framer: NWProtocolFramer.Instance) -> NWProtocolFramer.StartResult { return .ready } func wakeup(framer: NWProtocolFramer.Instance) { } func stop(framer: NWProtocolFramer.Instance) -> Bool { return true } func cleanup(framer: NWProtocolFramer.Instance) { } // Whenever the application sends a message, add your protocol header and forward the bytes. func handleOutput(framer: NWProtocolFramer.Instance, message: NWProtocolFramer.Message, messageLength: Int, isComplete: Bool) { try? framer.writeOutputNoCopy(length: messageLength) } // Whenever new bytes are available to read, try to parse out your message format. func handleInput(framer: NWProtocolFramer.Instance) -> Int { let message = NWProtocolFramer.Message(definition: MyProtocol.definition) _ = framer.deliverInputNoCopy(length: 1000, message: message, isComplete: true) return 0 } } var listenerRef: NWListener? = nil var receiveConnectionRef: NWConnection? = nil func startListener() { let options = NWProtocolFramer.Options(definition: MyProtocol.definition) let parameters = NWParameters.tcp parameters.defaultProtocolStack.applicationProtocols.insert(options, at: 0) let listener = try! NWListener(using: parameters, on: 12345) listenerRef = listener listener.stateUpdateHandler = { state in print("listener: state did change, new: \(state)") } listener.newConnectionHandler = { conn in if let old = receiveConnectionRef { print("listener: will cancel old connection") old.cancel() receiveConnectionRef = nil } receiveConnectionRef = conn startReceive(on: conn) conn.start(queue: .main) } listener.start(queue: .main) } func startReceive(on connection: NWConnection) { connection.receiveMessage { dataQ, _, isComplete, errorQ in if let data = dataQ { print("receiver: did received, count: \(data.count)") } if let error = errorQ { print("receiver: did fail, error: \(error)") return } // if isComplete { // print("receiver: is complete") // return // } print("receiver: will not start new receive to force back pressure") } } var sendConnectionRef: NWConnection? = nil var totalSent = 0 func sendRandomData(to connection: NWConnection) { var bytes = [UInt8](repeating: 0, count: 1000) let err = SecRandomCopyBytes(kSecRandomDefault, bytes.count, &bytes) assert(err == errSecSuccess) let message = NWProtocolFramer.Message(definition: MyProtocol.definition) let context = NWConnection.ContentContext(identifier: "Data", metadata: [message]) connection.send(content: Data(bytes), contentContext: context, completion: .contentProcessed({ errorQ in if let error = errorQ { print("sender: send failed, error: \(error)") return } totalSent += bytes.count print("sender: did send, total: \(totalSent)") sendRandomData(to: connection) })) } func startSender() { let options = NWProtocolFramer.Options(definition: MyProtocol.definition) let parameters = NWParameters.tcp parameters.defaultProtocolStack.applicationProtocols.insert(options, at: 0) let connection = NWConnection(host: "localhost", port: 12345, using: parameters) sendConnectionRef = connection // Guarantees a long-lived referenced. connection.stateUpdateHandler = { state in print("sender: state did change, new: \(state)") } sendRandomData(to: connection) connection.start(queue: .main) } func main() { startListener() startSender() dispatchMain() } main() exit(EXIT_SUCCESS)
Sep ’21
Reply to Core Image drawing corruption
The image view width is a multiply of 6 and should be able to represent all pixels as they are without any trick, so it doesn't seem like it should do that.
Topic: UI Frameworks SubTopic: AppKit Tags:
Replies
Boosts
Views
Activity
Jul ’23
Reply to Core Image drawing corruption
@FrankSchlegel wow thank you, I added the ROI callback (simply returning the images full extent) and the top image doesn't look corrupted anymore. I'm so confused as to why the default behavior is any different when an ROI callback is not specified, wow. Still not the end of the story though, when drawing large with interpolation disabled (NSImageInterpolationNone and kCAFilterNearest), the top image is doing something odd, new video here -> http://tclementdev.com/coreimage_metal_test2.mov
Topic: UI Frameworks SubTopic: AppKit Tags:
Replies
Boosts
Views
Activity
Jul ’23
Reply to Core Image drawing corruption
@FrankSchlegel here's a screen recording, top view is drawing the image in drawRect(), bottom view is assigning the image to the layer contents. The bottom view display what I expect. http://tclementdev.com/coreimage_metal_test.mov
Topic: UI Frameworks SubTopic: AppKit Tags:
Replies
Boosts
Views
Activity
Jul ’23
Reply to Core Image drawing corruption
For anyone at Apple seeing this, I filed FB12608056 with sample code and screen recording.
Topic: UI Frameworks SubTopic: AppKit Tags:
Replies
Boosts
Views
Activity
Jul ’23
Reply to Core Image drawing corruption
I've done some further experiments: if I set the CGImage (obtained from the CIImage) directly onto the contents property of the layer of my view, then it works and display fine. But if I implement drawRect() and draw the CGImage into the CGContext using CGContextDrawImage() then it appears corrupted. How weird is that?
Topic: UI Frameworks SubTopic: AppKit Tags:
Replies
Boosts
Views
Activity
Jul ’23
Reply to Is there a way to get the built-in list of anchor certificates from the OS?
@eskimo here it is: FB12059413
Replies
Boosts
Views
Activity
Mar ’23
Reply to Is there a way to get the built-in list of anchor certificates from the OS?
Would there be a way to tell whether an instance of SecCertificateRef is trusted as part of the immutable store vs. the system/user keychain?
Replies
Boosts
Views
Activity
Mar ’23
Reply to Is there a way to get the built-in list of anchor certificates from the OS?
iOS and macOS. Trying to block real attacks/snooping, not the device owner inspecting traffic.
Replies
Boosts
Views
Activity
Mar ’23
Reply to App disappears from the share sheet ios 15.3
I'm having this problem too. Is there any solution?
Topic: App & System Services SubTopic: Core OS Tags:
Replies
Boosts
Views
Activity
Dec ’22
Reply to SwiftUI app cycle and opening an app document
Seems like I have found a solution which is to add .handlesExternalEvents(matching: []) to the WindowGroup.
Topic: UI Frameworks SubTopic: SwiftUI Tags:
Replies
Boosts
Views
Activity
Sep ’21
Reply to NWConnection send buffer and when to send more data
Thank you Quinn. It is at least good to have confirmation and know where I can stand. Good to hear you plan to fix it soon as well, even though I have to work with it for now. I have had other issues with custom framers as well (FB9405024, FB9430130). Hopefully the tech will eventually mature and I can use it again.
Replies
Boosts
Views
Activity
Sep ’21
Reply to NWConnection send buffer and when to send more data
The framing protocol very much seems to be playing a role, this is what I think I have established with the help of Quinn. The code posted by Quinn works: the writer stops enqueuing quickly. I took Quinn's code and only added the protocol framer (that merely passes the data along) and now the writer enqueues into memory explosion.
Replies
Boosts
Views
Activity
Sep ’21
Reply to NWConnection send buffer and when to send more data
Using a method like this to handle input is roughly the same as calling connection.receive(minimumIncompleteLength: 1, maximumLength: 1000), is there a reason you are not parsing out the length of your frame from the packet header? Hi Matt, in my app I do parse the length from the packet header. This is a reduced sample code, the simplest possible that demonstrates the problem. I added a protocol framer that basically does nothing (just passing the data along), and it changed the behavior of the writer, which seems wrong to me. About your code, you need to remove these three lines: if error == nil { startReceive(on: connection) } Because the whole point is to see what happens when the other side does not read (or rather does not read fast enough). If you remove these three lines, you will see that the sender keeps enqueuing indefinitely into memory explosion.
Replies
Boosts
Views
Activity
Sep ’21
Reply to NWConnection send buffer and when to send more data
Sure. Thank you Quinn!
Replies
Boosts
Views
Activity
Sep ’21
Reply to NWConnection send buffer and when to send more data
Ok Quinn. I made further testing and the problem seems related to me using a protocol framer. Give it a try and let me know what you think. import Foundation import Network class MyProtocol: NWProtocolFramerImplementation { // Create a global definition of your game protocol to add to connections. static let definition = NWProtocolFramer.Definition(implementation: MyProtocol.self) // Set a name for your protocol for use in debugging. static var label: String { return "MyProtocol" } // Set the default behavior for most framing protocol functions. required init(framer: NWProtocolFramer.Instance) { } func start(framer: NWProtocolFramer.Instance) -> NWProtocolFramer.StartResult { return .ready } func wakeup(framer: NWProtocolFramer.Instance) { } func stop(framer: NWProtocolFramer.Instance) -> Bool { return true } func cleanup(framer: NWProtocolFramer.Instance) { } // Whenever the application sends a message, add your protocol header and forward the bytes. func handleOutput(framer: NWProtocolFramer.Instance, message: NWProtocolFramer.Message, messageLength: Int, isComplete: Bool) { try? framer.writeOutputNoCopy(length: messageLength) } // Whenever new bytes are available to read, try to parse out your message format. func handleInput(framer: NWProtocolFramer.Instance) -> Int { let message = NWProtocolFramer.Message(definition: MyProtocol.definition) _ = framer.deliverInputNoCopy(length: 1000, message: message, isComplete: true) return 0 } } var listenerRef: NWListener? = nil var receiveConnectionRef: NWConnection? = nil func startListener() { let options = NWProtocolFramer.Options(definition: MyProtocol.definition) let parameters = NWParameters.tcp parameters.defaultProtocolStack.applicationProtocols.insert(options, at: 0) let listener = try! NWListener(using: parameters, on: 12345) listenerRef = listener listener.stateUpdateHandler = { state in print("listener: state did change, new: \(state)") } listener.newConnectionHandler = { conn in if let old = receiveConnectionRef { print("listener: will cancel old connection") old.cancel() receiveConnectionRef = nil } receiveConnectionRef = conn startReceive(on: conn) conn.start(queue: .main) } listener.start(queue: .main) } func startReceive(on connection: NWConnection) { connection.receiveMessage { dataQ, _, isComplete, errorQ in if let data = dataQ { print("receiver: did received, count: \(data.count)") } if let error = errorQ { print("receiver: did fail, error: \(error)") return } // if isComplete { // print("receiver: is complete") // return // } print("receiver: will not start new receive to force back pressure") } } var sendConnectionRef: NWConnection? = nil var totalSent = 0 func sendRandomData(to connection: NWConnection) { var bytes = [UInt8](repeating: 0, count: 1000) let err = SecRandomCopyBytes(kSecRandomDefault, bytes.count, &bytes) assert(err == errSecSuccess) let message = NWProtocolFramer.Message(definition: MyProtocol.definition) let context = NWConnection.ContentContext(identifier: "Data", metadata: [message]) connection.send(content: Data(bytes), contentContext: context, completion: .contentProcessed({ errorQ in if let error = errorQ { print("sender: send failed, error: \(error)") return } totalSent += bytes.count print("sender: did send, total: \(totalSent)") sendRandomData(to: connection) })) } func startSender() { let options = NWProtocolFramer.Options(definition: MyProtocol.definition) let parameters = NWParameters.tcp parameters.defaultProtocolStack.applicationProtocols.insert(options, at: 0) let connection = NWConnection(host: "localhost", port: 12345, using: parameters) sendConnectionRef = connection // Guarantees a long-lived referenced. connection.stateUpdateHandler = { state in print("sender: state did change, new: \(state)") } sendRandomData(to: connection) connection.start(queue: .main) } func main() { startListener() startSender() dispatchMain() } main() exit(EXIT_SUCCESS)
Replies
Boosts
Views
Activity
Sep ’21