Skip to main content

Posts

Showing posts from 2019

UITextView and NSAttributedString: The Secret of Hyphenation (Swift 4.2.1)

If you want the text within a UITextView to be hyphenated (instead of inappropriately stretched in places when justified), forget NSParagraphStyle and its mutable partner, NSMutableParagraphStyle. At least this is what I've found transforming HTML into attributed text. I can set the hyphenation factor to zero for the paragraph style and the layout manager for the UITextView will override it. See here an example where a HTML file is held within the Assets folder. if let asset = NSDataAsset(name: "\(assetName)") { let data = asset.data let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.hyphenationFactor = 0.0 var dict:NSDictionary? = NSDictionary(dictionary: [NSAttributedString.Key.paragraphStyle : paragraphStyle]) do { let attr = try NSAttributedString(data: data, options: [.documentType: NSAttributedString.DocumentType.html, .characterEncoding: String.Encoding.utf8.rawValue], documentAttributes: &dict) textView.layout

Unfiltered Email: First steps in how not to get spam filtered

Pro-Level For pro-level email handling you can edit your DNS file with an SPF line and add a DMARC subdomain/line , and use DKIM signatures . This post isn't about that but if you want to look at your own DMARC record for the interest of it, you can do so using the terminal and the following line: dig txt _dmarc.example.com Replacing example.com with your own domain or the one your nosing around at. (You might find your hosting provider has already got you covered.) Your DNS file is also worth a look, so investigate how to view and edit. Using dig you can see your DNS file like so: dig example.com txt And this will reveal SPF settings. (Again, you might be pleasantly surprised to see you have an SPF record by default.) Back to Basics This post assumes you're not using a dedicated server, so might not have the necessary access to install DKIM or might not have the urge at present. But you've set up automated email and you're wanting to know why it's g

Loading books with a .mobi extension onto your Kindle

If you're running a desktop version of the Kindle app, you might find any attempts to open a .mobi book are met by protests that it can't be opened or that you simply see a blank page. (This is what happens to me on a Mac.) I'll get onto how you can read .mobi books on a Mac later. (Hint using Kindle Previewer.) This guidance will not solve the issue with the desktop Kindle app, however, if you are looking for a way to read your book on a Kindle e-ink device, or in a Kindle app on an Android, or iOS, device then this post will help you. Here are the steps you'll need to read your .mobi file: Install Send to Kindle onto your desktop, open and sign-in Drop your file into the drag area Select where you'd like the file delivered Check the box that says "archive in your Kindle library" Not only will it be delivered to your requested device. You will in future be able to download to different devices by logging into Amazon. Hover over the acco

Open Graph and Facebook: The Basics (Text, Images and App ID)

There are some basics you need to know when working with Facebook's Open Graph to tag your webpages. Descriptive Elements Let's start with the descriptive elements: url, type, title and description. For a website we can fill these out in the following way: <!-- Facebook Open Graph --> <meta property="og:url" content="https://www.gylphi.co.uk" /> <meta property="og:type" content="website" /> <meta property="og:title" content="Gylphi: Arts and Humanities Publisher" /> <meta property="og:description" content="Academic publisher of the arts and humanities from the twentieth century and beyond." /> The property values are hopefully clear enough to understand but are  expanded on here . Images One of the most important factors you'll want to include are images. Images should be a minimum of 600 px wide, but preferably 1080px wide (see  https://developers.faceb

Link Sharing and Search Optimisation using Facebook's Open Graph, Twitter Cards and Structured Data (JSON-LD)

This isn't a post taking you through the creation of metadata and markup for link sharing and search optimisation. (Sorry! Maybe another time.) It is instead a series of getting started links to help guide you towards what you need to include in your webpages to control how your pages get seen on the web from outside your website. Facebook: Open Graph Instructions for controlling title and image content that are paired with shared links are given here: https://developers.facebook.com/docs/sharing/webmasters Content types include: music, video, article, book, profile and website. The website type being the default. For information on adding rich detail to the type, see here: http://ogp.me Sharing debugger:  https://developers.facebook.com/tools/debug/ Twitter: Cards Twitter has a fallback of using open graph but with twitter cards you have rich functionality unique to Twitter: https://developer.twitter.com/en/docs/tweets/optimize-with-cards/overview/abouts-cards

