Flatiron School Week 6 – iOS Halftime Report

The Economics of Flatiron School

While I was still employed in Virginia, I thought long and hard about the value of going to a developer bootcamp.

Before deciding to come to the Flatiron School, I had gotten back into programming after a hiatus in college. I had taken a couple high school CS classes and I felt confident that I could learn to code on my own. I knew it would take longer than if I came to a bootcamp. Maybe 6 months instead of 3 months. $12K was a lot of money to me and having grown up without a lot of money, this would be the most money that I had spent on anything, so understandable this was a big decision. (I just noticed that it’s now $15K. My logic still applies.)

Whenever you quit a good job, there’s a lot of uncertainty. What if I don’t find another job? What if I don’t like New York?

Pre-Flatiron Pro/Con List

Pros:

  • A community of people to learn with
  • Frequent feedback from instructors
  • A structured environment that kept me moving forward
  • Placement services afterwards
  • Alumni connections
  • A commitment device
  • Getting a job 3 months earlier
  • Connect with the NYC tech community

Cons:

  • Spend 4-6 months of living expenses
  • Move to a more expensive city.

After a week, I realized that the math was actually really easy. Even if I got a job that was 60K, which is on the low end, I would be gaining $15K for having a job for three months earlier. So that by itself would equal the tuition, and I would be getting the other benefits thrown in as well.

That’s a no brainer, I gave my notice the next day.

A review of the first half

The Curriculum

We do a lot of labs here. One thing that I didn’t realize is that there is a lot of setup involved. In cooking, there is the concept of mise en place, or putting in place, that needs to be done before you can fire up the stove. It’s mostly cutting vegetables and measuring out slices and it’s really boring. Fortunately, the labs often have a lot of the setup done for us, so that we can get coding right away. That’s work that I would have had to do myself if I was learning on my own.

For the first six weeks, I’ve worked 55, 62, 60, 51, 62 and 52 hours, been able to do the labs and work on stuff on the side. I would say that 55-60 hours is probably a minimum number to everything done and work on side projects. I don’t think I would have worked this much on my own. The 12K was a commitment device to work hard. Being surrounded by talented and motivated people doesn’t hurt.

A lot of the iOS curriculum is being built out and sometimes I feel like a beta tester. That’s how something work though. No one is going to hand you perfect code. The swift change will also mean more changes for the curriculum. iOS is new and fast moving.

The Instructors

Most of the time, you can get a lot of instructions from tutorials, stack overflow and documentation. That’s when you don’t need an instructor. But there are also times when you hit on a problem that’s really annoying and you have no idea what to do. Apple Mach-o linker error is my least favorite. The error codes never make any sense. I google around for a while and don’t have the answer. That’s when you need an instructor.

The Students

Having 17 other people work on the same labs helps in a couple ways.

1. If you’re stuck, someone has the answer.

2. You solidify your learning when you explain a concept to someone else.

3. You crowdsource better ways to do the same thing.

Otherwise, I’ve been really impressed by the other students who come here. They’re thoughtful, entrepreneurial, artistic, and fun to hang out with. And they’ve all quit their jobs to be here, just like me.

One major advantage of working in a team is that you realize how hard git is with when you work with another person, something I would have waited to learn if I had taught myself.

The School

When you go to a “school”, it’s easy to forget that the Flatiron School is a startup. From hearing what the team believes, I think they know the importance of maintaining the brand and investing in the education of young people. They seem focused on the long term and building the HBS of developer schools.

Lunch

The school is in downtown New York. There’s a lot of places for lunch here.

Myself

Coming in, I had doubts about how much I’d prepared. I don’t feel that anymore. Six weeks in, I’m pretty comfortable that I can figure it out if I don’t know something. I know how to read Apple documentation, google stack overflow and ask for help. In fact, I think this comes more naturally to me than most people and the more code, the better I get.

This week, we learned about APIs and this was really the first time when coding became real. I can now build programs that change the state of the physical world. That feeling is incredibly empowering.

