Sunday, December 28, 2014

MFMailComposeViewController - Write an email with an image attachment

Updated with Xcode 7.1/Swift 2.1 (November 11, 2015):

Edit ViewController.swift as:

import UIKit
import MessageUI

class ViewController: UIViewController, MFMailComposeViewControllerDelegate {
    
    var myUIImage : UIImage!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let button = UIButton(frame: CGRectMake(100, 100, 100, 20))
        button.setTitle("Press", forState: UIControlState.Normal)
        button.setTitleColor(UIColor.blueColor(), forState: UIControlState.Normal)
        button.setTitleColor(UIColor.cyanColor(), forState: UIControlState.Highlighted)
        button.addTarget(self, action: "emailButtonPressed:", forControlEvents: UIControlEvents.TouchUpInside)
        view.addSubview(button)
    }
    
    func emailButtonPressed(sender: UIButton) {
        
        let myController = MFMailComposeViewController()
        myController.mailComposeDelegate = self
        myController.setSubject("Hello 123")
        myController.setMessageBody("Hello World!", isHTML: false)
        myController.setToRecipients(["mymail@mymail.com"])
        
        let imageData = UIImagePNGRepresentation(UIImage(named: "image.png")!)
        myController.addAttachmentData(imageData!, mimeType: "image/png", fileName: "image")
        
        self.presentViewController(myController, animated: true, completion: nil)
    }

    func mailComposeController(controller: MFMailComposeViewController, didFinishWithResult result: MFMailComposeResult, error: NSError?) {
        if result.rawValue == MFMailComposeResultSent.rawValue {
            self.dismissViewControllerAnimated(false, completion: {
                let alertController = UIAlertController(title: "", message: "Mail Sent!", preferredStyle: UIAlertControllerStyle.Alert)
                alertController.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil))
            
                self.presentViewController(alertController, animated:true, completion:nil)
            })
        }
        
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

}

Original post (December 28, 2014):

1. Create a UIButton and a UIImageView

2. Include an image file image.png (or a photo) in the project

3. Write the code as below:



import UIKit

import MessageUI

class ViewController: UIViewController, MFMailComposeViewControllerDelegate {

    @IBOutlet weak var myImage: UIImageView!
    
    var myUIImage : UIImage!
    
