Hacker News new | past | comments | ask | show | jobs | submit login

>"IOS sdk, on the other hand, has become a bit of a mess, due largely to the pace at which the field is moving ( although not as bad as android)."

Could you elaborate on whats messy with these SDKs?




For ios : look at the number of various apis you can use to do widget positionning and animations : calayer, uiview spring n struts, constraints, physic based, and yet none compose well with each other. IOS also doesn't have any good tech for offline storage ( core data should be burried once and for all) and swift relies on compile-time codegen hack to provide easy struct serialization, because techs like nscoding relied on obj-c runtime facilities and the language itself doesn't provide enough metaprogramming facilities to compensate.

Also, patterns like KVO are still found from time to time as a last resort in frameworks, while being famously unsafe and still rely on the obj-c runtime.

For android basically everything should be rewritten from scratch. Last time i managed a team of android developpers, we basically came to the conclusion that doing regular mvc while supporting a good market share meant recoding our own controller base classes and screen transitionning apis.


>> For ios : look at the number of various apis you can use to do widget positionning and animations : calayer, uiview spring n struts, constraints, physic based, and yet none compose well with each other. IOS also doesn't have any good tech for offline storage ( core data should be burried once and for all)

I disagree with most of this. Laying out views was a mess for a while but auto layout is easy to get right once you understand the fundamentals (especially when used in storyboards). Springs and struts is old pre-autolayout tech which shouldn't be used. CALayer is the lower level object that UIView is based on. Not sure what the complaint is here (they're mostly unrelated to autolayout/springs and struts).

As for CoreData it's a pretty simple way to manage your data. When originally introduced to iOS it was a mess but I've used it extensively in the last few years, first through a higher level framework (MagicRecord I think?) and now directly and it providing you exercise some care around threading it performs very well, especially for something simple like offline data storage.


As a ten year vet of Cocoa and Cocoa touch, I agree with your counterpoints. A lot of stuff is simply legacy.


Ever tried to have 60fps on a tableview with constraint-based layout cells ? CALayer is definitely not legacy, it's often the only way to get smooth animation. Spring n struts is also sometimes the best way to get fast position for smooth scrolling.

Ever had to deal with Core Data migration on an app that needs to evolve throughout the year ? Migration is a mess, and so is concurrency. My personal conclusion after having used Core Data on a pro application for 4 years, is that most of the time i really don't need a database and so i'm back to file-based backups for my app's data. Works well, no magic, and no performance or threading issue.


> Ever tried to have 60fps on a tableview with constraint-based layout cells

Yes. I've found AutoLayout to be acceptable in this case, provided you're not doing something awful.


We ran some casual benchmarks on this at work once, and it's important to note that the performance of AutoLayout dramatically improves based on the degree of nesting you employ.

If you have sixteen views on a cell and their locations all depend upon each other, it's going to take a long time to solve those constraints. But if you can break up the cell, say into four subviews with four elements inside them, it's likely to be faster (no guarantees, though)


Yup, it's easiest if you understand what the solver is doing and help point it towards solutions/find them trivially.

Unfortunately, i had to write my own constraint system and practice with it a lot to use AutoLayout with high performance where i was confident i was not introducing significant re-layout performance problems.


> Ever tried to have 60fps on a tableview with constraint-based layout cells ?

Yes, even on a 4S.


I came to the same conclusion WRT core data. I'm caching data myself to files. I would use SQLite directly if I need a real data store before I would use code data again


How in the world did you managed to use storyboard? I hate using it for moderate-complex UI apps. This guy say it better than me on why I hate storyboard (especially the first reason):

https://www.youtube.com/watch?v=g6yz5oX5iWc

FWIW, if you like and good at it, more power to you.


I use it in combination with programmatic UI for more complex things but find it's so much easier and faster when doing auto layout to just use storyboards.


The real reason for which i stopped using them is that it doesn't work well with git. As soon as you've got more than one people in the team, it's over.


It is actually a solvable problem if you're willing to dig into the details of the file changes. It isn't pleasant, but welcome to life. Team members can make conflicting changes as long as someone is willing to dig through the mud to make them all agree with each other. I've been doing it personally for a long time, it isn't my favorite part of the job but it does enable significant parallel productivity.


Absolutely right. This right here is the killer for me.


