Cloudron: Migrate app to different instance

Migrating apps from one Cloudron to another works by first creating a new backup of the app on the old Cloudron, copying the backup tarball onto the new Clodron’s backup storage and then installing a new app, based on the backup on the new Cloudron.

Prerequisites

The following steps will migrate an app

#1 Create a backup on the old Cloudron

$: cloudron login
$: cloudron list
$: cloudron backup create --app <appid>
$: cloudron logout

#2 Copy the new backup from the old Cloudron’s backup storage to the new one

It depends on your backup solution where your newly created backup is stored.
Use the same path for the new Cloudron correspondingly.

#3 Then login to the new Cloudron and install the new app based on the created backup

$: cloudron login
$: cloudron install --appstore-id=org.wordpress.cloudronapp --backup .../...tar.gz
$: cloudron logout

© Cloudron.io

Get all resource paths in bundle recursively

I’ve been looking for a way to search a subdirectory in my main bundle recursively – the following simple Swift extension does the trick.

I’ve been looking for a way to search a subdirectory in my main bundle recursively – the following simple Swift extension does the trick.

Bundle.main.paths(forResource: String?, ofType: String?) -> [String]?


let paths: [String]? = Bundle.main.paths(forResource: "my-resource", ofType: "my-extension")

Bundle.main.urls(forResource: String?, withExtension: String?) -> [URL]?

let urls: [URL]? = Bundle.main.urls(forResource: "my-resource", withExtension: "my-extension")

The source code of the extension

import Foundation

extension Bundle{
    
    func urls(forResource name: String?, withExtension ext: String?) -> [URL]?{
        guard let resourceURL = self.resourceURL else{ return nil }
        let enumerator = FileManager.default.enumerator(at: resourceURL, includingPropertiesForKeys: nil)
        
        var urls = [URL]()
        while let url = enumerator?.nextObject() as? URL{
            guard ext == nil && url.lastPathComponent == name || ext == url.pathExtension && url.deletingPathExtension().lastPathComponent == name else{
                continue
            }
            urls.append(url)
        }
        
        return urls.count > 0 ? urls : nil
    }
    
    func paths(forResource name: String?, ofType type: String?) -> [String]?{
        return self.urls(forResource: name, withExtension: type)?.map{ $0.path }
    }
}

Hör auf, Deine Leidenschaft zu suchen!

“not knowing” is the whole fucking point. Life is all about not knowing, and then doing something anyway. All of life is like this. All of it.
Screw Finding Your Passion by Mark Manson

Ein Appell an die Einfachheit des Lebens: Wie fällt ein Kind Entscheidungen? Es tut etwas, weil es ihm gefällt. Es lässt etwas bleiben, weil es ihm nicht gefällt. Es versucht sich in neuen Dingen und entscheidet danach, ob es ihm gefällt.

Keine Gesellschaftlichen Zwänge, keine Erwartungshaltungen, keine Schuldgefühle.

FolderBar: A new approach to more than 5 Tabs in a UITabBar

You may already came across the Apple tab limitation for the UITabBarController: You are only allowed to have a maximum of 5 tabs in a UITabBar.

UITabBar More Items UITabBar More Items Active

If you got more than these five items, an inconvenient and ugly moreNavigationController takes over and ruins your whole ui experience by it’s unnatural and complex user interface.

 

 

Well, you may argue if you got that much tabs you should rethink the navigation structure of your app – or the app as a whole. A lot of times this is true, but there are also a few total valid use cases.

In those valid cases, you had to circumvent the „More-Problem“ by using the well-known hamburger menu. This approach is far from ideal and there is a huge discussion going on. Simply have a brief look around and you’ll find a lot of resources (for example this one).

Long story short: I’ve decided to went down a new path.

FolderBar More Items FolderBar More Items Active

The idea is simple:

We just want the UITabBar to behave like any iOS Folder.

That was the birth of the all new and shiny FolderBar.

 

 

  1. The FolderBar can be opened if there are more than 5 items by tapping the open handle which is automagically added – or you can simply use a swipe gesture
  2. All items can be rearranged with drag & drop
  3. 1&2 together provide a simple, self explanatory and fully customizable quick access for the user – because the four upper items are never hidden

