Flatiron School Week 9 – Resolving my first real git merge conflict

This week we started our client projects. 19 people broke down into teams of 4 or 5. There were four clients and our team had four people. This was the first time that I really needed to deal with git merge conflicts and develop a workflow.

It wasn’t long before I had a conflict.

There were three files that I conflicts with:

  1. AppDelegate.m
  2. the .pbxproj file
  3. a xccheckout file

1. AppDelegate.m

I knew how to resolve the first one, but as I tried to do that, my file directory on the left side of Xcode disappeared. It was time to ask for help. Zach, one of our TAs, helped me put together a plan to resolve the conflicts.

I had to back out of the merge, so I used

git merge --abort

and then reset the head to the last commit because there some uncommit changes that I didn’t want anymore.

git reset --hard <commit id>

2. the .pbxproj file

Apparently that file directory is stored in the .pbxproj file. The way that we resolved this was by telling git to just join the two versions together in the .gitattributes file by adding:

*.pbxproj merge=union

Another way to resolve this is to choose one version of the pbxproj.

git checkout --ours <directory/file>

Replace “ours” with “theirs” to get the version being merged into the current branch.

I had to add in some files that were no longer referenced by the pbxproj file after the merge using this second method.

3. a xccheckout file

For the .xccheckout file, this was a file that should have been ignored. I added this to the .gitignore file.

*.xccheckout

The problem was that both versions that I was trying to merge still had this file in tracked files. I had to remove this file from both repos by running:

git rm --cached <directory/file>

Once the .xccheckout file was removed, I could merge the two repos.

Both the .gitignore and .gitattributes files should be set up at the beginning of a project.

Update

Since that week, we’ve had to resolve conflicts many times. Following Github’s workflow has been pretty useful. I’ve found that the best way to resolve conflicts is prevention. We designed our workflow so that each person worked on a different part of the app and that minimized conflicts.

Flatiron School Week 3 Notes to Self on Unit Testing

As I’ve started to work on my TinderClone side project more, I’ve realized the need to have good tests.

Why are tests useful?

Test Driven Development allows you to limit scope and develop in an efficient iterative way.

Tests makes sure things are working when you make changes in other parts of the code.

Tests automate a lot of actions that would be tedious to do manually every time.

When are tests needed?

Tests are especially helpful when you’re trying something experimental and don’t want it to break the rest of your code. (Branching is also a great idea when starting a new feature or something that you’re not sure will work.)

Tests are helpful for debugging large projects.

When are tests not needed?

When I work on smaller projects, I’ve found that tests are not worth the time needed to write them.

Week 3 Mistakes and Lessons

Topics this week: TableViewControllers

Symptom: When I see an empty table view controller, this is usually the culprit. 

Mistake: Forgetting to initializing the array in a table view controller.

Lesson: always initialize the array.


Symptom: The dreaded Apple Mach-O Linker Error. Linker command failed with exit code 1. This error is super intimidating because it’s so cryptic. (What the heck does that mean anyway?)

Mistake: Turned out that I had imported a KIF test file “TableViewControllerSpec.m” into another TableViewControllerSpec.m and it was giving the errors:

duplicate symbol _OBJC_METACLASS_$_TableViewControllerSpec ...
duplicate symbol _OBJC_CLASS_$_TableViewControllerSpec ...

Lesson: Don’t quit when you hit error messages. Read the logs, it usually gets you close to the problem.


Symptom: Realizing that the full solution to a problem is not worth implementing and not having the previous version. 

Mistake: Deleting code when it’s a partial solution to go for a full solution.

Lesson: Commit code before trying an experimental solution.


Symptom: Tests fail sometimes but not all the time.

Mistake: Not resetting the test conditions after each or before each tests. Test do not go on in order in KIF.

Lesson: Check the starting condition each time before a test is run. Resetting the tester is cool.

Week 2 Questions and Answers

Topics

  • “Deprecated”

  • Storyboard or programmatic views

  • Mystery letters next to file names

  • Designated initializer

  • _instanceVariables in inits and setters


Question: When I look at Storyboard segues, there’s the word deprecated next to push segues. What does deprecated mean?

Answer: Apple will not be phasing out that features soon in the next release. It looks like they’re replaced the push segue with a show segue.


Question: Should I be learning to use the storyboard or learning to make views programmatically?

Answer: It depends on the usage. Storyboard is great for building views quickly and with little code. I was told that one major drawback is that it’s almost impossible to merge conflicts on storyboards. This means that when another programming changing the same view, one person’s changes will be lost. This can be mitigated by creating xib files for each classes and one owner per class. Storyboard tutorial for iOS 7.


Question: What are those A, C and M letters next to file names on the project Navigator in Xcode.

Answer: Those are the git version control symbols. A for added. C for conflict. M for modified. More here.


Question: Do I make the base initializer(init) or the custom initializer (initWithName:Birthday:Hometown:) make the designated initializer?

Answer: Use the custom initializer as the dedicated initializer. For the base initializer, use the dedicated initializer and pass in default values. More here. It saves repeated code and makes there one point of failure.


Question: Why should I use _instanceVariable in the init and setter methods instead of self.instanceVariable? I thought that we were supposed to always call methods.

Answer: For one, using self.instanceVariable in the setter will get an infinite loop because it will keep calling setInstanceVariable. There is a thing called key value observing (KVO) (awesome tutorial), which notices whenever the setter method is called for a property. In the init method, we don’t always want other people to know that we’re setting the property value.

Week 1 Questions and Answers

Question: When should I explicitly write strong vs. weak when declaring properties in class interfaces?

In other words, what is the difference between

@property (strong, nonatomic) NSString *name;

and

@property (nonatomic) NSString *name;

?

And when do I use:

@property (weak, nonatomic) NSString *name;

Answer: I found the answer on Ry’s Objective-C Tutorial, which I think is an amazing reference, because it’s very well organized and comprehensive.

In short,

@property (strong, nonatomic) NSString *name;

and

@property (nonatomic) NSString *name;

are equivalent. However, the first version is better, because there is no doubt. (Learning iOS Development by Maurice Sharp et al. p.79)

An example of when to use weak is when two objects have each other in their properties.

A Person may have a

@property Computer *myComputer;

and a computer may have a

@property Person *owner;

but you would not want to have both properties be strong because it would cause a memory leak (the program will use memory and not give up the memory, slowing down the phone).

In this case, I would make the owner weak because the parent object is the Person and not the computer.

@property (weak) Person *owner;

Question: If I clone a branch from Github and the branch that I wanted was not moved to my local machine, what should I do to get that branch from the remote? 

Answer: git checkout -t origin/<branch name>


Question:

//Should I use
[NSMutableArray new];
//or
[[NSMutableArray alloc] init];
//?

Answer: It’s up to you. The latter is more consistent because sometimes you might

[[NSMutableArray alloc] initWithArry:newArray];

Question:

//Should I use
[newString length];
//or 
newString.length;
//?

Answer: Dot notation is more readable, but opinions may differ, sometimes within the same person. Ex.

Dot notation in Objective-C: 100% Pure Evil

In Which I Embrace Dot Notation