Swift Programming Language Evolution(github.com) |
Swift Programming Language Evolution(github.com) |
If they think they can be competitive for years (at the very least vs. Objective-C) with only platform-level concurrency support, it makes me wonder whether concurrency is generally better provided by the platform instead of the language for most needs.
Conventional wisdom would have it that for a systems & application language designed in 2014, a good concurrency story would be close to job #1.
Specifically:
* Support for annotations; the compiler/runtime can be informed about safety and marshaling concerns. * Anonymous function bodies. You can implement Go's "go func() { ... }()" pattern yourself, and a concurrency runtime can implement it. Rust uses the exact same pattern. * Generic iterators/streams. No need for channels as language primitive since you can write a generic channel implementation.
Go is nice, but its language-level concurrency is very much a side-effect of its intentionally impoverished type system. For example, the built-in "chan" type exists because otherwise a generic channel implementation would have to use interface{}, which is not type-safe and would be hell to work with.
Here's what's lining up to become Swift 4.0's concurrency support (all the concurrency models!): https://github.com/apple/swift/blob/master/docs/proposals/Co....
Some enum and extension magic easily lets you write things like:
Queue.UserInitiated.execute {
let url = NSURL(string: "http://image.jpg")!
let data = NSData(contentsOfURL: url)!
let image = UIImage(data: data)
Queue.Main.execute {
imageView.image = image
}
}The idea is to flatten the syntax without change of the runtime model in the same spirit they did error handling: feels like exceptions, but without ugly stack manipulations.
If you are interested, I have taken on implementing all major design patterns in Swift. I've gone through about 10 of them right now, (7 published on my blog).
If you've never worked with Swift but wish to get a feel for it without going through overly simple tutorials, check them out: https://shirazian.wordpress.com/2016/04/11/design-patterns-i...
One of the nice things about C is that K&R era C is just as valid as C written nowadays, but Swift appears to be going in the opposite direction, every major release adding and removing bits of syntax.
As someone unfamiliar with the language, it makes me not want to pick it up, since guides and documentation I read now will be incompatible with the newer release when it happens. Some early toying around during Swift's original announcement led to hard-to-debug errors (in part, caused by terribly useless error messages) when trying identical code on newer releases.
See http://fr.slideshare.net/andrzej_sitek/swift-and-kotlin-pres... for more details ...
Im trying to create a distributed application platform, using the bittorrent DHT for that.. so this is the part im working on right now.
I hope i can launch this in a couple of months from now, so swift can have a multiplatform UI and where applications can be distributed in a decentralized way.
It always struck me as a fairly warty syntax.
Consider Python where you usually do:
for item in iterator
If you want an integer sequence it's: for integer in range(1, 100)
and for those rare occurrences where you need an integer index as well: for index, item in enumerate(iterator)
Swift seems to have a similar approach. Why would you ever want the C-style iterators?Chalk this one up to shit hacker news says.
If you think one detail is most important, you're welcome to comment on that in the thread. Then your opinion is on the same level as other users'.
(Submitted title was 'Swift 3 will be portable / be able to run on more platforms'.)
Actionscript did open source, it create lot of unhappiness in the community and poor IDE performance but Swift is a different story, I'm looking forward to have Swift for server as long as the vendors contribution are growing, MS could be keen.
As an aside, I like that Apple is betting the farm on ARC. I wish I could have been a fly on the wall when they were discussing ARC versus GC.
GC is borderline but it feels like it might be one of those. In retrospect one giveaway is how easy it is to avoid almost all memory problems in C++ with RAII and STL.
Apple shipped a tracing GC (RC is a form of GC) for a while, but couldn't get it to work reliably or with adequate performance. ARC was a bit of a "Hail Mary" and is problematic in its own right, but certainly better than the GC it replaced.
Marcel
Last time I did any Objective-C you had to retain/release yourself so the auto stuff is interesting. As far as I can tell the benefit over Garbage Collection is that GC only works well when you have lots of excess spare memory, which is constrained on mobile devices.
It's not perfect, Generics and Protocols are fuzzy at best and if you aren't careful with optionals you can actively harm the stability of your code base. It has a long way to go on the server side but I do believe that it will and should be a great server side language platform. That said in my opinion it's the best language I've worked with professionally.
For reference I've professional written a decent amount of code in: Python Java C# C++/C Objective-C Perl PHP Node.js/JavaScript VB6/VB.net Ruby Groovy Scala
- It is incredibly fast compared to current interpreted languages (i. e. factor 30+ vs. Python, possibly faster than C)
- Linux & OS X, open source
- Typed, safe
People like node.js mostly b/c it allows some code to be written once and run on both the server as well as the client. Considering almost any Web API also has an IOS client, Swift has the same potential.
The debug messages were confusing. I never used Obj-C so I'm not sure if that's iOS or Swift that causes confusing error messages.
While it has gotten a little better, it is Swift.
(EDIT:) But I've been loving Swift so far! I've found that there is some consistency to the weird errors, so eventually you can start to map them to past experiences.
In a weird way it actually reminds me most of TypeScript - JavaScript-y, but with types and stronger enforcement of rules.
Link: https://www.natashatherobot.com/swift-guard-better-than-if/
If that happened, you'd finally have an open, fast, expressive, modern language that you could use on the server and on the fronted for iOS and Android. Couple that with Typescript & Aurelia for the web frontend and I'd be in programming nirvana.
Example: https://youtu.be/mgpAmqdiPKE
Check your local job boards, but if sell yourself as a Swift dev you're likely to be pigeon-holed into Apple-centric development for the foreseeable future.
With Apple sales and market share dropping like a rock in the last 12 months, that might not be the best position to put yourself in long term, career-wise.
Like "a rock"? Where exactly did you see that?
Apple STILL sold 50M frigging iPhones in its "failed" quarter -- and had more profits and revenues that 3 next competitors combined.
And that with supply constraints for mobiles, Intel dragging its feet with laptop/desktop CPUs, and an atypical extraordinary last year-over-year quarter to compare to.
Here's the relevant chart: http://www.statista.com/statistics/263426/apples-global-reve...
Neither sales nor market share have been dropping like a rock.
Apple had had their first year on year revenue decline in 13 years of continuous growth, but there is no indication that that anything is 'dropping'.
You want a young language to change a lot, because you don't really know what it needs until you get it out there and people use it. You want to make necessary changes as early as possible to cause the least pain. Major changes at the two-year mark will be a lot easier than major changes at the five or ten year mark, and waiting too long to fix a bad decision will probably mean it sticks around forever.
I would expect Swift 3 to be the last release with major source-breaking changes.
- Almost nobody actually used C prior to 1978.
- Most C compilers have supported both current and previous versions of the C standard via -std flags.
- Other languages with breaking changes, like Java, are similar. Java has always supported specifying the source language level via -src.
Swift is unique in breaking old code completely, without recourse other than semi-functional code rewriting tools.
I'm okay with the fast-moving nature of Swift. It's a very young language that obviously needed a lot of changes, and if they had to take the time to make the earliest features available all the way in version 3, Swift would already be bloated. But they have been able to do away with backwards compatibility which is difficult in the industry, and I think it allowed them to make a richer language, not held back by anything.
Side note: For at least some of the changes they've made, they've also built into the compiler and Xcode smart error messages that see the old syntax, and allow you to click one button to fix it to the latest syntax. Such as the old `for i in 0..10 {}` to the new `for i in 0..<10 {}`, Xcode will tell you to basically insert the `<` for the new operator.
> What does this mean looking forward? Well, Swift 2 to Swift 3 is going to be an unavoidably disruptive change for code since Cocoa renamification is going to land, and we’re going to be building impressive migration technology again. As such, we should try to get the “rearrange all the deckchairs” changes into Swift 3 if possible, to make Swift 3 to 4 as smooth as possible. While our community has generally been very kind and understanding about Swift evolving under their feet, we cannot keep doing this for long. While I don’t think we’ll want to guarantee 100% source compatibility from Swift 3 to Swift 4, I’m hopefully that it will be much simpler than the upgrade to Swift 2 was or Swift 3 will be.
http://ericasadun.com/2016/02/29/getting-ready-for-swift-to-...
It has very poor support for custom value types. Objective-C structs basically can't contain object pointers, so they're limited to simple things like CGRect. They also can't contain methods, so you end up writing associated code in global functions.
Protocols are extremely limited. They're basically just collections of method declarations. There's no way to add functionality to every class which conforms to a protocol.
Objective-C is often verbose to the point of painful redundancy. Consider:
NSString *x = [NSString stringWithFormat: @"%d", number];
Versus: let x = String(format: "%d", number)
Other examples include having to write the signature of every public method twice (once in the header and once in the implementation) and the need to do an annoying `self = [super init]` dance in every initializer.There's almost no functional programming stuff available, like map and reduce. This is not strictly a language complaint, but since the standard libraries are pretty tightly woven in, I think it still counts.
Generics support is really limited. What's there was only added to interoperate better with Swift, anyway!
That's a quick overview of some of the ways Swift improves on ObjC. I'm sure there's more.
That said, Swift feels similar while being more productive:
- Lots of nice syntactic sugar to reduce noise - Optionals (and chained calls) which do much the same - Type inference! - A REPL. Pretty amazing. - Bounds checking
lots more nice features too.
Rust, D, golang, swift all appear to share a common goal of having a mid-to-low-level imperative/OO language that has learned from C/C++/ObjC's mistakes.
Though some consider this a feature, YMMV.
IMHO, these operators are the worst features of C. Particularly I never understand the necessity of both i++ and ++i operators in language at the same time.
I don't mind removing them but their usecase is obvious: make the code more concise and more readable (and yes, if you program in C on daily basis you don't require a double take or thinking about what ++ does).
This is where a typed serialization comes in handy. (Protobufs, Thrift, Cap'n Proto, etc.) It is also possible to use an IDL to generate a type-safe API to deal with JSON -- although I don't know of any tools that emit Swift. Interfacing with third-party JSON APIs can be a pain though.
Maybe you can bring it back when we get hygienic macros (Swift 4.0? fingers crossed)
http://tylergaw.com/articles/building-osx-apps-with-js
JavaScript bridging works on iOS too!
Not at all. It's easy to think you're avoiding those memory problems, but they invariably crop up again and again.
For example, in Scala operators are (IIRC) implemented as methods on objects, there's a 'Nothing' bottom type that is used for covariant generic parameterization, and ADTs are implemented using inheritance in the form of case classes.
Swift has no top-level object type or bottom type, and a lot of its more functional style features (ADTs in the form of 'enums', value types that enforce immutability) are completely divorced from the object-oriented part of the language.
The one big area that separates the languages is tooling. I personally think Swift's tooling is much better. Faster compilation, faster runtime, faster startup, and better ide tooling.
Plus, I bet one of the things that’s holding proper concurrency back are Apple’s frameworks. I’d rather deal with callbacks for another year or two than use a rushed language feature.
Things that require a double take to read and parse do not help. Additional solutions to the same problem do not help.
There's a lot of cleverness that can come up in programming that may make for neat/short writing but that makes reading and purpose less clear. i++/++i helps with that with no special benefits.
I like how the Swift team approached the decision to remove them: thinking on whether it would make sense to add them had they not been there. And it doesn't, as they solve no particular problem; they're just a special, (not much) shorter solution to something that's already solved.
`for (l, r) in zip(c1, c2) {`
It is not simply motivated by making code concise, I would say `for num in collection.reverse()` is less error prone and clearer than `for (var i = collection.count; i >= 0; i--) { var num = collection[i] ... }`
The reverse collection iterator is computed lazily too, so there is no little perf overhead
I'm just curious with your experience what you are pointing to as problematic. Other than potential extra release calls in tight loops, the main downside I saw was it made the use of C structs way less appealing---at the same time, I wouldn't want to with manually memory managed C structs in GCD blocks.
- Lots of extra retains/releases can cause significant and unpredictable performance degradation, and even crashes: http://blog.metaobject.com/2014/06/compiler-writers-gone-wil...
- The language went from fun dynamic, optionally statically typed to strict static typing that restricts exploratory programming: http://blog.metaobject.com/2014/03/cargo-cult-typing-or-obje... http://blog.metaobject.com/2014/05/the-spidy-subset-or-avoid...
- People no longer write class-side convenience initialisers :-((
- The benefits are mostly marginal, and the non-marginal benefits are needlessly bundled with ARC
- The C interaction model of the Objective-C hybrid language was made much more complex, somewhat defeating the purpose of a hybrid language
That's off the top of my head.
IMO the example of Java is a great illustration of why Swift shouldn't be tied to source compatibility too soon. You don't want to be stuck supporting your 1.0 syntax until the end of time, or you'll end up like Java!
It sounds like instead, the cross platform appeal is that back end or background services can now be written on non-apple platforms?
Automatic reference counting inserts all of the refcount bumps. In Rust, you have to write the up count yourself, but not the downcount.
But, reference counting isn't used very often, at least in my experience. It's very useful when you have non-scoped threads, though.
Everything else is just where retain/release (clone/drop) calls are made. Rust is insanely good at not frobbing counts because you can safely take internal pointers and move pointers into a function without touching the counts at all. Swift has lots of interesting optimizations to avoid touching the counts, but it's hard to compete with a system that has so much great static information related to liveness of pointers and values.
As a simple example, consider this code (which is conveniently valid Swift and Rust, modulo snake_vsCamel):
let x = make_refcounted_thing();
foo(x);
This code in isolation will always not frob counts for Rust. This code may not frob counts in Swift, depending on what follows `foo`. In particular if foo is in tail position (or at least tail-position-for-the-life-of-x), then we can avoid frobbing, because we know foo's final operations will be to release its function args. foo may in turn punt releasing its function args to anyone it passes them to as a tail call. Note that Swift and Rust both have the usual caveats that "less is a tail call than you think" thanks to side-effecting destructors.The takeaway is that Rust's default semantics encourage releasing your memory earlier, which in turn means less traffic on the reference counts. Particularly interesting is that in Rust, you can run a function arg's destructor earlier than the end of the function by moving it in to a local variable. In Swift, I do not think this is possible (but I wouldn't be too surprised to be wrong -- Swift has tons of special attributes for these little things).
Part of the reason I really dislike the "reference counting vs. garbage collection" debate, and keep emphasizing that reference counting is garbage collection, is that it sets up this false dichotomy. In reality, there are all sorts of automatic memory management schemes that combine aspects of reference counting with tracing in different ways, most of which were created in the 80s and 90s. Sadly, almost nobody in industry is aware of this enormous body of work, and the simplistic "RC vs. GC" model has stuck in everyone's heads. :(
Here is the code to define and use a property pre ARC with properties:
@property NSString *name;
...
object.name = @"Marcel";
And here is the same code with ARC: @property NSString *name;
...
object.name = @"Marcel";
Spot the difference? Now it turns out that there are some differences, such as automatic generation of -dealloc methods and weak references and some cosmetic stuff. But overall, it's at best a subtle difference and for most code you won't be able to tell the difference.Pre Objective-C 2.0, there were solutions such as AccessorMacros[1], which handled the same use-cases except without the dot syntax (which is somewhat questionable) and have the advantage of being user-defined and user-extensible, so for example if you want a lazy accessor, you don't have to wait for your liege lord, er language supplier to add them, or create a whole new language to do the trick. Instead, you just write 4-5 lines of code and: done!
[1] https://github.com/mpw/MPWFoundation/blob/master/Classes/Acc...
- programmed in Objective-C for ~30 years
- implemented my own pre-processor and runtime (pre NeXT)
- programmed in the NeXT ecosystem professionally since 1991
- additionally, worked in Objective-C outside the NeXT/Apple ecosystem for many years
- worked with Rhapsody and with OS X since the early betas
- worked at Apple for 2 years, in performance engineering (focus: Cocoa)
- one of my projects was evaluating the GC
With that out of the way (and just like your 6 years, it has no actual bearing on correctness): which specific parts do you believe are inaccurate? I'd be happy to discuss, show you why you're wrong, or correct my post if you turn out to be right on something that can be verified (your opinion as to how awesome ARC is doesn't count).
Here's a quote from Chris Lattner:
"GC also has several huge disadvantages that are usually glossed over: while it is true that modern GC's can provide high performance, they can only do that when they are granted much more memory than the process is actually using. Generally, unless you give the GC 3-4x more memory than is needed, you’ll get thrashing and incredibly poor performance. Additionally, since the sweep pass touches almost all RAM in the process, they tend to be very power inefficient (leading to reduced battery life).
I’m personally not interested in requiring a model that requires us to throw away a ton of perfectly good RAM to get an “simpler" programming model - particularly on that adds so many tradeoffs."
I suppose they were able to do the binary-tree benchmark so much better than Java, because Swift supports 'UnsafeMutablePointers': http://benchmarksgame.alioth.debian.org/u64q/program.php?tes...
Edit: This Quora question mentions the performance of Swift before and after unsafe programs were included: https://www.quora.com/In-terms-of-performance-speed-is-Swift... The memory safe version used to be about 24x slower than C.
Swift is unfortunatelly usually an order of magnitude slower then Java and C# in real world according to last benchmarks I've made. I'm hoping that will change because I really love Swift.
… because it's faster to use a memory pool than GC for that … ditto C Rust Ada Fortran C++ …
http://benchmarksgame.alioth.debian.org/u64q/performance.php...
That Quora answer makes claims which are not true.
The Swift benchmarks game programs were always compiled with -Ounchecked (since Dec 7 2015).
The before was naive transliterations (from other programming languages) of single-core programs -- just to demonstrate that Swift was installed.
The after was someone doing the work and contributing programs written for Swift and written for multi-core.
[1]: https://benchmarksgame.alioth.debian.org/u64q/compare.php?la...
Note that I don't want to claim that Swift is faster than C in general/real life/anything but a few microbenchmarks. But the two just being within an order of magnitude makes a really strong case for Swift, I believe.
Being faster than C is not anything special in itself.
Most things being equal (typed, optimized, compiled, no runtime etc) C is mostly faster when it does something with a lower overhead than some other language (e.g. a specially written hashmap algorithm targeted to some program vs C++ std map type), not because of its primitives being faster.
Same reason Fortran is fast actually: it just disallows pointer aliasing entirely¹, meaning you get none of the flexibility of C pointers (heck, you don't even have pointers, basically), but if you're multiplying matrices it flies.
¹ I recall newer Fortrans have pointers, but as I'm not a Fortran programmer I don't actually know.
It arrived where it is today thanks to 40 years of research and exploring UB in optimizations.
90+% of your mobile code can be shared between Android and iOS. Not sure if that's something currently possible with Swift or not, but it was worth keeping C# around for our needs.
We're more of a "mobile app is something we also offer" and web is our main presence though, so your mileage may vary (especially if you're mobile-only or mobile-centric).
> 90+% of your mobile code can be shared between Android and iOS
This stat depends on how complex your app is, but it usually only applies to gaming. Otherwise it's almost always false.
We've already been down this path with the webview craze a few years ago. It was a total nightmare. These newer cross platform frameworks may no longer use webviews, but under the hood things are just as gross.
What is true though is that these cross platform frameworks always oversell themselves (with the exception of Unity3D). You end up trading in one problem for another.
Among the many problems you will encounter:
1. You miss a lot of newer features in the native platforms. If you want to incorporate those features somehow, the code becomes a conditional mess.
2. Performance is very meh and your hands are mostly tied in optimization. In both Android and iOS, getting performance correct (for example in a table view) requires a lot of tweaking. All of the cross platform frameworks I've used, including React Native, work for basic cases but quickly start dropping frames after that.
3. The majority of a mobile app's code is front-end, and this is not the place where you want to share code. Users on each platform expect different types of interactions and behaviors, not to mention UI aesthetics.
4. These different platforms all have their own characteristics and ways of doing things. These differences are not easily abstracted out. At the point where you are coding around these differences, you might as well have two different code bases. For all the complaining about differences between WebKit/Chrome/IE etc, the behavior is remarkably similar -- mobile platforms are far more diverged.
5. Native third-party libraries are very difficult to use because there is never the same library on the other platform. If there is, say with Facebook, they are not in sync.
6. You end up writing a lot of bridge code between iOS/Android and the framework. It's never pretty and painful to debug.
7. Getting locked into a third-party's framework is a bad place to be later on. Once it's in there, it's never coming out.
I could go on...
If you absolutely need to go cross platform early on, the best thing you can do for yourself is to lock down a common API/data model as early as possible, and create an aesthetic and design that is simple to implement on both platforms.
In my experience it's closer to 60%.
However, since you said my statement was completely false without a source, I felt compelled to show my sources.
51 million iPhones sold compared to 61 million the same quarter last year a DROP of 10 million. iPad an Mac also down double digit percentages, but iPhone is the only thing that really drives Apple. Overall sales DROP from $58B to $50B Source: http://money.cnn.com/2016/04/26/technology/apple-earnings/in...
iPhone market share also DROPPED from 18.3% to 15.3% in Q1. Source: https://www.idc.com/getdoc.jsp?containerId=prUS41216716
Sure Apple makes a ton of money and profit still, but you can't really argue that it's not dropping like a roick in the past 12 months. If you put $1,000 into Apple stock a year ago today, you'd have about $700 today. Source: https://finance.yahoo.com/echarts?s=AAPL+Interactive#{%22all...
Let me know where I went wrong, but I'm showing double digit sales drops, a large market share drop, and 30% stock value drops in the last 12 months. I'm not sure how my post is "completely false".
You mention the Mac, which as declined in absolute terms but has continued to grow relative to the declining market.
The same is true of the iPad, and there is evidence that it's decline is actually halting - I.e. it is reaching a plateau that is lower than its peak. Whether it will return to growth or not is an open question, but it is clearly not dropping like a rock.
So - the stock market story doesn't support your conclusion, nor does the iPad or Mac.
That leaves the iPhone. It is possible that the iPhone has reached a peak in terms of revenue.
Is it possible that it has reached an all time high in terms of active user base? That seems extremely unlikely.
For one thing, the total number of iPhones sold per year is still astronomical, and the devices have a long useful life. Even without a change of strategy, there will still be a huge number of new iPhone customers over the coming years.
Secondly there are many possible strategic solutions to a reduction in sales. Apple is selling far more SE devices than they anticipated, suggesting that there is pent-up demand for cheaper iPhones. They can address this segment easily, which will continue to increase the user base of IOS, even if revenue growth stagnates as a result of lower ASPs. This is just one possible strategy adjustment that would address the concern.
As I said, there has been a decline, but nothing supports your conclusion that Apple is 'dropping like a rock'. As such this is a bad conclusion on which to make a choice about whether to learn Swift or not.
At some point you have to realise that there's nothing Apple can do that would count as a success in some people's eyes. They are the most successful total failure I've ever heard of.
My assertion: Apple is dropping. Be careful about investing in Apple-only techs like Swift.
Your argument (I think): Apple is not dropping like a rock.
To support your argument, please provide a sources for the following:
- The last time Apple stock was down 30% from same day prior year.
- iPhone sales are not dropping > 10% (hence 'like a rock') .
- Mac sales are not dropping > 10% (hence 'like a rock').
- iPad sales are not dropping > 10% (hence 'like a rock').
- How iPhone + Mac + iPad all being down over 10% from prior year doesn't support my conclusion.
> it's at best a subtle difference and for most code you won't be able to tell the difference.
Which is a pretty dubious claim. I removed a lot of retain/release/autorelease calls when I moved to ARC. Perhaps I'm missing the OP's point...
My personal frameworks consist of 205584 non-comment, non-whitespace, non-single-bracket lines of code. Of these, 304 contain a retain, 1088 an autorelease, and 957 a release. That's 0.15%, 0.52% and 0.46% of the code respectively, for a grand total of 1.13%.
I'd have a hard time calling around 1% of total code "a lot", especially since the bulk of that is very simple boilerplate and trivial to write, but I guess everyone is different.
Mind you, this is a less-than-optimal code base, dating back to the mid 1990ies, with much more "but I am special" code that does do manual management where it shouldn't. Code I write today, even without ARC, has a significantly lower R/R density, well under 1%.
However, even of that 1%, the bulk is (a) releases in dealloc and (b) autorelease in class-side convenience initializers.
Quite frankly, I really miss convenience initializers in typical ARC code, writing [MPWByteStream streamWithTarget:Stdout] is so much nicer than [[MPWByteStream alloc] initWithTarget:Stdout] that (a) I wish people would write convenience initializers even in ARC mode (my experience is that they don't) and (b) I wrote a little macro that will generate an initializer and its convenience initializer from one specification. It's a bit nasty, so not sure I'll keep with it.
For the releases in dealloc, I once wrote an auto-dealloc that grubbed through the runtime to automatically release all the object instance variables (with an exception list for non-retained ones). It probably would have allowed me to eliminate the bulk of releases, but somehow I just didn't find it all that advantageous, writing those dealloc methods was just not that much of a hassle.
What may be interesting here is that the fact that I had an alternative may have been instrumental to realising it wasn't that big a deal. Things seem a lot worse when you don't have an alternative (or feel you don't have an alternative).
The same applies to ARC itself, at least for me: before ARC was released, it was exactly the solution I had wanted, especially in light of the GC madness. Again it was once I had used it in practice that it really became obvious how insignificant of an issue R/R was.
The only way I can see of getting significantly higher than 1% R/R code is by accessing instance variables directly, either because you are writing accessors by hand (why?) or grabbing at those instance variables without going through their respective accessors (why?!?!?). In both cases: don't do that.
Yet, whenever I mention these straightforward facts (particularly the numbers), people jump at me. Which is interesting in and of itself. My only explanation so far is that people generally write much, much worse code than I can imagine, or that R/R looms much larger in the collective Apple-dev psyche than can be justified by the cold, hard facts of the matter.
My guess is that's it's a little of the former and a lot of the latter. As a case in point, one dev who had jumped at me on a mailing list came back to me a little later in a private mail. He had converted one of his ARC projects back to R/R and was surprised to find what I had written to be 100% true: the R/R portion of the code was tiny and trivial, much less than he'd imagined, and hardly worth noticing, never mind fretting about.
However, the collective paranoia around R/R and the RDF around ARC seems to be big enough that reality doesn't really stand a chance. Which is of course also relevant. Perception matters, and that's why ARC is important.
It's safe to predict Swift will supported in Android and I still prefer iOS for entertainment whereas I have a bad experience on many Android phones for years including it took years for Samsung and LG to release new ROM.
Nobody's saying that Xamarin uses web views, but clearly there's a comparison to be drawn with the craze a few years back for writing mobile apps using web views. This was advocated as being cross-platform, allowing developers to write the same code and run it on multiple platforms. The downsides are the same in some ways, as the parent enumerated.
Xamarin's use of native UI is important, but in my experience it's clearly not as seamless as you think; while you access the UI natively, there are intrinsic architectural differences that make it difficult to do so in a high-performance manner without a lot of fairly hacky code.
I could write a long blog post about what a headache it is to support both platforms, but I don't think any of these frameworks solve the real pain points. It's generally a lot of small things which add up. It also takes a lot of team discipline.
Code sharing would be useful, but not massively since the majority of code is in the UI. When the UI is different, a lot of differences start to be needed in the non-UI code as well. Suddenly you are back at square one. Depends on the app though.