If you’re interested in integrating FolderBar in your project, simply drop me a line: folderbar@marco.betschart.name

 

Codify country name

import java.util.Locale;

/**
Codifies country names to their ISO country code and vice versa:
    - LocaleCountry.nameOf("CH", new Locale("en")) -> "Switzerland"
    - LocaleCountry.codeOf("Schweiz", new Locale("de")) -> "CH"
    - LocaleCountry.codeExists("CH") -> true
*/
public class LocaleCountry {
    
    public static String nameOf( String code ){
        return LocaleCountry.nameOf( code, Locale.getDefault() );
    }


    public static String nameOf( String code, Locale locale ){
        return new Locale(locale.getLanguage(),code.toUpperCase()).getDisplayCountry(locale);
    }
    
    
    public static String codeOf( String name ){
        Locale sys = Locale.getDefault();
        String code = LocaleCountry.codeOf(name, sys);
        
        if( code != null ){
            return code;
            
        } else if( !sys.getLanguage().equals("en") ){
            return LocaleCountry.codeOf(name,new Locale("en"));
        }
        
        return null;
    }
    
    
    public static String codeOf( String name, Locale locale ){
        String[] codes = Locale.getISOCountries();
        
        for( String code: codes ){
            if( name.equalsIgnoreCase(LocaleCountry.nameOf(code, locale)) ){
                return code;
            }
        }
        
        return null;
    }
    
    
    public static String codeOf( String name, Locale[] locales ){
        for( Locale locale: locales ){
            String code = LocaleCountry.codeOf(name, locale);
            
            if( code != null ){
                return code;
            }
        }
        
        return null;
    }
    
    
    public static boolean codeExists( String code ){
        String[] codes = Locale.getISOCountries();
        
        for( String comparison: codes ){
            if( code.equalsIgnoreCase(comparison) ){
                return true;
            }
        }
        
        return false;
    }
}

Public Email Domain

Check if a email string is an email address of a public email provider by just using this one liner in Swift:

"marbetschar@gmail.com" ~= PublicEmailDomain.Any

Full Swift source code:

enum PublicEmailDomain: String{
    case Any
    case Aol = "^aol\\.[a-z]{2,5}$"
    case iCloud = "^icloud\\.com$"
    case Mac = "^mac\\.com$"
    case Me = "^me\\.com$"
    case Bluewin = "^bluewin\\.ch$"
    case Eclipso = "^eclipso\\.[a-z]{2,5}$"
    case Freenet = "^freenet\\.ch$"
    case Gmx = "^gmx\\.[a-z]{2,5}$"
    case Gmail = "^gmail\\.[a-z]{2,5}$"
    case Googlemail = "^googlemail\\.[a-z]{2,5}$"
    case Hotmail = "^hotmail\\.[a-z]{2,5}$"
    case Inbox = "^inbox\\.[a-z]{2,5}$"
    case Outlook = "^outlook\\.com$"
    case Live = "^live\\.[a-z]{2,5}$"
    case Msn = "^msn\\.com$"
    case Net24 = "^net-24\\.at$"
    case Online = "^online\\.de$"
    case TOnline = "^t-online\\.de$"
    case Web = "^web\\.[a-z]{2,5}$"
    case Yahoo = "^yahoo\\.[a-z]{2,5}$"
    case Zoho = "^zoho\\.[a-z]{2,5}$"
    case Yandex = "^yandex\\.[a-z]{2,5}$"
    
    static let allValues: [PublicEmailDomain] = [
        Aol,
        iCloud,
        Mac,
        Me,
        Bluewin,
        Eclipso,
        Freenet,
        Gmx,
        Gmail,
        Googlemail,
        Hotmail,
        Inbox,
        Outlook,
        Live,
        Msn,
        Net24,
        Online,
        TOnline,
        Web,
        Yahoo,
        Zoho,
        Yandex
    ]
}

extension PublicEmailDomain: Equatable{}

