Info

Programmer by day, artist by night

Posts from the Programming Category

Developing iOS11 Apps with Swfit - Lecture 1 Summary

What’s New

After completing the 1st lecture, here is what I found new from the previous courses I took a few years ago.

  • Uses Swift 4, Xcode 9
  • Rename (refactor) with cmd + click on variable name
  • Fuzzy match on intellisense (was available form Xcode 8)
  • Back to developing card game¬† (the previous few years focused on developing calculator)
  • Outlet collections

The following video shows the state of the app Concentration after completing lecture 1.

 

The course Developing iOS 11 Apps with Swift by Stanford (cs193p) is available for free from https://itunes.apple.com/us/course/developing-ios-11-apps-with-swift/id1309275316

Professor Paul Hegarty of Stanford University teaching Developing iOS 10 Apps with Swift, from Lecture 1, graphite on copier paper, 8.5″ x 11″

The course Developing iOS 10 Apps with Swift by Stanford has been around for a while (about 6 months) free on iTunes:
https://itunes.apple.com/us/course/developing-ios-10-apps-with-swift/id1198467120

Had been following the course since the Objective-C days and it’s time to take the latest version in the same tradition.

Here are the course contents based on the 17 lectures :

1. Introduction to iOS 10, Xcode 8 and Swift 3
2. MVC; iOS, Xcode and Swift Demonstration
3. More Swift and the Foundation Framework
4. Views
5. Gestures and Multiple MVCs
6. Multiple MVCs, View Controller Lifecycle, and Memory Management
7. Error Handling, Extensions, Protocols, Delegation, and Scroll View
8. Multithreading and Text Field
9. Table View
10. Core Data
11. Core Data Demo
12. Autolayout
13. Timer and Animation
14. Dynamic Animation Demo
15. More Segues
16. Alerts and Action Sheets, Notifications, Application Lifecycle, and Persistence
17. Accessibility

Will publish the code like before on Github but this time will put all the projects and assignments in one repository:
https://github.com/sanjibahmad/Developing-iOS-10-Apps-with-Swift

So follow along, if you want, with me and feel free to point out if my code can be improved or if the projects and assignments can be done better ūüôā Good luck!

From the Course Programming Methodology CS 106A Offered at Stanford University

Having spent more hours than I am willing to admit, finally solved Karel the Robot Problem 3 (from Assignment 1).

Please don’t look at the solution until you have solved it yourself. Otherwise you will be depriving yourself of a cool mental accomplishment.

Having said that, here’s my train of thoughts as I was trying to solve the problem:

1. Thought that ignoring the checkerboard might lead to a simpler solution. Think linearly about Karel dropping beepers alternatively on each move “over a single horizontal line” till the end is reached. Later turn the horizontal line into a checkerboard. Made some progress but the solution started getting increasingly complex.

2. Realized that the core of the problem is really the turns Karel needs to make while traversing through the checkerboard. Dropping beepers at alternate locations isn’t the real problem. So I ignored the beeper issue. This lead to a cleaner solution.

3. Karel’s movement itself shouldn’t be in any if/else control statement. It makes a mess of the code because of too many if/else checks. Karel should just move forward. Then figure out which direction it should face. You can see this behavior in lines 26-29 below. Lines 31-49 shows the logic behind setting Karel’s direction.

4. Finally the beeper code is in line 17, 19. Karel moves twice in each iteration of the while loop. Line 19 checks for even-count columns in Karel’s world. Line 21 puts a last beeper for odd-count column worlds.

5. Line 15 checks for a single-count column world.

I Googled for other solutions to compare after solving the problem. Feeling happy that the solution below is 50 lines of code. If you can think of a simpler solution then please let me know.

/*
 * File: CheckerboardKarel.java
 * ----------------------------
 * When you finish writing it, the CheckerboardKarel class should draw
 * a checkerboard using beepers, as described in Assignment 1.  You
 * should make sure that your program works for all of the sample
 * worlds supplied in the starter folder.
 */

import stanford.karel.*;

public class CheckerboardKarel extends SuperKarel {

