43 comments

[ 0.22 ms ] story [ 82.3 ms ] thread
This is one of those "how the hell Xcode didn't have this already?" type of things. A very welcome change, I personally don't do much iOS development but got those EXC_BAD_INSTRUCTION errors in past and they were always very misleading to me.
Rename refactoring swift also finally came after 2 years. Maybe xcode product manager is replaced by someone who more understand developer. Every release on xcode 9 has big impact. Gladly apple now hear developer. Before this, xcode 8 is the worst IDE
Or more realistically and less dramatically, some these big features took a lot of effort and engineering investment before they were ready for production.

Apple tends to re-think the current technology and implements their ideal solution. This takes longer but avoids the duck tape approach I've seen in various iterations of Visual Studio. As a concrete example the refactoring tools in Xcode9 work for both C++ (for the first time!), Objective-C and Swift using the same framework.

Best of all the API to write your own refactoring tools has been carefully designed, and there have been some high quality external contributions already to the refactoring tools.

What's wrong with the way Visual Studio does things?
I actually think Visual Studio does refactoring pretty well. It is not a new innovation from Apple. Xcode, in this case, is just catching up with a much needed feature and I still think it's not quite there.
Xcode 8 is still better, because Xcode 8 actually works.

Xcode 9.2 might be great, but 9.1 doesn't seem to take any interest in the most urgent problems of 9.0, i.e everything breaks as SourceKit grinds relentlessly in the background chewing up more and more memory (it reached 18 gigs physical ram on my 16 gig MacBook somehow!).

First it forgets how to find symbols, or refactor, then text entry slows so much until I have to wait a few seconds every time I type just to see what I typed, finally the editor just freezes for lengthy periods. That's just the most prominent problems.

Fortunately restart fixes these problems, but not most others.

This kind of problem is almost always extremely project-specific. There are an infinite variety of compiler flags, custom build steps, etc.

Set "defaults write com.apple.dt.Xcode IDESourceKitServiceLogLevel 3" and SourceKit will write a log to /tmp with all the details of what it is doing while indexing. A lot of people find they have header hygiene problems or module problems that happen to work while building in certain configurations but aren't actually correct, resulting in missing modules or broken headers from the indexer's point of view.

Dealing with C/C++ headers, includes, modules, et al is part of the reason a lot of editors never bother with trying to offer complicated refactoring, autocomplete, etc. It is far from trivial no matter what build system you are using.

If you file a bug report and attach your project someone on the indexer team will personally take a look.

If you can, you should file a radar and attach a copy of your project.
i need company approval but will try.
Is this the first time a feature is exclusive to swift, and not available for Objective-C? I wish they would offer this for regular Objective-C apps as well. UIApplication is an objc class after all!
Objective-C is C; it doesn’t do the various range and nil checks that Swift does to exit properly.

Because of that, it cannot do that.

not entirely true. if you use Obj-C data types (NSArray etc) you get an exception for out-of-range accesses.
Right, I feel like I've seen exceptions for a lot of errors ending up with xcode hanging on an exc_bad_whatever disassembly of some sort of main() routine, things like putting nil values in arrays, inconsistent uitableview datasource implementations, etc. Usually shows an alright stack trace logged to the console but the main xcode editor still opens a useless disassembler in system code?
Stick `po $arg1` in your exception breakpoint and it will print the exception (well, for Obj-C exceptions; I don't remember offhand how to look at C++ exceptions since I so rarely deal with them).
Thanks for the tip. It's usually not a problem to figure out what's wrong (the exception is dumped to the debugger), but it's a bit useless that the main editor in xcode switches to an irrelevant disassembly view at the same time :)
It shouldn't. Xcode usually switches to the shallowest stack frame that has source code available when hitting a breakpoint.
Oh, I was talking about uncaught exceptions where no breakpoint has been set.
Uncaught exceptions don't enter the debugger until it bubbles back up to main(), so the stack in the debugger is useless there.
Right, I was hoping this new Xcode 9.1 feature could improve upon that for Objective-C as well. Perhaps capturing a copy of the stack when the exception is raised, so it open the main editor window on the appropriate source line where that exception was raised.
It's not available for Obj-C because this has to do with a Swift-only feature. The closest equivalent in Obj-C is throwing exceptions.
> Note that this improved experience is only available when the app’s entry point is written in Swift (i.e. your app delegate with the @UIApplicationMain/@NSApplicationMain attribute).

Interesting requirement, is this because it requires a predictable entry codepath in order to work?

I'm guessing because it has to insert code into main() to set up the coordination with Xcode.

EDIT:

Ok, I looked into it. There's no code inserted into main(). The way this works is Xcode sets up an internal breakpoint on _swift_runtime_on_report, which is an empty function that is called during fatal errors specifically to allow Xcode to break on it.

I don't know why this requires main() to be written in Swift.

and/or some type of custom exception/signal handler?
(comment deleted)
One thing I've never understood is why break on all exceptions is not the default in Xcode. It'll happy crash the app with an assembly stack trace with no way to see the offending code unless break on all exceptions is setup.
Because there's no way for the debugger to only break on uncaught exceptions, and you don't usually want to break on caught exceptions. Various frameworks (most infamously CoreData) use caught exceptions internally as a control flow tool.
I've never seen this with Core Data (unless you have the multithreading-violation argument set). I do see it with some of the AV frameworks, but those are C++ exceptions, so as long as I only break on ObjC exceptions I don't hit it.

Edit: I forgot 1 ObjC exception I see frequently from AVFoundation on macOS. That one does cause an annoying breakpoint hit.

It's been awhile since I've used CoreData, but I don't remember these being an issue.
Maybe if it were the default various frameworks would be less likely to use exceptions as flow control.
There are a few places in AppKit where you need to determine an object's state by catching an exception because there's no method available. (Checking whether an NSColor is a pattern comes to mind -- only way is to try getting the pattern image and it will throw if it's not a pattern color.)

The really frustrating thing is that Obj-C didn't even have exceptions originally, so someone basically looked at exceptions when they were added and thought: "I know, I'll use them as part of the API"...

Can't you check if the NSColor.type == NSColorTypePattern?
I might be misremembering that one! Will have to check. Thanks!
NSColor.type is new in macOS 10.13.
Right, calling save on a NSManagedObjectContext often throws c++ exceptions.
Remember to turn off C++ exceptions or you'll constantly be breaking on `return UIApplicationMain(...)`

https://stackoverflow.com/questions/26127004/xcode-throws-an...

That doesn't normally happen. As mentioned in that article, one thing that can trigger it is if you incorrectly remove a custom font while not removing it's use in UI elements in your application.
So if we use swift to write our main function and call UIApplicationMain, then this wouldn't apply?
Yeah it does. I tested a CLI app in Xcode 9.1 which was just a single main.swift file and it showed my fatalError() nicely.
Xcode have soo so many places where it need to be fixed. No wonder why people rather use android studio. And swift version is changing every 6 momths to ruin everything.. good luck