zoukankan      html  css  js  c++  java
  • Swift, Playgrounds, and XCPlayground

    http://www.codeschool.com/blog/2014/12/12/swift-playgrounds-xcplayground/

    Swift, Playgrounds, and XCPlayground

    Swift Playgrounds are a great feature of Xcode 6 that allow you to create a single file to test out code before adding it to your app’s main codebase. Prior to Playgrounds, if you wanted to test out code, you had a couple options — you could create a new git branch off of master of the app you’re working on, or, if you’re like me, you could open a brand new project with the Single View Application template and try to build enough of a base to start testing the feature you want.

    Playgrounds reduce the amount of steps between having an idea and prototyping it, but there’s certain things they can’t do right out of the box, like network requests or showing rendered views when you try to draw UIViews.

    Fortunately, these features are just a module import away.

    XCPlayground

    XCPlayground is a new module that has a few methods to help you get the most out of Playgrounds. Adding it to your playground is as simple as adding an import statement right near the default UIKit import, like this:

    import UIKit // there by default
    import XCPlayground // add this in
    

    XCP EXECUTION SHOULD CONTINUE INDEFINITELY

    Let’s say you want to prototype some code that requests an API endpoint and returns some JSON data. The setup for that scenario might look like this:

    // create a session object
    let session = NSURLSession(
        configuration: NSURLSessionConfiguration.defaultSessionConfiguration())
    
    // make a network request for a URL, in this case our endpoint
    session.dataTaskWithURL(NSURL(string: "http://localhost:8080/notes")!, 
        completionHandler: { (taskData, taskResponse, taskError) -> Void in
    
        // create an NSArray with the JSON response data
        var jsonReadError:NSError?
    
        let jsonArray = NSJSONSerialization.JSONObjectWithData(
            taskData, options: nil, error: &jsonReadError) as [AnyObject]
    
    }).resume()
    

    The problem you’ll run into when you run this code, though, is that your playground execution happens so fast the completion handler won’t have enough time to complete before execution stops. That means that none of the code inside of the handler will run, and you won’t have that JSON response data.

    The solution? Call XCPSetExecutionShouldContinueIndefinitely() at the top of your file just below the imports, and set the continueIndefinitely boolean argument to true. This tells your playground it shouldn’t stop right away, and you’ll now see the jsonArrayobject has data that’s been returned from the API.

    image00

    XCP SHARED DATA DIRECTORY PATH

    It’s common to prototype apps with local data first. Often the design of the API that eventually returns real data is being built alongside the app, and not having to immediately account for all of the edge cases that come with asynchronous callbacks can help developers focus on view layout and other core features.

    In a normal Xcode project you can easily import files and folders directly, but playgrounds don’t offer the same support. Instead, each time a playground is opened, it’s assigned a new random container buried deep in the /var folder. That container holds a Shared Playground Data folder that is symbolically linked to/Users/HOME_FOLDER/Documents/Shared Playground Data, so anything you put in that folder will be available in your playground.

    The XCPSharedDataDirectoryPath string constant always holds a reference to that shared folder, so any files you want to access in your project can be put in that Shared Playground Data folder and accessed in the playground.

    A SMARTER SHARED DIRECTORY PATH

    Putting all of your files in that shared /Documents subfolder is fine until you’ve got multiple playgrounds, so why not organize all of your files per-playground just like you usually do per-project? There’s no direct support out of the box for this, but you can create a helper method that makes things easier. Here’s the one I use:

    func pathToFileInSharedSubfolder(file: String) -> String {
        return XCPSharedDataDirectoryPath +
               "/" +
               NSProcessInfo.processInfo().processName +
               "/" +
               file
    }
    

    NSProcessInfo().processInfo() creates an object that contains tons of information about what Xcode is currently running, which right now is your playground! The processNameproperty of that process is the same as the file name of your playground, so if I haveNetworkPrototype.Playground, then processName will be NetworkPrototype. That gets appended along with a / to the end of that Shared Playground Data folder path. Finally, I append the file name string I passed into the function as an argument called file.

    image02

    Now, grabbing the contents of a file inside a playground is a little easier. For example, like grabbing a JSON data object from a local JSON file:

    let jsonData = NSFileManager.defaultManager().contentsAtPath(
        pathToFileInSharedSubfolder("data.json"))!
    

    Or, loading a locally stored image into a UIImageView:

    let imageView = UIImageView()
    imageView.image = UIImage(contentsOfFile: pathToFileInSharedSubfolder("code-school.png"))
    

    XCP CAPTURE VALUE

    Prototyping data operations is nice, but you’re also probably going to want to build up some actual views at some point. For example, take the following playground code:

    let view = UIView()
    view.frame = CGRectMake(0,0,320,568)
    view.backgroundColor = UIColor.lightGrayColor()
    
    let imageView = UIImageView()
    imageView.frame = CGRectMake(20, 20, 280, 51)
    imageView.image = UIImage(contentsOfFile: pathToFileInSharedSubfolder("code-school.png"))
    view.addSubview(imageView)
    
    let label = UILabel()
    label.frame = CGRectMake(0, 100, 320, 30)
    label.textAlignment = .Center
    label.text = "Welcome!"
    view.addSubview(label)
    

    This creates a view and sets the background color to gray, adds an image view that’s sourced from a local file (see the above section), and adds a label with the text “Welcome!”. One way to see that rendered view is to click on the tiny eyeball icon in the debug panel in the playground, but even then you only get to see the view preview once before you have to collapse the panel and get back to coding.

    By calling XCPCaptureValue() and passing it an identifier string and a view object, you’ll be able to see that view in the timeline, like this:

    ...
    label.text = "Welcome!"
    view.addSubview(label)
    
    XCPCaptureValue('mainView', view)
    

    view there is that gray UIView object we created above. If you pair this withXCPExecutionShouldContinueIndefinitely like I described above, you’ll have a continuously updating UIView preview right inside of your playground!

    image01

    Here’s a zip file that contains the Code School logo and a playground that has all of the code in this post: CodeSchoolProtoPlayground.zip. Let us know what you think about Swift Playgrounds, and if you’d like to see more blog posts on iOS, in the comments section below!

    SHARE THIS POST

    ABOUT THE AUTHOR

    Content Producer and Developer at Code School. Enjoys building iOS and web apps, and then figuring out the best way to teach people how to build their own.

  • 相关阅读:
    hdu2083 简易版之最短距离
    android:layout_gravity和android:gravity属性的差别
    java设计模式演示样例
    [CSS] Transition
    [React] React Fundamentals: Precompile JSX
    [React] React Fundamentals: JSX Deep Dive
    [React] React Fundamentals: Build a JSX Live Compiler
    [Angular 2] 8. Better ES5 Code
    [rxjs] Throttled Buffering in RxJS (debounce)
    [rxjs] Demystifying Cold and Hot Observables in RxJS
  • 原文地址:https://www.cnblogs.com/xuejinhui/p/4616658.html
Copyright © 2011-2022 走看看