Matt Condon

Full Stack & iOS Dev · The MVP MVP

On Communities and Coding

Sunday, November 15, 2015

Working Around Other People, By Default

The concept of “working around other people by default” has led to some of my favorite experiences; it organically creates a creative, collaborative environment that you won’t find anywhere else, and I want to bring that feeling to a consistent location in New York.

re: New York

I think the biggest impact on the NYC technology ecosystem will be the creation of a central location where interesting, creative people can go to work around other interesting, creative people. I’m imagining a space similar to a cafe, in the sense that individuals and groups go there to work on projects, that promotes a much larger understanding of community and collaboration, just like the early days of casual hackathons. My best friendships were forged in similar circumstances and I’ve been searching for ways to extend that same experience to everyone.

Making Carthage-compatible Frameworks with Swift

Sunday, November 15, 2015

How to Make a Carthage-compatible Framework in Swift

Because I’ll inevitably forget this 3 months from now.

Create a Cocoa Touch Framework

Share the Default Scheme

This lets Carthage know what to build.

First, find the Edit Scheme option,

Then check the Shared option at the bottom of the panel.

Now Add Some Code

public class MySuperCoolClass {
    ... code ...

    public func doTheThing(withTheThing thing : UIThing) -> MYThing {
        ... moar code ...
    }

    func doAnotherThing() {
        ... code ...
        // this func not visibile from project linking this framework
    }
}

Note that the class (and any methods you want users of the lib to access) must be marked as public.

Develop Locally

Now, to develop locally, drag your Cocoa Touch Framework project into the project or workspace that you want to use it in. If you drag it into a project, Xcode will offer to create a workspace for you. Do that.

Next, add your framework to the “Embedded Binaries” and the “Linked Frameworks and Libraries” sections.

Your classes and whatnot will be available like normal:

import MyModule

class SomeProjectClass : MySuperCoolClass {
  ... code ...
}

Publish

To publish your Carthage-compatible framework, the source must be available on git, but it also needs tags associated with each release.

git tag 0.1.0
git push origin master --tags

Notice the --tags flag to push the tags to the remote; by default they are not included.

Use it!

Fantastic, your code is now on the Internet™.

Test your setup by making a new project and adding your framework to your Cartfile:

github "Shrugs/TabBatScrollableViewController" >= 0.1.0

If you’d like more information about actually using Carthage, the raywenderlch blog post is a good starting point.

UIScrollView, AutoLayout, and SnapKit

Saturday, November 14, 2015

How to get UIScrollView working with AutoLayout, Programmatically

Without Storyboards, visual AutoLayout constraints, or any other nonsense.

I’m using SnapKit, which makes AutoLayout creation not suck. It makes it a snap, even.

I’m just going to give you the code, and talk about it later.

The Code

The view hierarchy looks like so:

"rootViewController.view" UIView
    +--- "containerView" UIView
      +-- "scrollView" UIScrollView
          +-- "contentView" UIView
              +-- Subview 1 UIView
              +-- Subview 2 UIView
              +-- Subview 3 UIView

Step 1

Set the containerView contraints to whatever you want. In my project, it looks like:

view.addSubview(containerView)
containerView.snp_makeConstraints { make in
  make.top.left.right.equalTo(view)
  make.bottom.equalTo(tabBar.snp_top)
}

Step 2

Pin the scrollView’s edges to the containerView

containerView.addSubview(scrollView)
scrollView.snp_makeConstraints { make in
  make.edges.equalTo(containerView)
}

Step 3

Pin the contentView’s edges to the scrollView:

scrollView.addSubview(contentView)
contentView.snp_makeConstraints { make in
  make.edges.equalTo(scrollView)
}

Step 4

Finally, for all of your subviews, The subviews must have defined widths and heights, but also pinned to the contentView. You can get these widths and heights from a superview, but that superview can’t be the scrollView.

Here’s what this looks like when adding n full-sized subviews to the contentView for use in a paging view controller:

for (i, vc) in vcs.enumerate() {
  addChildViewController(vc)
  scrollView.contentView.addSubview(vc.view)
  vc.view.snp_makeConstraints { (make) -> Void in
    if i == 0 {
      // first one, pin left
      make.left.equalTo(scrollView.contentView)
    } else if i == vcs.count - 1 {
      // last one, pin to previous and contentView's right
      make.left.equalTo(vcs[i - 1].view.snp_right)
      make.right.equalTo(scrollView.contentView)
    } else {
      // nth one, pin to previous
      make.left.equalTo(vcs[i - 1].view.snp_right)
    }
    // pin to the top, bottom of contentView
    make.top.bottom.equalTo(scrollView.contentView)
    // define the width and top/bottom relative
    //    to a _parent_ view of the UIScrollView
    make.width.equalTo(containerView)
    make.height.equalTo(containerView)
  }
}

Notice that the left-most subview is pinned to the left of the contentView and the right-most is pinned to the right of the contentView.

Also note that each subview gets the same constraints that the scrollView has, but that’s just because I want the heights & widths of the subviews to be the exact same size as the scrollView itself.

Why This Works

To size the scroll view’s frame with Auto Layout, constraints must either be explicit regarding the width and height of the scroll view, or the edges of the scroll view must be tied to views outside of its subtree.

There’s lots of writing on the topic (each of those are separate links).

The gist is that by pinning your subviews to contentView and then deriving the width and height from views outside the scrollView, the AutoLayout engine has enough information to define the width and height of the scrollView’s .contentSize.

Want these posts in your inbox?

Woo hoo! You'll get (infrequent!) emails from me.

Whelp, some of the duct tape holding the internet together broke. Try again?
Only this content (and infrequently!), because that's just how I roll.