Notes for the second half

1. Maintain health

2. Appreciate the people and the time that we have left

3. Make good art

4. Do a lot of work

There’s two more weeks of instruction left before client projects start. My Flatiron presents is in three weeks, so there’s a lot to be excited about.

Flatiron School Week 6 – An analogy for understanding blocks

Blocks can be a really confusing concept and they’re further obfuscated by the crazy syntax. So crazy there’s a website just for the syntax.

Here’s one way to think about blocks.

If you’ve ever worked in a corporate office before, you know about making decks (powerpoint presentations) as I did in my former life.

  1. When your team needs to build a deck, your manager probably tells you to help him with a couple slides for the story he’s going to tell. He’s the architect but he doesn’t make graphs. So he IM’s you to make them and to tell him when you’re done. (Message one sent.) While he’s waiting for you, he’s continuing to work on other parts of the slide, so that he’s ready when you come back with the data.
  2. Let’s say that you can only make these fancy looking graphs for him and you don’t know what he’s going to do with it. This time, the data he needs is outside your normal scope. So you call up your friend over in finance to get the right numbers and ask him to email it to you. (Message two sent.) While he’s digging those out for you, you figure out how you want to display the data on the chart.
  3. Your friend get the data and emails it back to you.
  4. You take the data and put it in the graphs and send it to your manager.
  5. Your manager takes your graphs and puts it in the slide.

Congratulations! You’ve just used blocks.

Here’s what it would look like in code.

You have the Manager, Analyst, and DataAnalyst classes.

What does the manager need to do?

To the outside, the manager knows how to make decks, but they don’t know how the decks are made.

Manager.h

#import <Foundation/Foundation.h>

@interface Manager : NSObject

- (void)makeDeck;

@end

Manager.m

//
//  Manager.m
//  blockAnalogy
//
//  Created by Xida Zheng on 11/8/14.
//  Copyright (c) 2014 xidazheng. All rights reserved.
//

#import "Manager.h"
#import "Analyst.h"

@interface Manager ()
@property (strong, nonatomic) Analyst *analyst;

@end


@implementation Manager


- (void)makeDeck
{
    //make the start of the deck
    
    [self getGraphsFromAnalyst:self.analyst withCustomStyling:^(NSArray *graphs) {
        //any custom styling required for this deck
    }];
    
    //make the rest of the deck
}


- (void)getGraphsFromAnalyst:(Analyst *)analyst withCustomStyling:(void (^)(NSArray *))customStyling
{
    [analyst makeGraphsWithSpecifications:[NSDictionary new] CompletionEmail:^(NSArray *graphs) {
        //standard graph handling (i.e. put the graphs on slides)
        customStyling(graphs);
    }];
    
    //make the rest of content on the slides with graphs
}

@end

In order to make the deck, the manager, needs their analyst to get graphs and passes those graphs through any custom styling instructions before the slide makes it into the deck.

(Step 1.) Calling [analyst makeGraphsWithCompletionEmail…] is like IM’ing the analyst to make the graphs. The manager provides the analyst with specifications for the graphs and instructions for when the analyst is done.

What does the analyst do with that information?

(Step 2.) He takes it and translates the conversation with his manager into an algorithm to make the slides and a data request for his friend.

(Step 4.) After he receives a response back, he turns the data into graphs based on his manager’s specifications and send the graphs back to his manager via email.

//
//  Analyst.m
//  blockAnalogy
//
//  Created by Xida Zheng on 11/8/14.
//  Copyright (c) 2014 xidazheng. All rights reserved.
//

#import "Analyst.h"
#import "DataAnalyst.h"

@interface Analyst ()
@property (strong, nonatomic) DataAnalyst *friend;
@end


@implementation Analyst

