The Optional Data Type

Int, String, UIButton, AnyObject

Exclamation!
declare -var x:Int!
unwrap -x!

let w = Int("123")
w * 2

class BetterViewController: UIViewController {
	//var myButton: UIButton
}
import UIKit

class ViewController: UIViewController {
	var button:UIButton!

	override func viewDidLoad(){
		super.viewDidLoad()
		var title = button.titleForState(UIControlState.Normal)
	}
}
import UIKit

class Beverage {
	var category:String
	init (category: String){
		self.category = category
	}
}

class HotDrink: Beverage {
	var pairing:String

	init(category: String, pairing: String){
		self.pairing = pairing
		super.init(category: category)
	}
}

class ColdDrink: Beverage {
	var vessel:String

	init (category: String, vessel: String){
		self.vessel = vessel
		super.init(category: category)
	}
}

Optional

import UIKit
var x: Int
x = nil

var c: UIColor
c = UIColor.redColor()
c = nil

The method, .toInt(), is deprecated in the String struct. We now use the initializer method, Int(_: String), from the Int struct.

var y: Int
var s1: String
var s2: String

s1 = "123"
s2 = "ABC"

y = Int(s1)
y = Int(s2)

class ViewController: UIViewController {
	var button: UIButton
}

Constants and Variables

import UIKit
let encrouragement = "You can do it!"

var personalizedEncouragement = "You can do it, Lauren!"
personalizedEncouragement = personalizedEncouragement.stringByReplacingOccurrencesOfString("Lauren", withString:"Cameron")

let birthYear = 2008
var currentYear == 2017
var age = currentYear - birthYear

let buildingCapacity = 300
var attendance = 220
attendance += 2

var goat = UIImage(named:"Chinese-New-Year-3.jpg")!
let yearsOfTheGoat = [1967, 1979, 1991, 2003, 2015]
let yearsOfTheSheep = [1967, 1979, 1991, 2003, 2015]
yearsOfGoat.append(2027)

String

import UIKit
import Foundation

var funWithStrings = UIImage(named:"kittenWithOrangeString.jpg"):

let myFirstString = "no "
let mySecondString = "no problems"

let theTruth = myFirstString + ", " + mySecondString

var doggyDiet = "Lulu eats 25lbs of dog food per month"
var dogName = "Ferris"
var ferrisPic = UIImage(named:"SpringerdoodleFerris.jpg")
var lbsPerDay = 0.75
var daysPerMonth:Double = 30.0
doggyDiet = "\(dogName) eats \(lbsPerDay * daysPerMonth) of dog food per month"

var frankiePic = UIImage(named:"frankie.jpeg")!
lbsPerDay = 0.25
dogName = "Lil Frankie"
doggyDiet = "\(dogName) eats \(lbsPerDay * daysPerMonth) of dog food per month"

access an array of characters

var password = "Meet me in St. Louis"
for character in password.characters {
	if character == "e" {
		print("found an e!")
	} else {
		
	}
}

if else

if hungry && !vegetarian {
	println("Let's eat steak!")
} else if hungry && vegetarian {
	println("How about pumpkin curry?")
} else {
	println("nevermind")
}
var thereIsPie = true
if hungry || thereIsPie {
	println("Let's eat!")
} else {
	println("Let's wait.")
}

Ternary conditional

if question {
	answer1
} else {
	answer2
}

hugry ? println("Let's eat!") : println("Let's wait.")
hugry || thereIsPie ? println("Let's eat!") : println("Let's wait.")

Swift types

import UIKit
import Foundation

class LightSwitch {
	var on: Bool = true
}

var livingRoomSwitch = LightSwitch()
livingRoomSwitch.on
var dollarSign: Character = "$"
var myFirstSwiftString String = "no' money"

Optional and Tuples

let kitchenSwitch = LightSwitch()
let ticketPrice = 13.75
let swiftIsFast = true
let encouragement = “You can do it!”

let ticketPrice = 7.5
let allowance = 10.0
var iceCreamPrice = 3.0

var pic UIImage(named:"Choe.png")!

if allowance >= ticketPrice + iceCreamPrice {
	println("Let's go to the movies!")
} else {
	println("Let's watch a movie at home and eat ice cream")
}
var hungry = true
var vegetarian = false

if hungry {
	println("Let's eat!")
} else {
	println("Let's wait.")
}

Verify Loader Behavior

add log message to
initLoader(), onCreateLoader() callback, Loader startLoading()method
onLoadFinished() callback, Loader loadInBackground() method
onLoaderReset() callback, queryUtils fetchEarthquakeData() method

