Invalid initializer call with same type 'FileAttributeKey' as parameter

This blog post is brought to you by the developer of BitBudget. BitBudget is an automated budgeting app for Android and iOS which syncs with your bank account and helps you avoid overspending. If you’d like to quit living paycheck-to-paycheck and get a better handle on your finances, download it today! https://bitbudget.io

Ran into a little bug tonight going through the official quick start guide for the Realm Database on iOS. The app which I’m building needs to be able to access the database while running in the background, so according to the Realm documentation developers need to change some security settings for the folder containing the database in order to access that database from the background. Without changing the security settings, the folder containing the database will be encrypted and not accessible when a user’s iPhone is locked. The official documentation suggests adding the following lines of code so that the Realm Database is accessible even when the phone is locked:

let realm = try! Realm()
// Get our Realm file's parent directory
let folderPath = realm.configuration.fileURL!.deletingLastPathComponent().path
// Disable file protection for this directory
try! FileManager.default.setAttributes([FileAttributeKey(rawValue: NSFileProtectionKey): NSFileProtectionNone], ofItemAtPath: folderPath)

However, when I tried using this little snippet of code in my current iOS project (WingsuitGP) I received the following error message: Invalid initializer call with same type ‘FileAttributeKey’ as parameter
Luckily, someone on StackOverflow got me pointed in the right direction: invalid initializer call with same type ‘XXXX’ as parameter
But I still needed a little help from Xcode’s suggested bug fixes to get it to work just right. So here is what I ended up with if anyone else is struggling with this annoying error:

let realm = try! Realm()
// Get our Realm file's parent directory
let folderPath = realm.configuration.fileURL!.deletingLastPathComponent().path
// Disable file protection for this directory
try! FileManager.default.setAttributes([FileAttributeKey.protectionKey: FileProtectionType.none], ofItemAtPath: folderPath)

 

How To Install a Cocoapod

Quick little blog post here on how to install a Cocoapod into an Xcode project. This is sort of for my own personal reference because I haven’t memorized how to do this yet, but if you need a more in depth tutorial check out How to Install a CocoaPod by Sean Allen.
First, enter a few terminal commands:

$ cd Desktop/SwiftPlayground/MySuperSweetXcodeProject
$ pod init
$ open -a Xcode Podfile


Next, edit (and save) your Podfile:

# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'
target 'MySuperSweetXcodeProject' do
  # Comment the next line if you're not using Swift and don't want to use dynamic frameworks
  use_frameworks!
  # *** ADD YOUR POD ON THE LINE BELOW ***
  pod 'MySuperSweetCocoaPod'
end


Last, run one final terminal command:

$ pod install

 

Hello, World with the Realm Database for iOS in Swift

This blog post is brought to you by the developer of BitBudget. BitBudget is an automated budgeting app for Android and iOS which syncs with your bank account and helps you avoid overspending. If you’d like to quit living paycheck-to-paycheck and get a better handle on your finances, download it today! https://bitbudget.io

As I mentioned in my previous post, I’ve been doing a little hacking today using the Realm Database for iOS (using Swift). The official tutorial from Realm is pretty good, but it leaves out where exactly to put certain snippets of code within the Xcode framework as many official tutorials for various programming frameworks and libraries often do. So I just wanted to jot down this quick blog post for my own personal reference, or maybe to help another developer out there in cyber-space to get up and running with the Realm Database for iOS:

  1. Install Realm using the Cocoapods Dependency Manager (See this tutorial for help getting started with Cocoapods if necessary)
  2. Create a New Xcode Project

Okay, so now you have you have Realm installed and have created your new Xcode project. Now we are going to make our “hello, world” app inspired by one of the stupidest games of all time: Cookie Clicker
Cookie Clicker is a pretty ridiculous game. The gist of the whole thing is you click a button and then you get cookies. That’s it! Pretty much all there is to it. The only thing is, with Cookie Clicker, you want to be able to save the number of cookies baked in between running the game, so I thought it would make an excellent example for learning the basics of Realm. The app will simply consist of a single screen with a label which displays the number of cookies baked, and a button the user can press to bake more cookies. And using the magic of the Realm Database, we will be able to save the number of cookies baked by our users. In addition to the single screen, we will have one ViewController (ViewController.swift) and another swift file called Cookie.swift which we will use to declare our Cookie class. Just remember to connect the label to the view controller (control-drag) to create your IBOutlet for the cookieCountLabel, and also make an IBAction connection by control-dragging from your bakeCookiesButton to the ViewController.
NOTE: See my previous blog post regarding the error message “Could Not Build the Objective-C Module ‘RealmSwift‘” if necessary.
CookieClickerScreenshot