    @IBAction func emailButtonPressed(sender: UIButton) {
        
        var myController = MFMailComposeViewController()
        myController.mailComposeDelegate = self
        myController.setSubject("Hello 123")
        myController.setMessageBody("Hello World!", isHTML: false)
        myController.setToRecipients(["mymail@mymail.com"])
        
        var imageData = UIImagePNGRepresentation(myUIImage)
        myController.addAttachmentData(imageData, mimeType: "image/png", fileName: "image")
        
        self.presentViewController(myController, animated: true, completion: nil)
    }
    func mailComposeController(controller: MFMailComposeViewController!, didFinishWithResult result: MFMailComposeResult, error: NSError!) {
        if result.value == MFMailComposeResultSent.value {
            let alertView = UIAlertView()
            alertView.message = "Mail Sent!"
            alertView.addButtonWithTitle("OK")
            
            alertView.show()
        }
        self.dismissViewControllerAnimated(false, completion: nil)
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        
        myUIImage = UIImage(named: "image.png")
        
        self.myImage.image = myUIImage


Friday, December 19, 2014

supportedInterfaceOrientations - Support Landscape orientations only.

Update March 18, 2016: 

It seems that the Swift 1 code below is no longer required for Xcode 7.2.1 (Swift 2.1.1).
Just define the portrait/landscape settings in the General ->Deployment Info -> Device Orientation section of the project settings.

========== Swift 1 code below ============

This disables the portrait orientation.

//Auto rotate is still enabled.
    override func shouldAutorotate() -> Bool {
        return true
    }

//Only the left and right landscape orientations are supported.
    override func supportedInterfaceOrientations() -> Int {
        return Int(UIInterfaceOrientationMask.LandscapeLeft.rawValue) | Int(UIInterfaceOrientationMask.LandscapeRight.rawValue)

    }

Wednesday, December 17, 2014

UIButton with an image. Scale: aspect fit.

Updated with Xcode 8.0/Swift 3 (September 19, 2016): 


override func viewDidLoad() {
    super.viewDidLoad()
        
    let image = UIImage(named: "image.png")
    let button = UIButton(frame: CGRect(x: 100, y: 100, width: 200, height: 200))
    button.imageView?.contentMode = UIViewContentMode.scaleAspectFit
    button.setImage(image, for: UIControlState.normal)
    button.addTarget(self, action: #selector(buttonPressed), for: UIControlEvents.touchUpInside)
    view.addSubview(button)
}
    
func buttonPressed() {
    print("button pressed!!")
}

Updated with Xcode 7.1.1/Swift 2.1 (November 12, 2015): 


    override func viewDidLoad() {
        super.viewDidLoad()
        
        let image = UIImage(named: "image.png")
        let button = UIButton(frame: CGRectMake(100, 100, 200, 200))
        button.imageView?.contentMode = UIViewContentMode.ScaleAspectFit
        button.setImage(image, forState: UIControlState.Normal)
        button.addTarget(self, action: "buttonPressed:", forControlEvents: UIControlEvents.TouchUpInside)
        self.view.addSubview(button)
    }
    
    func buttonPressed(sender: UIButton) {
        print("button pressed!!")
    }

Original post (December 17, 2014): 

   override func viewDidLoad() {
        super.viewDidLoad()
        
        let image = UIImage(named: "image.png") as UIImage!
        let button = UIButton.buttonWithType(UIButtonType.System) as UIButton
        button.frame = CGRectMake(100, 100, 200, 200)
        button.imageView?.contentMode = UIViewContentMode.ScaleAspectFit
        button.setImage(image, forState: .Normal)
        button.addTarget(self, action: "buttonPressed:", forControlEvents: UIControlEvents.TouchUpInside)
        self.view.addSubview(button)
    }

    func buttonPressed(sender: UIButton) {
        println("button pressed!!")
}

Friday, December 5, 2014

presentPopoverFromRect - Show a photo from the photo album to a popover with an iPad

1. Drag a UIImageView and Button to the storyboard.
Adjust the view mode of UIImageView to Aspect Fit

2. Control-drag to create:

    @IBOutlet weak var picture: UIImageView!
    
    @IBAction func photoAlbum(sender: UIButton) {

    }

3. Add delegates

class ViewController: UIViewControllerUINavigationControllerDelegate, UIImagePickerControllerDelegate, UIPopoverControllerDelegate {

4. Complete Code:


class ViewController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate, UIPopoverControllerDelegate {

    @IBOutlet weak var picture: UIImageView!
    
    var myPopOverController : UIPopoverController!
    
    @IBAction func photoAlbum(sender: UIButton) {
        var myImagePickerController = UIImagePickerController()
        myImagePickerController.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
        myImagePickerController.delegate = self
        
        myPopOverController = UIPopoverController(contentViewController: myImagePickerController)
        
        myPopOverController.presentPopoverFromRect(sender.frame, inView: view, permittedArrowDirections: UIPopoverArrowDirection.Any, animated: true)
    }

    func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) {
        let myImage = info[UIImagePickerControllerOriginalImage] as UIImage
        self.picture.image = myImage
        myPopOverController.dismissPopoverAnimated(true)

    }

Thursday, November 27, 2014

iOS Architecture - Cocoa Stack

APP

Cocoa Touch - UIKit

Media

Core Services - Foundation

Core OS


=====================

Link:
http://www.cnblogs.com/kkun/archive/2012/04/25/2470166.html


=====================

UIKit:
Prefix: UI
Examples: UIApplication, UIWindow, UIScreen, UIView, UIViewController...etc.

Foundation:
Prefix: NS
Examples: NSData, NSDate, NSInteger, NSArray, NSLog, ...etc.

Monday, November 24, 2014

CIFilter - Invert the photo color by built-in filter

//Updated December 22, 2014:
//Keep the photo orientation.

//Updated December 30, 2014
//Remove the error: BSXPCMessage received error for message: Connection interrupted
//Modify this: CIContext(options:[kCIContextUseSoftwareRenderer: true])


import UIKit

class ViewController: UIViewController,UIImagePickerControllerDelegate, UINavigationControllerDelegate {

    @IBOutlet weak var picture: UIImageView!
    
    @IBAction func photoAlbum(sender: AnyObject) {
        if(UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.SavedPhotosAlbum)) {
            var pickerController = UIImagePickerController()
            pickerController.delegate = self
            self.presentViewController(pickerController, animated: true, completion: nil)
        }
    }
    func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) {
        
        let uiPictureSelected = info[UIImagePickerControllerOriginalImage] as UIImage
        let myOrientation : UIImageOrientation = uiPictureSelected.imageOrientation //Keep the photo orientation.
        let ciPictureSelected = CIImage(image:uiPictureSelected)

        var myFilter = CIFilter(name: "CIColorInvert")
        myFilter.setValue(ciPictureSelected, forKey: kCIInputImageKey)
        
        let ciOutputImage = myFilter.outputImage
        
        let ciContext = CIContext(options:[kCIContextUseSoftwareRenderer: true])
        let cgOutputImage = ciContext.createCGImage(ciOutputImage, fromRect: ciOutputImage.extent())
        
        let uiOutputImage = UIImage(CGImage: cgOutputImage, scale: 1, orientation: myOrientation)
        self.picture.image = uiOutputImage
        
        picker.dismissViewControllerAnimated(true, completion: nil)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

    }

Tuesday, November 18, 2014

UIImagePickerControllerSourceType.Camera - Take a photo

1. Drag a UIImageView and Button to the storyboard.
Adjust the view mode of UIImageView to Aspect Fit

2. Control-drag to create:

    @IBOutlet weak var picture: UIImageView!
    
    @IBAction func takePhoto(sender: AnyObject) {

    }

3. Add delegates

class ViewController: UIViewControllerUIImagePickerControllerDelegateUINavigationControllerDelegate {



4. Complete Code:

class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {

    @IBOutlet weak var picture: UIImageView!
    
    @IBAction func takePhoto(sender: AnyObject) {
        if(UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.Camera)) {
            var pickerController = UIImagePickerController()
            pickerController.delegate = self
            pickerController.sourceType = UIImagePickerControllerSourceType.Camera
            self.presentViewController(pickerController, animated: true, completion: nil)
        }
    }
    func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) {
        let pictureTaken = info[UIImagePickerControllerOriginalImage] as UIImage
        self.picture.image = pictureTaken
        UIImageWriteToSavedPhotosAlbum(pictureTaken, nil, nil, nil)
        picker.dismissViewControllerAnimated(true, completion: nil)
    }

Monday, November 17, 2014

presentViewController(pickerController - Show a photo from the photo album

Updated with Xcode 7.1/Swift 2.1 (November 11, 2015):

Edit ViewController.swift as below:


import UIKit

class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {

    var imageView : UIImageView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
       
        let button = UIButton(frame: CGRectMake(70, 100, 200, 20))
        button.setTitle("Pick a Photo", forState: UIControlState.Normal)
        button.setTitleColor(UIColor.blueColor(), forState: UIControlState.Normal)
        button.setTitleColor(UIColor.cyanColor(), forState: UIControlState.Highlighted)
        button.addTarget(self, action: "photoAlbum:", forControlEvents: UIControlEvents.TouchUpInside)
        view.addSubview(button)
        
        imageView = UIImageView(frame: CGRectMake(50, 150, 200, 200))
        imageView.contentMode = UIViewContentMode.ScaleAspectFit
        view.addSubview(imageView)
    }
    
    func photoAlbum(sender: UIButton) {
        if(UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.SavedPhotosAlbum)) {
            let pickerController = UIImagePickerController()
            pickerController.delegate = self
            self.presentViewController(pickerController, animated: true, completion: nil)
        }
    }
    
    func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
        let pictureSelected = info[UIImagePickerControllerOriginalImage] as! UIImage
        imageView.image = pictureSelected
        picker.dismissViewControllerAnimated(true, completion: nil)
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

}

Original Post (November 17, 2014):

1. Drag a UIImageView and Button to the storyboard.
Adjust the view mode of UIImageView to Aspect Fit

2. Control-drag to create:

    @IBOutlet weak var picture: UIImageView!
    
    @IBAction func photoAlbum(sender: AnyObject) {


    }

3. Add delegates

class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {

4. Complete Code:

class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {

    @IBOutlet weak var picture: UIImageView!
    
    @IBAction func photoAlbum(sender: AnyObject) {
        if(UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.SavedPhotosAlbum)) {
            var pickerController = UIImagePickerController()
            pickerController.delegate = self
            self.presentViewController(pickerController, animated: true, completion: nil)
        }
    }
    func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]) {
        let pictureSelected = info[UIImagePickerControllerOriginalImage] as UIImage
        self.picture.image = pictureSelected
        picker.dismissViewControllerAnimated(true, completion: nil)
    }

Saturday, October 25, 2014

NSThread.detachNewThreadSelector