Hey on the struct serialisation thing, try the new codable feature, it's so great. I can probably delete 20% of my code in swift 4!


Also Apple uses a lot of patterns that lead to goto hell because of NeXT's foundations in the delegate pattern:

https://en.wikipedia.org/wiki/Delegation_pattern

So you start some sequence (like a new UIViewController) and interact with it via callback events instead of having a single (blocking) thread of execution that waits for the view controller call to return like a function. This makes it virtually impossible to deterministically model flow control. Note that since Android copied many metaphors from iOS, it also inherited these complexities in things like its Activity class.

I agree that Core Data probably needs to go away (at least its iCloud integration) and be replaced by Firebase or PouchDB etc.

KVO was a great missed opportunity because it's not clear who is watching a value. I think the pattern itself has merit from a functional programming perspective (after all this is how Excel works).

I generally avoid native mobile development now for these reasons among many, not to mention cross-platform issues. We likely need web metaphors running above native code, writing plugs where necessary (like Cordova or React Native). These are generally quite painful to use though, so I don't see many solutions materializing for at least several more years.


>So you start some sequence (like a new UIViewController) and interact with it via callback events instead of having a single (blocking) thread of execution that waits for the view controller call to return like a function. This makes it virtually impossible to deterministically model flow control.

Why on earth would you have a single blocking thread on a UI app?


What I was trying to say is that in the olden days of say the 80s, Mac OS used cooperative threads and you just wrote a main loop that was completely self-contained. We made OS calls from there, the OS didn't call us with events like it does today (at least most of the time). So programs were much simpler to debug because we didn't have callback or goto hell.

The tradeoff was that it took pages of boilerplate to make even the simplest app, and Apple got made fun of incessantly for it. So they largely fixed that with OS X's message passing metaphors, but unfortunately due to bloat and a lot of other reasons, the boilerplate issue came back, and now we're also stuck with untraceable program flow.

To answer the original question - I have worked on both blocking and nonblocking code, and unfortunately nonblocking code doesn't scale. It eventually becomes too complex to follow the flow. It's like comparing a coroutine to a state machine. My personal feeling is that we're in a kind of nonblocking bubble right now and that the callback style that pretty much all frameworks use today is not going to be the way it's done in the future. I don't know what will replace it, but it will likely be something more like Redux/Elm/Clojure and declarative GUI syntax like how the web used to work.


I don't think that Core Data is that bad for local storage; it's basically just an ORM.


It also doesn't help that these APIs are rapidly changing, in ways ranging from minor rearrangements that the XCode auto-upgrader can mostly handle, to real porting hassles. I've been working on a project that was started in early 2016, so it was originally in Swift 2, the then-current version. A ton of things changed for Swift 3, which came out 6 months later, in late 2016. And a bunch of things are changing again with Swift 4 (although not as many as in the 2->3 upgrade). I haven't yet looked into Swift 5, but presumably that brings yet more API changes.

A lot of time is spent just on this treadmill of porting previously working things to modified APIs. To make it worse, you have to manage a 4-way compatibility matrix between Swift versions, XCode versions, iOS versions, and macOS versions, where only very specific combinations work.