<RelativeLayout
	xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="match_parent"
	android:layout_height="match_parent">

	<ListView
		android:id="@+id/list"
		android:orientation="vertical"
		android:layout_width="match_parent"
		android:layout_height="match_parent"
		android:divider="@null"
		android:dividerHeight="0dp"/>

	<TextView
		android:id="@+id/empty_view"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:layout_centerInParent="true"
		android:textAppearance="?android:textAppearanceMedium"/>

</RelativeLayout>
private TextView mEmptyStateTextView;

@Override
protected void onCreate(Bundle savedInstanceState){
	mEmptyStateTextView = (TextView) findViewById(R.id.empty_view);
	earthquakeListView.setEmptyView(mEmptyStateTextView);
}

@Override
public void onLoadFinished(Loader<List<Earthquake>> loader, List<Earthquake> earthquakes){
	mEmptyStateTextView.setText(R.string.no_earthquakes);
}

Async Task In Quake Report App

private class EarthquakeAsyncTask extends
AsyncTask<String, Void, List<Earthquake>>{
	...
}

https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&eventtype=earthquake&orderby=time&minmag=6&limit=10

Loader
https://developer.android.com/guide/components/loaders.html?utm_source=udacity&utm_medium=course&utm_campaign=android_basics

Loader manager
https://developer.android.com/reference/android/app/LoaderManager.html?utm_source=udacity&utm_medium=course&utm_campaign=android_basics

Loader callback
https://developer.android.com/reference/android/app/LoaderManager.LoaderCallbacks.html?utm_source=udacity&utm_medium=course&utm_campaign=android_basics

package com.example.android.quakereport;

import android.content.AsyncTaskLoader;
import android.content.Context;

import java.util.List;

public class EarthquakeLoader extends AsyncTaskLoader<List<Earthquake>>{
	private static final String LOG_TAG = EarthquakeLoader.class.getName();

	private String mUrl;

	public EarthquakeLoader(Context context, String url){
		super(context);
		mUrl = url;
	}

	@Override
	protected void onStartLoading(){
		forceLoad();
	}

	@Override
	public List<Earthquake> loadInBackground(){
		if (mUrl == null){
			return null;
		}

		List<Earthquake> earthquakes = QueryUtils.fetchEarthquakeData(mUrl);
		return earthquakes;
	}
}

Handle Empty or Null Cases

protected Event doInBackground(String... urls){
	if (urls.length < 1 || urls[0] == null){
		return null;
	}

	Event result = Utils.fetchEarthquakeData(urls[0]);
	return result;
}
protected void onPostExecute(Event result){
	if (result == null){
		return;
	}
	updateUi(result);
}
private class EarthquakeAsyncTask extends AsyncTask {

	protected Event doInBackground(String... urls){
		if (urls.length < 1 || urls[0] == null){
			return null;
		}

		Event result = Utils.fetchEarthquakeData(urls[0]);
		return result;
	}

	protected void onPostExecute(Event result){
		if (result == null){
			return;
		}

		updateUi(result);
	}

}

Asynctask callback methods

onPreExecute(): before the task is executed, Main
doInBackground(Params…): After onPreExecute, Background
onProgressUpdate(Progress…): After publishProgress() is called, while doInBackground is executing, Main
OnPostExecute(Result): After doInBackground() finishes, Main

Review of generics
ArrayList
add(E e)->requires object of type E as input
get(int index)->returns object of type E
ArrayAdapter

private class DownloadFileTask extends AsyncTask{
	protected Long doInBackground(RUL... urls){
		int count = urls.length;
		long totalSize = 0;
		for(int i = 0; i < count; i++){
			totalSize += Downloader.downloadFile(url[i]);
			publishProgress((int)((i/(float) count)* 100));
			if(isCancelled()) break;
		}
		return totalSize;
	}
	protected void onProgressUpdate(Integer... progress){
		setProgressPercent(progress[0]);
	}
	protected void onPostExecute(long result){
		showDialog("Downloaded " + result + " bytes");
	}
}
private class DownloadWebpageTask extends AsyncTask<String, Void, String>{
	@Override
	protected String doInBackground(String... urls){
		try {
			return downloadUrl(urls[0]);
		} catch (IOException e){
			return "Unable to retrieve web page. URL may be invalid.";
		}
	}

	@Override
	protected void onPostExecute(String result){
		textView.setText(result);
	}
}