Please note, this blog entry is from a previous course. You might want to check out the current one.
The lecture starts with additional information on how to control the appearance of a view in different size classes and how to inspect constraints in various size classes.
Scroll Views
Adding sub views to a scroll view works similar like adding views to any other view. The only important difference is to define the content size of the scroll view:
scrollView.contentSize = CGSize(width: 3000, height: 2000) logo.frame = CGRect(x: 2700, y: 50, width: 120, height: 180) scrollView.addSubview(logo) aerial.frame = CGRect(x: 150, y: 200, width: 2500, height: 1600) scrollView.addSubview(aerial)
Various methods allow to detect which part of the scroll view is currently visible, to scroll programmatically, or to control its properties:
let upperLeftOfVisible: CGPoint = scrollView.contentOffset let visibleRect: CGRect = aerial.convertRect(scrollView.bounds, fromView: scrollView) func scrollRectToVisible(CGRect, animated: Bool)
To allow zooming the limits of the zoom scale need to be set, and a delegate defining the view to zoom. It’s also possible to zoom programmatically.
scrollView.minimumZoomScale = 0.5 // half its normal size scrollView.maximumZoomScale = 2.0 // twice its normal size func viewForZoomingInScrollView(sender: UIScrollView) -> UIView var zoomScale: CGFloat func setZoomScale(CGFloat, animated: Bool) func zoomToRect(CGRect, animated: Bool)
Closures
Closures encapsulate pieces of code and capture variables of the surrounding context. To avoid referencing loops, weak references or unowning is necessary e.g.:
class Foo { var action: () -> Void = { } func show(value: Int) { println(“\(value)”) } func setupMyAction() { var x: Int = 0 action = { [unowned self] in x=x+1 self.show(x) } } func doMyAction10times() { for i in 1...10 { action() } } }
Multithreading
To avoid stalling user interaction, lengthy tasks should be performed on other queues than the main queue. Only to report back to the user interface it is necessary to return to the main queue.
dispatch_async(notTheMainQueue) { // do something that might block or takes a while dispatch_async(dispatch_get_main_queue()) { // call UI functions with the results of the above } }
Depending on the task other queues have different priorities:
QOS_CLASS_USER_INTERACTIVE // quick and high priority QOS_CLASS_USER_INITIATED // high priority, might take time QOS_CLASS_UTILITY // long running QOS_CLASS_BACKGROUND // user not concerned let qos = Int(<one of the above>.value) let queue = dispatch_get_global_queue(qos, 0)
Tasks might even be dispatched to other queues to be run in the future …
… and there might be some methods which run be default on other queues.
The lecture and its slides are available via iTunes named “9. Scroll View and Multithreading”. The code for the cassini demo is available on GitHub and at Stanford.
Hi there,
Have you actually tried class Foo mentioned above (Closures section)? I can’t get it to work in playground.
The code from the lecture was for Swift 1.1. I guess you are using Swift 2.x?
That is correct, I am using latest version of Swift. However I still think there is something wrong with the logic, I decided to test because it doesn’t make sense to me. Please can you try?
Hi Martin,
Have you had a chance to test it in Xcode?
Cheers
Sorry, no, I still hoping Stanford will publish the iOS-9 course early January. If not, I guess I should update the code for Swift 2.x
Happy Holidays!