CS333

Mobile Development


Ilya Loshkarev
loshkarev.i@gmail.com

Core Location

Location Manager

  • Tracks changes in the user’s current location
  • Reports changes from the onboard compass
  • Monitors regions of interest
  • Reports the range to nearby beacons

Permissions


							// Authorize for location tracking in foreground
							locationManager.requestWhenInUseAuthorization()
							// Authorize for location tracking in background
							locationManager.requestAlwaysAuthorization()
						

Fails silently without permission

Requires related privacy keys in Info.plist

Authorization Status


							.authorizedAlways // authorization for background updates
							.authorizedWhenInUse // authorization for foreground updates
							.notDetermined // authorization is not granted yet
							.restricted // authorization is restricted by the device
							.denied // authorization is explicitly denied
						

							CLLocationManager.authorizationStatus()
						

Enable Location Updates


							locationManager.startUpdatingLocation()
							locationManager.startMonitoringSignificantLocationChanges()
							locationManager.startUpdatingHeading()
							locationManager.startMonitoring(for: CLRegion)
						

Location Manager Delegate


							locationManager(_:didChangeAuthorization:)
							locationManager(_:didUpdateLocations:)
							locationManager(_:didUpdateTo:from:)
							locationManager(_:didUpdateHeading:)
							locationManager(_:didEnterRegion:)
						

The protocol whose methods you use to receive events from an associated location manager object

Location


							var coordinate: CLLocationCoordinate2D
							var altitude: CLLocationDistance
							var timestamp: Date
							var speed: CLLocationSpeed
							var course: CLLocationDirection
						

Accuracy


							locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
							locationManager.distanceFilter = 1
							let accuracy = locationManager.location!.horisontalAccuracy
						

Less accurate location methods save battery power

Map Kit

Apple Maps

  • Released with iOS 6 (19.09.12)
  • Replaced Google Maps
  • Fully vectorized

MapView


							mapView.mapType = .hybrid
							mapView.showBuildings = true
						

Provides an embeddable map interface, similar to the one provided by the Maps application

Annotations


							protocol MKAnnotation : NSObjectProtocol {
								public var coordinate: CLLocationCoordinate2D { get }

								optional public var title: String? { get }
								optional public var subtitle: String? { get }
							}
						

To use this protocol, you adopt it in any custom objects that store or represent annotation data

Map View Delegate


							mapView(_:viewFor:)
						

Annotation Views


							func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
								let pin = mapView.dequeueReusableAnnotationView(
										withIdentifier: "pinAnnotationView") as! MKPinAnnotationView
								pin.annotation = annotation
								return pin
							}
						

Annotation views remain anchored to the map at the point specified by their associated annotation object

Geocoder


							geocodeAddressString(addressString: String,
										completionHandler:([CLPlacemark]?, Error?) -> Void)
							reverseGeocodeLocation(_ location: CLLocation,
										completionHandler: ([CLPlacemark]?, Error?) -> Void)
						

Provides services for converting between a coordinate and the user-friendly representation of that coordinate

Map Item

DirectionsRequest

Overlay

AVKit

Anatomy of Media

asset tracks

AVAsset is a container for media streams

AV Player


							let player = AVPlayer(url: videoURL)
							if player.currentItem.status == .readyToPlay {
								player.play()
							}
						

AVPlayer is a basic object to play media files

Anatomy of Player

AVPlayer Classes Connections

AVAsset is a container for media streams

AVPlayer ViewController


							let player = AVPlayer(url: videoURL)
							let playerViewController = AVPlayerViewController()
							playerViewController.player = player
							self.present(playerViewController, animated: true) {
								if let player = playerViewController.player!,
									player.currentItem.status == .readyToPlay {
										playerViewController.player!.play()
									}
							}
						

AVPlayerViewController is a default way of presenting audio and video

Player Callbacks

Most AVPlayer callbacks are KVO based


						// new item
						player.addObserver(self, forKeyPath: "currentItem",
							options: [.new, .initial] , context: nil)
						// errors
						player.addObserver(self, forKeyPath: "status",
							options: nil , context: nil)
						// update periodically
						player.addPeriodicTimeObserver(
							forInterval: CMTimeMake(1, 100), queue: DispatchQueue.main) {
								time in print(String(format: "%02.2f", CMTimeGetSeconds(time)))
							}
						

Queue Player


							let queuePlayer = AVQueuePlayer()
							let playerItem = AVPlayerItem(url:fileURL)
							queuePlayer.insert(playerItem, afterItem:nil)
							// queue as many items as you like
							queuePlayer.play()
						

Audio Recorder


							let recorder = AVAudioRecorder(url: resultURL, settings: [:])?
							if recorder.prepareToRecord() {
								recorder.record()
							}
						

