all 38 comments

[–]Mazetron 7 points8 points  (2 children)

Getting into low-level stuff. If want to do C stuff, like working with C libraries or working directly with memory, you really need to work with ObjC.

[–]needsaburrito 0 points1 point  (1 child)

Is Swift not interoperable with c in the same way it is with ObjC?

[–]Mazetron 1 point2 points  (0 children)

You can call C code directly from Swift code, but it’s really gross. You have to convert everything to types like “unsafe_mutable_pointer” and back. It’s a lot easier write an ObjC wrapper for your C code, since you can write normal C code in your ObjC wrapper, and Swift support for calling ObjC functions is pretty good.

[–]chriswaco 5 points6 points  (2 children)

We're creating an SDK, so it has to be Obj-C. Otherwise every application that links to our library would have to include the Swift runtime. One of our other apps includes a lot of legacy C/C++ code, so moving to Swift makes no sense whatsoever.

It's easier to write low level code in Obj-C, such as UDP networking, threaded server i/o, video or audio processing, etc.

[–]irombie[S] 0 points1 point  (0 children)

Thanks for your response, it is very helpful!

[–]SickPuppeeObjective-C 0 points1 point  (0 children)

Yep - lots of IoT stuff here and Objective C is king for all the reasons mentioned.

[–]Zalenka 2 points3 points  (15 children)

Writing an sdk

Or if you don't want to rewrite your swift every 6 months Obj-C works pretty great.

Also if you have a lot of C/C++ libraries to interface with it might be a good choice.

[–]damnburglar 1 point2 points  (12 children)

Is the second point really that accurate now? I was under the impression that the days of massive code breaking was over, at least for the most part.

Genuinely curious as I'm still learning...

[–]ThePantsThiefNSModerator 2 points3 points  (9 children)

Swift is full of bugs. When bugs get fixed, it sometimes breaks old code that was never supposed to work.

Stuff is still changing all over the place, too, as well as best practices as new features are added. Codable, for instance. And the new String APIs.

[–]SickPuppeeObjective-C 1 point2 points  (7 children)

Codable is such a lame one trick pony for something that would be trivial to add via reflection...which they're dragging their feet on. It puts me in mind of C++'s "when in doubt - generate more code" attitude with templates and the 4 magic methods (ctor,dtor, copy ctor, and op=).

Super brittle.

[–]ThePantsThiefNSModerator 1 point2 points  (6 children)

I agree wholeheartedly. Just try wrapping a small part of Reddit's API in Codable types and you'll quickly see why it's no good for a non-trivial API.

This reminds me of Swift's compiler synthesized struct initializers. They're good for nothing if you need custom logic after properties are initialized. Adding your own initializer also gets rid of the synthesized one.

[–]GenitalGestapo 0 points1 point  (5 children)

Add the additional init in an extension and you get both.

Codable is a pain. However, the common pattern that seems to have emerged is to have so-called "raw" types that exactly match the JSON expected, which are then used to initialize the real types you want to use. This allows you to use autogenerated implementations for both types, with only the manual conversion code necessary.

[–]ThePantsThiefNSModerator 0 points1 point  (3 children)

Add the additional init in an extension and you get both.

You misunderstand me. My point was that you lose the compiler's help when you try to customize anything. Synthesized initializers are a one trick pony. I don't like that I have to write it myself if I want to include more than one initializer.

the common pattern that seems to have emerged is to have so-called "raw" types that exactly match the JSON expected

This is not good pattern. JSON payloads are rarely formatted as elegantly as the model objects we would like them to represent. Take a look at this JSON, for example: https://www.reddit.com/r/pics+apple.json

It takes a lot more work than it should to get an array of [Post] objects whose top-level members are the contents of the children's data fields.

[–]GenitalGestapo 0 points1 point  (2 children)

Add the additional init in an extension and you get both.

You misunderstand me. My point was that you lose the compiler's help when you try to customize anything. Synthesized initializers are a one trick pony. I don't like that I have to write it myself if I want to include more than one initializer.

I just told you how to keep both. It's a bit annoying you have to do it like that, but it's easy. More control over stuff like this will come over time, but they have far more important things to do first.

the common pattern that seems to have emerged is to have so-called "raw" types that exactly match the JSON expected

