Sketches and diagrams with arrows look very innocent, yet they mean so much for our work. But they only carry meaning if you’re honest with yourself and depict what’s really going on in the app; then they become a great tool to understand and analyze code. (Better than note-taking can ever be when it comes to object-oriented code.)
This weekend, I browsed around on Medium and found a post about “3 ways to pass data from model to controller”. Comments indicate that people like it because it talks about the important basics: how do you pass info around? It’s probably the most essential object-oriented programming question ever. How can you couple components?
I dabble with RxSwift right now. Figuring out how to write tests for pure functions and reactive code, I tried to write an assertion for incoming events: Doesn’t compile because equating arrays with Optional<URL> in them won’t. In other words, [Recorded<Event<URL>>] (non-optional) would work.
Junior Bontognali summed up what most people think about most other people – especially after the U.S. presidential election and Dash for iOS going Open Source: people in general are not ready for generous behavior.
Bogdan’s Dash for iOS is on GitHub now. One tweet highlighting an ugly if statement got lots of attention. One twitter user suggested cutting off Bogdan’s fingers. That’s not a real threat, of course. It’s just a stupid joke. But suddenly you’re in 4th grade again and everyone is making stupid jokes because someone pulled down someone else’s pants.
The thing is, Bogdan of Kapeli is too busy to accept pull requests that don’t add features. Maybe because testing these for regressions is pretty time consuming without and end-user benefit. Who knows. So he already turned down a pull request that would fix the aforementioned if-statement – and many others.
Dash probably isn’t ready for Open Source, either. A Swift library as simple as ReSwift took us over a month to port to Swift 3. Maintenance is time-consuming, no matter how big or small the project. Complaining is stupid and childish, but that’s the noise we have to deal with if we don’t want to be stupid and childish ourselves.
I don’t think everyone’s grown-up enough for democracy. I only hear about 3rd wave feminism and presidential elections in the U.S. from YouTube. Junior quoted Evelyn Beatrice Hall, and that applies just nicely to all the hate that’s going ‘round:
I disapprove of what you say, but I will defend to the death your right to say it.
It seems lots of people with the power to act in public space don’t want to defend anything except their own self-loathing and self-interest. (Looking at you, “safe space” discussions.) If you read my previous ramblings about morals, you will notice that I usually point out that bitching doesn’t help. It will only strengthen victim mentality. Only doing will improve the situation. That’s why I won’t stop open-sourcing code and I’m looking forward to getting feedback by amazing people. The majority of not-so-amazing people on the internet have to be filtered out. It’s worth the effort to reach the good folks.
We developers are familiar with the benefits of Open Source-distributed code: we can re-use the stuff other people achieved in our own applications and experiments. Giving back to “the community” feels nice, too. Most of the day-to-day benefits are centered around the free re-use. But the mentality of being part of Open Source is far more than that. I realized how precious the mindset is to me when I thought about how the gym I train at is managed.
The picture Dan is painting is dim, but it’s also spot-on. Wishes don’t always come true, and you probably know that some people on the web simply complain and write open letters to Apple instead of wishing for a better future.
Dan’s stance is more productive than complaints, though: Because when you complain, you’re adopting the mentality of a deserving victim. Change the status quo instead.
It’s your turn to do what’s right: if you don’t believe in what’s going on, make something better. On the Mac, you have the power to do so. As an indie app developer, you can distribute your software outside the Mac App Store. Or you can try new business models like Setapp is doing (which I presume to be subscription based for unlimited access to a wide range of apps).
Bitching doesn’t help. It doesn’t improve your own mental state, and it doesn’t make the world a better place. Only doing something will bring change.
Drawing from Dan’s list of wishes, a controversial topic is In-App Purchases. Some people say IAP are the future of making business, that paid up front is dead, and that developers should deal with the reality and adapt. Instead of finding out the truth, think about what you want to make, and which future you want to help bring about. Then act accordingly and never falter.
I watched “Managing Consistency of Immutable Models” by Peter Livesey where Peter shows how RocketData works. Very worth the time! I’d call RocketData a uni-directional data source. It’s uni-directional because you set up the DataProvider as the source once, wire update notifications to view updates via the delegate property, and you’re done with the setup. Update events include:
I utilize NSResponder actions in TableFlip to move the selection around. Naturally, neither a standard NSTableView nor a custom NSResponder implement default behavior for (most of) the methods I need to support arrow key movement, tab movement, and the usual shortcuts, like Cmd-Left to jump to the first cell in the current row. Or Alt + arrow keys to insert a row or column next to the selection. So I implemented this in a custom NSResponder subclass.
I participate in this year’s BundleHunt “Holiday Bundle” (running until January). I submitted both the Word Counter and TableFlip – mostly to see what happens.
The Bundle Experiment
I’ll disclose the details of my calculation later. This is an experiment: does presence in a bundle with so many hundreds of thousands of subscribers affect my regular sales and visibility? Being part of the bundle is like advertising, only I don’t really pay anything, I just make a lot less money when somebody buys the app from the bundle ($0.60 per license sold, or 97% discount for an app priced at $19.99). If the bundle sells 5000 times and 50% of bundles include one of my apps, that’s about $47,000 I will thus have “spent” on marketing. Imagine that. What a crazy number!
“These 2500 people could’ve paid you $20 instead and you’d be rich!” – Not quite.
My tools are targeted at users with very specific needs. The bundle is mostly targeted at folks wanting to make a deal. It’s people I may usually not attract at all. So even if I sell 2500 licenses through the bundle, I bet most of the customers will be people who wouldn’t have bought the apps without the bundle. I don’t really lose money if that’s true.
Part of the experiment is to find out what kind of people are going to buy the bundle.
Bundle Customer Ethics
I said this sometime in the past already: if you care about 1 app in a bundle of 10 and don’t want or need the other 9, contact the developer directly and ask for a discount. If MyDreamApp costs $50 and is part of a bundle for $20, ask the developer to buy the app directly for $20. This way they will make 10x more than from the bundle alone (ignoring bundle fees). That’s infinitely more % than not having you as a customer at all. It’s a good deal for everybody.
I’ve just finished updating the book “Exploring Mac App Development Strategies” for Swift 3. Looking at my Word Counter, this 4th edition sports about 15000 new words in the book and code combined: I re-wrote a lot of chapters and source files. I also expanded a few sections to add more context and incorporate things I learned in the past 2 years.
I’m converting code for my first book to Swift 3. It uses Cocoa Bindings a lot, including NSTreeController. Now the compiler changed; and one of the issues I faced was working with the NSTreeController.arrangedObjects. The compiler assumed a wrong type of the children property (see the docs) and reported “Ambiguous use of ‘children’”.
Last week, Red Queen Coder’s blog post about iOS job interviews was discussed a lot. The interviewers asked her to sketch how to implement a linked list on a whiteboard. She couldn’t. And thinks it is pointless. (I agree.) But then people on social media responded that she should just learn (that is: memorize) that kind of stuff to get a good job. Read her transcript, it’s a well-written story of how a job interview and the onslaught by narrow-minded people who defend the status quo (and their own status as the establishment) made her wonder what’s wrong with the community at large.
The folks at Swifting.io wrote a blog post about iOS software architectures. The comparison of VIPER and Clean Swift/VIP is very interesting: the VIP approach favors uni-directional flow, which I like very much. The article is worth a read for that alone!
They falsely consider MVC and MVVM to be software architecture approaches, though, and too point out that MVVM and MVCsuffer from similar drawbacks.
I just grokked how value transformations can not be a pain in tests. I’m writing a simple export module which takes a table from TableFlip and renders it as LaTeX. So the input is a Table and the output a String. But the module is not just a single function, mind you. That’d be a huge function, and not very open for configuration changes later. I factored it into a few sub-components, of course.
When facing a legacy code base, changing the mess to an orderly architecture can cause confusion: where to start? What to do? An exemplary question: How do I refactor a Big Ball of Mud into layered architecture? Refactoring the existing code base seems like a logical step; after all, refactorings are designed to improve existing code, and improvement is what you’re up to.
Picking up on my post “MVVM Is Quite Okay at What It Is Supposed to Do”, here’s a few images which illustrate the problem of mistaking MVVM for a solution to a structural problem. It’s the whole post in 2 images. Model–View–View-Model helps with the view layer. It can be a tool to break up a view controller into smaller things. But it’s still only a refactoring of view components into more objects.
This is a very sad thing to happen to Bogdan Popescu, sole developer of Dash: as far as I can tell, Dash is the only app he is selling at the moment, and now the exclusive iOS store was taken from him. The macOS App Store was probably more lucrative for Bogdan than selling licences on his own – at least that’s what other developers consistently report when they sell on both platforms.
So here’s another reason why Apple’s App Stores are risky for developers. Not only will search ads skew the results. And not only do you have to make up for the 30% cut by Apple. Developers have no way to defend themselves against giants like Apple (or Amazon in the realm of books, for that matter). There’s no separation of powers. The companies own these channels. It feels weird that they can do as they please, but there’s nothing to complain, really.
The power of the customer is limited, too. Do you know anybody who doesn’t have a strong opinion why his smartphone is better than someone else’s? Anybody who would switch platforms at will? Who won’t lose anything in the process or find it painful? – I don’t, and so there’s no real pressure for Apple in the long run. Not paying for the next iPhone and using Android instead is not an option for most iPhone users. It’s probably even worse with Macs. I wouldn’t want to use a Windows or a Linux PC if I can help it.
I pushed the button. Now TableFlip is here! TableFlip is a text-based visual table editor. It will become your go-to application to edit tabular data because it’s blazingly fast, lightweight, and fun to use. You can use it to quickly create tables from scratch and copy the result anywhere – or you can use it to edit tables in existing documents. That’s what “flipping” stands for:
So now you can place ads for your app to pop up in search results.
I don’t like this move. Because it changes the chances of developers to make it in the list of search results. The App Store’s aren’t a great place to discover a fitting solution. Now, the search results aren’t even guaranteed to be 100% relevant.
If I had the money, I’d use Search Ads to try to increase my revenue. Without money, you’re screwed, though.
At least the pricing sounds good: you pay for a tap and you can put a daily cap on your ad budget. So literally everyone can try to use Search Ads to increase the odds. The thing is that each tap is priced according to the market, though. If your competitors are willing to spend a lot more than you, chances are a limited budget will not make it:
You determine the maximum amount you are willing to pay for a tap on your ad. Using a second price auction, Search Ads calculates the actual cost of a tap based on what your nearest competitor is willing to pay for a tap on their ad, up to your maximum cost-per-tap bid, so you’ll always pay a fair market price. (Source)
Apart from the amount of fairness of pricing and other technical details, I find the very move to place Search Ads in the App Stores troubling in itself.
Apple have responded to my issues with broken NSLocale property availability. The properties are actually convenience accessors which you can re-impement youself for use before iOS 10. These properties are new in iOS 10, and you could add equivalent properties for older OSes using an extension like the one shown below:
Literals represent something. Magic numbers are a form of literal. This insight goes at least as far back as the book Structured Design by Edward Yourdon and Larry L. Constantine (from 1979!), on page 94. The number 79 can truly represent the result of 80-1, which in turn can express two other concepts:
We’re converting a rather big and clumsy project to Swift 2.3 at the moment. Strangely, NSLocale gives us a lot of headaches. The API hasn’t changed visibly, but the implementation seems to have. From Objective-C’s point of view: And from Swift’s: That property certainly isn’t new. Neither are the dozen others in that header file from Foundation.
The latin root of “proprietary” indicates this is something someone created in a special way. We can say it is owned by someone, intellectually. But then again, every file format was conceived by a human being; so the origin alone doesn’t suffice to grasp this concept. Take a look at the general introduction of “Proprietary format” on Wikipedia. Accessed today (2016-09-18), it reads (highlighting mine):
It’s much like MVVM, whereas here the view model is the store’s state.
This Flux-like approach is still a big improvement over convoluted view controllers or not thinking about data flow at all. But I wonder if the gain is so much higher compared to properly separated MVC. Who reads the store’s state? Only the views? Then the state is truly a view model; but how do side-effect populate to the rest of the app, like renaming or deleting things? I’d tend towards dispatching the change event to other stores, too, which may or may not react to the event. Then the view component’s state is updated independently from the database, say, using the same event dispatch mechanism.
To model the flow of truth on a component basis (which is still uni-directional: from store to view) compared to a single global app state (ReSwift) sounds like a very easy to do component redesign. You can start with anything and “fluxify” it. Then move on to the next component that’s particularly convoluted. You may not even want to convert all your components to this data flow approach when some components are simple enough as they are. Symmetry of component design will suffer, of course, but if you’re aware of this and conclude it’s better not to convert everything, that’s fine.
With ReSwift, I interpret the global app state to be a state with real (Domain) Model objects. To make a state displayable, I derive view models from it. This came very natural to me. But Ben’s posts got me thinking: could there be situations where keeping view model state around is better than keeping “real” model state?
It is time to go public: I’ll release TableFlip in October. Sign up for the release notification: http://tableflipapp.com/Much love goes out to my beta testers! ❤️ You are great! I didn’t anticipate that we’d have so many discussions. Thanks for all your amazing feedback so far. The past 12 weeks were wild; now it’s time to calm down a bit and make things right.
The thing is, tests are just code. If you have a hard time constructing your own objects with some particular state, it might be a sign that your API is hard to use!
This is all there is to the magic of test-driven development, we could say. A test is client code. This means it doesn’t have the inside perspective of the object or module under test. It has an outside perspective. Through tests you see how your production code is used (by other parts of your code or by other people in the case of libraries, say).
You start with a test. This means: you start with an outside perspective, asking yourself questions like “What would be a good (public) interface for this?” – The opposite is ad hoc reasoning, something along the lines of “I have this NetworkManager there and maybe just call it and return the JSON. Okay. Oh, now JSON doesn’t work, I need to send a custom object along, so I’ll just parse the JSON and create an object. But if that fails, hmm, I cannot send nil, so I’ll force unwrap and let someone else deal with this.” Or something.
These improvised solutions can cause trouble because all they do is focus on the perceived requirements of the object you’re writing, ignoring the requirements of code that uses the resulting code.
Writing tests first kind of equals writing your app outside-in, starting with the calling code, then implementing the code that’s to be called. Only test cases are super focused and you verify a lot more behavior and setup code with a single run than you could ever do with manual testing.
Experienced programmers will be able to switch perspectives even without writing tests. Their experience helps them to make it less likely to produce waste, whereas “waste” is code you write and then discard because you find it doesn’t fit.
According to Ed Yourdon, in the 1970’s global state was actually widely preferred over passing parameters to functions or subroutines. I had to laugh when I read the paragraphs on the most common objections, but this seems to have been a serious issue.
But I dare say: interruptions are only ruining your day if they are external. If you take a break, things don’t look that bad. You can train yourself to re-focus. And I argue this is a useful skill.
It took me a while to train this skill, but nowadays I’m interrupting myself at my home desk every 30 minutes, get up and move a bit to stay healthy. I don’t need 10 minutes to refocus. I sit down, take a deep breath, and continue to write code. Just like that.
Talking makes things worse, though; makes it harder to re-focus. That’s pretty obvious, isn’t it? After all, you switch contexts and engage in a different activity that uses a lot of your attention. Socializing is important to us pack animals, so there’s no way to not read faces and listen for subtleties in intonation. It’s just what we do. And it pulls all of our attention away from other things.
If I have the work break for myself, though, I can continue to mull over a problem in my head. In this case, getting up and leaving the keyboard means to interrupt an activity that may not lead anywhere at the moment. I bet you know this situation: you can’t seem to figure out how to fix a bug because some components are too entangled; whenever you try to change something, something else breaks. (Of course this never happens in your own projects.) A break then interrupts the need to type on the keyboard and produce code. It helps switch from typing mode to thinking mode. It’s like facilitating the proverbial ideas you always seem to get in the shower.
If you’re afraid of interruptions eating away your productivity, I challenge you to install controlled breaks every 30 minutes to get used to the flow. Sitting for an hour straight already kills your body. You won’t notice if you’re not reasonably healthy; it just feels normal, but it isn’t normal.
I bet that my training to do regular work breaks makes me more resilient to short external interruptions. Put me in an office and see for yourself 😀
For some reason, I couldn’t find or load Dave Winer’s comments, so I decided to blog about it instead: Dave reported that after announcing to shutdown of his outliner Fargo in 9 months, now users just get in touch with him for the first time.
Swift.assert bit me, and it bit pretty hard. What do you expect to happen in this code: … compared to this code: If your answer is “only the second variant will actually execute sendAction in release builds,” then you’re way smarter than I. Until now I assumed that Swift.assert behaves similar to assertion macros in Objective-C where the code is passed through in release builds. I never cared to read the documentation:
On the Mac, toggle or switch widgets aren’t very common, yet. On iOS, you don’t see lots of checkboxes. This article on UX Movement points out that switches are for immediate actions while changes to checkboxes require a submit button to be pressed.
Now I think about preference panes in Mac apps. They usually perform changes to NSUserDefaults immediately. But using switches on a Mac still feels wrong. Maybe just because I’m not used to it, but still.
macOS’s Notification Center has a switch to toggle “Do not Disturb”. It works, but I don’t use it a lot, so there’s not much opportunity to get accustomed to it.
It took me a while to grok the use of “Middleware” in ReSwift. ReSwift’s own tests illustrate what you can do with it: you can filter or modify actions before they are passed to the Reducers, for example.
As soon as you write a piece of software, you “architect” it. Can’t get around that; but if you do not do it consciously, the resulting structure may not be great. Taking ownership of the process is important to change the result and create maintainable software. When we write/architect software, we worry about two things:
Criticism targeting MVVM (Model–View–View-Model) from late last year essentially points out it’s not the silver bullet some take it for. Most of the stuff is missing the point. How are you supposed to make sense of it? What’s good advice for your project?
I found this on Seth Godin’s Blog: A dollar more (vs. a dollar less): But what happens if Lyft (or your project) decides to race to the top instead? What if they say, “we’re always a dollar more than Uber”?
An NSTableView is usually embedded in a NSScrollView. If you set the columns not to span the full width, the two of them will take care of drawing an empty table header cell to the right so that the interface doesn’t look weird. But I want to have a weird interface. Because TableFlip’s tables are different than the usual NTableView use cases.
When I added a sheet to display on top of TableFlips’ document, I wondered why the text field appear disabled, tabbing through elements didn’t work, and overall functionality was limited to accepting click events: It turned out you have to make sure that you disable most of the NSWindow settings in Interface Builder except the title bar (NSTitledWindowMask). Only with a title bar (which is never visible in a sheet anyway) will the interaction work properly.
It started innocently enough, with a customer being confused about paying for “the same app” twice. Now I wonder if the traditional pricing strategy for software is obsolete. I found this on Twitter, and then I got hooked: @fehnman @ulyssesapp like I said, it’s how you choose to sell it. +£50 for an app is pushing it.
—@eatmorefish (9:35 AM - 31 Jul 2016)
The following isn’t a universal truth. It’s a report about my observations of a recurring theme in everything that’s great. First you imitate. Then you improvise. And then you may innovate. Imitation means repeating existing things to reach a deeper understanding of how it was done in the past. Improvisation means connecting the static patterns in creative ways to solve problems. Innovation means deviating from the known patterns in new and effective ways.
David Sparks and Jason Snell started a new podcast about going indie in general called Free Agents. The first episode, The Temptation of Yes, is so packed with good stuff that I recommend you listen to these guys for 35 minutes.
I ran into trouble with custom collections the other day and wondered how to reliably find out what the bare minimum for a custom CollectionType is. The compiler will only help a bit: It’s conforming to neither CollectionType nor SequenceType. Now I know SequenceType requires the generate() method – but don’t let this fool you. CollectionType will provide that for you if you meet its requirements.
I just changed the blog archive to show all past articles reduced to the titles on one page. There still are annual collections of the old-style excerpts. I hope it helps to browse the stuff I published over the years. Still I find the sheer mass of topics unwieldly. That’s why I started to work on a curated and commented list of articles, like a table of contents. Will let you know when it’s ready.
I executed my plan from earlier this week to split TableFlip’s monolithic view model into sub-view models. The process wasn’t too complicated. The highlights: The current hierarchy of controllers in the view layer is as follows: The window doesn’t look too complicated and there truly are not that many view components involved, but still it’s quite some work to keep things well coordinated. The TableViewController file clocks in at about 400 lines of code although it mostly delegates stuff to other objects. There’s still room for improvement, but I have to see patterns, first. I even extracted NSTableViewaDataSource and NSTableViewDelegate into different objects months ago. Today I doubt this was a good idea in the first place. We’ll see.
The upcoming changes in TableFlip’s user experience made me ponder how I structured the app’s modules. The bottleneck I created in my app is simple: there’s one presenter which transforms the model into a view model; the presenter defines a protocol for the view it expects and passes the view model to the object that satisfies this contract.
They moved to a Flux-inspired “unidirectional flow” approach where state changes are performed in a Store (in the backend, if you will) and updates pushed to the user interface (the frontend). No ad-hoc view updates, no shortcuts. User events are emitted, handled by the store, and state updates affect the view. That’s it. So it’s always obvious how the user interface got into the state it’s in: all the details are plainly visible in the current state object.
Ben’s post is very deep and detailed. You’ll learn a ton from it:
architectural discussion: why “unidirection flow”, and why Flux?
setup of actions/events and the store type
basic state–view bindings via Reactive Cocoa
how testing stores (and views) is straightforward with this setup
I can’t wait for the next post in this series. Most of this easily applies to ReSwift, too, of course. And guess who just got inspired to refactor TableFlip so the model and view become even more loosely coupled?
Today I learned that a NSWindow’s field editor cannot trivially be set to “single line mode.” A field editor is a NSText subclass like NSTextView, but NSTextField is only a configurable widget that uses the field editor. How does the “single line mode” setting do what it does? I have no clue.
Façades are very important tools when I flesh-out the modules of an application. They turn out to be only the logical consequence of basic object-oriented programming principles, internal cohesion of objects namely, paired with decoupling of application modules (like “model” and “view”). Take a complex view that has many subviews. When you need to update a single piece of the user interface, how do you get there?
During my rather relaxed late evening workouts I catch up on podcasts now. Although I don’t enjoy listening to people talk (I prefer reading), this is a great source of inspiration and seems to be the premier way in which people share their experience.
Marco Arment and David Smith run Under the Radar. In episode 26, they talk about Marco’s deviations into AppKit—Mac app development. (Their shows are always under 30 minutes, so I suggest you give it a try.)
Marco’s app Quitter is available for free. He couldn’t put it into the Mac App Store because its main feature is to quit other apps. That doesn’t work with Sandboxing. So Marco had to release it directly.
I found a few things especially noteworthy:
Direct distribution means you have to worry about installation, updates, and payments yourself. It’s more work. So Marco made it free. (P.S.: I wrote a book on direct distribution.)
Marco was rather afraid to ship an update: maybe he didn’t test thoroughly and introduced a bug; it seemed to me he missed the safety net of app reviews.
Then again, shipping a bug fix update is fast and easy, too. It takes zero time to make an update available to customers.
The absence of app reviews in direct distribution is both frightening and liberating. I am afraid to ruin my customers’s lives with every Word Counter update I ship. It’s true, you can break things. But you can also make things right within the hour. You don’t have to wait for anybody else. (Even though iOSapp review times have improved a ton, from 7 to 2 days!)
I am astonished that both Marco and David have years of experience working with UIKit but didn’t ship a single Mac app in the meantime. Or do contract work back in the day. “iOS exclusive” sounds insane to me, but for them it has worked quite well!
What’s your experience? Do you remember your first contact with AppKit? Are you afraid to try? Comment, email, or tweet me your response!
Take optionals, for example. Optionals demarcate when something’s not there at all. When an optional is nil, this may signify something went wrong. That’s much more explicit than relying on a convention like returning -1 for failed requests. This is convenient and changes the game of handling edge cases completely. Because whenever you receive an optional, you have to deal with its two-fold nature. Checking for -1 can slip your mind. Forgetting to unwrap an optional is unlikely.
Animating and (de)activating Auto Layout constraints always leaves me puzzled at first. When on iOS, I try to not add constraints with explicit width/height values to train myself to rely on relative values. This helps me cover multiple screen sizes with the same settings.
I asked Lawrence MacFadyen on Twitter recently if his UIStackView animation wouldn’t work without an explicit width. Seems it does, so he published an updated post.
A beta tester of TableFlip suggested I make the table grow automatically when one navigates to the edge of the table and presses the arrow key in direction of the edge. I am conflicted about this proposal. On one hand, being able to grow the table easily is important. Spreadsheet applications usually present you with an infinite canvas. This is behavior people know (and maybe even expect).
Today was the second time during the development of TableFlip that I started to implement a new feature in the wrong way: starting with an explicit event type that is triggered by pressing a button in the user interface. This is a 1:1 mapping of user intent to an event that performs changes in the model. Next time I’ll start from another point of view instead to not rush too many minuscule changes until I hit a roadblock and hate myself. Here’s what went wrong.
I’ll send out a beta invitation to everybody on the TableFlip Newsletter this week. If you want to help me find quirks in the app and overall make it more usable, this is your chance!
Everyone who reports an issue will get a free license when the beta ends. Also, I’ll invite interested folks in batches, so you may not get your hands on the app this time but maybe in 2 weeks.
Check boxes in AppKit are realized with buttons. The API reads kind of weird, because the NSButton.state property does so many things, so here’s a simple subclass I do sometimes employ: Now it’s easy to use checkbox.isChecked = true. I’d even consider check() and uncheck() commands if I used this in many places to reduce the noise and clarify what’s going on further, maybe.
The location of a piece of code always matters. I was fiddling with the Charts library today and found out that if you set a chart’s data to nil, it renders some informative text by default. My data source doesn’t pass nil but an empty array around, though, so I had to convert empty arrays to nil to make use of this feature.
All 3 amazingly useful objc.io books are 30% off this week. Grab all three of them in a bundle and save even more.
If you use my link, I’ll even get a small kickback thanks to their affiliate program. I wholeheartedly recommend you take at least the time to read the samples. The team updates their ebooks regularly, and you’ll get a Swift 3.0 edition later this year, too.
This post is part of a series on getting NSSegmentedControl to work in your toolbars. Earlier this week I posted how to create a segmented toolbar item with 1 label for each segment. Now some options in TableFlip depend on context: without a selected cell, you cannot remove the selection, for example. So I disabled some segments and it looked alright:
Ever wondered how Apple Mail’s NSToolbar achieves the effect of individually labeled buttons shown in groups? Update 2018-11-23: I discovered a flaw in the target–action-mechanism of NSToolbarItems. They don’t fire if the label is hidden. This post’s approach is still valid enough, but is now part of a series of posts on the topic, with the 3rd one providing a fix:
Now that TableFlip is nearing completion, I want to share details of how I created this piece of software with you. Today, I’ll start with the bigger picture: the application architecture. Earlier this year, I got to know ReSwift from a talk by Benjamin Encz which I loved.
When parameter lists grow or two kinds of parameters seem to go together a lot, it’s time use the extract parameter object refactoring for greater good – then you can even specify sensible defaults.
This is a typical way to pass a set of options to an objects during initialization in a language like Swift. In languages like JavaScript or Ruby, dictionaries of key–value pairs can work just as well. Using dictionaries in Swift for this can be a pain, though.
Now Soroush wrote about a way that uses the Then microframework as a replacement for configuaration dictionaries. This way you don’t have to promote every property to the initializer’s list of parameters. Here’s a before and after, where you can see that without then you have to write a lot of repeating boilerplate:
That’s a Swift alternative to Ruby’s hash-based option initializers. There, the dictionary’s key is used as the setter’s name which is then invoked like so:
Understanding Uncle Bob’s Principles of Object-Oriented Design (which resulted in the SOLID principles) is super important to really grasp the use of design patterns (like MVVM) and architectural patterns (like VIPER). It’s like the grammar for crafting proper object-oriented software.
And now here’s the good news: there is a Swift playground (and Markdown file to read online) that illustrates all the principles by Uncle Bob: The Principles of OOD in Swift 2.2
Check it out, take notes, and keep the principles close to your heart. They may save your life someday.
Today I learned that you can cancel a delayed dispatch_block_t with the new dispatch_block_cancel (available since OS X 10.10/iOS8.0). Thanks Matt for the post – here’s a Swift example:
letwork=dispatch_block_create(0){print("Hello!")}# Execute after 10sletdelayTime=dispatch_time(DISPATCH_TIME_NOW,Int64(10*Double(NSEC_PER_SEC)))dispatch_after(delayTime,dispatch_get_main_queue(),work)dispatch_block_cancel(work)# Will never print "Hello!"
Note: canceling doesn’t work if the block is being executed.
If I knew that this API existed, I might not have used the very cumbersome approach from below in Move!.
Super-Weird Legacy Version of a Cancelable Delayed Block
For historic purposes, here’s an adaptation of the cancelable dispatch block you may find on the internet that I once have adapted for Swift:
typealiasCancelableDispatchBlock=(cancel:Bool)->Voidfuncdispatch(cancelableBlockblock:dispatch_block_t,atDatedate:NSDate)->CancelableDispatchBlock?{// Use two pointers for the same block handle to make// the block reference itself.varcancelableBlock:CancelableDispatchBlock?=nilletdelayBlock:CancelableDispatchBlock={cancelinif!cancel{dispatch_async(dispatch_get_main_queue(),block)}cancelableBlock=nil}cancelableBlock=delayBlockletinterval=Int64(date.timeIntervalSinceNow)letdelay=interval*Int64(NSEC_PER_SEC)dispatch_after(dispatch_walltime(nil,delay),dispatch_get_main_queue()){guardletcancelableBlock=cancelableBlockelse{return}cancelableBlock(cancel:false)}returncancelableBlock}funccancelBlock(block:CancelableDispatchBlock?){guardletblock=blockelse{return}block(cancel:true)}
The trick is this: the delayed block delayBlock: CancelableDispatchBlock captures its context where a reference to cancelableBlock is included – but not set yet. Then you make the reference point to the delayBlock itself.
The actual canceling is a fake, though. The block is still called. It aborts early if the cancel parameter is true, though.
I was confused about the term “to hustle” for quite a while, probably because I’m non-native. I found it in various books about startups and solopreneurship, and from the context I deduced it might have something to do with marketing. Shawn Blanc was the first to make sense of this: it usually means to do a lot of work. To break a sweat working towards your goals.
That’s why I’d like to add a few items to Shawn’s list:
Start eating real food and stop swallowing garbage.
Give yourself the chance to detox; remove everything that may affect your brain for a while – porn, social media, coffee, tea, sugar.
Exercise and move every day. Walk for 30 mins if you can’t muster the strength for anything else.
A lot of people I met in tech are interested in body-hacking, life-hacking, and the like. Optimizing sleep for example. Or ditching processed food because, you know, better focus and stuff. This is the search for technical solutions (stuff you set up once and then do it like an automaton) when the underlying challenges are those a corporeal life itself presents.
The fundamentals are the same no matter if you want to be a healthy over-performer in tech or a professional athlete: push your limits and swing the pendulum back and forth from stress to relaxation: Fast and eat; exercise and rest; work and meditate. Your performance is not only about how quick you can throw together a working app. It’s also about how long you can excel at what you do before wearing out.
So take care, don’t overwork, don’t underwork, and push yourself on all frontiers in life at once.
Editing NSTableView cells with a double-click is the default behavior. I wrote about how to make the column header cells editable already. But in order to figure out how to end an active editing session when the user hits ⌘S to save the document, I grew more and more disappointed by the day.
In “Creating a Cheap Protocol-Oriented Copy of SequenceType (with a Twist!)” I created my own indexedEnumerate() to return a special kind of enumeration: instead of a tuple of (Int, Element), I wanted to have a tuple of (Index, Element), where Index was a UInt starting at 1. A custom CollectionType can have a different type of index than Int, so I was quite disappointed that the default enumerate() simply returns a sequence with a counter for the elements at first.
As you may know, I’m totally immersed in getting TableFlip ready to ship. By some random circumstance, I recently stumbled upon Paul Jarvis’s getting started post about online businesses.
I already read the hip books about startups: Startup Owner’s Manual (meh), Lean Startup (ok), $100 Startup (inspiring), Lean Entrepreneur (meh), Running Lean (good one) – you name it. I still found Paul’s action-oriented collection valuable to get started. It’s the little first steps that matter which I tend to forget sometimes.
With TableFlip, I wanted to know if a visual Markdown table editor would be something people liked. So I put together a landing page for it and asked around. By sheer luck I managed to get 300 subscribers in about a month. I’m excited to show them the first test build. – Sadly, I cannot say that I have any fancy techniques to share. Being connected to other people that love to re-tweet your announcements or post links to their blogs helps a lot. Nothing else has had any effect for me, like, ever.
I posted a link to Joa Allen’s recommendation to get in touch with truly loyal people with a free app MVP that solves 80% of their problems already.
The bottom line of all this is: Just. Do. It. You need feedback, so get something out as quickly as possible. Then you may be able to fend off starvation in the long run.
Brent Simmons brings up valid concerns about the current state of Swift: you cannot write any software using Cocoa (AppKit for Mac or UIKit for iOS)
with Swift without somehow interfacing with the Objective-C runtime. That’s kind of weird , don’t you think?
This is super relevant if you’re on your own or even starting to pursue a career in programming. It doesn’t matter how much time you spend. The intensity of focus counts. Call it myelin or what else you will: only deliberate practice will make you better. “Deliberate” means it’s challenging. And that you pay attention to the challenge. That you elaborate why you failed. All of this takes a bit of extra time, but the result is so much better than simply dashing through and hoping for the best.
It’s easy to leave the StackOverflow copy & paste “”coders”” behind.
I know for sure that I need to pick up a book on Core Image and Core Animation sometime, soon, because I have no clue how to use these frameworks. It’s not a blind spot. It’s a known weakness. Doing a challenging project in these areas will catapult my skill further towards mastering the craft.
Here’s my invitation to you: take a minute to evaluate where you stand. What does make you uncomfortable? Take note of that. Make these things projects. Then do or plan some research for each to find out how to tackle these known unknowns. Then execute.
In a recent usability post of Raluca Budiu, the common mobile app pattern of sliding menus is criticized: when the menu button is at the left edge and the content slides away to the right, then hiding the menu again requires the user to move her hand, and reading the menu items requires her to move her finger out of the way. With fat fingers, this is even more of a problem.
I’m taking this week off to finish TableFlip for a testing round (for which you still can sign up!) and I decided to run a little promotion and give away Calendar Paste 3 for iPhone and iPad for free. The promotion runs until Sunday (May 15th), so hurry and tell your friends!
I use nanoc as my static site creator for this blog. It’s written in Ruby, my favorite scripting language. And so I use a Rakefile to automate most things, like generating a fresh copy of the site and deploying it to my server. Only last week did I find out how to make Rake not continue when a part of its tasks failed. Most of the stuff I use is wrappers around shell commands with a few system notifications sprinkled in. $? does capture the latest shell call’s return value (kudos dnsimple.com):
Daniel Jalkut of MarsEdit fame is slowly getting up to speed with Swift. I have a few Swift-only projects already (Move!, TableFlip and secret in-progress ones). On top of that, every feature I add to the Word Counter is a Swift module, too. The main code of the Word Counter is still in Objective-C, though.
Integrating new types to the project using Swift is awkward. There’re things you can only use in one direction. Most if not all Objective-C code can be made available for Swift and works great. The other way around, not so much. Also, Objective-C imports from the -Swift.h file won’t be available in Swift-based test targets. So you’ll have to isolate these even further, create wrappers, or whatever. Porting a class to Swift can work, but the side effects on testing make it harder.
I like Daniel’s advice to write your unit tests in Swift if you’re still not certain if you should make the switch to this new and volative language. It’s a good idea to get your feet wet.
Considering the problems I ran into with the Word Counter, though, I wouldn’t know how, honestly.
Took me a while to not only figure it out but actually fix that Emojis are encoded in a special way using UTF-8.
If things are well on your side, you’ll see a “thinking” emoji here: 🤔
I wanted to be able to enter these in text files, read them in, display them, and save the contents in a way that they are visible in the text file again. Sounds trivial, but everydouble-encoding trick I found on the web resulted in escaping the unicode char codes (\ud83e etc.)
Reading stuff in worked with basic NSUTF8StringEncoding, but writing not so much. Turns out the last byte of a line was stripped for some reasen. Turns out all of this was my fault. Thanks to playgrounds for giving me feedback about matching encoded data.
Emoji seem to take 7 bytes when you look at the UTF8-encoded NSData representation. In my tests, it seemed that when an emoji was the last character in a line things went broke. I had to enter characters after it to work. These characters wouldn’t be stored, but at least the emoji would be visible.
My fault was that I was padding strings to have a certain length like so:
I was not using NSString but native Swift Strings, so I expected things to go well. But they didn’t. I don’t know for sure why this method from foundation wreaks havoc with strings containing emoji, but it sure did. At first, the fact that 1 emoji character consists of 2 UTF8-encoded unicode values at once resultet in truncating the line. Even when I increased the padding to 2x the visible character count, the last visible character was lost in the end.
I found a cheat: calculate the byte size of the given string and fill up manually:
Works like a charm and doesn’t use data. TableFlip beta testers will probably find more edge cases, but at least the app doesn’t crash or ruin your files.
During the last weeks, I tried to use map() even when the conversion wasn’t straightforward to learn how it affects reading code. I found that some applications of map() were dumb while I liked how others turned out to read. The functional programming paradigm is about writing code in a declarative way, which has its benefits.
Vikas Thakur is an INTP personality type – very common among programmers I’d say. He wasn’t good at micro managing himself until he found the tools to prevent bad habits (casually browsing the web) and track his progress to gather intelligence about how he works. He found 5 tools and 5 habits to do the trick (among them my Word Counter).
If you suffer from unwillingly checking your Twitter feed, have a look at his tips. There may be something for you, too. My flat mate un-learned wasting time on YouTube and Facebook with a tool last year. I recommend you give it a try and see for yourself if that sounds like you.
I love guard statements. It helps make code much more readable and keep methods un-intended.
I feel less amorous about guard-case and if-case matching, though:
ifcase.Fruit=foodType{...}
This reads an awful lot like Yoda conditions where you place the constant portion on the left side. This isn’t even a typical boolean test (which would use the equality operator ==) but a failable assignment (=). I can force myself to read and write it this way, but it always feels backward to me. It took me quite a while to memorize this, which I found surprising, as it was comparatively easy to learn Swift in the first place.
Apart from the guard-case portion, the example contains your standard guard-let unwrapping. The else clause is special though, and I didn’t know this would work:
guardsomeConditionelse{returnprint("a problem")}
When the function is of return type Void, you can return a call to another void function. This is shorter than splitting these two instructions on two lines, but it’s too clever for every reader to understand. print("a problem"); return is just as compact, as Terhechte points out.
When you work with view-based NSTableViews, cells by default contain a NSTextField. You can edit cell contents with them. The headers are not designed to be edited, though. You don’t have much control over the column headings from Interface Builder. So you have to build this yourself.
Daniel Steinberg’s presentation “Ready for the Future: Writing Better Swift” teaches us a lot about readable code. He refactors a calculation into many functions with very specific responsibilities. The resulting functions are super slim.
Apart from the » operator which merely changes foo.map(bar) to foo » bar, the functions are very small, easy to read. This reminds me of the result of 3/4 of Sandi Metz’s arbitrary rules for writing Ruby code:
Classes must be shorter than 100 lines
Methods must be shorter than 5 lines
Always pass less than 4 parameters into a method
Of course the result is a lot of functions for a rather simple algorithm. But it works well because it is easy to read in the long term. Even newcomers can grasp what’s going on without knowing much about the language or typical Cocoa-programmer conventions.
Bonus: you can unit test each function to check if the parts of the overall algorithm works as expected.
A refactoring in a side project requires finding places where a property we want to get rid of is currently used. Finding the property name in the project will not work very well because other types use a similar named property. We only want to remove Banana.size, but not Jeans.size.
Currying is a very useful and interesting thing. It means that you can write functions in parts. If you don’t provide all parts at once, you won’t get the “real” result but a closure that accepts the missing parameters. Like this, with spacing added to reveal how the nested closure maps to the chain of return types:
Although I knew there’s a “cookbook” book series, I haven’t read any of these before I read Erica Sadun’s The Swift Developer’s Handbook. The code listings are called “recipes”, and most of the time rightly so: I bet I copied about a dozen of the recipes into my own handy code snippet index to extend Swift’s capabilities with super useful things like safe Array indexes.
That’s a recent question from the comments put in my own words. A view model that encapsulates the display state sounds promising at first. But when you don’t have a simple view that displays one thing, how do you model that in code? How do you model a sequence of view controllers, for example a more complex checkout process?
I’d make that not private but internal and group these in a struct to separate them from other Selector stuff:
extensionSelector{// One for each view module ...structBanana{staticletchangeSizeTapped=#selector(BananaViewController.changeSizeTapped(_:))}structPotato{staticletpeelSelected=#selector(PotatoViewController.peelSelected(_:))}}// ...button.addTarget(self,action:.Potato.peelSelected,forControlEvents:.TouchUpInside)
I have uploaded updated versions of all my books today so you can enjoy the latest Swift 2.2 syntax. If you bought from my store, you can download the latest version using the link you received in your order confirmation mail. Lost it? No problem, I’ll re-send it to you if you get in touch via e-mail.
Something short and sweet I want to share with you because I love how it reads: restoringSelection is a function that takes a block and performs whatever the block does while restoring the current selection in a table view (here: NSTableView). Here’s the implementation. The resulting code from above reads so much nicer than querying selection() first and restoring it afterwards. It communicates very clearly that some state from before will be preserved (or restored).
They discuss general project architecture, using tools to generate module files, and how passing data from one Wireframe to another works in their app.
I haven’t used VIPER in an iOS app, yet, but I used the concept in the Word Counter. There, nothing’s disposed after setup, so I have all Wireframes and their components setup once upon launch. The authors use Wireframes as factories for view controllers.
A Note about Syncing Changes: Where to Handle Sync Events
Further down, under “How to deal with listening changes from backend?”, the authors show how synchronization changes take effect.
The SynchronizerService merges changes into the Core Data stack,
the Core Data Stack sends a notification,
the Interactor receives the notification,
and changes are then pushed through the Presenter to the View.
This works, but I find the decision to be weird. Now the Interactor prepares data when requested and pushes changes upon synchronization events.
Usually, the Presenter is created in such a way that it both presents data to the view and handles events from the view. You can split this into two objects, let’s say Presenter and EventHandler. Then it becomes clear that the EventHandler can deal with events both from UI interaction and from syncing. It’s the best fit to translate any event into a command for the Interactor so it does its job.
I thought it’d be straigthforward and simple to make a NSMenuItem from the main menu implement a toggle – be it a checkmark or switching “Show X” with “Hide X” conditionally. Turns out that’s not quite as simple as I had hoped. Cocoa bindings would work but make things complicated. Most stuff on the web uses view tags to find items in menus. That’s not my favorite solution for anything. menuNeedsUpdate wasn’t called when I had hoped it would, either. So I tried a few different setups and settled with a boring and verbose way to switch “Show X” and “Hide X” depending on a boolean flag the current NSDocument window exposes.
Krzysztof Zabłocki (@merowing_) shared his approach to “Behaviors” in a Slack channel the other day. These are functional extensions to view controllers that you can wire via Interface Builder (!) to inject behavior into a scene.
When you implement CollectionType or SequenceType in custom types, you get a lot for free with just a few steps, like being able to use map on the collection. Any CollectionType implementation comes with enumerate() which, when you iterate over the result, wraps each element of the collection in a tuple with its index:
I’d like to officially announce my next project: TableFlip. Open any Markdown file with TableFlip and you can visually edit the tabular data included. Save and the Markdown file is updated. It’s that simple. It’s also Markdown-aware simple table data editing app. It’s fast and lean and pretty. No need to fire up monstrosities like Excel for Mac or even Apple’s own Numbers to edit simple data that naturally fits the 2D-arrangement of a table.
This is mostly a reminder for my future self: It doesn’t suffice to create a TXT file and add it to the target in the file inspector (⌘⌥1) to be able to read it as part of the bundle. You also have to drag it into the “Copy Bundle Resource” build phase of the target so it get, well, bundled into the product. (In my case, it was the test target.)
Create an empty file or add an existing file to the target’s group in Xcode and make it part of the proper target,
drag it into “Copy Bundle Resources” build phase,
load it using NSBundle(forClass: TheTestCase.self).URLForResource("filename", withExtension: "txt").
Storing PLIST or JSON files for structured data works just as well. I happen to require plain text flavors most of the time and always wonder why the loading fails for a couple of minutes.
I’m back from my vacation and very deep into programmin already. Before I left, my subconscious mind brought up the notion of a Lens (functional programming) while I was modelling tabular data in Swift and I think this is a very cool approach to keep value types clean and easy to test. I use lenses in my current project to provide a specialized interface to operate with the table. The lenses provide access to column and row iterators, independent of the table’s underlying data structure. This way the table doesn’t have to worry about all this stuff.
I’ll be on vacation for the next week. Maybe I cannot hold my breath and publish a post nonetheless, but I’ll try not to. Either way, for the next week everything from my store is 20% off so you can have fun while I’m away.
Apps
The Word Counter to increase writing productivity,
Move! to not die from sitting in front of your computer.
Just found this today in a Slack channel. It seems we can actually reference and re-use Xib files by overriding awakeFromCoder!
If we are loading from placeholder view, we create a real view and then we transfer some common properties from it and all it’s subviews, then we just return that instance in place of placeholder, otherwise we just return normal view (This method is implemented on NSObject so we can call super, but this still should be done with method swizzling instead of category smashing).
When the kNibReferencingTag is set, the current instance (self) is treated as a prototype. From that prototype we transfer common properties to the realView which is properly loaded from a Nib. That means it doesn’t go the kNibReferencingTag path but the usual path, deferring to super.
The sample app contains SomeView with its own Xib that should be reused.
In the app’s Xib, we have a scene that uses it as follows:
I know, Xib files aren’t the best to read. Here’s what it boils down to:
Create a scene using a view controller of type ViewController.
In its main view place 3 subviews …
of type SomeView,
all with the tag 616,
and a few standard color properties – apparently all set to white. It doesn’t matter anyway since the SomeView.xib will dictate what it really looks like.
Unlike @IBDesignable components, you won’t have any live preview in Interface Builder. Just empty placeholder boxes.
I read Karl Bowden’s Featherweight Router TL;DR and kind of like how routes are handled. The setup looks complicated, though:
letsomeRouter=Router(aDelegate).route("animal",children:[Router(aDelegate).route("animal/mammal",children:[Router(aDelegate).route("animal/mammal/cow"),Router(aDelegate).route("animal/mammal/pig"),]),Router(aDelegate).route("animal/fish",children:[Router(aDelegate).route("animal/fish/salmon"),Router(aDelegate).route("animal/fish/trout"),]),])// Using regex's for matchingletsomeRouter=Router(aDelegate).route("animal",children:[Router(aDelegate).route("animal/\\w+",children:[Router(aDelegate).route("animal/\\w+/\\w+")])])
Child routers carry the path component of the parent with them. Also, this is very verbose. I imagine a more terse version, like:
// Assuming `aDelegate` is used for all of them and passed along,// let's omit it during setup of sub-routes:letrouter=Router(aDelegate){routerrouter.route("animal"){routerinrouter.route("mammal"){routerinrouter.route("cow")router.route("pig")}}}
Or let’s say some part is variable, like viewing a user profile:
I have added a /now page to this site which shows what I’m currently doing, thinking about, or whatever. I like the idea. Kudos to Matt Gemmell for showing his.
Did you know you can import only parts of a module? Found this in the Swiftz sample codes:
letxs=[1,2,0,3,4]importprotocolSwiftz.SemigroupimportfuncSwiftz.sconcatimportstructSwiftz.Min//: The least element of a list can be had with the Min Semigroup.letsmallestElement=sconcat(Min(2),t:xs.map{Min($0)}).value()// 0
import protocol or even import func were very new to me. Handy!
Maybe my Google-fu is lacking or there’s not much about this on the web: how do you separate handling local notifications when the app is in foreground from when it is in background? After all you’ll probably want to show a specific view when the user taps a notification badge. Here’s one way to do it.
Rethrows saves us a lot of duplicate code. Look at my naive approach to write an iterator in Swift 1 from last year which I later extended for throwing with Swift 2:
The rethrows keyword makes the method a throwing one depending on the closure you pass in. Only if the closure throws each will throw, too. The compiler will know what happens – just like generic functions are write-once, use-many-times.
Of course I later found out that Swift 2 came with forEach already bundled in. So there’s no use in this anymore except for this very illustrative blog post to remember that throws/rethrows is different from throws/throws.
Jordan Morgan of Buffer wrote about MVC on iOS. The idea is simple. Don’t mix view logic into the model; don’t control all view minutiae from the controller; don’t make intelligent views that fetch stuff from servers or similar.
His comparison of good VS bad execution of these principles is worth the read!
I shared that picture the other day and though, well, why not share an updated picture of my workplace here, too? Since 2013, some things have changed. This is my equipment:
How do you test NSURLSession properly? After all, using it in tests directly will hit the servers; that’s not what you want to do 1000s of times per day. Even if you use a localhost based server replacement the tests will be slower and potentially error-prone as the server replacement may not be 100% accurate. Anyway – there’s a popular series of posts about that topic. There, you’ll learn how to mock NSURLSession in your tests. I think the advice is good to move on quickly, but it only shifts the problem slightly out of sight. There are better alternatives.
When DevMate launched, I dabbled with the backend a bit and I really liked it. They use FastSpring for the store and enabling DevMate to integrate into your FastSpring account is very simple.
It seemed to be kind of expensive, though. Since then, they changed the pricing model once or twice and made the platform more attractive to upcoming indies and teams with a lower budget. Now it’s free.
Their SDK seems to provide easy integration. I think I’ll check it out with my next app to tell you more about the details. I just hope they’re doing well – lowering the price could just as well mean that they try to attract more devs because it doesn’t pay off to run the platform at the moment. (I think I’ll just ask them to be sure.)
Rogue Amoeba develop lots of popular software. Now Piezo 1.5 exits the Mac App Store.
While the App Store has many shortcomings, it’s the onerous rules and restrictions Apple has for selling through the Mac App Store which pose the biggest problem. The type of software we make is precluded from being sold through the store, particularly now that sandboxing is a requirement, and Apple has shown no signs of relaxing those restrictions. Fortunately, unlike iOS, the Mac platform is still open. We’re able to distribute and sell direct to our customers, right from our site. We’ve got almost 15 years of experience and success doing just that, and we have no plans to stop.
Their apps that work on the App Store stay there.
Shameless self promotion: Are you worried about the recent trend of abandoning the MAS? I wrote a book about publishing apps outside the Mac App Store. There’s nothing you have to fear. It’s fun.
After reading Sam’s post, I discussed a code snippet with him. Shortsightedly, I told him I didn’t like the following snippet because it controls project instead of doing the object its own job: It made me wonder if we can do better, though, with standard OOP practice. My proposal was a simple toggle method:
Sam Ritchie wrote “Building a Unidirectional Data Flow app with Realm” the other day. I haven’t worked with Realm before, but the state propagation seems super interesting now that I dabble with ReSwift from time to time. His post excited me to try out Realm, soon.
Imagine a complex view with many sub components. This is more common in Mac apps where a window contains multiple panes, lists, graphs, whatever. How do you react to interactions 5 levels deep? Let’s say you avoid massive view controllers which do everything on their own and want to encapsulate event handling outside the view hierarchy – what should you do?
In a recent post, I wasn’t too fond of inline helper functions. Similar things can be accomplished with blocks instead of functions, as both are closures that capture their contexts. Blocks don’t even have to have a name. Inner functions and blocks share the same semantics. Found in Little Bites of Cocoa #180:
“Using a private function means having a hardwired link to an anonymous collaborator. Over time, this will slowly hurt more.” (@jbrains) I was thinking about this the other day when I wrote tests for a presenter. It receives a date, formats it, and makes the view update a label with the result. Simple. (The real thing actually does a bit more, but that doesn’t matter much.)
Sure, now there’s a subclass of NSButton that doesn’t do much and will not be reused in the app. But the intent of delegating DateRangeData to the sub-components is clearer.
Clean and maintainable code will help you see what’s going on when you read the code. title = dateRange.range doesn’t convey everything showDateRange(dateRange) does.
Xcode now offers two kinds of tests natively. You don’t have to rely on 3rd party JavaScript libraries anymore to automate the iOS simulator and assert view conditions. So with the advent of native UI Automation tests, can you rely on them to verify your app works? Here’s the two sides of the 1 criterion you’ll ever need to find out:
Matt Galagher is back writing at Cocoa with Love. His goal is maintainability, which is the greatest of all, I think. It’s easy to copy code samples together to create an app, bur it’s hard to create a product you can keep alive and make better over years. In that vein, his first article, “Partial functions in Swift, Part 1: Avoidance”, includes a lot of details why partial functions will hurt you. This is a great topic. Read his post for the basic set theory involved.
In Swift, you can define functions within functions. These are often referred to as helpers.Rob Napier brought this to my attention recently. Like any other closure, helper functions capture variables from their surrounding context if needed. This way you don’t have to pass them along as parameters.
As I’m exploring the use of block based API, which means to assign closures or functions handles to properties or pass them around as parameters to other functions, I found a few benefits and drawbacks in comparison to protocol-based object interactions. Here’s a breakdown of criteria for blocks and delegates.
My e-book about creating and selling apps for Mac without the Mac App Store is now available on amazon.com if you prefer a print edition!
Why does print cost less?
The digital edition will be updated regularly with the latest Swift syntax. Further editions and major revisions are free for customers, too. I can’t do that with a print edition on your bookshelf, obviously. That’s why.
It feels weird, I know, because paper costs money and print book feel more precious. I’m making about 50% less with each sale, so there’s quite some cost involved printing the book. The feeling of physical good in your hand is part of the perceived value, and everyone would tell me I should factor that in, but I’m a bad businessman. It’s the right thing to do. Why should you pay more for something with less long-term value only because my costs are higher?
My humble work break timer Move! has been reviewed by Catalin Chelariu over at Softpedia. I didn’t find any Twitter account or anything to thank him, so here it is: thanks for the review!
Catalin had one wish, though:
However, it would be great if there was an option to postpone the break, as it simply may not be possible to interrupt your current activity in certain situations.
I have to say that I totally understand where this comes from – I used AntiRSI and similar software in the past which offered a postpone button. It was useful. But it was also opening the doors to hell.
So I’m sorry to say that if your job demands you to sit down for whatever reason, then Move! isn’t going to be your app. It’s made for everyone, because everyone needs to get up more often. 30mins really isn’t that bad. Some corporate environments don’t care about your health, though, so you may need to increase the work duration.
What I wish for this app myself is the ability to start a break early, i.e. when I have to leave the desk for a while. Or a setting for work hours, so that it doesn’t interfere me watching a movie after 9 p.m., for example.
I love Mind Node for Mac. Now they added tasks. I think that’s weird, but I can see how this is useful for some people. You can devise plans and operate on them without having to export the outline to a task management application, for example.
It looks great and maybe I can use this for a little side-project which doesn’t really need traditional taks (which I put into OmniFocus) but could benefit from checking off items nevertheless.
Krzysztof Zabłocki wrote about the concept of “Flow Controllers”. Assimilating the concept, I imagine they’re similar to the bootstrappers I use during app launch, only Krzysztof says there’s just one initial flow controller after launch while the others are used when transitions need to take place.
Separating state from transitions is a higher-level goal of architecting apps – and is especially amiss in UIViewController-centered iOS apps. “Flow Controllers” encapsulate the change or transition. This includes setting up the view controller according to the presentation needs:
Configuring view controller for specific context - e.g. different configuration for an Image Picker shown from application Create Post screen and different when changing user avatar
Listening to important events on each ViewController and using that to coordinate flow between them.
Providing view controller with objects it needs to fulfill it’s role, thus removing any need for singletons in VC’s
The singleton Krzysztof talks about is the usual way app state is modelled.
Here’s a slightly modified example to illustrate how a flow controller manages transitions between view controller scenes with configureProgramsViewController, configureCreateProgramViewController, or similar:
funcconfigureProgramsViewController(viewController:ProgramsViewController,navigationController:UINavigationController){viewController.state=state// Add button action callback to show the next sceneviewController.addProgram={[weakself]_inguardletstrongSelf=selfelse{return}letcreateVC=// recreate a view controller, e.g. from a StoryboardstrongSelf.configureCreateProgramViewController(createVC,navigationController:navigationController)navigationController.pushViewController(createVC,animated:true)}}
The flow controller owns the state here and takes care of pushing view controllers onto the navigation stack. This will not work with segues. It’s a replacement for them.
Benjamin Encz’s presentation “Unidirectional Data Flow in Swift” about ReSwift features global app state: there’s one AppState type that acts as the facade to model and navigation state which is the single point of truth of every state in the app. This is a game changer when you suffer from massive view controller syndrome. In this post, I’d like to show you how he envisions the state of an app and what a next step could look like.
I think I found something better than closures to handle events. Instead of dispatching closures that are themselves the changes that should be performed, simply declare the change.
enumAction{caseResizeBanana(BananaId,Size)}
Now you need some kind of action handler, which Benjamin Encz calls “reducer” in his presentation “Unidirectional Data Flow in Swift”. Think of a list of reducers as a Chain of Responsibility only without the final consummation of the action. It is passed throughout the whole responder chain. Why reducer? Because they operate similar to the reduce function. The end result will be the combined result of all reducer’s mutations.
This is cool, because no component needs to know what such an action entails – none except the appropriate reducers.
If closures were great because where you type them you can see what is going on (more like “how” in my opinion), a simple action enum is even simpler, telling what should happen.
Works well with CQRS, I imagine. Will have to write a demo app using CQRS sometime to validate.
The current project is called ReSwift and code is available on GitHub.
In a post about the Swift reflection API, I found the conversion code from a Bookmark struct to a Core Data object interesting. Let’s call the latter ManagedBookmark.
What puzzles me: which object should be responsible for the adaptation from one to the other?
Bookmark converts itself to a NSManagedObject using a NSManagedObjectContext you also have to pass in. (That’s what Benedikt did in his post.)
ManagedBookmark provides an initializer or other factory taking in a Bookmark and, as always with managed objects, a NSManagedObjectContext.
Option 2 is pretty clear. Using Bookmarks public interface, the managed object will set its attributes. This requires a NSManagedObject subclass wheras option 1 can work with a dictionary of values.
My main worry is that in option 1 Bookmark, a value type of the application, has to have knowledge about Core Data. Usually we’d fare better if we separate Core Data from our own model.
With extensions in Swift (and categories in Objective-C) we have the power to add new behavior to existing types in other locations. Does this help?
Extending a type in a different file hides that detail at first sight – but the extension, when it’s not private, is available in the rest of the code base, too. It just appears as if you put the code in the type definition itself.
Now if Bookmark is included in a “Bookmarking” module you import, an extension can add behavior without mixing Core Data visibly into the model layer. The Bookmarking module will not get altered when you extend one of its types in the client code.
I like organizing Swift code in modules because the boundaries are very strict. You cannot cheat yourself into mixing responsibilities and blurring boundaries that easily.
The Word Counter is my biggest software project so far, and it’s growing. To add features, I discovered the use of Swift modules with joy. I can write code for all levels of the new feature in isolation in a new project that compiles fast. Later I plug the resulting project and module into the Word Counter, et voilà: feature finished.
Rui Peres proposes to make UITableViewCell view models the topmost model data. Traditionally, Cocoa developers stored something in arrays that corresponded to the indexPath of a cell. In principle, this qualifies as “model” data already, but it’s not yet a view model. In practice, it can even be something different than a view model entirely – and make your view controllers slimmer!
Reflecting on a recent change of the Word Counter’s file monitoring module, I think I re-discovered a commonly advised pattern in my code: to separate state from state changes. There’s an object that knows how to handle files based on extension: plain text files’s words are counted differently than Word or Scrivener files. Call it Registry. Previously, this was set up once and didn’t change. Now I wanted to make this configurable so users can add custom plain text extensions. This means changing that object’s state.
I don’t like the way I tend to create view controller event handlers. They are almost always just a sink for methods which have nothing in common conceptually but are tied together because of the view’s capabilities. So I began experimenting. Closures can encapsulate changes. This works well with callbacks for Repositories which fetch entities from your data store. Instead of returning them, you can pass them forward:
I code on a late 2011 Mac Mini with 8 GBRAM and a 256 GBSSD. This machine is a ton faster than my old MacBook Air was. Compilation still takes time, but it seems that iRamDisk helps a bit.
Lately I wondered if I could cut down the 30s compilation time (3mins with a clean build folder) if I had a Mac Pro, or MacBook Pro, or iMac, or whatever next tier device. Faster cores, more cores, doesn’t matter. But buying a Mac for $3k is out of question at the moment. So I’ve been looking for other tricks.
The only thing that’s faster than a SSD is RAM. That’s when I found the app iRamDisk. It offers an option to move the derived data folder to a virtual disk in RAM. It seems I can reduce the clean build time from 3mins to 2mins with that. Xcode needs about 1.5GB derived data for the Word Counter – at least that’s how big I had to make the RAM disk to not get filled quickly. The overall memory pressure is a bit higher, the Mac is using swap more, but compilation becomes faster at last.
There’s a downside, too: after every reboot the RAM disk is empty, so Xcode has to index the project again and compile fresh at least once a day. Depending on your usage this can be annoying or not be a problem at all.
I did know that universal links help integrating web content and native app scenes: regular web links may show the content in the browser on most devices but magically open the content within your native app when it’s installed. The prime example I knew was IMDB’s movie database, but it obviously works for recipes as well.
The source code isn’t prominently linked anywhere. I went to the CocoaPods spec and downloaded the source tar file (at the bottom of the spec).
The “source” contains a framework which publishes two classes, GSDAppIndexing and GSDDeepLink. There’s a sample iOS app on GitHub by Google as well.
You use GSDAppIndexing to register your app with its iTunes ID – but the sample application doesn’t do that at all. The docs indicate this is needed to expose content to crawlers, though. The sample app does handle links in AppDelegate:
Instead of routing, it only stores the link for display purposes. There you see what GSDDeepLink is good for: extracting the real deep links from the Google search deep link call.
What’s it good for?
It will show deep links (perhaps more prominently?) when you browse Google on Mobile Safari. In other words, regular visitors with a Mac probably won’t notice any difference.
The following is the expected URL scheme according to the GSDDeepLink.h file, split up into multiple lines for reading convenience:
Annotation:
ios-app://544007664/vnd.youtube/www.youtube.com/watch?v=aISUYHTkTOU
Original Deeplink:
vnd.youtube://www.youtube.com/watch?v=aISUYHTkTOU
Callback URL:
googleapp://
Final URL:
gsd-vnd.youtube://544007664/
?google-deep-link=vnd.youtube%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DaISUYHTkTOU
&google-callback-url=googleapp%3A%2F%2F
&google-min-sdk-version=1.0.0
The following is just totally made up: I assume the GSDDeepLink helper actually sends back some statistics to Google. Otherwise I wouldn’t know what the wrapped URL would be good for at all. (Suggestions welcome.) GSDDeepLink does overlay the status bar for a short while according to the header documentation so users may return to the search results.
I still don’t get the benefit from using Google’s framework in my projects. When users reach my website via Google, the native app is expected to open automatically anyway. So there’s only the formatting of app-related search results left as a benefit as screenshots indicate.