Unable to register NSUndoManager in Swift 6.1 GM seed2 - swift

I am unable to get NSUndoManager to function in Swift Xcode release 6.1 GM Seed 2. I've read several times the article How do I register NSUndoManager in Swift? but I can't make it work in 6.1.
Here is a code snippet showing my attempt:
func zoomFractalClick(imagePoint: NSPoint?) {
//NSLog("Point zoomed \(imagePoint)")
if imagePoint == nil { return }
let tag = zoomPopUp.selectedItem!.tag
// Try setting undo/redo
undoManager.registerUndoWithTarget(self, selector: Selector("resetFractalDef"),
object: StructWrapper<MJFractalDefinition>(object: fractalDef))
//(undoManager.prepareWithInvocationTarget(self) as AppDelegate).
// resetFractalDef(StructWrapper<MJFractalDefinition>(object: fractalDef))
fractalDef.zoomBounds(centerPoint: imagePoint!, zoomPower: Double(tag))
drawFractal()
}
func resetFractalDef( fractalDef: StructWrapper<MJFractalDefinition>) {
self.fractalDef = fractalDef.object
drawFractal()
}
class StructWrapper<T> {
let object: T
init( object: T) {
self.object = object
}
}
Using the 'simple' method, everything compiles and runs correctly even saving the Undo. However when I select Undo from the Edit menu, I get the error that it can't find the selector 'resetFractalDef'.
I've also tried the prepare with invocation method of Undo, and it fails at the point where it tries to prepare the undo with invocation target reporting 'EXC_BREAKPOINT'.
Please, any help would be appreciated. I am a Java programmer learning to program in the Apple environment mostly enjoying the using Swift.

Related

EXC_BAD_ACCESS when access to class property

I have a very simple code, but when I call testFunc() it crashes on line value = NSObject() with error EXC_BAD_ACCESS (code=EXC_I386_GPFLT). Could anyone explain, why does it happens?
class A {
var object: Any?
convenience init() {
self.init(nil)
}
private init(_ object: Any?) {
self.object = object
}
}
class B: A {
var value: Any?
func test() {
value = NSObject()
}
}
func testFunc() {
let b = B()
b.test()
}
If I run your code in a Mac command line tool, it works just fine. If I run it as an iOS playground, it crashes.
It looks like a bug in playgrounds to me. (It wouldn't be the first time. I find playgrounds pretty unstable, and tend to test out non-UI coding ideas with command line tools rather than playgrounds because I find playgrounds to be flaky and unreliable.)
I tried adding print statements at various points, and the first time I added a print statement it didn't crash. Then several edit/run cycles later, it didn't crash again. I don't see anything wrong with your code (other than the fact that it doesn't really do anything, and there's no real point in creating an empty NSObject.)

An error occurs in the overridden function of XCUITest

An error occurs in the overridden function of XCUITest.
I have never mentioned XCUITest.
The error is: "Method does not override method in superclass".
This happens when you change Xcode from version 11.4 beta 2 to 11.3.1 and build.
what should I do?
import XCTest
class SampleAppUITests: XCTestCase {
override func setUpWithError() throws {
// Put setup code here. This method is called before the invocation of each test method in the class.
// In UI tests it is usually best to stop immediately when a failure occurs.
continueAfterFailure = false
// In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
}
override func tearDownWithError() throws {
// Put teardown code here. This method is called after the invocation of each test method in the class.
}
func testExample() throws {
// UI tests must launch the application that they test.
let app = XCUIApplication()
app.launch()
// Use recording to get started writing UI tests.
// Use XCTAssert and related functions to verify your tests produce the correct results.
}
func testLaunchPerformance() throws {
if #available(macOS 10.15, iOS 13.0, tvOS 13.0, *) {
// This measures how long it takes to launch your application.
measure(metrics: [XCTOSSignpostMetric.applicationLaunch]) {
XCUIApplication().launch()
}
}
}
}
Explained in the release notes:
https://developer.apple.com/documentation/xcode_release_notes/xcode_11_4_beta_3_release_notes
You (the template) are calling methods that don’t exist when you use Xcode 11.3.1 or before. Use availability to replace setUpWithError and tearDownWithError (Swift 5.2) with simple setUp and tearDown (Swift 5.1).

EKEventStore.calendars is always empty after clean install

I have a weird issue on my iOS app where, after a fresh install, if I try to add calendar events (after accepting the native calendar permissions prompt), my eventStore singleton never shows any available calendars, and defaultCalendarForNewEvents is always nil.
I've tried to debug it, and the odd part is that, if I try po EKEventStore().calendars(for: .event), then I can see them all (still on fresh install).
If I then kill the app and reopen it, my eventStore singleton suddenly starts working as expected.
I'm not sure if this behaviour has been documented before, it seems very strange to me and I couldn't find other posts with this specific issue...
Hereafter a snippet of my CalendarManager class and how the eventStore singleton is declared.
class CalendarManager {
// MARK: Variables
static let sharedInstance = CalendarManager()
fileprivate init() { }
let eventStore = EKEventStore()
// further business logic...
}
And further down, the code where I encounter issues:
func createEvent(for workout: Workout, sendReminder: Bool = false) -> Bool {
// If I add a breakpoint below and check a new instance of EKEventStore,
// I can see all calendars & defaultCalendarForNewEvents,
// however this `guard` never lets us through...
guard let calendar = CalendarManager.sharedInstance.eventStore.defaultCalendarForNewEvents else { return false }
// create event with default calendar...
}
What am I doing wrong?
Make sure you aren't initializing EKEventStore before requesting calendar permissions.

