The joys of creating Xcode project files
nibblestew.blogspot.com
nibblestew.blogspot.com
And Apple keep bolting stuff on to it (and the new stuff doesn't work - Canvas for SwiftUI previews for example).
It's slow, broken in numerous ways, depends on file formats that aren't used anywhere outside of Apple and completely undocumented. It is such a painful tool to use.
Feature creep is never a good thing.
It’d have been better to build tools for Swift in its own right, allowing those tools to integrate - probably by using distributed objects.
But, it isn’t that way so such is life.
Just remember — integration doesn’t mean it has to be bad or slow (current Xcode can always be improved).
Windows has at least one tool for tabbed windows though! Check out Stardock Groupy if that sounds like your sort of thing (and I swear there was another one but I can't find it, maybe Groupy is a rebrand?)
But desktop OS vendors seem to still be operating under the paradigm of making their desktop environments as approachable by computer novices as possible. Maybe still a good business decision, but the future for desktop OSs is clearly with professionals and enthusiasts, and it's my hope more advanced human/computer interface approaches will follow.
You can have better window management facilities on Linux, but you have to choose between software that copies the mainstream paradigm of, as you say, pushing new views onto navigation controllers (and I'd add using tabs/split-panes built into the window itself instead of being offloaded to a more sophisticated window manager), or software that's quite rough around the edges.
How is VS Code so popular, if its big brother Visual Studio can do everything it does and more?
Doesn't this signal that the market prefers lightweight IDEs over heavier ones?
Me personally, I would love to have a text editor on the left and the iOS simulator on the right and that's all you need to ship. Xcode Playgrounds attempted to execute this shift, but they still need much more attention until they can function as well as the regular workflow does (which is sad, 'cause the regular workflow sucks).
I only know extremely few people who'd use VS Code for C++, so "popular" is really ecosystem-dependent
Even doing something as simple as upgrading Xcode via the App Store is painful, often progressing insanely slowly and taking hours or even tens of hours on an otherwise fast connection. It has been like this for years and years and Apple has done nothing to fix it, like most Xcode issues.
I have a fully loaded MBP 16” w/ i9, 32GB RAM and the fan starts very quickly due to indexing and whatever else it is doing.
A few months ago I moved to a ryzen development machine running Linux mint to code rust using IntelliJ. Responsiveness and stability is night and day. It’s a shame, too - swift is a lovely language and I’d love to use it more. But life is too short to put up with Xcode.
Some other devs on the team just got M1s. They are backend though... so I haven’t seen an M1 running Xcode yet. Very curious but I am guessing it is night and day... for half the cost or less.
It has to be wed to the OS in such a way that makes the propensity for this vague failure state to occur, because I've never had it happen with anything else.
Upgrading from the App Store sometimes will hang at 99% and no matter what you do save some weird incantations to remove stuff from this secret App Store cache to remove the download to begin its excruciatingly slow download again, only with the hope in your heart this impenetrable and silent error doesn't happen again.
And of course none of this is addressed by Apple. You think you can just download versions from the developer site? Well enjoy, and I am not joking, a 30+ minute unzipping of the .xip file (yep that's right, it's not a .zip).
Apple does not care about it's developer ecosystem, even though you are such a huge part of it's success. It's apparent in their thread bare documentation, their terrible tools, their greedy practises.
I get it. They are a business. But they do not deserve their halo.
This SO post is continually updated with the latest builds and is a bookmark for me. https://stackoverflow.com/questions/10335747/how-to-download...
Why is this the current paradigm of developing on a platform that notoriously "just works"?
I've been a mobile dev for many many years and most of my time was spent focused on iOS.
I didn't find Xcode that bad, but sometimes annoying issues do keep popping up, for example stuff related to provisioning profiles.
Last few years more of my time was spent with Xamarin and the macOS version of Visual Studio (rebranded Xamarin Studio) and it's quite a bit worse than Xcode. Xamarin Studio has the tendency to get really slow after extended usage and I pretty much never had such issues with Xcode. Few things are more frustrating to me (not to mention a huge productivity killer) than writing code in a slow, laggy editor. At least Xcode doesn't have that issue (most of the time).
However, what I really like is to be able to just use a simple text editor for my work. Lately, as a hobby and for side-projects, I've been using Sublime Text with LÖVE 2D (Lua) and this has been really fun to me. No project files to deal with, no complicated UI stuff (visual editors and the like), no more downloading of gigabytes of simulators after an update (as long as I focus on macOS & Windows that is), etc...
With MAUI, Microsoft will make the default Xamarin project structure also really simple, just a few lines of code. That should make it a lot easier to use a simple text editor for Xamarin dev work, instead of the slow Visual Studio for macOS IDE. Perhaps Apple should follow suit with Xcode.
It will be interesting to see where things go in the coming years though, because between SwiftPM, SwiftUI, SourceKit, and the SourceKit LSP I think many of us may be shifting toward a workflow more centered around a light editor. A few days ago I was toying around with SourceKit LSP in Sublime Text 4 and it's surprisingly servicable - most of my projects have abandoned xibs/storyboards already so I could probably make that setup work if I put some time into getting Sublime's build system set up.
The fact that Xcode crashes reliably, and has done so for years without being fixed is a stain on apple’s reputation for making otherwise good products.
> I didn't find Xcode that bad, but sometimes annoying issues do keep popping up, for example stuff related to provisioning profiles.
In my experience, iOS/macOS devs have just kind of "got used to it" with regard to Apple's developer tooling. Once you know how to work with all of it at an advanced level it doesn't seem that bad.
I think the issue is when developers that haven't spent considerable amounts of time acclimating have to work with Apple's dev tools. If you haven't been hazed into being productive with Apple's tools, they won't work how you expect and it won't be obvious why.
So I can say with confidence that writing swift using modern Xcode is the worst experience with an IDE I’ve ever had. Dropped keystrokes, random crashing, device-dependent compiler errors (“Error: this method spent too long type checking”). And so on. It’s an obvious, avoidable disaster zone. Dear Apple, fixing the bugs in your software is more important than adding new features!
In comparison, VSCode+Typescript and Visual Studio+C# are the best IDE experiences I’ve had. Fast, stable, smooth, reliable and easy to set up. And little things work well - like inline documentation, autocomplete, project wide renaming and integrated debugging. Microsoft nails it. IntelliJ+Rust is close but it has a few obvious rough edges.
https://maemo-leste.github.io/ https://postmarketos.org/ https://wiki.debian.org/Mobile#software-distros https://www.pine64.org/ https://puri.sm/
SkSL warm-up doesn’t help newer iPhones using Metal.
Flutter recently migrated from OpenGL to Metal for all newer iOS devices. (Please reference Metal on iOS FAQ on which iOS devices are considered new enough to use Metal.) However, Skia currently only implemented the SkSL warm-up for OpenGL. So the SkSL warm-up would only speed up older iOS devices by default. If you find shader compilation jank to be an issue for your app on newer iPhones, please let us know by filing a GitHub issue. In the longer term, we have a plan to use test-based shader warm-up to mitigate this. If there’s an urgent need for fixing shader compilation jank on newer iPhones, please leave feedback on Issue 61045, and we can help you turn on OpenGL for your app.
https://flutter.dev/docs/perf/rendering/shaderand comment from last week on a flutter issue say it's working for them on the master channel. https://github.com/flutter/flutter/issues/79298#issuecomment...
It's also a bit indicative that this kind of issue is left standing for years. The desktop resize jank one similarly took years to resolve.
It was the end of 2009. I was working for a small startup doing some Twitter clone. We decided that we want to provide an iPhone app, and since we already provided Twitter like API, the easiest way is to just fork an open source iOS Twitter app to replace all the API endpoints to ours.
I was doing that, using Xcode. One day the compiler complained something like "unexpected `\`". Looking at the code in Xcode, I don't see any \ around the position compiler pointing to.
After stared at the code for an hour, I finally decided to open that file in vim, and sure there's an \ added before a double quotation mark I believe, while in that context an escape is not needed (and doing that is wrong, thus the complaint from the compiler).
So Xcode's editor, trying to be smart, auto escaped a double quotation mark at the wrong place, and don't show it in the editor at all. Their compiler caught the error.
Automatic preview updating paused [Resume]
* Having to buy a computer, use a new OS, use a new editor and buy a new phone to just get started.
* MacOS, XCode and/or iPhone updating and breaking my own and third party code ad hoc.
* Having to know/learn C, Obj-C and Swift 1, 2, 3, 4 and 5. Being forced to constantly translate between these, and check timestamps on documentation/SO/guides to determine how much use there is in even skimming it as the amount of deprecation and half-implemented things that I'm not supposed to use in production means my confidence in implementation is near zero.
* Brittle pipelines, impossible fresh installs that break in the weirdest ways (Ruby? What?), publishing and generally interacting with Apple making otherwise quick actions take days.
* XCode not working great with GIT, having to reboot it when it randomly stops working all together, input latency, code highlighting that half of the time doesn't work at all or is very slow (on a brand new M1).
I work as a consultant, and often have to learn new languages/runtimes for my job, but nothing has been as bad as iOS.> There is no other data in this object. Its only reason for existing, as far as I can tell, is to point to the actual PBXFileReference object which contains the filesystem path.
Now, that statement is true most of the time. But not always. Let's say you have a file in two targets (targets ~= binaries). In one of those targets, you need to set a build flag, but not the other, how do you do it? Well, you set it on the PBXBuildFile, rather than the PBXFileReference. In otherwords, you can have 2 different PBXBuildFile's, with 2 different sets of flags, pointing at the same actual file on disk.
Whether that's a good design or not is definitely up for debate, but I wanted to clarify that there are reasons behind everything.
Going further:
> Since everything has a unique ID, a reasonable expectation would be that a) it would be unique per object and b) you would use that ID to refer to the target. Neither of these are true. For example let's define a single build target, which in Xcode/CMake parlance is a PBXNativeTarget. Since plist has a native array type, the target's sources could be listed in an array of unique ids of the files. Instead the array contains a reference to a PBXSourcesBuildPhase object that has a few keys which are useless and always the same and an array of unique ids.
Let's take a sub-statement here first: > Since everything has a unique ID, a reasonable expectation would be that a) it would be unique per object
The author claims this is false, but I've never seen a case where this hasn't held up. Numerous libraries depend on this fact.
> you would use that ID to refer to the target
Also claimed as false, but you do. The argument the author makes talks about the build file stuff I mentioned above, so they may just be misunderstanding or have mis-spoken/written.
Just to re-iterate, I'm not a fan of this format at all. I'm actually in the middle of converting a million line project to use XcodeGen just so I can get away from it. But everything does have a reason.
Xcode 12 UX is an example where Apple seemed willing to invest. There may be reasons pbxformat is bad, but there is no reason Xcode 13 or 14 couldn't address them. After all, it's only software.
90% of the tech rant blog spam on HN is people who don't fully understand the tool they're using.
Something doesn't work the way they expect for their particular project or their specific need, and they blather on about how bad it is.
When the reality is that these things are often done for a reason, but the author's myopia prevents him from understanding that there are other people doing other things in the world.
I'd like to see more assumption of positive intent on here, but it's definitely a hard task. I hope I didn't offend the original author here. I tried to ensure that I explained without chastising.
This must be one of the most frustrating and unthankful tasks in the entire domain of programming.
No thanks. I am one whom cmake has tried. When it works, it works well. When it doesn't, it is utterly impenetrable.
I actively avoid any GitHub projects that use cmake because it's just normally too painful to use, and it brings on an episode of PTS. Just writing this is causing my blood pressure to rise.
How Apple thinks that a single god file is a good idea is crazy to me. No other build tool needs this.
A similar project from Google is Tulsi [1] but even though it can also generate xCode project files I think it’s more geared towards making iOS projects work well with Bazel.
Additionally, it is the only sane way I've found of handling whitelabel application development. Here's an example for anyone who wants to see it in action: https://github.com/onebusaway/obakit
This might seem strange, but I think the negativity here makes sense, and is justified on multiple fronts.
On a technical front, Xcode is pretty awful. It’s slow and unstable, and seems to have only gotten worse over the last decade. Many comments here express this in detail.
This matters so much because tools become an extension of our bodies. Using bad tools makes us feel ineffective, weak and slow. If I can’t trust Xcode to receive keystrokes (yes, a real bug I encounter frequently), my brain interprets that bug as me being physically impaired and unable to type. It’s awful.
This is made so much worse because Xcode - and any bad product from Apple - betrays Apple’s promise to it’s customers. Apple’s promise is “we sell premium products which are worth the extra cost because they’re delightful. Buy from us and we’ll take care of you”. Steve jobs used to say this sort of thing quite explicitly. This is why people hold Apple to a higher standard - because Apple promises a higher standard with their branding and their prices. It wouldn’t matter so much if Xcode were part of an open ecosystem and we had choice - I wasn't angry a few years ago when Atom was laggy and slow. I just shrugged, uninstalled and used something else. But iOS devs are mostly locked in. They have nowhere to go.
And practically speaking, people from all over the tech industry are on HN. Plenty of people at Apple are here - even if they can’t say so. Hopefully a bit of public shaming will be read by someone at Apple with the authority to right the ship. We can hope.
> Don’t create multiple Bundle IDs of the same app. If your app has different versions for specific locations, sports teams, universities, etc., consider submitting a single app and provide the variations using in-app purchase.
If the app is content-heavy, and that content varies between each instance of the app, they're more likely to be okay with it, but it is still a difficult road fraught with pain and risks.
Under “standards”, the man page appears to have the following cheeky warning for pl: “The pl command obeys no one's rules but its own.”
https://www.unix.com/man-page/osx/1/pl/ or just type “man pl” or “man plutil” at Terminal.
Here’s an example of how to read and write an xcodeproj file using Python and these two utilities: https://gist.github.com/brunogama/3929457
https://github.com/fiddlerwoaroof/objc-lisp-bridge/blob/mast...
Anyways, it’s definitely true that plists support a superset of the data types supported by JSON: plutil will not convert the Safari bookmarks file to JSON, for example.
So while it is true that you can use these tools to convert a Plist from a binary or legacy format to JSON or XML and back, there are no guarantees you’ll be able to understand what was written to the plist originally.
The plist format does not encode metadata describing itself in any common standardized way: it’s not a JSONSchema, an XML Schema or even a protobuf .proto file. A well-written plist can be as self-describing as JSON or XML, though the concept of a schema for plist files doesn’t exist as far as I’m aware, outside of how apps choose to serialize objects, that is. (The data structures an app uses could be considered a schema for a plist but it assumes the data structures themselves are versioned when they need breaking changes…)
https://developer.apple.com/library/archive/documentation/Ge... has an example of “stringly-typed” keys and values. There’s not much validation in a generic plist editor just as there isn’t validation in JSON or XML by default, but any app can add its own validation to ensure what it saves to a plist is something it can read later… that’s where the confusion over objects and codables comes in. If an app wrote the object to a part of a plist, it can thus de-serialize it from how it wrote it. If your app doesn’t understand another app’s plist, that’s pretty normal for complicated files or data kept by third-party apps. Few apps consider metadata and longevity when they write to disk, such that migrations are handled version to version as they need to, etc.
They should port their custom tools like IB, view debugger, etc. over to Visual Studio Code and get out of the IDE game.
Eight? Eight?
Good Lord.
You want to end up with one backslash `\`. After one escape, you get `\\`. If you escape the escaped string, you get `\\\\`. After another layer, you get `\\\\\\\\` for a single backslash.
Here's a somewhat realistic example: You need a piece of javascript in a string literal, and you need that javascript to generate a regex matcher for a single backslash. You could do that like this:
let code = "new RegExp(\"\\\\\\\\\")";
It's not _that_ uncommon when you need to marshal one language through many layers of languages (in my example, the regex language being marshalled through a javascript string literal and then another layer of javascript string literal). In XCode's case, two layers are obvious; you want a backslash, so you need the string which is fed to the shell to contain `\\`, so your XCode string literal has to be `"\\\\"`. For some unknown reason, there's a third level of escapes which takes us to `"\\\\\\\\"`.
Apple has been working on the tooling for the past several years. They improved the editor performance, created a new build system (llb), made a native dependency manager (swiftpm). For third-party tools they have released an LSP extension (hopefully they’ll end up using it internally in Xcode).
Yes, XCode originates from NeXTSTEP’s Project Builder: https://en.wikipedia.org/wiki/Project_Builder
What became Xcode started out life as "Project Builder" (with a space), which was where the pbxproj file format was introduced. This debuted with Mac OS X (possibly circa DP4?) and was a ground-up rewrite - new UI, new project format, new build system (originally it used Jam, a little-known build system created by Perforce, before switching to something custom... IIRC it would generate an ephemeral Jamfile at build time).
For a while both could be installed on the same system - you needed ye olde NeXT ProjectBuilder for WebObjects 4.5 projects, and it was known as ProjectBuilderWO on Mac OS X for a while as a result.
When Apple started "improving" stuff it turned into the SomeProject.pbproj/project.pbxproj file and was not editable by a human. This file would later become SomeProject.xcode/project.pbxproj and then SomeProject.xcodeproj/project.pbxproj all the while getting worse and worse and less editable and less readable/understandable.
Here is the entire project file (PB.project) for IORegistryExplorer from Mac OS X 10.0
{
APPCLASS = NSApplication;
DYNAMIC_CODE_GEN = YES;
English_RESOURCES = {};
FILESTABLE = {
CLASSES = (
RExplorer.m,
"RExplorer-OutlineDelegate.m",
"RExplorer-BrowserDelegate.m",
CustomOutlineView.m,
RSearch.m,
RBool.m
);
English_INTERFACES = (IORegistryExplorer.nib);
FRAMEWORKS = (AppKit.framework, Foundation.framework, IOKit.framework, System.framework);
FRAMEWORKSEARCH = ();
H_FILES = (
RExplorer.h,
CustomOutlineView.h,
"RExplorer-OutlineDelegate.h",
"RExplorer-BrowserDelegate.h",
RSearch.h,
RBool.h
);
IMAGES = (IORE.tiff);
INTERFACES = ();
OTHER_LINKED = (IORegistryExplorer_main.m);
OTHER_RESOURCES = (IORE.icns);
OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, CustomInfo.plist);
SUBPROJECTS = ();
};
LANGUAGE = English;
MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles";
NEXTSTEP_APPICON = IORE.tiff;
NEXTSTEP_BUILDTOOL = /bin/gnumake;
NEXTSTEP_DOCUMENTEXTENSIONS = ();
NEXTSTEP_INSTALLDIR = "$(SYSTEM_DEVELOPER_APPS_DIR)";
NEXTSTEP_JAVA_COMPILER = /usr/bin/javac;
NEXTSTEP_MAINNIB = IORegistryExplorer.nib;
NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc;
PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make;
PDO_UNIX_INSTALLDIR = /Applications;
PDO_UNIX_JAVA_COMPILER = "$(JDKBINDIR)/javac";
PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc";
PROJECTNAME = IORegistryExplorer;
PROJECTTYPE = Application;
PROJECTVERSION = 2.8;
WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make;
WINDOWS_INSTALLDIR = /Applications;
WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe";
WINDOWS_MAINNIB = "IORegistryExplorer-windows.nib";
WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc";
}
Simple. Elegant. Usable.Just as SwiftUI has allowed me to ditch endless awful Apple UI file formats, Swift Packages are a relatively simple way to avoid much of what might otherwise require the rest of Xcode to configure.
I feel like there may be an internal tug of war happening in Apple but I sincerely hope the people advocating for damn-near-undiffable file formats will lose.
I’ve not used storyboards/xib in years, in both objc and swift.
I am building my Sciter using premake5 on Win/Lin/rPI/Mac.
Premake5 is very useful to generate projects and makes for different platforms/IDEs. But on Mac premake5 is really works to create .dylibs only - seems like to generate GUI app on Mac XCode is the only option, is it?
import AppKit
_ = NSApplication.shared
NSApp.setActivationPolicy(.regular)
let window = NSWindow(contentRect: NSRect(origin: .zero, size: CGSize(width: 500, height: 500)), styleMask: [.titled, .closable, .miniaturizable, .resizable], backing: .buffered, defer: true)
window.title = "Test"
window.center()
window.makeKeyAndOrderFront(nil)
NSApp.activate(ignoringOtherApps: true)
NSApp.run()
into a file and run it to get a window.Enough said. Xcode is the worst devtool I ever used