AV Capture View


							let session = AVCaptureSession()
							let frontalCamera = AVCaptureDevice.defaultDevice(
								withDeviceType: .builtInWideAngleCamera,
								mediaType: AVMediaTypeVideo, position: .front)
							if let input = try? AVCaptureDevice(frontalCamera) {
								session.addInput(input)
							}
							view.setSession(session,
								showVideoPreview: true, showAudioPreview: true)
							view.delegate = self
						

AVCaptureView is a default way of presenting a video capture

Streaming Media


						let asset = AVURLAsset(streamURL)
						asset.resourceLoader.setDelegate(self, queue: DispatchQueue.main)
						// play video/audio
						let playerItem = AVPlayerItem(asset:asset)
						let player = AVPlayer(playerItem)
						// pause if playerItem is not ready yet
						NSNotificationCenter.default.addObserver(self,
							selector: #selector(pauseIfStalled),
							name: AVPlayerItemPlaybackStalledNotification, object: nil)
						player.play()
						

If you don't need to handle loading process events
default resourceLoader works just fine

Hardware Access


							let session = AVCaptureSession()
						

Allows to access any capture devices
and configure capture settings

AVCam Example - Apple Developer

User Notification

Notification

  • Alert – displays a text message with possible media attachment and actions
  • Badge – shows a number on the app's icon
  • Sound – bing! din-don! etc.

User Notification Center

Manages the notification-related activities for your app


							let center = UNUserNotificationCenter.current()
							center.getNotificationSettings
								{ setting in print(settings.authorizationStatus) }
							center.requestAuthorization(options: [.alert, .sound, .badge])
								{ granted, error in print (granted) }
						

User Notification Center Delegate


							func userNotificationCenter(_ center: UNUserNotificationCenter,
								didReceive response: UNNotificationResponse,
								withCompletionHandler completionHandler: @escaping () -> Void)
								{ /* user taped on notififcation */ }
							func userNotificationCenter(_ center: UNUserNotificationCenter,
								willPresent notification: UNNotification,
								withCompletionHandler completionHandler:
									@escaping (UNNotificationPresentationOptions) -> Void)
								{ /* notification should be presented in foreground */ }
						

Notification Content

Stores the content of a local or remote notification


							var content = UNMutableNotificationContent()
							content.title = "Notification"
							content.body = "Hello Word!"
							content.badge = 42
							content.sound = UNNotificationSound.default()
							content.attachments = [ try UNNotificationAttachment(
									identifier: "attachmentImage", url: imageUrl, options: nil) ]
						

Notification Triggers

Provides common behavior for subclasses that trigger the delivery of a notification


							UNTimeIntervalNotificationTrigger // triggers after timeout
							UNCalendarNotificationTrigger // triggers at specified moment
							UNLocationNotificationTrigger // triggers for location in region
						

Notification Request

Contains a notification’s content and the condition that triggers its delivery


						let request = UNNotificationRequest( identifier: "notificationID",
									content: content, trigger: trigger)
						center.add(request) { error in print(error?.localizedDescription) }
						

Apple Push Notification Service

Remote Notification Scheme

Remote Notifications Setup

  1. Enable remote notifications (XCode)
  2. Register with Apple Push Notification service (developer.apple.com)
  3. Receive an app-specific device token
  4. Send the device token to your notification provider server
  5. Handle incoming remote notifications

Registering for APN


							UIApplication.shared.registerForRemoteNotifications()
						

							application(_:didRegisterForRemoteNotificationsWithDeviceToken:)
							application(_:didFailToRegisterForRemoteNotificationsWithError:)
						

Device token should be sent by Provider to APN Services
for the notification to be delivered

Handling Remote Notifications


							func application(_ application: UIApplication,
							didReceiveRemoteNotification userInfo: [AnyHashable : Any],
							fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void)) {
								guard let data = userInfo as? [String : Any] else { return }
								// process data and call handler
								completionHandler(.newData)
							}
						

The system launches your app
(and puts it in the background state)
when a remote notification arrives

Notification Service Extension

Provides additional notififcation handling logic


							class NotificationService: UNNotificationServiceExtension {
								override func didReceiveNotificationRequest(
										request: UNNotificationRequest,
										withContentHandler contentHandler: (UNNotificationContent) -> Void)
									{ /* populate notification content */ }
								override func serviceExtensionTimeWillExpire()
									{ /* notififcation will be terminated */ }
							}
						

Additional binary target compiled by Xcode

Notification Content Extension

Allows to configure UIViewController
as an attachment for notififcation

Notification Content Extemsion

Additional binary target compiled by Xcode

Related Resources