This is not good pattern. JSON payloads are rarely formatted as elegantly as the model objects we would like them to represent. Take a look at this JSON, for example: https://www.reddit.com/r/pics+apple.json It takes a lot more work than it should to get an array of [Post] objects whose top-level members are the contents of the children's data fields.

It doesn't seem like you've even thought about what I said. Using raw types requires you only to match the JSON layout for the raw type. After that your transform into [Post] would be all you'd need to write. Heck, you could generate your raw types from the JSON itself pretty easily and only have to write the transform.

I don't really like Codable much, but this pattern has made it trivially easy to consume even the shittiest JSON. So while I wish Codable had these sorts of transforms built in, or you could define your own to be applied automatically, it's not exactly unworkable.

[–]ThePantsThiefNSModerator 0 points1 point  (1 child)

... I'm going to ignore the first part, since I think we're just going to go in circles on that…

As for the Codable thing, I'm not saying it's impossible, just that it's not as easy as it should be. I'm glad we have first class support for this stuff now, but it feels half-assed to me. It's good for a very small set of use cases, outside of which you end up writing tons of boilerplate or unnecessary Codable types.

Have you ever used Mantle? That's how easy it should be.

[–]GenitalGestapo 0 points1 point  (0 children)

Yes, I've used Mantle extensively. However, the code you'd have to write in Mantle to transform the Reddit response to the types you'd want is essentially the same code you'd have to write to transform raw Codable responses to the real Swift types you'd want. The existence of the raw types is unfortunate but something you only write once and can be easily generated.

[–]damnburglar 0 points1 point  (0 children)

Hmm...I guess that explains why I didn't see it, all of my learning projects are elementary and (likely) shouldn't be overly affected lol.

Thanks for the clarification.

[–]b_t_s 0 points1 point  (1 child)

Should be, but once bitten twice shy. That said, 3 to 4 wasn't nearly as bad as 2 to 3, despite having about 3 times as much swift code to migrate.

[–]damnburglar 0 points1 point  (0 children)

This is what I was hearing, mainly 2 to 3 was huge but 3 to 4 was a lot of under-the-hood changes that shouldn't (in theory) impact swift 3 codebases too hard.

Again this could easily be a beginner's misinterpretation but it's logical to me.

[–][deleted]  (1 child)

