A closer look to Swift
Swift was first introduced at the WWDC 2014. It was all new and shiny and we did not know what to expect from the programming language. In my talk that I gave at Macoun 2014, the biggest German-speaking conference for iOS and Mac OS developers, I took a closer look to Swift. Which new and old language concepts and paradigms Swift is built upon? What good parts and what pitfalls does it have? Is Swift a functional language? Can it be used to program in the functional style? These are the questions I tried to answer. The Swift playgrounds from my talk are available on GitHub.
Domain-Specific Languages (Mobile Edition)
Last year, I gave a talk about domain-specific languages at Macoun, the biggest German-speaking conference for iOS and Mac OS developers.
Many software developers wish they could create their own programming language. A language that would exactly meet their taste and needs. However, language development is considered to be complex and laborious. Fortunately, there are frameworks for domain-specific and programming language development that make this a simple task. Domain-specific languages are widely used today. Just think of CSS, SQL, the visual format language of iOS and OS X Auto Layout constraints or the Objective-C predicate format. So let’s see, how we can easily create our own language, use an iOS device as an editor for it and generate source code or even a whole native app for multiple platforms from it.
In my talk, I gave a definition of problem domain and domain-specific language (DSL) and showed some examples of different domains. I also compared different kinds of domain-specific languages and pointed out the benefits of their use. My language implementation examples made use of the parser generator framework ParseKit and the IDE for language development Xtext. And finally, I demonstrated the Applause DSL and its usage for creating apps for different mobile platforms.
The video of my talk is in German. If you are interested in listening to this topic in English don’t hesitate to contact me. I’ll be happy to speak at your event.
Xtending Android development
Android is an amazing operating system that combines technical innovation with high popularity among the end-consumers. In spite of fragmentation, there is a large amount of developers across the world who enjoy developing applications for Android. Today, most Android applications are written in Java. Unfortunately, Java is known to be deficient in some modern language concepts and idioms like conciseness, declarativity, modularity mechanisms, the map/reduce pattern or immutable data. Wouldn’t it be great if there was a more advanced programming language for Android development? Luckily, there is one and it integrates seamlessly with Java. This language is Xtend.
Xtend is a statically-typed programming language that compiles to Java. Xtend has a clear and concise syntax. Although lambda expressions will be finally introduced in Java 8, Xtend’s syntax for them is significantly more readable. Another feature that makes Xtend a functional language is the absence of statements. Code written in Xtend is executed by evaluating expressions. Operator overloading in form of an operator-to-method mapping makes possible to fully customize operator semantics. Extensions methods allow for enhancing closed types with new functionality. Although the language is statically typed, its polymorphic method invocation combined with the use of extension methods brings duck typing to Xtend. Other powerful features like the type-based switch expression, shorthand property access and local type inference make programming in Xtend a real fun. But what probably even more important than the language features is the full, bidirectional interoperability with Java, a low learning curve for Java developers, comprehensible and efficient generated Java source code and a great IDE support. All this makes Xtend ready for immediate use in every environment where Java and Eclipse are used for development. If you are new to Xtend, check out its documentation.
In this tutorial, we will write an Android application in Xtend, build an APK and run it on the Android emulator. We will implement a simple application called Is Following? which let us check if a Twitter user follows another Twitter user.
To be able to follow the tutorial, you need to be acquainted with Android development and the Eclipse IDE.
Setting up the IDE
First, we’ll install and configure the IDE and create a project. You can skip the first three steps, if you already have an Eclipse installation that you use for Android development.
- Download and install Eclipse IDE with built-in Android Developer Tools from http://developer.android.com/sdk/index.html.
- Follow the instructions at http://developer.android.com/sdk/installing/bundle.html to set up your Android SDK for the first time.
- Alternatively, you can use an existing Eclipse installation and set it up as described at http://developer.android.com/sdk/installing/index.html.
- After you have Eclipse, Android SDK and the ADT plugin ready, install the latest Xtend release. To do so, go to Help -> Install New Software… and paste the Xtend update site http://download.eclipse.org/modeling/tmf/xtext/updates/composite/releases into the Work with field.
- Choose Xtend.
- Click Finish and follow the instructions of the installation wizard.
Creating a project
Now, we’ll create a project and start writing the application. You can download the complete source code from https://github.com/nossipova/isfollowing.
- Create a new Android Application Project with only one blank activity
MainActivity
.
- The compiler compliance level of the project needs to be set to 1.6.
Creating a layout
Create a simple layout that consists of:
- an editable field for each of both Twitter names,
- a button to start the request and
- a text view that will show a result.
Writing the application
Our application will have an activity to interact with the user and a communicator which will send requests to Twitter and process its responses. The communication with Twitter will be performed asynchronously. Let’s implement these components.
- Delete the class
MainActivity.java
that was automatically generated through the project creation. - To create a new Xtend class, select New -> Xtend Class from the project context menu in the Package Explorer.
- On the first page of the creation wizard, type
MainActivity
in the Name field and selectandroid.app.Activity
as a superclass. - Click Finish.
- The class we’ve just created will show an error:
Mandatory library bundle 'org.eclipse.xtext.xbase.lib' 2.3.0 or higher not found on the classpath.
Use the available quick fix to add Xtend libraries to the classpath.
MailActivity
will have two methods:onCreate(Bundle)
andshowResult(Object)
. The first methodonCreate(Bundle)
prepares the content view and registers the click listener callback of the Check button. In the callback, we initialize the communicator, use its methodisNetworkAvailable(Context)
to test if network is available and execute the communicator asynchronously. The second methodshowResult(Object)
updates the UI with the response received from the communicator by setting the text value in the result text view.
package de.nataliaossipova.isfollowing import android.app.Activity import android.os.Bundle import android.widget.Button import android.widget.EditText import android.widget.TextView class MainActivity extends Activity implements AsyncDelegate { override onCreate(Bundle it) { super.onCreate(it) R$layout::activity_main.setContentView val button = R$id::Button01.findViewById as Button button.onClickListener = [ var communicator = new TwitterCommunicator communicator.delegate = this as AsyncDelegate if (communicator.isNetworkAvailable(this)) { val editText1 = this.findViewById(R$id::EditText01) as EditText val editText2 = this.findViewById(R$id::EditText02) as EditText communicator.execute(editText1.text.toString, editText2.text.toString) } ] } override showResult(Object it) { var isFollowing = Boolean::parseBoolean(it as String) var resultView = this.findViewById(R$id::ResultView) as TextView resultView.text = if (isFollowing) { this.getString(R$string::yes).toUpperCase } else { this.getString(R$string::no).toUpperCase } } }
- Create a new Xtend class
TwitterCommunicator
as a subclass ofandroid.os.AsyncTask
. The subclass overrides two methods:doInBackground(Params...)
andonPostExecute(Result)
. IndoInBackground(Params…)
method, we create a new Twitter URL from both Twitter names passed in as parameters. After that, we open an HTTP connection and read the input stream from it. The second method passes the data read from the input stream to the main activity.
package de.nataliaossipova.isfollowing import android.content.Context import android.net.ConnectivityManager import android.os.AsyncTask import java.io.BufferedReader import java.io.InputStream import java.io.InputStreamReader import java.net.HttpURLConnection import java.net.URL class TwitterCommunicator extends AsyncTask<String, Void, String> { private AsyncDelegate delegate override protected doInBackground(String... it) { var url = new URL('https://api.twitter.com/1/friendships/exists.json?screen_name_a=' + get(0) + '&screen_name_b=' + get(1)) (url.openConnection as HttpURLConnection).inputStream.readStream } override onPostExecute(String it) { if (delegate as Object != null) { delegate.showResult(it) } } def setDelegate(AsyncDelegate it) { delegate = it } def isNetworkAvailable(Context it) { val networkInfo = (getSystemService(Context::CONNECTIVITY_SERVICE) as ConnectivityManager).activeNetworkInfo if (networkInfo != null && networkInfo.connected) { true } else { false } } def private readStream(InputStream it) { var reader = new BufferedReader(new InputStreamReader(it)) var line = '' var sb = new StringBuilder while ((line = reader.readLine) != null) { sb.append(line) } if (reader != null) { reader.close } sb.toString } }
- To avoid tight coupling between the activity and the communicator, we will make use of the delegate pattern. Create a new Xtend class
AsyncDelegate
. This time it will be an interface, so replace the keywordclass
with a keywordinterface
in the newly created Xtend class. The interface declares only one methodshowResult(Object)
. We will call this method from the post execute callback ofTwitterCommunicator
.
package de.nataliaossipova.isfollowing interface AsyncDelegate { def void showResult(Object it) }
Our MainActivity
already implements the AsyncDelegate
interface.
Build and Run
Now, when we are done with writing source code, add permissions android.permission.INTERNET
and android.permission.ACCESS_NETWORK_STATE
to the Android manifest and let’s build an APK and run it on an AVD.
We need to tell ADT how to export the Xtend libraries. Choose Properties -> Java Build Path from the project context menu and go to the Order and Export tab. Select the checkbox beside Xtend library.
After closing the Properties window, you can launch the application on an existing AVD or a device.
Where to go from here
Now that you know how to use Xtend for Android development, go and create awesome Android apps in this sophisticated programming language!
Don’t hesitate to let me know if anything of the above is confusing to you or if you’d like me to go into more detail.
CocoaPods, locally speaking
CocoaPods is a simple-to-use but efficient framework for managing dependencies in Xcode. You might have already used it to manage library dependencies hosted on GitHub. Otherwise, take a look at the CocoaPods website first. But do you also know that you can use CocoaPods to manage dependencies that are not stored in a GitHub repository or any other remote repository at all? Let’s see how to do that.
Let’s say, you have an Xcode project named Provider
which you want to include into another Xcode project named Consumer
. First, you need to write a pod specification for your Provider project. The crucial part of specifying a local dependency is how you define the source
attribute. In this case, source
should contain a path to the Provider repository, relative to the Podspec file. So, if you placed the Podspec into the root of the Provider project, the path will be '.'
. The second option of the source
attribute needs to be a tag or a commit number. If you want to test your changes while developing, you will probably use a commit number, for example: 'abcd123'
. Putting both things together, we get:
s.source = { :git => '.', :commit => 'abcd123' }
The remaining part of the Podspec won’t differ from the one you would write to use with a remote repository. So, your Podspec will look something like this:
Pod::Spec.new do |s| s.name = 'Provider' s.version = "0.0.1" s.summary = 'Provider is a framework for consuming RESTful web resources on iOS.' s.homepage = 'https://bitbucket.org/<some-username>/provider' s.license = 'Apache License, Version 2.0' s.author = { 'Natalia Ossipova' => 'natalia.ossipova@<some-domain-name>.com' } s.source = { :git => '.', :commit => 'abcd123' } s.platform = :ios, '5.0' s.requires_arc = true s.source_files = 'Provider' s.resources = 'Provider/Default.png', 'Provider/Default@2x.png', 'Provider/Default-568h@2x.png', 'Provider/en.lproj/InfoPlist.strings' end
To find out what other attributes you might need to fill in refer to the CocoaPods wiki.
Here are some tips to make you Podspec work:
- If your Xcode project contains subfolders, list all of them containing source files in the attribute
source_files
:s.source_files = 'Provider', 'Provider/Globals', 'Provider/Model', 'Provider/View', 'Provider/Services'</code>
- If you defined imports globally in a *.pch file, specify it as the
prefix_header_file
attribute:s.prefix_header_file = 'Provider/Provider-Prefix.pch'
- List all resources, i.e. all PNG, *.strings and XIB files, in the
resources
attribute.- Give your
Localizable.strings
file of the Provider project a unique name, e.g. Provider-Localizable.strings
, and use NSLocalizedStringFromTable
in the Provider code.After finishing and validating the Provider Podspec, you need to point your Consumer to Provider by using the :path
option in the Podfile of Consumer. The path to the Provider project can be relative to the Podfile. If, for instance, you checked out both projects into the same folder, your Podfile will look like this:
platform :ios, '5.0' pod 'Provider', :path => '../Provider'
Now, you can install the Consumer dependency and work on both projects. Don’t forget to update the commit number in the Podspec each time you’ve committed your changes on Provider to a local repository.
New blog
Hello, I’ve just started this blog. Please wait a little until it is filled with thoughts about mobile systems, language engineering and software architecture. I hope to see you here again.