    override func viewDidLoad() {
        super.viewDidLoad()
        
        NSThread.detachNewThreadSelector(Selector("mythread"), toTarget: self, withObject: nil)
        
        println("End viewDidLoad()")
    }

    func mythread() {
        NSThread.sleepForTimeInterval(1.0)
        for var i = 1 ; i <= 5 ; i++ {
            println("\(i)")
        }
    }

==========================
Output:

End viewDidLoad()
1
2
3
4
5

Monday, October 6, 2014

MKDirections - Draw a route from location A to location B

Updated with Xcode 8.0 (Swift 3) on September 19, 2016.
Updated with Xcode 7.3.1 (Swift 2.2) on June 15, 2016.
Updated as a simple tutorial on May 25, 2015.

1. Disable 'Use Auto Layout' in the storyboard file inspector.

2. Drag a MapKit View to the storyboard.



3. Control-drag the MapKit View from the storyboard to ViewController.swift. Name the MapKit 'myMap'.



The result is:

@IBOutlet weak var myMap: MKMapView!

4. Complete the code as below:

Update (September 19, 2016): Xcode 8.0 (Swift 3)


import UIKit
import MapKit

class ViewController: UIViewController, MKMapViewDelegate {

    @IBOutlet weak var myMap: MKMapView!
    