AFAIK Swift 3 was supposed to be the last version to introduce breaking changes. Have they changed that policy? I know that the last Swift update I did was very manageable compared to in the past (where I'd easily lose a day or two).


This project's still on Swift 3, so I don't have first-hand experience upgrading to Swift 4. It looks like there are breaking changes though, albeit not nearly as many as 3 had.

The most notable one looks like in the String API [1]. There are a few other minor ones that most projects won't hit, like in the dictionary/set API [2]. A few of these are also slightly more breaking than it initially seems because they've added temporary compatibility workarounds marked as deprecated in Swift 4 to avoid breaking as much working Swift 3 code, but these will go away for Swift 5, so you do still have to port anyway (just not immediately).

[1] https://github.com/apple/swift-evolution/blob/master/proposa...

[2] https://github.com/apple/swift-evolution/blob/master/proposa...


I don't see why keyed archiver wouldn't work with swift. I've implemented identical systems in C++ with no dynamic features. Or you can just use JSON serialization for offline storage. I pretty much never use core data. Don't get why people use it so much. On iOS you are a single user of your data so you can easly rely on a combination of plain files for storage. I've seen how Java devs go crazy using core data to just store a few hundred bytes of data. I think people overcomplicate storage 90% of the time.


Keyed archiver doesn't work with structs, and it also probably doesn't work whenevr you start nesting classes. It relies on introspection and dynamic typing for that, which can't work right now with swift.

It's one reason they had to rely on compile-time codegen to implement the swift4 equivalent.


For me it feels like the messaging is pretty clear: use AutoLayout. Springs and struts aren't used anymore, constraints are just a part of how AutoLayout works, and I'm not even sure what you mean by physic based.


I assumed they were talking about UIDynamics (https://www.bignerdranch.com/blog/uidynamics-in-swift/)


I found myself wasting months to do something that should have been handled better in iOS.

- APIs return non-descriptive error codes like -16405. Some of them aren't documented. And even the ones that are are not found clearly. Different codes are documented in different files. If you don't know where to look, you won't find it. Java-style descriptive error names like InvalidFrameRateException are sorely missing. iOS should either adopt exceptions or at least string error codes like INVALID_FRAME_RATE, not -16405.

Sometimes, there's no error code at all. I'm trying to record a video, using a AVCaptureMovieFileOutput, which is supposed to save to a file, and it doesn't. There's no error code, no exception, no log message telling me what went wrong and how to fix it. I spent a day or two trying various possibilities but nothing worked.

- Common abstractions like a photo gallery class aren't missing. It took me a month to write my own, because there are a lot of cases to deal with: swiping left and right, pinching to zoom, double-tapping to zoom, keeping the photo centered while zooming, taking care not to zoom the whitespace, keeping the photo gallery in sync with the Photos app (the user might delete a photo either in your app or in the Photos app, and you need to sync in both directions), and so on. Even now my gallery class doesn't support swipe down to close, which the Photos app supports, as I was told yesterday. That's what happens when you make people reimplement things — you'll get an inconsistent UX.

Forget a photo gallery class. Even a zoomable photo view is missing. It took me days of messing with UIScrollView to figure this out, until I found the ray wenderlich tutorial.

- Some APIs come in both sync and async versions, while others, like permissions, come only in an async version, though a sync version would be easier. Even the async APIs are inconsistent -- some invoke your callback on the main thread (UIKit APIs), some invoke it on the same thread you invoked it on, and some in a random thread (AVCapture). I filed a radar asking for consistency (maybe all async APIs can take a queue to invoke the callback on) but Apple closed it as WontFix.

Unfortunately, Swift doesn't have async/await, so dealing with the async APIs is a pain, and for some reason, this is not even a priority in Swift 5. It's being put off for years.

- Permissions are a pain to deal with, especially the common case that your app can't run without some permissions, like Camera and Photos for a camera app. I had to deal with the following cases:

+ You should take care to request a permission only after the previous one has been approved or denied by the user. Otherwise, you'll get a prompt for Camera, and before you respond, it disappears and is replaced by a prompt for Photos. And before you can respond, it disappears and is replaced by Location. When you respond to it, the Camera prompt re-appears, but again disappears and is replaced by Photos. This is a bad UX, caused by iOS not queueing multiple permission requests internally and asking the user for one only after the previous request was responded to.

+ You should ask for location before camera, because a GPS fix can take time.

+ You should take care to obtain permission before accessing the camera, otherwise the camera will vend frames consisting of black pixels, which you might accidentally save to the Photos app.

+ iOS distinguishes between a permission being denied (by the user) and restricted (by an admin or parent). My app would crash in the latter case, because the camera device is not found. But not in the former, because the camera exists but vends black frames.

+ If the user changes permissions of your app while it's running, Apple says that iOS will kill your app and restart it so that you don't have to deal with permission changing dynamically. Except when it doesn't, which goes back to the denied vs restricted case above.

In summary, you waste months of your time working around insufficiently-documented iOS issues, or debugging things, or reimplementing common things in every app.

I conclude that iOS is a poorly-designed platform from the developer point of view. Maybe other platforms are worse, I don't know, but iOS certainly is far from what it could have been. Ideally, you should implement only what makes your app unique.


[flagged]


Please be civil and avoid gratuitous negativity, as the HN guidelines say.

There's no need for statements like "you have developed a terrible app" or "You are the type of developer that..."




Consider applying for YC's W25 batch! Applications are open till Nov 12.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: