How to deal with the lack of reflection in Swift? - ios

As an experienced Objective-C developer who is now learning Swift , I'm really missing some of the reflection and dynamic features of Objective-C.
For eg: I had written a JSON serializer which automatically mapped keys and values using KVO and Objective C introspection , and there are open source libraries like Mantle which do this.
I could declare my object as an NSObject subclass and proceed but I feel that this is not the Swift way of doing things.
Is there any other way to accomplish the same tasks , while avoiding boilerplate , using what Swift provides ?

EDIT: (2016) this answer is auto-dated. Some of the advice may still be relevant but now that Swift is open-source, I would look into other possible answers.
There is no native KVO reflection like what you described built into Swift. See:
https://stackoverflow.com/a/24092370/798682
And based on what we do know about how the Swift compiler optimizes method execution at compile time (vs the pure runtime implementation of ObjC) it doesn’t seem likely to be added anytime soon. See https://stackoverflow.com/a/25438299/798682 and
http://blog.untitledkingdom.co.uk/obj-c-vs-swift/
for more info on that.
With all that being said, here is a blog post on some KVO alternatives in Swift:
http://blog.scottlogic.com/2015/02/11/swift-kvo-alternatives.html
and another that details some of the reflection capabilities that are in Swift:
http://freecake.angelodipaolo.org/simple-reflection-in-swift/.

Related

Is there any life-cycle graph for Swift look like same as we know for Objective-C?

We know iOS life-Cycle as below Graph with Objective-C:
e.g. where is main() in Swift project , or where is AppDelegate.swift's functions?
It's the same because it's not a language depending life-cycle. It's an Application life-cycle.
You could change the language, but the way application works still be the same. If there were any differences, you won't be able to use swift/objc in the same project.
All calls are still there, but they change the way they look (but not named) a bit because of swift syntax. You could look them up here: Looking to understand the iOS UIViewController lifecycle

Making a Swift OSS library compatible with Objective-C

I am building a library in Swift, and it has to support Objective-C.
I already checked this answer which recommends to write the library in Objective-C but the requirements that were given to me are to write the library in Swift. I am delivering the library in source form, so the argument there (against writing the library in Swift) about unstable ABI should not apply in my case.
So I've heard that in order to make this Swift library work for Objective-C, I will have to avoid using the advanced features in Swift that are not available in Objective-C. Examples of these are:
Generics
Structs
All Swift classes must derive from NSObject
So my 2 questions are:
Where Can I find an exhaustive list for those constraints?
How can I quickly test that my library is compatible with Objective-C? I am not familiar at all in the interoperability topic of Swift and Objective-C. Not a lot articles that I could find online. Is the official Apple docs sufficient? and which parts can help?
I appreciate all the help here.
The most comprehensive list of Swift features not available from Objective-C is in the Swift Type Compatibility section of Apple's Using Swift with Cocoa and Objective-C guide.
Quoting from there, the list of exclusions are as follows:
Generics
Tuples
Enumerations defined in Swift without Int raw value
type
Structures defined in Swift
Top-level functions defined in Swift
Global variables defined in Swift
Typealiases defined in Swift
Swift-style variadics
Nested types
Curried functions
The whole guide is worth reading, but I'd pay particular attention to the Mix and Match section which describes calling Swift from Objective-C and vise-versa, including external frameworks.
I would definitely recommend doing as #Mike Taverne suggests: make a suite of unit tests in Objective-C which exercise the APIs you've developed in Swift. That's the best way to make sure it all works as expected.
There are more things good to know beforehand.
You cannot extend swift class by objective c class.
You cannot use #objc on generic swift class or method (you can use generics in #objc swift class on methods though)
So the api will be more limited than if written in objective c as it support generics (though people like to say not real generics etc...) and not to be able to extend any class you provide in your api can be quite limitation too, but still it's doable.
You just have to put #objc everywhere and compiler will say you very quickly what is not supported. Also casting can be quite tricky sometimes... I ended up to cast like this because I was reciving objective c generic class from swift in swift code
as! CSResponse<AnyObject> as! (CSResponse<AnyObject> & CSListData)
This is working code, but direct cast is imposible.
Best is to write pure swift for swift and use objective c libs as needed otherwise you will and up fighting to write one line of code. (like me :))

Giving or changing the implementation of method at runtime in iOS