	public void run() {
		if (frontIsBlocked()) turnLeft();		
		while (frontIsClear()) {
			if (noBeepersPresent()) putBeeper();
			moveKarelForward();
			if (frontIsClear()) {
				moveKarelForward();
				if (noBeepersPresent()) putBeeper();
			}
		}
	}
	
	private void moveKarelForward() {
		move();
		setKarelsDirection();
	}
	
	private void setKarelsDirection() {
		if (facingEast()) {
			if (frontIsBlocked()) {
				turnLeft();
			}
		} else if (facingWest()) {
			if (frontIsBlocked()) {
				turnRight();
			}
		} else if (facingNorth()) {
			if (rightIsBlocked()) {
				if (leftIsClear()) {
					turnLeft();	
				}				
			} else if (leftIsBlocked()) {
				turnRight();
			}
		}
	}
}

Testing Checkerboard Karel in different worlds:

Platform: iOS 8.x or later
Device: iPhone
Language: Swift
Motivation: when user unplugs their headphones, you wan’t to stop playing audio (iTunes like behavior) in your app

The following code snippet shows how to detect if headphones are plugged in (when the app starts or is woken up). The println() command below shows the state of the headphone connection.

let currentRoute = AVAudioSession.sharedInstance().currentRoute
if currentRoute.outputs != nil {
    for description in currentRoute.outputs {
        if description.portType == AVAudioSessionPortHeadphones {
            println("headphone plugged in")
        } else {
            println("headphone pulled out")
        }
    }
} else {
    println("requires connection to device")
}

In Line 4 above, we are checking if portType equals AVAudioSessionPortHeadphones. The full list of output port types are listed below:

  • AVAudioSessionPortLineOut
  • AVAudioSessionPortHeadphones
  • AVAudioSessionPortBluetoothA2DP
  • AVAudioSessionPortBuiltInReceiver
  • AVAudioSessionPortBuiltInSpeaker
  • AVAudioSessionPortHDMI
  • AVAudioSessionPortAirPlay
  • AVAudioSessionPortBluetoothLE

However while the app is running you can’t use the above code snippet to detect active changes in headphones connection. You will need to setup a notification observer for AVAudioSessionRouteChangeNotification in your app with the code below.

NSNotificationCenter.defaultCenter().addObserver(
    self,
    selector: "audioRouteChangeListener:",
    name: AVAudioSessionRouteChangeNotification,
    object: nil)

In line 3 above, the audioRouteChangeListener: is the method that will get notified once a change in headphones connection occurs. The println() statements below show the change in headphones connection to the device.

dynamic private func audioRouteChangeListener(notification:NSNotification) {
    let audioRouteChangeReason = notification.userInfo![AVAudioSessionRouteChangeReasonKey] as UInt

    switch audioRouteChangeReason {
    case AVAudioSessionRouteChangeReason.NewDeviceAvailable.rawValue:
        println("headphone plugged in")
    case AVAudioSessionRouteChangeReason.OldDeviceUnavailable.rawValue:
        println("headphone pulled out")
    default:
        break
    }
}

In line 4 above, we are checking switch-case values for AVAudioSessionRouteChangeReasonKey (identified by the variable audioRouteChangeReason). We are interested in two cases, NewDeviceAvailable (headphones plugged in) and OldDeviceUnavailable (headphone pulled out). The full list of cases are provided below:

  • Unknown
  • NewDeviceAvailable
  • OldDeviceUnavailable
  • CategoryChange
  • Override
  • WakeFromSleep
  • NoSuitableRouteForCategory
  • RouteConfigurationChange

A demo app utilizing the code above can be found here:
https://github.com/sanjibahmad/Is-Headphone-Plugged-In

Here’s a video showing how the app works:

 

Thanks to Udacity for the motivation to write this.

The problem: From page 37, Exercise 4, Chapter 2, Programming Erlang by Joe Armstrong

Run the file client and server code. Add a command called put_file. What messages do you need to add? Find out how to consult manual pages. Consult the manual pages for the file module.