Swift Privileged Helper (XPC Listener) Crashing with Illegal Instruction Error

I’ve created a Swift macOS app which uses SMJobBless to create a helper with escalated privileges. This works fine—the helper gets installed to /Library/Privileged Helper Tools and an accompanying LaunchDaemon gets created in /Library/LaunchDaemons. However, the helper is unable to start successfully. Instead, it crashes with an “Illegal instruction: 4” message.
I’ve prepared the helper to respond to XML connections by implementing the NSXPCListenerDelegate protocol. Here‘s my Helper main.swift code:
import Foundation
class HelperDelegate: NSObject, NSXPCListenerDelegate {
func listener(_ listener: NSXPCListener, shouldAcceptNewConnection newConnection: NSXPCConnection) -> Bool {
newConnection.exportedInterface = NSXPCInterface(with: HelperToolProtocol.self)
newConnection.exportedObject = HelperTool()
newConnection.resume()
return true
}
}
let delegate = HelperDelegate()
let listener = NSXPCListener.service()
listener.delegate = delegate
listener.resume()
The crash occurs on the last line, listener.resume().
I tried to launch the helper app manually from the command line (which is identical to what the LaunchDaemon does) and, again, it crashes with the above error message printed to stdout. I don’t have any more ideas on how to test this for the root cause. My implementation is more than rudimentary, following Apple’s guidlines for implementing XM services. Also, the various posts on SO regarding XML services haven’t helped me in resolving this issue. Has anyone of you tried to create a privileged helper in Swift successfully? BTW, the app is not sandboxed.
For the sake of completeness, here’s the code for the HelperTool class referenced in my HelperDelegate class above:
import Foundation
class HelperTool: NSObject, HelperToolProtocol {
func getVersion(withReply reply: (NSData?) -> ()) {
let version = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString" as String) as? String ?? "<unknown version>"
let build = Bundle.main.object(forInfoDictionaryKey: kCFBundleVersionKey as String) as? String ?? "<unknown build>"
if let d = "v\(version) (\(build))".data(using: .utf8, allowLossyConversion: false) {
reply(d as NSData)
}
}
}
And finally the HelperToolProtocol:
import Foundation
#objc(HelperToolProtocol) protocol HelperToolProtocol {
func getVersion(withReply: (NSData?) -> ())
}
Thanks for any help!
After days of testing I finally found a solution which makes my XPC helper launch correctly and respond to any messages. The problem lies in the last three lines of the main.swift module which currently read
let listener = NSXPCListener.service()
listener.delegate = delegate
listener.resume()
which, as put in the question, make the helper crash immediately upon the very last line.
I took these lines directly from Apple’s Creating XPC Services documentation. Here’s the documentation for the NSXPCListener resume() function:
If called on the service() object, this method never returns. Therefore, you should call it as the last step inside the XPC service's main function after setting up any desired initial state and configuring the listener itself.
The solution is to not call the NSXPCListener.service() singleton object but rather instantiate a new NSXPCListener object using the init(machServiceName:)initializer passing the same Mach service name that is being used on the main app’s XPC connection. As resume() in this case would resume immediately—thus terminating the helper—you have to put it on the current run loop to have it run indeterminately. Here’s the new, working code:
let listener = NSXPCListener(machServiceName: "Privilege-Escalation-Sample.Helper")
listener.delegate = delegate
listener.resume()
RunLoop.current.run()

LLDB 'thread return' command emits error in a Swift function

I am reading the Dancing in the Debugger — A Waltz with LLDB article. And I am trying the thread return command with Swift 2.2 as well as Swift 3.0.
My code is pretty simple:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let resust = test()
print(resust)
}
func test() -> Bool {
return true
}
}
and I added a breakpoint at the beginning of the test() function with a thread return false action. However, after command+R, my program stops at the breakpoint as expect, but with the following error:
"error: Error returning from frame 0 of thread 1: We only support setting simple integer and float return types at present.."
Here's a screen shot:
Then I tried the same in Objective-C code; everything goes well.
These are known bugs. The value types in Swift (Int, Bool, etc.) are all complex objects, and we haven't taught lldb how to overwrite the return values for them. Error handling will also make this tricky.
In general, forced returns are unsafe - more so with ARC and even more so with Swift, since you are likely to unbalance reference counts - not just on locals but potentially on objects passed in.