//
//  ViewController.swift
//  HelloRealm
//
//  Created by Christopher Pedersen on 2/25/19.
//  Copyright © 2019 Christopher Pedersen. All rights reserved.
//
import UIKit
import RealmSwift
class ViewController: UIViewController {
    @IBOutlet weak var cookieCountLabel: UILabel!
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        let realm = try! Realm()
        let cookies = realm.objects(Cookie.self)
        let cookieCount: Int = cookies.count
        if cookieCount > 0 {
            cookieCountLabel.text = "Cookies: \(cookieCount)"
        } else {
            cookieCountLabel.text = "Cookies: 0"
        }
    }
    @IBAction func onBakeCookiesButtonClicked(_ sender: Any) {
        let realm = try! Realm()
        let newCookie = Cookie()
        newCookie.type = "Chocolate Chip"
        newCookie.size = "Large"
        let cookies = realm.objects(Cookie.self)
        try! realm.write {
            realm.add(newCookie)
        }
        let cookieCount: Int = cookies.count
        cookieCountLabel.text = "Cookies: \(cookieCount)"
    }
}

//
//  Cookie.swift
//  HelloRealm
//
//  Created by Christopher Pedersen on 2/25/19.
//  Copyright © 2019 Christopher Pedersen. All rights reserved.
//
import Foundation
import RealmSwift
class Cookie: Object {
    @objc dynamic var type = ""
    @objc dynamic var size = ""
}
 

Could Not Build Objective-C Module 'RealmSwift'

This blog post is brought to you by the developer of BitBudget. BitBudget is an automated budgeting app for Android and iOS which syncs with your bank account and helps you avoid overspending. If you’d like to quit living paycheck-to-paycheck and get a better handle on your finances, download it today! https://bitbudget.io

Today I started experimenting with the hot Swift database library ‘Realm’ AKA RealmSwift for iOS and have run into a really annoying error while trying to follow along with the official tutorial: “Could not build Objective-C module ‘RealmSwift'” Luckily someone posted a fairly simple solution that I probably would have never figured out myself on a Github forum. To fix this error in Xcode, simply…

  1. GOTO Product > Scheme > New Scheme
  2. SELECT ‘RealmSwift’ from the Drop-Down Menu
  3. CLICK ‘OK’

And that’s it. Problem solved.
Reference: https://github.com/realm/realm-cocoa/issues/5973

 

startRelativeAltitudeUpdates on a Background OperationQueue

This blog post is brought to you by the developer of BitBudget. BitBudget is an automated budgeting app for Android and iOS which syncs with your bank account and helps you avoid overspending. If you’d like to quit living paycheck-to-paycheck and get a better handle on your finances, download it today! https://bitbudget.io

Doing a little hacking on my WingsuitGP app tonight so I can take it for a test flight tomorrow. The original prototype used a really ugly work-around to access altitude (pressure) data in the background, so I would like to make a note here of an excellent blog post demonstrating how to properly run altitude updates in the background on iOS: Locating a Snowboarder on a Slope
The example snippets of code I’ve found around the web regarding startRelativeAltitudeUpdates all had the updates running on OperationQueue.main, but after discovering the aforementioned mentioned blog post, it looks like it’s fairly simple to create your own OperationQueue and specify that you would like it to run in the background. I’m sure an experienced iOS developer would have been able to figure this out in 5 min., but… o well! Now I know 🙂

// Code Snippet by swifting.io
// https://swifting.io/blog/2017/10/30/46-locating-a-snowboarder-on-a-slope/
let queue = OperationQueue()
queue.qualityOfService = .background
queue.maxConcurrentOperationCount = OperationQueue.defaultMaxConcurrentOperationCount
let altimeter = CMAltimeter()
altimeter.startRelativeAltitudeUpdates(to: queue,
    withHandler: { data, error in //(CMAltitudeData?, Error?)
        guard error == nil else { return }
        guard let data = data else { return }
        //NOTE: process data 🏂!!!
})

 

My Latest Side Project: BuckBuckMoose

BuckBuckScreenshot635x380
Just launched my latest side project, BuckBuckMoose! Check it out on ProductHunt.

 

Why You Should Never Register a Domain with Finnish Domain Name Extension (.fi)

This blog post is brought to you by the developer of BitBudget. BitBudget is an automated budgeting app for Android and iOS which syncs with your bank account and helps you avoid overspending. If you’d like to quit living paycheck-to-paycheck and get a better handle on your finances, download it today! https://bitbudget.io

Well this is sort of a strange post, and I’m not sure if it will make any sense to anyone that happens to stumble upon it, but nevertheless, I have something to say about Finnish domain name extensions! I had this great idea the other day to create a web-app that saves all of your Google search queries so that you can blog about the answer after you find it. Think Quora, the question and answer site, except you answer all of your own questions.