func == (lhs: String, rhs: PublicEmailDomain) -> Bool{
    
    switch(rhs){
    case .Any:
        for publicEmailDomain in PublicEmailDomain.allValues{
            if lhs == publicEmailDomain {
                return true
            }
        }
        return false
        
    default:
        do{
            return try NSRegularExpression(pattern: rhs.rawValue, options: .CaseInsensitive).numberOfMatchesInString(lhs, options: [], range: NSMakeRange(0, lhs.characters.count)) == 1
            
        } catch _{
            return false
        }
    }
}


func ~=(email: String, publicEmailDomain: PublicEmailDomain) -> Bool{
    let domain: String = {
        let parts = email.characters.split{$0 == "@"}.map(String.init)
        return parts[parts.count - 1]
    }()

    return domain == publicEmailDomain
}

 

CouchbaseLite – Module maps

As convenient as the bridging header is, it has one key limitation—you can’t use it inside a framework project.  The alternative is to use a module.

This can be problematic when using Couchbase Lite for iOS for example.

To do this, create a directory in your project directory named CouchbaseLite. Inside the directory, create a module.map file that encapsulates library settings. For CouchbaseLitemodule.map looks like this:

module CouchbaseLite {
  header "../Pods/couchbase-lite-ios/CouchbaseLite.framework/Headers/CouchbaseLite.h"
  export *
}

Now add the new module to Import Paths under Swift Compiler – Search Paths in your project settings. Use ${SRCROOT} in the module path (e.g. ${SRCROOT}/CouchbaseLite) to insure that the project works no matter where it’s checked out.

SwiftCompiler - Search Paths - CouchbaseLite

This makes it possible to just import CouchbaseLite in your Swift files. Note that consumers of any frameworks you build using this technique are also going to have to add the module to their Swift search paths.

Many thanks and © to Matt Behrens!

XCTAssert

Overview

Detail

XCTAssert(expression, format…)

Generates a failure when expression evaluates to false.

 

XCTAssertEqual(a1, a2, format…)

Generates a failure when a1 is not equal to a2. This test is for C scalars, structs and unions.

 

XCTAssertEqualObjects(a1, a2, format…)

Generates a failure when !{ [a1 isEqual:a2] } is false (or one is nil and the other is not).

 

XCTAssertEqualWithAccuracy(a1, a2, accuracy, format…)

Generates a failure when a1 is not equal to a2 within + or – accuracy. This test is for scalars such as floats and doubles, where small differences could make these items not exactly equal, but works for all scalars.

 

XCTAssertFalse(expression, format…)

Generates a failure when the expression evaluates to true.

 

XCTAssertNotEqual(a1, a2, format…)

Generates a failure when \a1 is not nil.

 

XCTAssertNotEqualObjects(a1, a2, format…)

Generates a failure when { [a1 isEqual:a2] } is false (or both are nil).

 

XCTAssertNotEqualWithAccuracy(a1, a2, accuracy, format…)

Generates a failure when a1 is equal to a2 within + or – accuracy. This test is for scalars such as floats and doubles, where small differences could make these items not exactly equal, but works for all scalars.

XCTAssertNoThrow(expression, format…)

Generates a failure when expression does throw an exception.

 

XCTAssertNoThrowSpecific(expression, specificException, format…)

Generates a failure when expression does throw an exception of the specified class. Any other exception is okay (i.e. does not generate a failure).

 

XCTAssertNoThrowSpecificNamed(expression, specificException, exception_name, format…)

Generates a failure when expression does throw an exception of a specific class with a specific name. Useful for those frameworks like AppKit or Foundation that throw generic NSException w/specific names (NSInvalidArgumentException, etc).

 

XCTAssertNotNil(a1, format…)

Generates a failure when a1 is nil.

 

XCTAssertThrows(expression, format…)

Generates a failure when expression does not throw an exception.

 

XCTAssertThrowsSpecific(expression, specificException, format…)

Generates a failure when expression does not throw an exception of a specific class.

 

XCTAssertThrowsSpecificNamed(expression, specificException, exception_name, format…)

Generates a failure when expression does not throw an exception of a specific class with a specific name. Useful for those frameworks like AppKit or Foundation that throw generic NSException w/specific names (NSInvalidArgumentException, etc).

 

XCTAssertTrue(expression, format…)

Generates a failure when expression evaluates to false.

 

XCTFail

Generates a failure unconditionally.

 

And the oscar goes to … Harry Hornreich! – Thank you!