While trying to provide information about a map location via colored text in the Seattle Trails app I'm working on, I came to the realization that I would need to use a custom annotation callout view to meet my needs. Default callout views use a String value for their subtitle property, which does not allow color. NSAttributedStrings allow color and UILabels have an attributed text property available. The following is a tutorial of the mini-project I used to figure out how to achieve this.
First, set up a project with a map view and connect it to the default view controller via an IBOutlet:
Next, we want to set up a custom pin and view. Create a xib for the view, custom view class and map annotation class. When creating the xib, the size can be adjusted by dragging after setting it to freeform in the attributes inspector. Connect the xib to the view with IBOutlets:
Now the custom pin needs to be added to the map, which requires the view controller to implement MKMapViewDelegate and CLLocationManagerDelegate. The user's current location is obtained from CLLocationManager to drop the annotation pin on it. When getting the user's location, it is important to add NSLocationWhenInUseUsageDescription as a key to the info.plist and request authorization to access location data.
This is an oversimplified way to set up a pin, and it will be used differently in Seattle Trails; however, here the multi colored subtitle is set up with fixed ranges for the colors and then used to initialize a pin. The user location is set as the annotation pin's coordinates, which is then added to the map view.
When the annotation is selected, in didSelectAnnotationView, the custom annotation view is loaded from the xib file. The next part moves the view to be centered over the annotation pin. Since the touched map annotation type is known to be the custom annotation that was added to the map in viewDidLoad, it is casted to that type and stored in customAnnotation. That is used to set the custom view's title and subtitle before adding it as the annotation view to be displayed.
Last, the map region is set to move the map view to the annotation pin. Span x and y determine how far the map zooms in. Because a value of 1.0 is always equal to 69 miles, setting the value to 0.01 narrows down the view to slightly more than half a mile.
I hope this walkthrough ends up being helpful to someone, and I'm eager to receive feedback so that my intention can be better met through iteration. Please leave your comments and this code is available here: GitHub.
Swift It & Ship It!
My first client app built with Swift 2, Film Camp, is now in the App Store! After multiple intense months of collaboration, coding and user testing, I can say I've learned a lot. It was so much fun to build software on a team and an enlightening experience to be a solo developer.
It all started when I met Craig, who found me through Code Fellows. He was a serial entrepreneur who intended to experiment with app creation as a new venture. He told me that he wanted an app that could knit videos together, and before he decided to hire me, I sent him a prototype that did just that. Apparently that is a good way to get hired.
Craig had two other people on the project: Aaron, his co-founder and project manager, and Jonah, an experienced film-making teacher who would develop curriculum and influence feature design. For 6 weeks, we sprinted to a minimum viable product. On Mondays, we would meet and brainstorm. I'd code all week, and on Fridays, we would demo the current prototype to kids. This cycle was great for rapid iteration based on feedback! Getting a chance to debug the app during user sessions was a ton of fun!
Early on, the app design came solely from a donated half day with my friend, a professional designer, Mathew Weintrub. We learned the hard way that it is good to have an app fully designed from the beginning, because later on we had Josh with Adjust Creative fully flesh out the design of the app. His new design improved the app tremendously; however, it was a significant amount of extra work for me to implement what he came up with after having built it to the prior design.
The technical challenges faced in this app were many. I mostly relied on dogged determination to find solutions with documentation and Google. This gave me a renewed appreciation for blogs and tutorials created by the amazingly talented iOS community. As a new developer I do not know what I'd do without other developers sharing their wisdom freely online, and I must pay it forward soon.
Though it's exciting and fun to be a lone wolf developer, I suspect that my skills will grow faster when I am around other people with equal or greater development skill. Even if they don't work in the same stack, it is valuable to try and explain your thought process to someone who can question it. This challenge improves thinking by having to communicate it, and can result in the realization, sooner rather than later, that one's approach is flawed. I'm greatly looking forward to getting involved in larger projects and finding opportunities to be a mentee and mentor.
Film Camp is built with the latest Apple frameworks in Swift 2. Photos Framework is used to store the videos a user creates, to the device and AVKit, in tandem with AVFoundation, allow composing and previewing of media before it is merged into a video. I used NSCoding to persist data so that a project is continually saved and not lost when the app is exited. Swifty Dropbox and Social Framework allow a user to post videos to Dropbox and Facebook.
One of the most challenging tools I worked with was AVFoundation. Using time ranges, I had to knit together multiple 9 second audio clips with multiple 3 second video clips and a 30 second music track. This lead to me getting stuck for multiple days because there was a glitch in the Framework that would not let me merge the audio as multiple pieces without it breaking the video. After trying it a myriad of different ways I had to come up with my own solution, albeit less efficient, that involved exporting all the shorter audio clips into their own merged track before composing everything.
I think working with AVFoundation was my favorite part because I was able to improve my algorithms for composition of media items to be more general solutions which taught me how to write more elegant code. There were other quagmires like having to figure out how to share video with Facebook which has a lot of security hoops to jump through and a two part breakdown requirement for sending video. Challenges were what made this project the most rewarding in the end and I look forward to embracing the struggle with new future ones.
Embracing the struggle
Week 8 of the Code Fellows iOS Development Accelerator has been traversed and the beginning of a new path is here. This program has been the most challenging endeavor I have ever undertaken. The pace was very intense and "the struggle is real," as my instructor Brad Johnson warned us it would be.
A very large amount of ground was covered, in a relatively short period of time, to get me where I am today. Due to the current state of iOS, we covered two languages, Swift and Objective-C. Each week we made an app that had significant functionality. Some of the frameworks utilized include: Core Image, UIKit, Foundation, MapKit, Photos, Accounts, Social and WebKit.
To drill down a little further I will provide some examples of what was accomplished with these. In the first week we made a Twitter Clone, in Swift, which leveraged table views to display tweets that were fetched using the Social framework, Twitter's API, Oauth and, JSON serialization and parsing. A Xib was used to make custom cells that displayed the tweet's user image, name and tweet text. Images were lazy loaded for better performance.
Auto layout was used for displaying view contents dynamically in portrait and landscape orientations. Views were imbedded in a UI Navigation Controller which implicitly introduced us to the stack data structure through pushing views onto it. Swift optionals and down casting were great for the handling of JSON data. Closures made swift work of asynchronous callbacks and switch statements enable dynamic handling of HTTP response codes.
Week 5 was a traumatically awesome plunge into Objective-C. We built a "Location Based Reminders" app that included Apple Watch integration through WatchKit. The Core Location and MapKit frameworks provided the main functionality for this program. MKMapView was utilized for the display of the map and we started off by having 3 interesting locations to select on it. A button for each initiated an animated traversal to the location with a set region to show. I decided to switch to satellite view for this as my locations looked great using this.
For the next part, CLLocationManager and map annotations with callouts were used to place and track locations on the map. When the user long pressed a spot on the map, a gesture recognizer initiated an annotation at that point. The callout could be selected and a CLCircularRegion would be created, and registered with NSNotificationCenter, around the annotation for monitoring. This region was displayed with a rendered MKCircle overlay, and when crossed, it would trigger a local notification. Using WatchKit, we displayed the dropped annotation in a map view on the watch simulator.
Slow is smooth and smooth is swift
I have completed my fourth assignment in the Code Fellows iOS Foundations II course. I find programming to be addicting. I put in fourteen hours today and a couple each day prior, plus class. How productive were those hours? That depends on how you think about it. If I'd already had the experience I gained today, my final outcome would have taken one or two hours...
I sit down, think I am going to do awesome work, then proceed to break my program, in a myriad of ways. There is this masochistic thrill of repeated excitement, thinking I nailed the problem, followed by bouts of profuse swearing. I can't stop going until it is nailed, though, because all those "almost theres" just increase the anticipation of success, resulting in obsession.
What did I learn? Xcode is complex. My code can be awesome, but there are so many ways to break the program with things like an unset reuse identifier. Those need to be checked often, and I have to make sure to hit enter after typing in the string, or I will think it's set when it's not. This leads to tweaking the wrong things, trying to fix the problem. Also, if anything is deleted in the storyboard, I have to delete everything that related to it, like outlet connectors. If not, things may end up falsely appearing to be hooked up.
Programming will take mindfulness, patience, and the willingness to recheck everything as if I didn't just write it. When my code breaks, I have to switch roles and act as if I am investigating someone else's code. Assumptions about "what I have already done" can make the debugging process painful. Another thing I will have to get good at is recognizing the point where I need to seek help (a more seasoned investigator or maybe just a fresh set of eyes). It's easy to be hurried and have a chain of "this will only take a few more minutes to fix."
In summary, when things break, patiently check over everything as if someone else built it. Set a limit for the number of times through and/or the time to take going through, troubleshooting an issue. Seek help at that point, because though it feels good to single handedly solve it, there are other things that also need doing and our time is finite. Slow is smooth and smooth is SWIFT. ;)
Commit to code
Recently, I decided to commit to a skill path. I love technology and have been intending to become a creator of it for a while. So far, I have completed many courses on Team Tree House and it has been a great experience, however; it hasn't lead to much creation due to not having delved to a deep level of mastery. This online school is great and I will continue to use it, although I believe it is time to take it to the next level.
In order to learn a language, to the point of fluency, immersion is needed. High intensity of exposure is the best way. I have heard this from several reputable sources, like Tim Ferris for example. So after going to Meetups and perusing programming, I have decided on a starting platform, to immerse myself in. Enter iOS development at Code Fellows.
My commitment starts with $1500, for a month long class, called iOS Foundations II. Two nights a week, starting tomorrow, to prepare me for what will be the greatest academic challenge I have ever undertaken. Next, I take the plunge and leave my job, to learn full time, which is terrifying because it also costs $10,000.
This section is called the iOS Development Accelerator and to make sure there is no turning back, I have already put in notice with my current employer. There is a bright light at the end of this tunnel that I am launching myself down it. Code Fellows guarantees a job at the end with at least $60k a year in salary. When I get there, the money will be a bonus. The real reward is having a skill that I enjoy utilizing to conjure my dreams into reality. Wish me a little luck and a lot of perseverance!
Mind over water
One of my learning obsessions has to do with the human body. I want to know how it works and what its history has been in order to better understand it. Understanding is the key to greater cooperation and/or control.
My quest has led me to a fascinating idea. The way I understand it is that, historically, most people's bodies were more regularly exposed to cold temperatures than we currently are in our domesticated environments. Well, of course, but what else could that mean?
It turns out that internal temperature is controlled by metabolism; in this case, the consumption of body fat and hormone production. The idea proposes that because of our near constant exposure to warmth, our nervous systems have had reduced efficiency in these processes. It is like a muscle that is used in a very short range of motion for a very long time. It becomes weak and stiff outside of that range.
Enter Cold Thermogenesis:
How do we regain our "range of motion" -- our ability to quickly adapt body temperature internally, burn fat and increase hormone production? Get really, really, really, dangerously cold. Being curious, of course I experimented with this. After a few times of severe shivering, my body + 20lbs of ice + bathtub = trauma, I decided on a more sustainable route.
I now take cold showers, a habit that was difficult to build. It does seem to have benefits even though it is significantly less of a drop in temperature. I think it may raise my metabolism, although a high fat diet and adequate water consumption do that as well. It also seems to keep my skin tighter. When you get goose bumps from cold, those are muscles in the skin contracting and the harder they flex, the stronger they become, keeping skin tight. Not to mention the consequent increase in blood flow.
Finally, mind over water. When I step up to that shower head, every part of me wants to avoid discomfort and go warm. Each time I do not give in, my mental toughness gets a little stronger. Seems like a good trade off for something that can't hurt me and it is my favorite thing about this practice.
Live, learn & practice
Here I am many years ago. Torn hat, popped collar, busy shirt. It is St. Patrick's Day and I sure hope I look cool. Do these girls think I do? More likely than not, they are only thinking the same thing I am, about themselves.
At this time in my life I had no idea what I was doing and to this day I still don't. The good news is that none of us do. We are all just "making it up and making it real", as Dan Sullivan would say, or letting someone else do it for us and hoping it works out.
I am realizing that the more I learn from others, the better I can practice and have a little more prediction of the result, or at least guidance towards an intended one. This is because I am drawing from the experience of those who have practiced before me. Still, because the world is truly living chaos, which we seek neurotically to make do our bidding, we have no certainty.
In this sense, everything is a leap of faith. If I want something to be different, action must be taken with the faith that I will learn from and adapt to whatever may happen. Seek knowledge faster, act faster, experience faster, learn faster. There is so much I do not know, and that includes most of what I think I know, so I better stay fluid and learning.
One might ask, "Action? What action should I take? I am taking action." The answer is, I have no idea, remember? I am just figuring it out too. Your life is a complexity I can't possibly know thoroughly enough to advise on that. For myself, I have realized that my complaints will tell me. My complaints must be converted to actions if my soul is to expand and grow. Because they are myself disagreeing with what I am doing.
What actions will this mean for me? I think I know, but like you, I am actually waiting to find out. So, stay tuned.