cs193p – Lecture #5 – Objective-C Compatibility, Property List, Views

cs193p - Lecture #5 - Objective-C Compatibility, Property List, Views

Please note, this blog entry is from a previous course. You might want to check out the current one.

Objective-C Compatibility

Lecture #5 starts with theory on how Swift was built to be compatible with Objective-C and thus provides numerous seamless bridging methods:

  • NSString bridges to String
  • NSArray bridges to Array<AnyObject>
  • NSDictionary bridges to Dictionary<NSObject, AnyObject>
  • Int, Float, Double, Bool bridge to NSNumer – but not the other way around – use instead intValue, floatValue, doubleValue and boolValue

Additionally, it is possible to implicitly cast using as.

Property List

Property lists are collection of AnyObjects.

NSUserDefaults are a way to store property lists persistently between launchings.

Get the defaults:

NSUserDefaults.standardUserDefaults()

Store and retrieve property lists:

setObject(AnyObject, forKey: String)
objectForKey(String) -&gt; AnyObject?
arrayForKey(String) -&gt; Array&lt;AnyObject&gt;?
setDouble(Double, forKey: String)
doubleForKey(String) -&gt; Double

Though changes are saved automatically, it can be forced:

defaults.synchronize()

A short demo shows how to use property lists in the calculator app.

Views

UIViews are rectangular areas with a coordinate system for drawing and handling touch events. They are structured hierachically having a superview and subviews and a UIWindow at the very top.

Views most often are created using story board, but also in code:

addSubview(aView: UIView)
removeFromSuperview()

Thus it has two different initializers which might have to do the exact same setup:

func setup() { ... }
override init(frame: CGRect) {
    super.init(frame: frame)
    setup()
}
required init(coderaDecoder:NSCoder) {
    super.init(coder: aDecoder)
    setup()
}

Additionally awakeFromNib is called when a view is generated via a storyboard.

Views use special data structures to define values, points, sizes and rectangles:

typealias CGPoint = Double
struct CGPoint {
    var x: CGFloat
    var y: CGFloat
}
struct CGSize {
    var width: CGFloat
    var height: CGFloat
}
struct CGRect {
    var origin: CGPoint
    var size: CGSize
}

… with various convenience properties and functions:

var minX: CGFloat
var midY: CGFloat
intersects(CGRect) -&gt; Bool
intersect(CGRect)
contains(CGPoint) -&gt;Bool

The origin of the coordinate system is in the upper left corner. Its units are points with a varying number of pixels (contentScaleFactor) depending on the used device.

frame defines the view in the super view, the view itself is defined by its bounds.

Custom Views

drawRect(regionThatNeedsToBeDrawn: CGRect) is called to draw custom views. To trigger – and indirectly call drawRect:

setNeedsDisplay()
setNeedsDisplayInRect(regionThatNeedsToBeRedrawn: CGRect)

UIBezierPath are used to create shapes, e.g.:

let path = UIBezierPath()
path.moveToPoint(CGPoint(80, 50))
path.addLineToPoint(CGPoint(140, 150))
path.addLineToPoint(CGPoint(10, 150))
path.closePath()
UIColor.greenColor().setFill()
UIColor.redColor().setStroke()
path.linewidth = 3.0
path.fill()
path.stroke()

let roundRect = UIBezierPath(roundedRect: aCGRect, cornerRadius: aCGFloat)
let oval = UIBezierPath(ovalInRect: aCGRect)

… or clip a view using addClip(), or for hit detection:

func containsPoint(CGPoint) -&gt; Bool

Colors are handled using UIColor which even allows transparency using alpha values (don’t forget to set opaque to false).

Setting the hidden property of a view to true removes the view and its sub views completely from the screen.

To draw text use (mutable) attributed strings:

let text = NSAttributedString(&quot;hello&quot;)
text.drawAtPoint(aCGPoint)
let textSize: CGSize = text.size

… and define the attributes of parts of mutable attributed string using dictionaries and ranges:

func setAttributes(attributes: Dictionary, range: NSRange)
func addAttributes(attributes: Dictionary, range: NSRange)

NSForegroundColorAttributeName : UIColor
NSStrokeWidthAttributeName : CGFloat
NSFontAttributeName : UIFont

Concerning fonts it is best practice to use the ones defined in the user settings:

class func preferredFontForTextStyle(UIFontTextStyle) -&gt; UIFont

UIFontTextStyle.Headline
UIFontTextStyle.Body
UIFontTextStyle.Footnote

… for standard objects like buttons the system fonts:

class func systemFontOfSize(pointSize: CGFloat) -&gt; UIFont class func boldSystemFontOfSize(pointSize: CGFloat) -&gt; UIFont

Images can be drawn form the bundle or image assets, e.g.:

let image: UIImage? = UIImage(named: &quot;foo&quot;)
image.drawAtPoint(aCGPoint)
image.drawInRect(aCGRect)
image.drawAsPatternInRect(aCGRect)

… or from file sources, e.g.:

let image: UIImage? = UIImage(contentsOfFile: aString)
let image: UIImage? = UIImage(data: anNSData)

… or you can create them using core graphics (see UIGraphicsBeginImageContext).

UIViewContentMode defines what should happen when the bounds of a view changes. It could just been placed somewhere – .Left/.Right/.Top/.Bottom/.TopRight/.TopLeft/.BottomRight/.BottomLeft/.Center – scaled – .ScaleToFill/.ScaleAspectFill/.ScaleAspectFit – or redrawn – .Redraw.

The demo at the end of the lecture shows parts of the just learned theory.

The lecture and its slides are available via iTunes named “5. Objective-C Compatibility, Property List, Views”. The code for the calculator demo is available on GitHub. The code for the happiness demo is available on GitHub and Stanford.

FacebooktwitterredditpinterestlinkedintumblrmailFacebooktwitterredditpinterestlinkedintumblrmail

Leave a Reply

Your email address will not be published.