Nesting a UIStackView within a UIScrollView: Horizontal Scrolling

Horizontal Scrolling (UIStackView within UIScrollView) For horizontal scrolling. First, create a `UIStackView` and a `UIScrollView` and add them to your view in the following way: let scrollView = UIScrollView() let stackView = UIStackView() scrollView.addSubview(stackView) view.addSubview(scrollView) Remembering to set the `translatesAutoresizingMaskIntoConstraints` to `false` on the `UIStackView` and the `UIScrollView`: stackView.translatesAutoresizingMaskIntoConstraints = false scrollView.translatesAutoresizingMaskIntoConstraints = false To get everything working the trailing, leading, top and bottom anchors of the `UIStackView` should be equal to the `UIScrollView` anchors: stackView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true stackView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true stackView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true stackView.bottomAnchor.constraint(equalTo: scroll

The Weird and Auto-Magical Science of Integrating TextKit with UIPageViewController and Auto Layout

Let's suppose you are using TextKit to layout your text, i.e. the combination of NSTextStorage, NSLayoutManager and NSTextContainer, combined with UITextView. And let's also suppose that you'll be using Auto Layout to anchor a UIPageViewController's view to the views it will be sitting next to (or perhaps be using it within a UIStackView, you brave soul!). func textLayoutContainers(size:CGSize, scrolling:Bool, section:String, page:Int) { var textViewArr = [UITextView]() // Create attr string - content guard let textString = loadHTMLData(section: section, page: page) else {return} // Set up text storage and add string let textStorage = NSTextStorage(attributedString: textString) // Create a layout manager let textLayout = NSLayoutManager() // Add layout manager to text storage object textStorage.addLayoutManager(textLayout) // create text containers and views, adding eac

Life with a Garmin Forerunner 735xt: Adding Activity Profiles (Hike, Multisport, Row and SUP)

Adding Activity Profiles to your Activity List When you select your activity from the default list, you'll notice you only have Run, Run Indoors, Bike, Bike Indoors, Pool Swim, Open Water, Triathlon and Apps. This doesn't mean that you need to head to the Connect Store if you want to record activities like Hiking or Rowing. Instead do the following starting from the regular clock screen: Press the top right button Press the down button to enter Menu Arrow up to Settings Select with top right button Arrow up to Activity Profiles Select with top right button and press the same button again to Add New You are now faced with a number of options (addition to the default ones displayed on your Activity menu): Multisport SUP Row XC Ski Strength Cardio Other You can customise various elements of these profiles and if you go into Multisport  you not only have Triathlon but also Duathlon and Brick modes (for building varied combinations of sports). If you w

Life with a Garmin Forerunner 735xt: Exporting, Importing, Transferring and Following Courses from Strava

Export Importing a course from Strava requires a few steps, the first of which is exporting from Strava: Go to Strava on the web and select Dashboard > My Routes Select the route you wish to add to your Garmin Click on Export GPX Import Now go to Garmin Connect on the web and do the following: In the sidebar menu, expand Training Select Courses Over the map that appears will be a window with a list of courses contained in it. In the bottom right corner click on Import Drag or browse to import the file(s) your just downloaded Select the type of course you just downloaded when prompted Name the course and Save it. You can ignore the Send to Device button (it isn't necessary) Transfer You are now ready to transfer the course to your watch: Open the Garmin Connect app on your smartphone Select the hamburger menu button (top left) and then Courses Select the course you wish to transfer Tap on the top right export to phone but

Life with a Garmin Forerunner 735xt: Setting Time and Distance Formats the Right Way

This is the first in a series of posts of getting to know a Garmin Forerunner 735xt and it presumes you have installed the Garmin Connect app on your smartphone. The first thing I noticed when setting up my watch was that choices of time and distance formats reverted from what I chose when setting up through the watch's introductory screens to the presets after syncing with the Garmin Connect Android App. So kilometres were replaced by miles on my first run and time kept shifting back to 12h from my preference for 24h. I quickly learnt from this that choices made on the watch did not take priority, instead priority came from the app. The first issue was fairly easy to fix within the Connect App on my phone. Time was a bit more slippery and required visiting the Garmin Connect website. Changing Units of Measure in the Garmin Connect App Press the hamburger menu button Scroll down to the bottom of the menu and select Settings Select User Settings Scroll down to Units of Meas