Recently i caught with the a thought of changing the implementation of method after deployment
When i googled about objective c runtime and all, came to know about method swizzling methodExchangeImplementations etc.
I know that it could be possible by https://rollout.io/
But my thought is how to do Hot Patching by myself for simple things.
my idea is injecting the code using webservice call.
Webservice should give a replacement for particular method.
That string has to be converted to executable code
What i want to know is ...
How to inject the code in existing method of enterprise application.
For ex:
Consider this method in objective c
-(void)fetchTheResult{
// some code lines
}
After deployment i would like to change the method implementation to
-(void)fetchTheresult{
NSLog(#"test log");
//some Code lines
//some more lines
}
Please guide me the way to achieve this
This is a big question and you've some research to do to figure out an answer. Here as some things you can look into:
First you've referenced Rollout, you could follow the same idea and send your update as JavaScript. You'll need to study how to call JavaScript, swizzle methods, and probably dynamically add methods - more on that in a moment.
An alternative you can investigate is dynamic library loading - you can open, and call code in, a library which your app loads at runtime. So you could look at sending your update as a library. You'll still need to do method swizzling and probably dynamically add methods...
As well as method swizzling you may find you need to dynamically add methods - e.g. so you have something to swap the existing implementation to. A good place to find out how to do that is Mike Ash's writings on KVO - go DuckDuckGo (or Google)
HTH
It is not as easy as you think, at least in Objective C and other similar compiled languages. This kind of runtime changes to the code is only possible in interpreted languages like Javascript.
The basic problem is, the apps are not allowed to change the executable files themselves. The apps on iOS and Android run in a sandboxed environment, and thus have access to limited disk locations only.
Also, after compiling the code, the code does not know where the part of code is converted and stored in machine language. You have to understand the basics of compilers to understand this. There are heavy optimisations happening to your code during this process.

Swift ResearchKit Conditional ORKOrderedTask

I'm currently working on a medical research app with swift based on ResearchKit, which is an objective-c based framework. I'm trying to create a conditional ORKOrderedTask, like the one at: https://gist.github.com/mattio/9126ecc4f08b9f0497d9
Basically, it says that if the answer to the previous question is yes, then display the next question, if not, skip it. I can find the code for it in objective-c but I'm having trouble converting it to swift.
The recently merged ORKNavigableOrderedTask provides that exact functionality by means of using NSPredicates to check against previous or ongoing task results.
In the RKNavigableTaskExample repository you can find a small self-contained example on how to use the class. The example is written in Objective-C, but it should be easy to call the same APIs from Swift.

Why is there no Objective C AddressBook Framework for iOS, and how to best tackle the problems with C in Swift?

This might be really generic and rather about the framework in general than a programming question. But, in the light of Swift, and the tedious and sometimes impossible tasks you have interacting with C APIs, that question is very relevant.
When building a new app for iOS, I discovered that you can really have a hard time working with address book framework. First, there is the uncomfortable pointer passing that you have to do for many CoreFoundation Methods. Secondly, the functions mostly return that ugly Unmanaged objects, where you have to figure out if they are retained or not (ARC is several years old now!). Accessing the properties through their identifiers is terribly cumbersome and far from typesafe. And lastly, since there is no C Function Pointer Support yet, you can´t even call ABAddressBookRegisterExternalChangeCallback(addressBook: ABAddressBook!, callback: ABExternalChangeCallback, context: UnsafeMutablePointer<Void>) because the ABExternalChangeCallback is so far only defined in Objective-C!
Then I found that there is some nice Objective-C Api in the Mac OS Version of AddressBookFramework. How unfair! Isn´t the iOS Frameworks younger? Why do you think Apple did this? And when will they change this in your opinion? Did I miss something, and is there an Objective-C Api for iOS, too?
Any suggestions for how to tackle above problems in the most convenient and beautiful way are welcome, too! For my part, I´m writing a complete wrapper to obscure all the nasty pointer- C-Function- and global constants uglyness. As soon as it´s ready I´ll commit it to StackExchange and maybe Github to let others benefit and discuss my solution.
EDIT: finally managed to upload my wrapper to GitHub. See
https://github.com/SocialbitGmbH/SwiftAddressBook
I agree with you about what iOS provides to access to the address book.
I've posted an answer explaining how I handled the problem, using some functional aspects of swift, and how I dealt with extracting unmanaged objects.
Briefly:
I defined a custom operator to allow me chaining function calls to transform some input data
I implemented 2 generic functions to extract unmanaged objects
posted some code to show how I access to the address book, loop through all contacts, and retrieve some data for each one

Resources