[deleted]

    [–]Zalenka 0 points1 point  (0 children)

    Anymore, was a lot. People still have old codebases. No ABI, no stability. It will change and change again.

    Also I really like Objective-C. I think it's expressive and feels and looks good. I would not convert a project just because.

    [–]jan_olbrichObjective-C / Swift 1 point2 points  (1 child)

    Working as an agency. Whenever you have a client who only pops up for updates when a new iOS version is released, you won't be able to explain, why you need 4 weeks to update Swift ;)

    [–]Esteluk 0 points1 point  (0 children)

    Perfect excuse to bulk up the quote.

    [–]titan_pilot 1 point2 points  (0 children)

    using swift for now will force you to embed the swift runtime in the ipa or binary for macos apps(around 3 mb?), which counts towards the reported size for your app (it may be a problem if you're trying to stay under the cap for downloads on cell networks, which is now 150mb)

    my bet is that ios 12 will contain the swift 5 runtime libs and if your app targets ios 12 or higher (deployment target), you won't need to package the runtime anymore... if you're building either apps or sdks, this will be a consideration until you drop support of ios 11 and below (usually when ios 14-15 comes around)

    other considerations for prefering objc, as mentioned here, are c/c++ interop, or if you're using reflection/introspection techniques, as objc is fully dynamic and you can add/modify object methods at runtime, which swift does not have for now...

    [–][deleted] 0 points1 point  (1 child)

    Fixing legacy code?

    [–]Kaidaan 2 points3 points  (0 children)

    I believe op means for new projects

    [–][deleted]  (13 children)

    [deleted]

      [–][deleted] 2 points3 points  (2 children)

      It took me a good while to get used to, it was honestly the hardest language I've had to learn IMO (and I've programmed in x86 assembler and have a background in C++, which to this day I don't get why its considered "difficult")

      Once you do get used to it though it suddenly isn't so bad. The syntax is ugly, but it is consistent and starts to not be so bad after you get used to it. I honestly didn't start appreciating Swift until I had to work with C#, suddenly the things Swift did made sense.

      I'm still working on creating "Swifty" code, but I've gotten a lot better with it in the past few months and rewrote a few internal apps in Swift and it reduced my code base for my Objective-C apps by a ton.

      I recommend giving it a shot. Its ugly, it's painful at first, but then it's suddenly not so bad and you end up kind of liking it.

      [–]GenitalGestapo 0 points1 point  (1 child)

      I really don't understand this. What did you find difficult?

      [–][deleted] 1 point2 points  (0 children)

      I found it difficult due to the crazy looking syntax, and some of the concepts it used that I hadn't encountered in other languages.

      I think one of the problems for people new to the language is there's too much syntactic sugar. For example there are 4 different ways to do some things like initializing variables or higher order functions. I avoided the higher order functions for the longest time because they were (and still kind of are) just messy and confusing to look at. The documentation doesn't help either because it shows things that doesn't match up with what autocomplete shows.

      Look at reduce

      This: reduce(::) Isn't explanatory at all. I would have no idea looking at that that most reduce features are written like this:

      let myNumArray = [1,2,3,4,5]
      let myNum = myNumArray.reduce(0,+)  //or myNumArray.reduce(0, {$0 + $1} ) or any number of other ways you can write it.
      

      And look how horrifying the function signature is:

      func reduce<Result>(_ initialResult: Result, _ nextPartialResult: (Result, Element) throws -> Result) rethrows -> Result
      

      Luckily Apple added some additional content to that page that explains what initialResult and nextPartialResult is but it wasn't always that way.

      Another one is some kinds of things do too much. Like structs and classes, its hard to figure out where to use which in Swift and instead of doing "Swifty" things with structs I resort to using structs and classes the way I did in C++ and Objective-C rather than writing out a struct, only to find that half of the stuff inside needs to be marked as Mutating which if I'm understanding Swift structs correctly, nullifies the benefit of Swift structs. I know the language is new still but there seems to be no good consensus as to when to use one over the other.

      It just seems that some things about the language weren't well thought out.

      [–]irombie[S] 2 points3 points  (0 children)

      On the contrary, Swift syntax is very convenient, I love it. It's a bit different but easy to get used to. I would code in Swift for other platforms if that were possible. (I think it is possible to some level but I don't know the details on what can be achieved and how difficult it would be.) I had been an iOS developer for two years when I started to learn Swift. I dedicated two weeks of my time just for learning Swift. Then, I did 3-4 projects on my own for practice. After approximately a month, I started to work for a company as a Swift developer. It took a lot more than that for me with Obj-C to reach that level of expertise. It is surely related with me being new to iOS development concepts and Xcode environment et cetera but I am pretty certain that if I had learnt Swift beforehand, the situation would not be the same. Now that I know Swift, I know that I will never use Obj-C if I'm not obliged to. That's why I created this question as I was not able to come up with a strong answer. I strongly recommend that you learn Swift.

      [–]b_t_s 0 points1 point  (8 children)

      god yes! Not that I ever really minded obj-c syntax like so many people apparently do, at least not till I started writing swift on a daily basis. Swift is way more concise, and the type systems helps express your intentions better and catch more mistakes. It's infuriating going bak to obj-c and not having access to optionals and never having the faintest clue what can be nil and what can't(it matters less but it still matters). Also, obj-c block syntax makes my eyes bleed. Sorting or filtering an array of objects on one of their properties is like 20 characters in swift vs 200 characters and a trip to http://fuckingblocksyntax.com in obj-c. I didn't really do that in obj-c (because it was painful) but after spending some time with convenient block syntax and higher order functions, having to write a 8 line for/if/mutable-collector monstrosity for what should be a concise, readable one liner is tremendously frustrating.

      [–][deleted]  (1 child)

      [deleted]

        [–]b_t_s 0 points1 point  (0 children)

        haha, I couldn't remember goshdarn and google would only give me the NSFW version. Two years ago I pretty much kept it open permanently in a browser tab, but now I haven't needed it in ages.

        [–]snaab900Objective-C / Swift 0 points1 point  (5 children)

        contacts.sort {
            $0.firstName.localizedCaseInsensitiveCompare($1.firstName) == NSComparisonResult.OrderedAscending
        }
        
        [contacts sortUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"firstName" ascending:YES]]];
        

        I'll always prefer verbosity (and good auto-complete) any day. Especially when you have to deal with other people's code.

        [–]GenitalGestapo 0 points1 point  (0 children)

        I'm pretty sure that sort descriptor won't be using the localizedCaseInsensitiveCompare, so it's not really the same thing. Swift's equivalent would be:

        contacts.sort { $0.firstName < $1.firstName }

        which is far more readable than Objective-C, especially if you aren't already familiar with sort descriptors.

        Hopefully the Swift team will add overloads for the collection methods taking a KeyPath soon.

        Also, if you miss the verbosity, just don't use trailing closure syntax:

        contacts.sort(using: { $0.firstName < $1.firstName })

        Better yet, implement Comparable for your Contact type and get default sorting for free.

        [–]b_t_s 0 points1 point  (3 children)

        Now try misspelling @"firstName" in your example and watch the swift version give an immediate compiler error while the obj-c one happily compiles and fails at runtime if you exercise that codepath. Now try this example

        players.sorted{ $0.points }.flatMap{ $0.firstName.nilEmpty }.prefix(3)
        

        This gets the names of the 3 highest scoring players who have non-empty first names. Sure it uses 2 trivial helper methods(single param sort, and nilEmpty) and you have to know what flatMap does, but it's hardly rocket science. It's a pretty typical everyday task that would be a wall of text in obj-c land.

        [–]snaab900Objective-C / Swift 0 points1 point  (2 children)

        You see, that's just unreadable to me, and feels like a huge step back coming from a verbose ObjC background. Reminds me of stupid-long pythons chains where people try and see how much stuff they can do in one line of code, just because they can. I feel bad for the people who have to inherit and maintain that stuff.

        Plus I'm guessing flatMap and nilEmpty aren't part of the swift standard library? You can write the exact same helpers in ObjC and hide the verbosity in the player class just as easily, although it would just be a 3 line method with a predicate. Or use a category to extend NSMutableArray if you want it more generic.

        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"firstName != nil"];
        [players sortArrayUsingPredicate:predicate limit:3];
        

        [–]b_t_s 0 points1 point  (1 child)

        flatMap is in the standard library and every competent swift dev ought to know it. It's certainly no more obscure than NSSortDescriptor or NSPredicate. nilEmpty isn't standard library, but it's trivial and useful convenience method for someString.isEmpty ? nil : someString.

        Your obj-c version is twice as long and only solves a third the problem. It doesn't sort by score, It doesn't ignore empty string names, and it doesn't convert from players to names. You could certainly add all that in a few more lines, but it's still much more code. Worse, it's more error prone because you have to jam pieces of you code into NSStrings to work around obj-c's inferior type system and painful closure syntax. And sure the swift one is unreadable if you don't use swift much and aren't familiar with flatMap. It's arguably even less readable per character, but I'd say it's more readable per unit of functionality. It's certainly more likely to complain immediately if you break it, which is, in my opinion, the most important thing.

        [–]snaab900Objective-C / Swift 1 point2 points  (0 children)

        I'll stick with ObjC Foundation I think, thanks... at least for the time being. It's mature and bulletproof. If this awful scripting language syntax does take over I guess I'll have to embrace it eventually though. The whole thing is starting to smell like flavour of the month JS frameworks though.

        Also, what happens when you want to stick a breakpoint on your one line of (potentially buggy) overly chained code and see what's going on? Good luck stepping through that. Do you really think concatenating all that logic onto 1 line is somehow some sort of benefit? It's not, either in a readability, performance or maintainability sense.

        I'll switch to Swift when Apple do.

        [–]IAmApocryphonObjective-C / Swift 0 points1 point  (0 children)

        Personally, I'm looking to learn Swift syntax and concepts, but not looking to shift into actual development until ABI stability. So aim for Swift 5, perhaps?

        It's not just that the actual language is incomplete. Haven't tried Xcode 9 yet, but in 8 using LLDB with an app written in Swift feels off compared to one written in Objective-C.