- (void) makeGraphsWithSpecifications:(NSDictionary *)specifications CompletionEmail:(void (^)(NSArray *))completionEmail
{
    //turn specifications into a way to make for the graphs
    //turn specifications into a data request to your friend
    [self.friend getDataWithSpecifications:[NSDictionary new] CompletionEmail:^(NSString *data)    {
        //apply specifications with data
        NSArray *graphs = @[data];
        
        completionEmail(graphs);
    }];
    
    //make other graphs with data you're familiar with
}

@end

What did the data analyst friend have to do?

(Step 3.) Just take in the specifications from the analyst and send back the data in an email.

//
//  DataAnalyst.m
//  blockAnalogy
//
//  Created by Xida Zheng on 11/8/14.
//  Copyright (c) 2014 xidazheng. All rights reserved.
//

#import "DataAnalyst.h"

@implementation DataAnalyst

- (void) getDataWithSpecifications:(NSDictionary *)specifications CompletionEmail:(void (^)(NSString *))completionEmail
{
    NSString *data = @"data";
    
    completionEmail(data);
}

@end

I hope that helps clarify blocks. Let me know what you thought.

Remember, even though blocks are just funny looking objects, they’re misunderstood, and they deserve some love too.

Flatiron School Week 6 – Week in Review

Topics: Blocks, APIs

I’ve been writing three miniblogs a week on Mistakes and Lessons, Questions and Answers and Notes to Self. As I’ve progressed, I feel composition of my attention shift as well.

  • Since I’ve been making less time consuming mistakes and asking for help earlier, I don’t really have anything in the Mistakes and Lessons category. Since I’m still learning a lot, I’m going to call it Cool Stuff I Learned This Week
  • In terms of Questions and Answers, most of the questions I have are focused in areas that will take the form of side project demos.
  • I’ll still have making lots of Notes to Self.

My blog reflects that with a change in format with a Week in Review entry each week instead of three smaller ones.

Cool stuff I learned this week

  • UI changes must be made on the main thread.
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
         //stuff goes here ex:
         [self.tableView reloadView];
    }];
  • I didn’t know the difference between an access token and an API Client id & API Secret.
    The access token is used to authenticate an individual user, so that you can access their personal data.
    The client id and secret are used to authenticate to the API that you’re a registered app so that they allow you to continue to send many request to their server. This does not provide user authentication by itself.

Notes to Self

I like generalizing problems to find patterns in solutions and that turns out to be a really useful skill for a programmer, so that I can write reusable code.

Programming is very cumulative. Everything is built on a previously made part.

Playing chess while I was kid really helps me to visualize objects moving in my mind and that helps me keep track of blocks moving between classes.

Flatiron School Week 5 – Questions to ask before choosing an API to work on

In the last post, I ended by saying that developer time is valuable and to be selective about which APIs to work with. This post is going to talk about how to choose an API.

Why are you using the API?

If you’re building something for educational purposes or for fun, then the last two questions matter less. The questions are more geared towards people who want to build something that will be a good business or a feature that you want the company to add to their app.

What would be fun to work on?

If I’m into restaurants, Yelp and Foursquare easily come to mind.

Does the API solve your problem?

API limit what functionality they provide, called endpoints. Let’s say that I want to look at photos for restaurants. Do the Yelp and Foursquare APIs give me photos? They both do.

If I was looking for check-in information, Foursquare would have the edge because they were built on the check-in functionality.

What are the rules around API usage?

In their documentation, API typically have rules around how they can be used.

Foursquare’s rules are pretty open and clear on exceptions. I’m not sure if I would be “recreat[ing] the functionality of Yelp’s own website or mobile apps,” with the photo idea, which they say not to do.

Both APIs require attribution.

Foursquare only allows 4 pictures or tips to be shown from any one business.

With Yelp’s API, no data can be stored, while Foursquare requires that you refresh the data.

How easy is it to use? How well is it documented?

Good documentation is super helpful when you’re first starting out. I like that Yelp shows an example of their business response. Clarity around rules is also a must because it reduces hesitation over ambiguity.

How does the company treat it’s developers?

Do they communicate changes early in advance? Who owns the app that you make?