    var myRoute : MKRoute!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let point1 = MKPointAnnotation()
        let point2 = MKPointAnnotation()
        
        point1.coordinate = CLLocationCoordinate2DMake(25.0305, 121.5360)
        point1.title = "Taipei"
        point1.subtitle = "Taiwan"
        myMap.addAnnotation(point1)
        
        point2.coordinate = CLLocationCoordinate2DMake(24.9511, 121.2358)
        point2.title = "Chungli"
        point2.subtitle = "Taiwan"
        myMap.addAnnotation(point2)
        myMap.centerCoordinate = point2.coordinate
        myMap.delegate = self
        
        //Span of the map
        myMap.setRegion(MKCoordinateRegionMake(point2.coordinate, MKCoordinateSpanMake(0.7,0.7)), animated: true)
        
        let directionsRequest = MKDirectionsRequest()
        let markTaipei = MKPlacemark(coordinate: CLLocationCoordinate2DMake(point1.coordinate.latitude, point1.coordinate.longitude), addressDictionary: nil)
        let markChungli = MKPlacemark(coordinate: CLLocationCoordinate2DMake(point2.coordinate.latitude, point2.coordinate.longitude), addressDictionary: nil)
        
        directionsRequest.source = MKMapItem(placemark: markChungli)
        directionsRequest.destination = MKMapItem(placemark: markTaipei)
        
        directionsRequest.transportType = MKDirectionsTransportType.automobile
        let directions = MKDirections(request: directionsRequest)
        
        directions.calculate(completionHandler: {
            response, error in
            
            if error == nil {
                self.myRoute = response!.routes[0] as MKRoute
                self.myMap.add(self.myRoute.polyline)
            }
            
        })
    }
    
    func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
        
        let myLineRenderer = MKPolylineRenderer(polyline: myRoute.polyline)
        myLineRenderer.strokeColor = UIColor.red
        myLineRenderer.lineWidth = 3
        return myLineRenderer
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

}

======

Update (June 15, 2016): Xcode 7.3.1 (Swift 2.2)


import UIKit
import MapKit

class ViewController: UIViewController, MKMapViewDelegate {
    
    @IBOutlet weak var myMap: MKMapView!
    
    var myRoute : MKRoute!
    
