Jekyll2023-06-21T18:57:11+00:00https://alloc-init.com/feedalloc-initblog for @WestonHanners{"picture"=>"/images/me.jpeg", "twitter"=>"WestonHanners"}Moving to Mastodon2022-11-22T00:00:00+00:002022-11-22T00:00:00+00:00https://alloc-init.com/blog/mastodon<p>I think the past few weeks have had everyone thinking where are we going with
Elon Musk taking control of Twitter.</p>
<p>Like many I have had two concerns on the top of my mind.</p>
<ol>
<li>Should I delete my account?</li>
<li>Where are we going?</li>
</ol>
<p>The first issue seemed easy, I went ahead and requested my Twitter data
archive. It was time consuming, but not at all difficult. As my cursor hovered
over the delete button, I was suddenly reminded of all the sites I have signed
into with my Twitter credentials. I decided I would hold off on the full
account deletion and will simply let it lie dormant.</p>
<p>The second issue was a bit more interesting. I, was immediately reminded of
<a href="https://joinmastodon.org/">Mastodon</a>.
This decentralized, hub-based social network has been around for some years, but
mostly for small niche communities. Since I last checked, it looks like they
have really improved on their feature set and at this point, I didn’t seriously
consider any other options. I have a new profile set up <a href="https://techhub.social/@westonhanners">here</a>.</p>
<p>The cool thing about Mastodon is that you can join “hubs” that are interesting
to you, and there is no shortage of niche communities. I joined <a href="https://techhub.social/">Tech Hub</a>
most of the posts are tech centric and very interesting.</p>
<p>I think this is likely to be confusing to many people so I want to see if I can
help explain how this all works.</p>
<p>Be warned, I am still fairly new to Mastodon, but this is my understanding.</p>
<h2 id="what-is-affected-by-my-hub-choice">What is affected by my hub choice?</h2>
<p>Short answer: not much.</p>
<p>Your hub choice will determine your “local” feed content, on a typical
configuration this will be all posts from your hub.</p>
<p>Your “home” feed is a list of all the profiles you follow from your
hub or any other hub that isn’t explicitly blocked.</p>
<p>Finally there is a “federated” feed that is a unified feed from your hub and any
hub yours is working (or federated) with. You might see some people refer to
this graph of connections as the “Fediverse”.</p>
<p>I think the biggest issue would be if you chose a hub that gets defederated.
This has happened with some hub with extreme political, violent, or sexual
content. If you choose poorly the good news is you can always just pack up and
move to a different hub.</p>
<h2 id="what-client-should-i-use-on-mobile">What client should I use on mobile?</h2>
<p>I’ve tried a handful of iOS clients, but so far my favorite on iPhone is
<a href="https://apps.apple.com/us/app/metatext/id1523996615">Metatext</a>, It has a great UX and feels snappy.</p>
<p>A close second is <a href="https://apps.apple.com/us/app/toot/id1229021451">Toot!</a>. My biggest issue with Toot! is I think it over did
it a tiny bit with the animations.</p>
<p>There is an official client but I found it a bit sluggish and buggy.</p>
<h2 id="how-do-i-find-my-friends">How do I find my friends?</h2>
<p>This is probably one of the biggest conversion friction points, especially with
many hubs rate limiting rapid follows. With multiple hubs and no central
verification it can be difficult to determine if you are following the right
person. I do recommend using <a href="https://fedifinder.glitch.me/">fedifinder</a> to help locating your friends.</p>
<h2 id="what-are-these-metadata-fields">What are these Metadata fields?</h2>
<p>They are for whatever you like, you can add any additional information that you
think is useful for you profile. I personally put my twitter link, web site and
location.</p>
<p><img src="/images/mastodon-profile.png" alt="Profile Screenshot" /></p>
<h2 id="other-tidbits">Other Tidbits</h2>
<p>Not everyone will be onboard for calling posts “toots”, the MetaText client has
an option for renaming toot to post.</p>
<p>I think they also need to make it easier to follow people from a web link.
Right now you have to copy the users profile link and paste it in your own hub
to follow, it’s weird and unnecesary, I hope they figure it out soon.</p>
<p>If you have a website, you can easily get “verified” by adding a backlink to
your mastodon profile with <code class="language-plaintext highlighter-rouge">rel="me"</code> attribute set. Then add a “website”
metadata property on your profile with your website linked and it will get a
green checkmark. This tells your followers that you own the domain, and for most
reasons, this is nearly as good as twitter verification. More details
<a href="https://docs.joinmastodon.org/user/profile/#verification">here</a>.</p>
<p>There is a weird meme on Mastodon where no one refers to Twitter by name, like
It’s Lord Voldemort or something. If you see “birdsite” that means Twitter.</p>
<p>Oh yea, follow <a href="https://mstdn.social/@feditips">Feditips</a>. This account posts frequent tips and tricks and
has been a great resource for getting started.</p>
<h2 id="conclusion">Conclusion</h2>
<p>Mastdon is really interesting and I am going all in, I do think that some people
will have trouble “getting it” but maybe with some more updates and more
traction we can finally ditch the monolithic corporate social network.</p>
<p>I hear a bunch of people are heading to <a href="https://www.hivesocial.app/">Hive Social</a>, and maybe it will
become a big thing, but after MySpace, Frendster, Foursquare and now Twitter…
I think I am content to stick with Mastodon.</p>{"picture"=>"/images/me.jpeg", "twitter"=>"WestonHanners"}I think the past few weeks have had everyone thinking where are we going with Elon Musk taking control of Twitter.iOS 16 Blog Post for YML2022-06-08T00:00:00+00:002022-06-08T00:00:00+00:00https://alloc-init.com/blog/ios-16-changes<p>I helped Hannah Reedy (one of our Senior Product Managers at YML) write an
article on iOS 16 changes.</p>
<p><a href="https://medium.com/ymedialabs-innovation/3-changes-in-apples-new-ios16-that-chief-digital-officers-need-to-take-advantage-of-right-now-fc50122bf635">Check it out</a>.</p>{"picture"=>"/images/me.jpeg", "twitter"=>"WestonHanners"}I helped Hannah Reedy (one of our Senior Product Managers at YML) write an article on iOS 16 changes.Some reasons SwiftUI might not be right for you2019-12-12T00:00:00+00:002019-12-12T00:00:00+00:00https://alloc-init.com/blog/swiftui-issues<p>As work slows down for the holidays, I have found myself with some spare
time. I decided to sit down and tinker with SwiftUI to see what it could do.
While I was impressed with how easy it was to get pixels on-screen, test them
and get data flowing, there are still several issues. I am going to document
them here.</p>
<h2 id="navigation-bar-customization-missing-feature">Navigation Bar Customization (Missing Feature)</h2>
<p>This should have been simple, a navigation bar with a left button, a right
button, a text-based title, and a tint color applied. Looking at the
documentation it would appear <code class="language-plaintext highlighter-rouge">.accentColor()</code> is what I wanted. I applied it
and found that while it does apply the tint color to bar items, it does not
apply it to the title text.</p>
<p>There is a terrible workaround where you can set the leading items as an Hstack,
Add a title view, then set the width to match the screen, but I <em>really</em> do not
recommend doing this.</p>
<p>for the record, I also tried setting <code class="language-plaintext highlighter-rouge">.foregroundColor()</code> to the same effect.</p>
<p>Filed a Radar.</p>
<h2 id="scroll-view-paging-missing-feature">Scroll View Paging (Missing Feature)</h2>
<p>If you want a scroll view to snap to pages (useful for snapping to cards or
other content) in UIKit it was as easy as setting <code class="language-plaintext highlighter-rouge">.isPagingEnabled = true</code> on
a UIScrollView. This feature seems to have been omitted from SwiftUI.</p>
<p>Filed a Radar.</p>
<h2 id="navigation-links-only-work-once-bug">Navigation Links Only Work Once (Bug)</h2>
<p>Take the following example using Xcode Version 11.3 (11C29), This is currently
the latest build.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>struct Detail: View {
var body: some View {
Text("Detail")
}
}
struct ContentView: View {
var body: some View {
NavigationView {
List {
NavigationLink(destination: Detail(), label:{ Text("Hello") })
NavigationLink(destination: Detail(), label:{ Text("Hello 2") })
}
.navigationBarTitle("Testing")
}
}
}
</code></pre></div></div>
<p>If you were to launch this and tap the first link, tap back, then tap the first
link again, it will not load.</p>
<p>Tapping the second link, in this case, <em>will</em> load.</p>
<p>Filed a Radar.</p>
<h2 id="most-autocompletes-do-not-work-as-expected-editor-issue">Most Autocompletes Do Not Work As Expected (Editor Issue)</h2>
<p>Buttons are the obvious offender.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Button(action: {
}, label: { () -> PrimitiveButtonStyleConfiguration.Label in
})
</code></pre></div></div>
<p>Most of the time, what you are looking for is</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Button(action: {
print("Hello")
}) {
Text("Hello")
}
</code></pre></div></div>
<p>I am still not sure what <code class="language-plaintext highlighter-rouge">PrimitiveButtonStyleConfiguration.Label</code> means.</p>
<h2 id="no-good-collectionview-equivalent-missing-feature">No Good CollectionView Equivalent (Missing Feature)</h2>
<p>While you can create some decent views that look like CollectionView by nesting
scroll views, there is no method of doing this where the data is dynamically
loaded.</p>
<p>The only component in SwiftUI that appears to use dynamic loading is List.
ScrollView will require all items to be loaded into memory before it can
render.</p>
<p>All of this to say, if you need a horizontal scroll view to load in many items,
SwiftUI will cause you some serious performance issues.</p>
<p>I am not sure if this is intentional or not. It is possible that Apple doesn’t
want heavy usage of horizontal scroll views.</p>
<p>I will be watching this going into June.</p>
<h2 id="conclusion">Conclusion</h2>
<p>SwiftUI is really fun and the data flow is just awesome. It makes building new
screens super quick and opens the door to a ton of prototyping.</p>
<p>I am sure these will all be fixed in time, but many of these are deal-breakers
and as it is right now, I will not recommend SwiftUI for any paid projects I
am involved with.</p>
<blockquote>
<p>This article will be updated as I find more issues.</p>
</blockquote>{"picture"=>"/images/me.jpeg", "twitter"=>"WestonHanners"}As work slows down for the holidays, I have found myself with some spare time. I decided to sit down and tinker with SwiftUI to see what it could do. While I was impressed with how easy it was to get pixels on-screen, test them and get data flowing, there are still several issues. I am going to document them here.SwiftUI Tutorial Series2019-12-05T00:00:00+00:002019-12-05T00:00:00+00:00https://alloc-init.com/blog/hacking-with-swift<p>Paul Hudson of <a href="https://www.hackingwithswift.com">Hacking With Swift</a> has been kicking ass since June digging
in to the very depths of SwiftUI. Along with his <a href="https://www.hackingwithswift.com/quick-start/swiftui">book</a>, he has also been
churning out and an ever growing series of videos.</p>
<center>
<iframe title="Hacking with iOS: SwiftUI Edition" width="560" height="315" src="https://www.youtube.com/embed/videoseries?list=PLuoeXyslFTuZRi4q4VT6lZKxYbr7so1Mr" frameborder="0" allow="picture-in-picture" allowfullscreen="">
Hacking with iOS: SwiftUI Edition
</iframe>
</center>
<p>This series starts from the basics and moves into helping you understand a lot
of how the framework works under the hood.</p>
<p>If you have any intention of learning SwiftUI, I highly recommend watching.</p>{"picture"=>"/images/me.jpeg", "twitter"=>"WestonHanners"}Paul Hudson of Hacking With Swift has been kicking ass since June digging in to the very depths of SwiftUI. Along with his book, he has also been churning out and an ever growing series of videos.Scroll to top in iOS 13 UI Testing2019-08-08T00:00:00+00:002019-08-08T00:00:00+00:00https://alloc-init.com/blog/scroll-to-top-ios13<p>In XCTestCase if you want to scroll to the top of a scrollable view, you
tap on the status bar</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>XCUIApplication().statusBars.firstMatch.tap()
</code></pre></div></div>
<p>However, this is doesn’t work in iOS 13.</p>
<p>I filed a radar during the beta and they just got back to me with this.</p>
<p>The status bar is no longer part of the application, it’s part of the system
UI (“springboard”). Change your test as follows:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>let systemApp = XCUIApplication(bundleIdentifier: "com.apple.springboard")
systemApp.statusBars.firstMatch.tap()
</code></pre></div></div>
<p>This seems like it should be important, but it was not documented anywhere on
Apple’s website.</p>
<p>If still need to support Xcode 10 / iOS 12, I recommend using the
following extension</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>extension XCUIElement {
func scrollToTop() {
if #available(iOS 13, *) {
let systemApp = XCUIApplication(bundleIdentifier: "com.apple.springboard")
systemApp.statusBars.firstMatch.tap()
} else {
XCUIApplication().statusBars.firstMatch.tap()
}
}
}
</code></pre></div></div>
<p>I figured I would share this so that it is at least documented somewhere.</p>{"picture"=>"/images/me.jpeg", "twitter"=>"WestonHanners"}In XCTestCase if you want to scroll to the top of a scrollable view, you tap on the status barTips for Great Conference Calls2019-07-21T00:00:00+00:002019-07-21T00:00:00+00:00https://alloc-init.com/blog/great-conference-calls<p>Working in software development, is it guaranteed that you will attend a conference call at some point. I hate to use the cliché, but it’s 2019 and some people are still terrible at this. You will hear noises in the background, people won’t pay attention or will talk over each other and you have technical blunders.</p>
<p>So I decided to put together a list of tips for improving your conference call experience.</p>
<h2 id="find-a-good-meeting-space">Find a good meeting space</h2>
<p>This one sounds obvious, but try to make every effort to obtain a quiet space to have your meeting. Conference rooms are the best choice, but barring that, any quiet space will do.</p>
<p>Also be aware that while it may be quiet for you, you will be potentially making the space less quiet for other people. Avoid taking calls at your desk if you are in an open office.</p>
<p>If it is nice outside and you are the only caller from your end, it can sometimes be nice to go for a walk. I have taken calls on city walking trails and parking garages before. This might not be ideal for every call, but it’s a good option to have.</p>
<h2 id="join-on-time">Join on time</h2>
<p>When you schedule a meeting, you are making a promise to your attendees, you are taking up peoples time. if you fail to join people who could otherwise be doing useful work are instead waiting in dead silence for the call to begin.</p>
<p>Don’t be late.</p>
<p>If you absolutely must be late, make sure you send out a notification as early as possible to let them know of your delay or, even better, update the calendar invite with a new start time.</p>
<h2 id="sound">Sound</h2>
<p>If you are taking the call alone, use headphones with a microphone. These typically sound better because the microphone is close to your mouth, but be mindful you don’t move around much if it is laying against your shirt. Avoid Bluetooth headphones unless you know they are of a high quality so you don’t sound robotic.</p>
<p>Mute yourself when you are not speaking. Learn how to mute your call in the software you use and make liberal use of that button.</p>
<p>If you are taking a call with multiple people, avoid using Laptop microphones. Also, be aware they can pick up the sound of every keystroke if you are typing while talking. We have a couple <a href="https://www.jabra.com/Business/speakerphones/jabra-speak-series/jabra-speak-510">Jabra Speak 510’s</a> in our office, and they work great.</p>
<p>Make sure you silence your phone and laptop.</p>
<p>I like to do a quick audio and camera check before I join a call, most conferencing software will have a screen for this in their settings. Check your Mic and Camera to make sure the correct devices are selected.</p>
<h2 id="pay-attention">Pay Attention</h2>
<p>If you aren’t presenting or on camera, it can be easy to pull out your phone and browse Reddit or stare blankly out a window, but try to pay attention having to ask “wait, what did you say again” can be embarrassing.</p>
<p>Put your devices in Do Not Disturb mode so you don’t get sidetracked by text messages or other notifications. iOS has a great feature where your phone will remain silenced until the end of your current calendar item.</p>
<p>For meeting hosts, try to stay on topic and keep people involved in the conversation, this will prevent wandering minds.</p>
<p>If you find a meeting has become sidetracked and the main topic is complete, please don’t hesitate to let people uninvolved in the side topic know they are free drop off.</p>
<h2 id="keep-your-desktop-clean">Keep your desktop clean</h2>
<p>If you are going to be sharing your screen, make sure your desktop is not cluttered. Take special care to remove documents with confidential or private information. Remove that funny meme your friend sent you. Just make sure your desktop has nothing that will embarrass you or your company. To make it easier, you can just make a folder called “clutter” and move everything in there.</p>
<p>I’ve already mentioned Do Not Disturb mode several times in this post, but if you are screen sharing and you get an inappropriate text message from a friend, you will regret not silencing your notifications.</p>
<h2 id="do-a-camera-check-before-joining-video-calls">Do a camera check before joining video calls</h2>
<p>Before you join the meeting fire up your camera and take a look at your background.</p>
<p>Check for clutter. Dirty laundry, trash, alcohol bottles… I have seen all of this, and it’s just unprofessional.</p>
<p>Make sure you don’t have proprietary information up on a whiteboard. If you do client work, this is especially important as it can have legal ramifications.</p>
<p>Check yourself. Look in the mirror, make sure you are as presentable as you would be in person.</p>
<h2 id="open-questions">Open Questions</h2>
<p>Try to avoid asking undirected questions, try to keep them directed at individuals.
Asking questions like these will cause one of three things to happen.</p>
<ol>
<li>Multiple people answer at the same time and they talk over each other</li>
<li>No one talks and you get dead air and have to direct your question at a specific person anyways.</li>
<li>What you want to happen, happens and the correct person and only that person answers.</li>
</ol>
<p>You get a 1/3 chance for it to work, It’s awkward and you should just avoid it if possible.</p>
<p>If you are running a standup meeting, you get to pick who talks first, don’t open it up to the floor.</p>
<h2 id="in-summary">In Summary</h2>
<ul>
<li>Find a quiet place that won’t bother other people.</li>
<li>Be punctual or notify everyone you will be late as soon as possible.</li>
<li>Take measures to prevent interrupting sounds.</li>
<li>Pay attention so people don’t have to repeat themselves.</li>
<li>Check your desktop before enabling screen sharing.</li>
<li>Check your environment before joining a video call.</li>
<li>Avoid undirected questions.</li>
</ul>
<p>I hope you found this useful and if you didn’t, great job, you were probably already doing the right thing.</p>
<p>Please share this and perhaps we can make conference calling better for everyone.</p>{"picture"=>"/images/me.jpeg", "twitter"=>"WestonHanners"}Working in software development, is it guaranteed that you will attend a conference call at some point. I hate to use the cliché, but it’s 2019 and some people are still terrible at this. You will hear noises in the background, people won’t pay attention or will talk over each other and you have technical blunders.A Framework Author’s Case Against Frameworks2017-12-21T00:00:00+00:002017-12-21T00:00:00+00:00https://alloc-init.com/blog/framework-authors-case<p>I was looking at my YouTube subscription feed this morning, and this gem popped
up. While I don’t agree with his prejudice against native apps, I think Adrian
adds a few more points to go well with <a href="blog/2017.12.18">yesterday’s blog post</a>.</p>
<center>
<iframe title="Watch Video" width="560" height="315" src="https://www.youtube.com/embed/VvOsegaN9Wk" frameborder="0" allow="picture-in-picture" allowfullscreen="">
Watch Video
</iframe>
</center>{"picture"=>"/images/me.jpeg", "twitter"=>"WestonHanners"}I was looking at my YouTube subscription feed this morning, and this gem popped up. While I don’t agree with his prejudice against native apps, I think Adrian adds a few more points to go well with yesterday’s blog post.The Trap of Libraries2017-12-17T00:00:00+00:002017-12-17T00:00:00+00:00https://alloc-init.com/blog/the-trap-of-libraries<p>One of the worst feelings I can ever have in iOS Software Engineering is cloning
an existing project for the first time and looking at the Podfile. I feel it gives
me a good sense of how the project is going to go. If there are only 1 or 2 pods,
I sigh a breath of relief, if there are more, I start the mourning process.</p>
<p>It’s not like having a handful of pods are always a bad thing, but most of the time
they definitely are.</p>
<p>Here is a short list of things that I don’t mind seeing in a Podfile.</p>
<ul>
<li>HockeyApp</li>
<li>Fabric</li>
<li>Google Analytics</li>
<li>Urban Airship</li>
</ul>
<p>Libraries like these are helpful, they integrate backend services that might be
overwhelming to create from scratch, and allow you to focus more on your app.
While they tend to be a little larger than one would like, the companies that maintain
them tend to spend time making sure they are low impact, relatively bug-free, and
fairly easy to keep updated.</p>
<p>Here is a list of libraries that send a chill down my spine.</p>
<ul>
<li>ReactiveCocoa</li>
<li>Mantle</li>
<li>AFNetworking</li>
<li>Facebook Pop</li>
<li>ZXingObjC</li>
</ul>
<p>There are many more I could list here, but let’s get to the point. These libraries
are a loan from the bank of tech debt. Using some of these commits large portions
of your code to require constant maintenance, and you can only avoid it for so long.</p>
<h2 id="the-first-problem">The First Problem</h2>
<p>When I tell people my thoughts on these libraries, they always tell me…</p>
<blockquote>
<p>They are open source, if there is something you don’t like you can always just fix it.</p>
</blockquote>
<p>or</p>
<blockquote>
<p>If the maintainer goes away or stops supporting it, you can take it up.</p>
</blockquote>
<p>Let’s run a little thought experiment on this, shall we?</p>
<p>Take AFNetworking for example…</p>
<p>If I am building a library that uses Apple’s URLSession to build my network stack,
I can be fairly confident that it will be maintained as long as the platform is.
It has a lot of features, is relatively bug-free, and I don’t have to pour over its
source-code with every update to make sure it is following the new best practices.</p>
<p>However, if I use AFNetworking, I potentially have to wait weeks before
new language, security, and platform features are integrated. I am not sure if
you remember the <a href="https://gist.github.com/AlamofireSoftwareFoundation/f784f18f949b95ab733a">certificate pinning issue</a>, but the gist of it is that the
maintainers identified a security issue introduced in one of their patches and,
to their credit, they patched it in about a week. The problem arose in that every
developer who used the library didn’t follow the news, or had to wait for internal
company processes to allow a release, then wait for Apple’s (at the time), slow,
app review to patch this vulnerability. The effect of this was that over 1000 apps
on the app store had this issue.</p>
<p>Now this is a big, frequently used library and the maintainers did the best they
could to fix the problem as quickly and as loudly as they could, but can you say
that you follow the git issues and blogs related to every single library you use?
A small “syntactic sugar” library could easily introduce security issues without
your knowing, and if it’s not used by A LOT of people, it will fly completely under
your radar (I will avoid the obvious pun here).</p>
<p>And what if this library wasn’t even well maintained?</p>
<p>Yes, you could fork the library and start maintaining it yourself, but do you think
your clients and managers will agree that spending several hours a week maintaining a
library is a good thing? How would they feel if you are only using a couple functions?
If they are ok with it, you probably have a great job with very understanding
colleagues and you are probably on retainer, or work in a big corporation.
Consulting/Agency work doesn’t usually afford this luxury.</p>
<p>Even if you only use popular, well-maintained libraries, you can still be hit by…</p>
<h2 id="the-second-problem">The Second Problem</h2>
<p>In the beginning of this article, I talked about the dread I feel opening up an
existing project’s Podfile for the first time, the worst thing you can see is at
the top.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>platform :ios, '6.0'
</code></pre></div></div>
<p>This means one or two of the following.</p>
<ol>
<li>This project hasn’t been updated in a LONG time.</li>
<li>This project relies on a library that no longer exists.</li>
</ol>
<p>If the issue is the former, you will probably have well over 100 random deprecated
API warnings, and if you are lucky, only a couple hard errors. If it is the latter,
get prepared to spend a lot of time extracting that pod from the application.</p>
<p>For example, I am looking forward to having to spend quite a few hours extracting
Mantle from an application because the app heavily relies on a feature no longer
present. This is not even close to the first time I have had to deal with this.
Smaller libraries are a bit more loose with redefining their entire API in an
update, completely breaking the hosting app, and sometimes introducing new bugs
that can take weeks of updating to work out.</p>
<p>It can also be easy for someone working on the project to work around issues and
never actually update the library. When it finally comes time that you do run
<code class="language-plaintext highlighter-rouge">pod update</code>, you might find that you now have a week or more of fixes to get
the new library running. Maybe you are the good guy (or gal) who spends time
keeping pods updated and therefore you don’t have to waste weeks doing the epic
rewrite, if you are this person, would you like a <a href="https://ymedialabs.com/careers/">job</a>?</p>
<p>Libraries can be useful when a task is too complicated or requires large amounts
of infrastructure, but what I see a lot of the time are tiny, single-purpose,
libraries that only marginally improve the workflow.</p>
<p>This sort of library can also dictate your entire architecture. They can lock you
into something that might be trendy now, but in a year or two, you find yourself
scratching your head and wondering how you ever got into this mess in the first
place.</p>
<h2 id="the-solution">The Solution</h2>
<p>If you are using a smaller library, why not write it yourself? Autolayout DSL’s,
JSON parsers, custom animations; these aren’t generally very complicated to do
on your own and since you wrote it, you should be able to easily fix it when
needed. It will reduce app bloat, improve security, and you will get better at
the problems these libraries solve.</p>
<p>Reducing boilerplate and simplifying common programming tasks are the siren
songs of software engineering, they can be quite attractive, and it is easy
to add them to your project. In reality, for larger projects, they are traps
that lock you into spending quite a lot of your time putting out the fires
they can create.</p>
<p>If you want my opinion, they are best avoided when possible.</p>
<h2 id="afterthoughts">Afterthoughts</h2>
<p>It was not my intent to spend so much time picking on AFNetworking, it
just provided a good example for issues I will encounter. AFNetworking was
incredibly useful back before NSURLSession was a thin, but it is so easy to
do it right with just foundation libraries these days, I wonder why it is
still so popular for simple networking tasks. If you know why, please
<a href="https://twitter.com/WestonHanners">tweet at me</a>.</p>{"picture"=>"/images/me.jpeg", "twitter"=>"WestonHanners"}One of the worst feelings I can ever have in iOS Software Engineering is cloning an existing project for the first time and looking at the Podfile. I feel it gives me a good sense of how the project is going to go. If there are only 1 or 2 pods, I sigh a breath of relief, if there are more, I start the mourning process.Auto-Completion And Organization for NotificationCenter2017-01-23T00:00:00+00:002017-01-23T00:00:00+00:00https://alloc-init.com/blog/notification-center-autocomplete<p>I may be late to the party, but I just discovered the most amazing trick thanks to
<a href="http://swiftandpainless.com/selector-and-the-responder-chain/">this article</a>.</p>
<p>Have you seen this before?</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>NotificationCenter.default.post(name: NSNotification.Name(rawValue: "didSomething"), object: nil)
</code></pre></div></div>
<p>… yea, its pretty ugly, not to mention incredibly error prone. If you have to use this same
notification in multiple parts of your app, you are very likely to typo that string literal at
some point.</p>
<p>But, I just discovered some syntax sugar to help clean that up.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>extension NSNotification.Name {
static let appDidSomething = NSNotification.Name(rawValue: "didSomething")
}
</code></pre></div></div>
<p>With that in place, you can start adjusting your call-sites like this.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>NotificationCenter.default.post(name: .appDidSomething, object: nil)
</code></pre></div></div>
<p>How glorious is that?</p>
<p>In retrospect, it seems a bit obvious, but the best tricks usually are.</p>{"picture"=>"/images/me.jpeg", "twitter"=>"WestonHanners"}I may be late to the party, but I just discovered the most amazing trick thanks to this article.Self-Explained Swift2017-01-19T00:00:00+00:002017-01-19T00:00:00+00:00https://alloc-init.com/blog/self-explained-swift-2<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>// Self-Explained Swift #2
// Tools to make our code easier to manage and read.
import UIKit
import PlaygroundSupport
// Welcome to my second Self-Explained Swift. In this playground, we are starting with
// the code from the previous post but with some new changes and the old comments removed.
// If you feel like you don't understand something, go back and check it out.
// The idea I want to convey in this post is "Tool Creation". You can create many tools
// that can be reused throughout your app that will help cut down on coding mundane tasks
// such as view creation and common layout constraints.
// The "Tools" in this instance will be extensions. If you are not familiar with them,
// extensions allow you to bolt new functions on to existing types. Below I have added
// a few functions to assist us in initializing common UI elements, and generating common
// view layouts.
extension UIView { // Layout extension
// This function will encapsulate the process of adding a view, enabling autolayout,
// and configuring the common constraints
func constrainTo(view: UIView) {
// Turn on autolayout
view.translatesAutoresizingMaskIntoConstraints = false
// Because of the way we worded the function, view will be the parent and self,
// the child. It might look a little strange here, but as you will see below, it
// reads quite nicely in the call-sites.
view.addSubview(self)
// I was notified about the new NSLayoutAnchor system since my last post, this
// makes alot nicer constraint building, so we use that here.
view.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
view.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
view.leftAnchor.constraint(equalTo: self.leftAnchor).isActive = true
view.rightAnchor.constraint(equalTo: self.rightAnchor).isActive = true
}
}
extension UIStackView {
// UIStackView has alot of things that are frequently changed from the defaults. This
// new init overload will allow us to one-line most of it.
convenience init(arrangedSubviews: [UIView],
axis: UILayoutConstraintAxis,
distribution: UIStackViewDistribution,
alignment: UIStackViewAlignment) {
// Chain to the original initializer.
self.init(arrangedSubviews: arrangedSubviews)
// Set our custom properties here.
self.axis = axis
self.distribution = distribution
self.alignment = alignment
// Again, it's nice to hide this away, since we will always need it off anyways.
self.translatesAutoresizingMaskIntoConstraints = false
}
}
// Here we are going to make class functions to help create a sort of "theme" for
// our app.
// For the most part, this is just our previous button code, refactored into a
// class function. We provide function parameters to set things likely to be
// different per instance.
// We also want to set translatesAutoresizingMaskIntoConstraints, so we can completely
// remove that from our view controller code.
extension UIButton {
class func standardAwesomeButton(title: String) -> UIButton {
let button = UIButton()
button.setTitle(title, for: .normal)
button.translatesAutoresizingMaskIntoConstraints = false
return button
}
}
extension UILabel {
class func standardAwesomeLabel(title: String) -> UILabel {
let label = UILabel()
label.font = UIFont(name: "Menlo", size: 14)
label.textColor = .white
label.text = title
label.textAlignment = .center
label.translatesAutoresizingMaskIntoConstraints = false
return label
}
}
class OurAwesomeViewController: UIViewController {
lazy var titleLabel: UILabel = {
return UILabel.standardAwesomeLabel(title: "Awesome")
}()
lazy var button: UIButton = {
let button = UIButton.standardAwesomeButton(title: "Press Me")
button.addTarget(self,
action: #selector(OurAwesomeViewController.buttonTest),
for: .touchUpInside)
return button
}()
override func loadView() {
super.loadView()
view.backgroundColor = .blue
// We are using our custom UIStackView Initializer, This will reduce quite
// a bit of the duplicated code and make your call-sites much easier to read.
let verticalLayout = UIStackView(arrangedSubviews: [titleLabel, button],
axis: .vertical,
distribution: .fill,
alignment: .fill)
verticalLayout.isLayoutMarginsRelativeArrangement = true
verticalLayout.layoutMargins = UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20)
// Call our new layout function, this encapsulates and simplifies the common
// task of adding views and setting their constraints.
verticalLayout.constrainTo(view: view)
}
func buttonTest(sender: UIButton) {
view.backgroundColor = .red
}
}
// Fire up our awesome view controller in a playground.
PlaygroundPage.current.liveView = OurAwesomeViewController()
PlaygroundPage.current.needsIndefiniteExecution = true
// As you can see, this greatly cleans up our layout code and makes it easier to
// manage. The View Controller is now ~43 lines of code and centralizes our styling.
// One forgotten property or function call could have caused your view to not render,
// but with this new setup, that code is now shared among other views and should be
// much easier to diagnose, and less likely to happen in the first place.
// Using these techniques, you can make your view controllers smaller, and simply
// theme creation. You could (if you wanted to) make several extensions for different
// styles of buttons, labels, or any sort of UI element. A change in any one would
// instantly be reflected across your app, with the only downside being the initial
// one-time setup.
// That's it for #2, next time, we will adjust the architecture to move your app-logic
// out of the ViewControllers as well.
</code></pre></div></div>
<p><a href="/downloads/2-LayoutImproved.zip">Download This Playground</a></p>
<p>Check out the previous post: <a href="blog/2016.12.28">Self-Explained Swift #1</a></p>{"picture"=>"/images/me.jpeg", "twitter"=>"WestonHanners"}``` // Self-Explained Swift #2 // Tools to make our code easier to manage and read.