Foursquare seems to remove functionality and gives a few months for developers to adjust.

What is the longevity of the platform?

Deprecation of API features does make you wonder what they will remove next. How long do you think you can continue to use the API? How long before something else comes along that’s more popular?

In my hypothetical example, I have seen that Yelp has better search results though. In the end, I would choose Foursquare because it seems like you are free to do more with it.

Flatiron School Week 5 Notes to Self

I love animations.

Animation are the closest thing to art in iOS development. It’s like directing a movie or moving a paintbrush.

I started playing RGB express this week and I just love their level set up animation where the puzzle falls down from the sky in delayed stages.

Up next to explore: Core Animation, Core Graphics, and UIKit Dynamics

Flatiron School Week 5 Questions and Answers

Question: Should I be using frame or constraints to draw views in iOS?

Answer: Constraints. Autolayout will be able to adjust to the four different screen sizes, so you don’t have to. It’s like the CSS of iOS.


Question: I know how to animate the background color of a UIView from black to red with animateWithDuration … What do I use when I want to make it go from black to blue to red?

Answer: I could use two animations with different durations, or key frame animations.


Question: One of the labs this week was making a game with four draggable images. After finishing the lab, I noticed that I could drag multiple images at a time and that they would collapse to one location at the end of the drag, because I had only accounted for one object. How can I make it so that the user can only drag one object at a time?

Answer: One solution I found online used one gesture recognizer in the superview and detected which object was pressed using hitTest:. However, this did not solve my problem. I could still take the two. This question is still open, but I can imagine a solution where I store the locations of a four objects in an array and update it as I change each object’s location.

Flatiron School Week 5 Mistakes and Lessons

Topics: Autolayout, views, gesture recognizers

Symptom: The gesture recognizer doesn’t work.

Mistake: Making one recognizer and assigning it to four objects.

Each gesture recognizer can only have one owner and each assignment meant that it was just being reassigned to the latest view.

Lesson: Make one gesture recognizer for each object.


Symptom: Constraints were not working.

Mistake: I had assigned constraints to the view.

Lesson: Constraints are sent to the superview. Gesture recognizers are sent to the view.


Symptom: My game’s win conditions were being satisfied when they shouldn’t have been.

Mistake: When comparing the two views’ centers, I checked if the difference was less than a threshold, when I meant to use the absolute value of the difference.

Lesson: Unexpected wins are bugs too. They should be understood as much as bad bugs.


Symptom: My autolayout had more constraints than I thought I had specified.

Mistake: To deal with the iPhone size plus, I had constraints for when trait collections display scale were 3, but had forgotten to wrap the other constraints in an else statement.

Lesson: Those willTransitionToTraitCollection:withTraitCollection: methods can get really complicated and I have to be careful with the large if statements.


Flatiron School Week 4- Hacking together the TinderClone Swipe Feature

The Tinder Swipe

The central part of Tinder’s design is the swiping mechanism. The feature allows people to focus on one match at a time and make a decision before moving on to the next match.  Good for spending more time on matches and good for reducing the speed of data consumption.

I wanted to learn about animations, so this weekend I hacked together a prototype of the feature.

Demo

All the code can be found here along with a video demo. The code is very dirty, but that’s topic for another week.

Process

Step 1. Look up how to do it.

The next step in my TinderClone project is to make the swipeable images. Richard Kim has a really cool blog entry about how to make this feature three different ways. Since I’m taking on this project to learn to code, I took the “build it from scratch” way and tried to follow Nimrod Gutman’s blog. I totally failed. Twice.

It turns out that I didn’t really understand how UIView and UIImageViews worked. So, I decided to play around with them.

Step 2. Read up on UIViews

I read thought through the Apple View Programming Guide. in particular, the view and window architecture. I didn’t really understand bounds very well, so I started an Xcode project called playingWithBounds, that ended up being my project.