    override func viewDidLoad() {
        super.viewDidLoad()

        let point1 = MKPointAnnotation()
        let point2 = MKPointAnnotation()
        
        point1.coordinate = CLLocationCoordinate2DMake(25.0305, 121.5360)
        point1.title = "Taipei"
        point1.subtitle = "Taiwan"
        myMap.addAnnotation(point1)
        
        point2.coordinate = CLLocationCoordinate2DMake(24.9511, 121.2358)
        point2.title = "Chungli"
        point2.subtitle = "Taiwan"
        myMap.addAnnotation(point2)
        myMap.centerCoordinate = point2.coordinate
        myMap.delegate = self
        
        //Span of the map
        myMap.setRegion(MKCoordinateRegionMake(point2.coordinate, MKCoordinateSpanMake(0.7,0.7)), animated: true)
        
        let directionsRequest = MKDirectionsRequest()
        let markTaipei = MKPlacemark(coordinate: CLLocationCoordinate2DMake(point1.coordinate.latitude, point1.coordinate.longitude), addressDictionary: nil)
        let markChungli = MKPlacemark(coordinate: CLLocationCoordinate2DMake(point2.coordinate.latitude, point2.coordinate.longitude), addressDictionary: nil)
        
        directionsRequest.source = MKMapItem(placemark: markChungli)
        directionsRequest.destination = MKMapItem(placemark: markTaipei)

        directionsRequest.transportType = MKDirectionsTransportType.Automobile
        let directions = MKDirections(request: directionsRequest)

        directions.calculateDirectionsWithCompletionHandler({
            response, error in
            
            if error == nil {
                self.myRoute = response!.routes[0] as MKRoute
                self.myMap.addOverlay(self.myRoute.polyline)
            }
        
        })
    }
    
    func mapView(mapView: MKMapView, rendererForOverlay overlay: MKOverlay) -> MKOverlayRenderer {
        
        let myLineRenderer = MKPolylineRenderer(polyline: myRoute.polyline)
        myLineRenderer.strokeColor = UIColor.redColor()
        myLineRenderer.lineWidth = 3
        return myLineRenderer
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

}

======

Previous Post (May 25, 2015):
import UIKit
import MapKit
import CoreLocation

class ViewController: UIViewController, MKMapViewDelegate {

    @IBOutlet weak var myMap: MKMapView!
    
    var myRoute : MKRoute?
    
    override func viewDidLoad() {
        super.viewDidLoad()

        var point1 = MKPointAnnotation()
        var point2 = MKPointAnnotation()
        
        point1.coordinate = CLLocationCoordinate2DMake(25.0305, 121.5360)
        point1.title = "Taipei"
        point1.subtitle = "Taiwan"
        myMap.addAnnotation(point1)
        
        point2.coordinate = CLLocationCoordinate2DMake(24.9511, 121.2358)
        point2.title = "Chungli"
        point2.subtitle = "Taiwan"
        myMap.addAnnotation(point2)
        myMap.centerCoordinate = point2.coordinate
        myMap.delegate = self
        
        //Span of the map
        myMap.setRegion(MKCoordinateRegionMake(point2.coordinate, MKCoordinateSpanMake(0.7,0.7)), animated: true)
        
        var directionsRequest = MKDirectionsRequest()
        let markTaipei = MKPlacemark(coordinate: CLLocationCoordinate2DMake(point1.coordinate.latitude, point1.coordinate.longitude), addressDictionary: nil)
        let markChungli = MKPlacemark(coordinate: CLLocationCoordinate2DMake(point2.coordinate.latitude, point2.coordinate.longitude), addressDictionary: nil)
        
        directionsRequest.setSource(MKMapItem(placemark: markChungli))
        directionsRequest.setDestination(MKMapItem(placemark: markTaipei))
        directionsRequest.transportType = MKDirectionsTransportType.Automobile
        var directions = MKDirections(request: directionsRequest)
        directions.calculateDirectionsWithCompletionHandler { (response:MKDirectionsResponse!, error: NSError!) -> Void in
            if error == nil {
                self.myRoute = response.routes[0] as? MKRoute
                self.myMap.addOverlay(self.myRoute?.polyline)
            }
        }
    }
    
    func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -> MKOverlayRenderer! {
        
        var myLineRenderer = MKPolylineRenderer(polyline: myRoute?.polyline!)
        myLineRenderer.strokeColor = UIColor.redColor()
        myLineRenderer.lineWidth = 3
        return myLineRenderer
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

}

5. The result: