A technical blog written by Cory, an indie app developer.
Don't wanna be here? Send us removal request.
Text
STM32F401CCU6 Blackpill DFU recovery
If you should happen to "brick" your blackpill dev board in such a way that it doesn't respond to your STLINK v2 debugger anymore, you can recover it by flashing a known-good program via USB Device Firmware Update (DFU) mode.
Every stm32f4 has a built-in DFU bootloader in ROM. To boot into DFU mode, connect the board to your computer via USB (directly, do not use an st-link debugger) hold down the BOOT0 button, and then briefly press the NRST button.
Once in DFU mode, we can flash a known-good program onto it to reset it to a usable-state. I used https://github.com/a5021/STM32F401CCU6-Blink-Bare-Metal/ (`cd ide; make`).
Before we can flash that program, we need to convert the ELF executable into a stm32 proprietary DfuSe format. To do that, I used:
https://github.com/majbthrd/elf2dfuse
cd elf2dfuse
make
./elf2dfuse ../STM32F401CCU6-Blink-Bare-Metal/ide/build/STM32F401CCU6-Blink-Bare-Metal.elf ./out.hex
Now that we have out.hex a DfuSe format binary known-good program for our microcontroller, we just need to flash it over to the board. To flash it, I used dfu-util (`brew install dfu-util`):
dfu-util -a "@Internal Flash /0x08000000/04*016Kg,01*064Kg,01*128Kg" -D ./out.hex
To figure out the exact "@Internal Flash" string to use for that command, run `dfu-util --list` to list the possible dfu targets. They vary slightly between boards (one board I have ended in 03*128Kg, the other 01*128Kg).
That's it. Tap the NRST button to reboot out of DFU mode, and you should see a quick repeating pattern of blinks as the Blink-Bare-Metal program runs.
1 note
·
View note
Link
My sixth Swift Package Manager module, Matches is a wrapper on NSRegularExpression that makes simple regexes easier.
import Matches let match1 = "string1\nstring2".firstMatching("(^s)") // => "string1" let matches = "string1\nstring2".everyMatch("(^s.*)") // => [["string1"], ["string2"]]
Previous modules:
https://github.com/coryalder/Later - Easy semaphores
https://github.com/coryalder/Ape - HTTP request helper
https://github.com/coryalder/LevenshteinSwift - Distance between words
https://github.com/coryalder/SwiftLeftpad - my reply to the npm left-pad controversy
https://github.com/coryalder/ConditionalSet - 7 loc, set dictionary keys using optionals
0 notes
Link
A tiny library I've being using to simplify some REST api tasks. Think of it as solving some of the problems Alamofire does, but it's under 100 lines of code so you can wrap your head around the whole thing. 🙈🙊🙉
Example usage:
_ = Ape(url: request) { resp in guard case .JSON(let json) = resp.body else { return } print("json is \(json)") }
2 notes
·
View notes
Text
Build Swift from Visual Studio Code, including packages
The following lets Visual Studio Code build your Swift project, using your Package.swift file to bring in Swift Package Manager modules.
{ "version": "0.1.0", "command": "/Library/Developer/Toolchains/swift-latest.xctoolchain/usr/bin/swift", "showOutput": "silent", "args": ["build"], "problemMatcher": { "pattern": { "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$", "file": 1, "line": 2, "column": 3, "severity": 4, "message": 5 } } }
Save it into .vscode/tasks.json, and hit Cmd-Shift-B to build. Output will be in the usual place (.build/debug/).
1 note
·
View note
Link
wow. much downloads. very profit
1 note
·
View note
Photo

GifTV 1.1 is out now, with a cool new Channel list and Top Shelf support. Search "gi" in the tvOS App Store to find it ¯_(ツ)_/¯
1 note
·
View note
Link
I wrote about my fuzzy autocomplete strategy over on Medium
0 notes
Photo