Take-aways:

  • Views are made on top of Core Animation layers (CALayer). Views have animation, but go to CALayer to one layer deeper for more control.
  • Subviews are arranged in an array in the superview.
  • UIContentMode is useful for sizing images. I played around with this later.
  • I thought the bounds property might have something to do with Box Sizing in CSS, but it’s much simpler. The bounds change the frame of the box.

UIView properties

  • frame- used for making objects. CGRectMake()
  • bounds- changes the size of the view, but not the center.
  • center- very important for moving objects around.
  • transform- used to rotate, move and scale objects. It’s the finishing touch. The object is drawn and then transformed. When an object is rotated, it remembers what it’s heigh and width were when it wasn’t rotated.
  • alpha- 1 is opaque and 0 is fully transparent. Great for
  • backgroundColor- useful for seeing where the rectangle is.

Step 3. Playing around with the UIView properties

I made single view project where I drew boxes and changed the bounds, and so on to see what would happen.

Step 4. Playing around with CGAffineTranform

When I got to Coordinate System Transformations, I started playing around with rotating and moving boxes.

I made a slider to rotate an UIImageView.

//slider
        CGRect slideFrame = CGRectMake(100, 400, 200, 20);
        self.pictureRotationAngle = [[UISlider alloc] initWithFrame:slideFrame];
        [self.view addSubview:self.pictureRotationAngle];
        self.pictureRotationAngle.minimumValue = 0;
        self.pictureRotationAngle.maximumValue = 2*M_PI;
        self.pictureRotationAngle.value = M_PI/2.0;
 
        [self.pictureRotationAngle addTarget:self action:@selector(rotateImage) forControlEvents:UIControlEventValueChanged];
 
        self.picture.transform = CGAffineTransformMakeRotation(self.pictureRotationAngle.value);

Step 5. Finding the Event Handling methods

Where other solutions mentioned at the top used UIGestureRecognizers, I imagined that these event handling methods could move my picture around too. They used UITouch objects.

I was touching my UIImageView and nothing was happening. Googling around, I found that UIImageViews are not user interactive by default. So, I had to set it.

    self.picture.userInteractionEnabled = YES;

I also set the

What is UITouch?

I didn’t know, so I built the first three methods and NSLogged the touch and event objects. They were very descriptive.

2014-10-27 18:58:26.919 TinderSwipeFeature[65292:2410541] <UITouch: 0x7fdf015533a0> phase: Moved tap count: 1 window: <UIWindow: 0x7fdf01409040; frame = (0 0; 375 667); gestureRecognizers = <NSArray: 0x7fdf01403730>; layer = <UIWindowLayer: 0x7fdf01414c50>> view: <UIImageView: 0x7fdf01684780; frame = (37.8671 64.9702; 402.124 402.124); transform = [0.99420459268393058, -0.10750454821160646, 0.10750454821160646, 0.99420459268393058, 0, 0]; clipsToBounds = YES; opaque = NO; layer = <CALayer: 0x7fdf01684ac0>> location in window: {256, 332} previous location in window: {255, 332} location in view: {192.38019379786252, 249.92073845470227} previous location in view: {191.38598920517859, 249.81323390649064}

UITouch has a lot of really useful info:

  • Size of the screen: 375 width and 667 points height.
    frame = (0 0; 375 667)
  • The view touched and it’s location
    view: <UIImageView: 0x7fdf01684780; frame = (37.8671 64.9702; 402.124 402.124)
  • Current touch location in view and window
    location in window: {256, 332} 
    location in view: {192.38019379786252, 249.92073845470227}
  • Previous touch location in view and window
    previous location in window: {255, 332}
    previous location in view: {191.38598920517859, 249.81323390649064}
  • Timestamp
    2014-10-27 18:58:26.919

I now had the velocity of touches and I just needed to update the view being touched with a new center value to move it.

That was the key to solving the problem.

I added the other Tinder style animations associated with swiping. All of these were based on using the x location of the touch divided by the width of the phone to calculate a factor that would modify the rotation of the image and the opacity of the overlaps.