Additional Specifications

  • We should be able to run “erl” from a directory of our choice other than where the .erl source files are located
  • We should be able to specify a directory of our choice in¬†afile_server:start¬†Dir argument
  • We should be able to put a file from a directory other than the current directory to the directory specified in Dir argument above

Solution

{Client, {put_file, File}} ->
  Source = filename:absname(File),
  Destination = filename:join(Dir, filename:basename(File)),
  Client ! {self(), file:copy(Source, Destination)}</pre>
  • We will use the file:copy function.¬†copy/2 has a source and a destination
  • source = the absolute filename
  • destination = dir name + base filename

Testing the solution

1> c("../erlang/afile_server").
{ok,afile_server}
2> c("../erlang/afile_client").
{ok,afile_client}
3> FS = afile_server:start("../erlang").
<0.46.0>
4> afile_client:ls(FS).
{ok,[".idea","afile_client.beam","afile_client.erl",
     "afile_server.beam","afile_server.erl","erlang.iml","foo",
     "geometry.beam","geometry.erl","hello.beam","hello.erl",
     "shop.beam","shop.erl","shop1.beam","shop1.erl"]}
5> afile_client:put_file(FS, "../foo").
{ok,5}
6> afile_client:put_file(FS, "Test.java").
{ok,382}
7> afile_client:ls(FS).
{ok,[".idea","afile_client.beam","afile_client.erl",
     "afile_server.beam","afile_server.erl","erlang.iml","foo",
     "geometry.beam","geometry.erl","hello.beam","hello.erl",
     "shop.beam","shop.erl","shop1.beam","shop1.erl",
     "Test.java"]}

The files foo and Test.java are now showing up in the response from aflile_client:ls(FS) in line 7 above.

Full source code

afile_server.erl

-module(afile_server).
-export([start/1, loop/1]).

start(Dir) -> spawn(afile_server, loop, [Dir]).

loop(Dir) ->
  receive
    {Client, list_dir} ->
      Client ! {self(), file:list_dir(Dir)};
    {Client, {get_file, File}} ->
      Full = filename:join(Dir, File),
      Client ! {self(), file:read_file(Full)};
    {Client, {put_file, File}} ->
      Source = filename:absname(File),
      Destination = filename:join(Dir, filename:basename(File)),
      Client ! {self(), file:copy(Source, Destination)}
  end,
  loop(Dir).

afile_client.erl

-module(afile_client).
-export([ls/1, get_file/2, put_file/2]).

ls(Server) ->
  Server ! {self(), list_dir},
  receive
    {Server, FileList} ->
      FileList
  end.

get_file(Server, File) ->
  Server ! {self(), {get_file, File}},
  receive
    {Server, Content} ->
      Content
  end.

put_file(Server, File) ->
  Server ! {self(), {put_file, File}},
  receive
    {Server, Status} ->
      Status
  end.

stanford-university-itunes-course-developing-ios-8-apps-with-swift
Stanford University has released a new course on iTunes a few days ago on developing iOS 8 apps with the Swift language:

https://itunes.apple.com/us/course/developing-ios-8-apps-swift/id961180099

So far lectures 1 to 5 has been released:

  1. Logistics, iOS 8 Overview
  2. More Xcode and Swift, MVC
  3. Applying MVC
  4. More Swift and Foundation Frameworks
  5. Objective-C Compatibility, Property List, Views

The high quality of the instructional material in this course follows in line with the previous iOS courses as taught by Paul Hegarty. Having followed the last iOS 7 course, suffice to say that these lectures provided by Stanford University for free are better than many paid online courses on iOS.

Paul Hegarty, who currently teaches at Stanford University used to work at NeXT Computers. Here’s a video of him talking about Steve Jobs.

Though erlang-solutions.com provides pre-built binaries for Mac OS X (among other OS), an alternate and easy way to install Erlang on Mac OS X is via brew. Simply type:

brew install erlang

Once installed, you can test it by typing “erl” in the Terminal to fire up the Erlang interactive shell:

Now that you have Erlang installed, what next? Highly recommend Joe Armstrong’s Programming Erlang (2nd Edition).¬†It’s always nice to read programming books authored by language creator themselves. Joe Armstrong’s Github page also has some goodies related to the book and other information.

joe-armstrong-programming-erlang-2nd-edition-book-cover

For a little inspiration, here’s “Erlang the Movie”:

Apple’s latest language Swift provides some nifty behaviors and characteristics. Three things we are loving about Swift so far are:

  1. Awesome OOP features: Structs, Enums, Classes can all have methods, optional binding, type safety
  2. Cool Functional language features: Closures (the shorthand syntax is a delight to use), nested functions and types
  3. Interesting Cocoa binding behaviors, as if the language was written to build beautiful Cocoa apps

We are getting solid feeling of how Swift was designed to create powerful and elegant programs. Experience will tell more down the line.

Here is a fun experiment with prefix operators. We wrote the following two custom global functions to mimic Lisp’s + prefix operator:

@prefix func + (ints: Int[]) -> Int {
    var sum = 0
    for int in ints {
        sum += int
    }
    return sum
}
@prefix func + (strings: String[]) -> String {
    var sum = ""
    for string in strings {
        sum += string
    }
    return sum
}

+[100, 200, 200]
// returns 500

+["comp", "uter"]
// returns "computer"

Assignment 3 (Set Card Matching Game with History) from “Developing iOS7 Apps for iPhone and iPad (Fall 2013) by Stanford University” took a bit longer than usual to complete. The major highlights of the assignment are:

  • Set card matching in addition to the playing card game implemented in the last assignment
  • Status history access via segueing through Navigation Bar button

With an object oriented approach, it was easy to keep the logic in the CardMatchingGame model the same for both Set Card and Playing Card. Here is a list of changes since the previous assignment:

  • Allowing 2 or 3 card for Playing card game
  • Not disabling match-mode slider during gameplay, as it doesn’t make sense to click Redeal card button twice for a new match mode
    • Previous behavior:
      • Click Re-deal button
      • Choose match-mode
      • Click Re-deal button
    • Current behavior:
      • Choose match-mode
      • Click Re-deal button
  • Status moved out of the model into the ViewController
  • Removed cheat mode for debugging

Download Solution to Assignment 3: Set Card Matching Game with History

One should rewrite code for improved performance, structure and design. But how many times? In the beginning my thought was to possibly rewrite code twice. Later I found rewriting my own code three or four times made it better. This lead to very stable code and useful particularly as a library, API or framework. Now my belief is that to properly understand a problem and to produce really great code, it needs to be written half a dozen times to a dozen times!

I am sure a lot of people are laughing at the claim above, I assure you that I am not code challenged.¬†Here’s what Charles H. Moore (Chuck Moore), inventor of the Forth Language has to say about rewrites:

Before you can write your own subroutine, you have to know how. This means, to be practical, that you have written it before; which makes it difficult to get started. But give it a try. After writing the same subroutine a dozen times on as many computers and languages, you’ll be pretty good at it. If you don’t plan to be programming that long, you won’t be interested in this book.

For more information please see: Programming a Problem-Oriented-Language by Charles H. Moore (http://www.colorforth.com/POL.htm)

The more one writes the same code again and again, a few amazing things happen. The code structure gets better. Refactoring improves. Code quality goes up. And most importantly a pattern emerges leading to improved and solid design. The code becomes extremely elegant and beautiful. Highly satisfying to use.

For most commercial projects, rewriting so many times if at all, is course not financially possible.¬†Too many times software gets written, becomes a success, but no one dare rewrite it because of the resource implication to undertake such a task.¬†But if one was to write code for personal projects then nothing is more satisfying than to improve one’s work.¬†It is important not to be afraid to begin from scratch.

Hope this theory does not lead to code obsession. A proof that code rewrite is important and necessary can be proven if you ask yourself a few questions, ask yourself:

  • Am I better programmer today than yesterday?
  • Could my code today be better than what I wrote before?

When I reflect back the answers are always true. So the code that I can write today will always be better. Hence the call for a rewrite!