I released a thing. Rivet - Effortless Affiliate Link Toolbox. It makes sharing Amazon and iTunes product links from your iPhone effortless. I built it because creating posts for Weird iOS from my phone was way too difficult. I'm hopeful I'm not the only one with this problem :)
0 notes
Text
Invert a UIImage at runtime using Core Image’s CIFilter in Swift
Works great, assuming your UIImage is CGImage-backed (if you created it using imageNamed, then it's CGImage-backed).
extension UIImage { func invertedImage() -> UIImage? { let img = CoreImage.CIImage(CGImage: self.CGImage) let filter = CIFilter(name: "CIColorInvert") filter.setDefaults() filter.setValue(img, forKey: "inputImage") let context = CIContext(options:nil) let cgimg = context.createCGImage(filter.outputImage, fromRect: filter.outputImage.extent()) return UIImage(CGImage: cgimg) } }
Gist
0 notes
Photo
LevenshteinSwift
This is a class extension on Swift.String I created to calculate Levenshtein distance, a metric for measuring the difference between two strings. I needed this as part of building an autocomplete system for my upcoming app, Rivet. I had been using an Objective C category written by Mark Aufflick, but since I ended up writing my own autocomplete controls I figured I might as well port the Levenshtein code to Swift. I wrote up a simple test-case, and an example project allowing you to score two strings (shown above).
#levenshtein#string distance#autocomplete#suggestions#autocorrect#objective c#swift#objc#port#rivet#ios#apps#cocoa
0 notes
Link
Amazon Product Advertising API + Alamofire (+ SHXMLParser)
Today I wrote some code to fetch product info from Amazon's Product Advertising API. I used Swift, Alamofire (for networking), and SHXMLParser because Amazon's API only provides XML endpoints. This code may also be helpful if you're signing other requests for an Amazon's API or if you want to use Alamofire to interact with an XML-only API
It's not polished, nor-battle tested, enough to put up as a CocoaPod, but I figured I'd get it out on Google now in case others are stuck trying to sign Amazon requests, etc.
#amazon#aws#alamofire#amazon product advertising api#api#swift#SHXMLParser#ios#iphone#cocoa#objective-c
1 note
·
View note
Link
I started a blog to catalogue all the weird and wonderful iOS apps out there. Artful, interesting, useless but moving, etc. I believe software can be a vehicle for wonderful things, that aren't necessarily "games" or "tools". This is my attempt to collect them all.
If you have any suggestions, please send them my way!
2 notes
·
View notes
Link
While updating Riposte and Whisper for iOS 7, one of the recurring problems I had was getting our view hierarchy to layout correctly. The most troublesome APIs are those for the system status bar and...
An excellent rundown of all the gotchas when dealing with the new status bar and navigationbar underlaps
0 notes
Link
I made a thing for when you are working with NSURL and you can't remember the difference between the `-(NSString *)query` and the `-(NSString *)parameterString`. Click the method name, the associated component is highlighted in red in the URL at the top of the page.
1 note
·
View note
Photo
Open the CocoaPod bay door, iPhone!
I’ve just released an iOS app for CocoaPods users. The app, Podlife, is designed to help you keep your pods up-to-date, find new libraries to make building apps faster, and give you quick access to documentation while on the go.
Podlife is free, with a single optional in-app-purchase, so if you have a moment please check it out and see if you find it useful. There is a contact button in the app, and I’d love to hear feedback and comments!
Check it out!
0 notes
Link
So I wrote a pretty cool addition to DMAFWebViewController.
If you set webViewController.webView.footerView to a UIView, the view will be placed inside the webView's scroll view below all the web content. If the web content changes size (because a page loads) the footer will be pushed below the web content.
I think this may be a novel way of doing this. Googling around for a way to add a footer to UIWebView I found UIWebView with Header and Footer which uses javascript calls to ask the webview how large its content is.
I also used objc_setAssociatedObject to store the content size. You need to remember the last contentSize because you need to adjust the contentSize in order to make room for the footer. You'd get infinite recursion if you didn't watch for this. The reality is I could easily have used a property to do this, I was just keen to try out the whole associatedObject thing.
The above linked commit details all the changes needed to make this happen.
EDIT: Pages that are shorter than the UIWebView's frame don't trigger a contentSize change. Adding this to layoutSubviews fixes the issue by triggering one manually the first time layoutSubviews is called:
if (!objc_getAssociatedObject(self.scrollView, "associated_height")) { NSValue *value = [NSValue valueWithCGSize:self.scrollView.contentSize]; [self observeValueForKeyPath:@"contentSize" ofObject:self.scrollView change:@{NSKeyValueChangeNewKey : value} context:nil]; }
See this commit for the change in action.
2 notes
·
View notes
Text
Put a UISlider into a Popover
To clean up the UI of my app Chack! I decided to move the UISlider from the toolbar to a popover coming from a toolbar button.
Before:

After:

There's more going on than just the change to the UISlider, but the key part of this is there used to be a UISlider in the toolbar, and now it's accessed via a button on the toolbar. This leaves room for another button, which I've used to add a proper color picker. It means more taps for the user, but overall I believe it's an improvement in control and usability.
To do this change, I tried a bunch of things. The first thing I did was try UIPopoverController. I was quickly reminded that this only works on iPad, not on iPhone. sad trombone.
So the next step is always a trip to cocoacontrols.com and cocoapods.org to look up a viable replacement. If I can't find something there, I generally settle in to build it myself, but usually something already exists that can be adapted.
After auditioning a few popover classes, I settled on PopoverView. I tried WEPopover first, but I ran into some problems where the popover was making my UIBarButtonItem disappear every time I showed it. I never sorted out the issue, but PopoverView works well enough, and looks great. The only downside is that it doesn't have a present-from-bar-button-item method on it.
pod 'PopoverView', '~> 0.0.1'
You are using CocoaPods, right? Add the above line to your Podfile and run pod update to install it. If you're not using cocoapods already, HEAVEN HELP YOU, YOUR SOUL IS LOST!
Once installed, go to your view controller and add a custom UIView to your nib, outside of your main view. Place a single UISlider in the center of the view. It's going to be rotated to be vertical, so you want to make it as wide as the containing view is long (less 20px margins on either side). Since my view is 270px tall, I made my UISlider 230px wide and centered it.

Xcode doesn't offer a way to visually make a vertical slider, but you can do it in the .xib by using User Defined Runtime Attributes. Go to that section, and set the Key Path to layer.transform.rotation.z, the type to String and the value to -1.570795 (which is -pi/2).

Now wire up the UIBarButtonItem to a IBAction method on your view controller (sliderButtonAction:), and wire up the UIView that contains the UISlider to an IBOutlet (sliderView). Don't forget to #import "PopoverView.h".
-(IBAction)sliderButtonAction:(id)sender { UIView *topView = nil; NSArray* windowViews = [[[UIApplication sharedApplication] keyWindow] subviews]; for (int i = windowViews.count - 1; i >= 0 ; i--) { topView = [windowViews objectAtIndex:i]; if (!topView.isHidden) break; } [PopoverView showPopoverAtPoint:(CGPoint){147.0f, topView.frame.size.height-44.0f} inView:topView withContentView:self.sliderView delegate:nil]; }
The first bit of this method finds the topmost view, and the second bit uses the topmost view to present the popover. A major downside to PopoverView, as mentioned earlier, is that you have to specify the location of the popover's presenter. This means either hard-coding it, as I've done, or writing some code (as WEPopover has done) to find the location programmatically. I chose the easy way out, and just fudged the location. Annoying if I change the button layout ever, but it works for now.
And amazingly, that's it. PopoverView handles hiding and showing the popover, and prevents two popovers from showing at once (grounds for app store rejection, I know from personal experience). You need to wire the slider up to your UI to do whatever it's supposed to do, but that's the basic premise.
1 note
·
View note