Step 6. Playing with contentMode

When I put the picture in the UIImageView, it would not fit in the frame, so I had to set clipsToBounds to YES and change the contentMode from UIViewContentModeScaleToFill to UIViewContentModeScaleAspectFill. UIViewContentModeScaleAspectFit also works but you get white space on the sides.

    self.picture.contentMode = UIViewContentModeScaleAspectFill;
    self.picture.clipsToBounds = YES;

The other options such as UIViewContentModeTop maintain the size of the image, and align the listed edge to the corresponding edge in the box. For example,

  • UIViewContentModeTop aligns the image to the top of the UIImageView.
  • UIViewContentModeTopLeft aligns the image to the top and left of the UIImageView.

Step 7. Animation timing

For the touchesEnded method, I wanted to animate the image moving back into location.

[UIView animateWithDuration:0.4 delay:0 usingSpringWithDamping:0.6 initialSpringVelocity:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
                ... reset image
            } completion:nil];

CGAffineTransformIdentity removes all transforms (rotations, scaling, translations).

Step 8. Animation for the picture flying off the screen or springing back

To animate the picture flying off to the side, I set a swipe threshold of 30% of the width.

if (differenceInTouchLocationX > aTouch.window.frame.size.width*0.2) {
            [UIView animateWithDuration:0.5 animations:^{
                viewTouched.center = CGPointMake(self.view.frame.size.width*2, currentLocation.y + 0.5 * speedY) ;
 
            }];
            NSLog(@"%@", aTouch);
        }else if (differenceInTouchLocationX < -aTouch.window.frame.size.width*0.3)
        {
            [UIView animateWithDuration:0.5 animations:^{
                viewTouched.center = CGPointMake(-self.view.frame.size.width*2, currentLocation.y + 0.5 * speedY) ;
            }];
        }
        else { 
             ... //springs back to original location
        }

Step 9. Add the overlap images (Like and Nope)

self.like = [[UILabel alloc] initWithFrame:CGRectMake(20, 20, 100, 50)];
 [self.like setFont:[UIFont systemFontOfSize:100]];
 self.like.text = @"L I K E";
 self.like.adjustsFontSizeToFitWidth = YES;
 [self.like setBaselineAdjustment:UIBaselineAdjustmentAlignCenters];
 [self.like setTextColor:[UIColor colorWithRed:47/255.0f green:156/255.0f blue:28/255.0f alpha:1]];
// self.like.backgroundColor = [UIColor blueColor];
 self.like.transform = CGAffineTransformMakeRotation(-20* M_PI/180);
 self.like.alpha = 0;

Boy, I learned a lot by just reading the documentation and Googling. That was fun!

Flatiron School Week 4- Notes to Self

Blogging is an intentional investment in time

One reason I blog is to review what I’d learned that week.

The other goal in this blog is to document my creative process. There are two styles of documenting process.

  1. Make the thing, write about it afterwards.
  2. Record nuggets of information and write the blog entry along the way.

Both have their benefits and drawbacks.

  • The first gets to the answer faster, but misses out the details of the process.
  • The second slows down the discovery process, but maintains an accurate record of events. Errs on the side of too much detail that people won’t care about.

This weekend, I spent more time coding the Tinder swipe feature and didn’t have as much time to blog. I wanted to finish. I found that trying to recreate my process of discovery after the fact was time consuming and demotivating. Perhaps that’s not a good strategy. If I haven’t been taking notes along the way, I should just provide a summary of key points.

That’s probably what people care about anyway.

Flatiron School Week 4- Questions and Answers

Topics: Cocoapods and Core Data

Question: Should I use [array mutablecopy] or [NSMutableArray arrayFromArray:array]  ?

Answer: Both are the same if the array is already made. Stylistically, prefer the latter.


Question: Is order maintained in Core Data?

Answer: No, if you want to maintain order, add an attribute like createdAt and use an NSSortDescriptor to order by created time.