Info

Programmer by day, artist by night

Posts from the Programming Category

20180102_011958

MVC Communication Methods

Views use:

  • Outlets – target action
  • Delegates – should, will, did
  • Data Source – data at, count

Models use:

  • Notification & KVO (Key Value Observing)

Additional Notes

The Card struct is UI independent. It’s tempting to allow the Card to also store the emoji symbol. However the emoji symbol is a view element. Therefore it should not be allowed in Card.

Classes get free initializers as long as all their instance variables are initialized.
Struct also get free initializer allowing all its instance variables to be initialized.

Lazy vars cannot have property observers (didSet).

State of the App after Implementing the Code from Lecture 2

Source code

The source code of the app Concentration is available here:
https://github.com/sanjibahmad/Concentration

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

Notes

  • Property observers are used to keep the UI in sync with instance variables. For example: var flipCount = 0 { didSet { flipCountLabel.text = “Flips: \(flipCount)” } }

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