Since I’m sort of into domain name hacks, I decided on the name proli.fi/c for my new blogging tool, as the idea for the tool is to greatly increase the number of blog posts that users of the tool write. However… several days later my Finnish domain, registered through 101domain.com, still isn’t ready to use! So if by any chance someone looking into registering a Finnish domain happens to stumble upon this post, don’t do it!
UPDATE: Eventually everything was resolved. For some reason 101domain.com needed to verify my date of birth with the Finns.

 

Where You Can Find the Full Episode of Jack Dorsey on the Joe Rogan Podcast (Episode 1236)

Apparently Jack Dorsey’s appearance on the Joe Rogan Experience didn’t go very well, and the full episode has been pulled from YouTube. Luckily, someone in the comments went ahead and posted a link for an audio version of the full episode:

 

h.appening.me/ow's Terms of Service

Terms of Service

1. Terms

By accessing the website at http://h.appening.me/ow, you are agreeing to be bound by these terms of service, all applicable laws and regulations, and agree that you are responsible for compliance with any applicable local laws. If you do not agree with any of these terms, you are prohibited from using or accessing this site. The materials contained in this website are protected by applicable copyright and trademark law.

2. Use License

  1. Permission is granted to temporarily download one copy of the materials (information or software) on Christopher Pedersen’s website for personal, non-commercial transitory viewing only. This is the grant of a license, not a transfer of title, and under this license you may not:
    1. modify or copy the materials;
    2. use the materials for any commercial purpose, or for any public display (commercial or non-commercial);
    3. attempt to decompile or reverse engineer any software contained on Christopher Pedersen’s website;
    4. remove any copyright or other proprietary notations from the materials; or
    5. transfer the materials to another person or “mirror” the materials on any other server.
  2. This license shall automatically terminate if you violate any of these restrictions and may be terminated by Christopher Pedersen at any time. Upon terminating your viewing of these materials or upon the termination of this license, you must destroy any downloaded materials in your possession whether in electronic or printed format.

3. Disclaimer

  1. The materials on Christopher Pedersen’s website are provided on an ‘as is’ basis. Christopher Pedersen makes no warranties, expressed or implied, and hereby disclaims and negates all other warranties including, without limitation, implied warranties or conditions of merchantability, fitness for a particular purpose, or non-infringement of intellectual property or other violation of rights.
  2. Further, Christopher Pedersen does not warrant or make any representations concerning the accuracy, likely results, or reliability of the use of the materials on its website or otherwise relating to such materials or on any sites linked to this site.

4. Limitations

In no event shall Christopher Pedersen or its suppliers be liable for any damages (including, without limitation, damages for loss of data or profit, or due to business interruption) arising out of the use or inability to use the materials on Christopher Pedersen’s website, even if Christopher Pedersen or a Christopher Pedersen authorized representative has been notified orally or in writing of the possibility of such damage. Because some jurisdictions do not allow limitations on implied warranties, or limitations of liability for consequential or incidental damages, these limitations may not apply to you.

5. Accuracy of materials

The materials appearing on Christopher Pedersen’s website could include technical, typographical, or photographic errors. Christopher Pedersen does not warrant that any of the materials on its website are accurate, complete or current. Christopher Pedersen may make changes to the materials contained on its website at any time without notice. However Christopher Pedersen does not make any commitment to update the materials.

6. Links

Christopher Pedersen has not reviewed all of the sites linked to its website and is not responsible for the contents of any such linked site. The inclusion of any link does not imply endorsement by Christopher Pedersen of the site. Use of any such linked website is at the user’s own risk.

7. Modifications

Christopher Pedersen may revise these terms of service for its website at any time without notice. By using this website you are agreeing to be bound by the then current version of these terms of service.

8. Governing Law

These terms and conditions are governed by and construed in accordance with the laws of TX and you irrevocably submit to the exclusive jurisdiction of the courts in that State or location.

 

h.appening.me/ow Privacy Policy

Privacy Policy

Your privacy is important to me. It is  my (Christopher Pedersen) policy to respect your privacy regarding any information I may collect from you across my website, http://h.appening.me/ow, and other sites I own and operate.
I only ask for personal information when we truly need it to provide a service to you. I collect it by fair and lawful means, with your knowledge and consent. I also let you know why I am collecting it and how it will be used.
I only retain collected information for as long as necessary to provide you with your requested service. What data I store, I will protect within commercially acceptable means to prevent loss and theft, as well as unauthorised access, disclosure, copying, use or modification.
I don’t share any personally identifying information publicly or with third-parties, except when required to by law.
My website may link to external sites that I do not operate. Please be aware that I have no control over the content and practices of these sites, and cannot accept responsibility or liability for their respective privacy policies.
You are free to refuse our request for your personal information, with the understanding that I may be unable to provide you with some of your desired services.
Your continued use of my website will be regarded as acceptance of our practices around privacy and personal information. If you have any questions about how I handle user data and personal information, feel free to contact me (chris@topherpedersen.com).
This policy is effective as of 1 February 2019.