{"id":1172,"date":"2021-06-04T13:55:04","date_gmt":"2021-06-04T11:55:04","guid":{"rendered":"https:\/\/www.sl-soft.de\/?page_id=1172"},"modified":"2024-01-19T17:25:49","modified_gmt":"2024-01-19T16:25:49","slug":"swiftletsmoveit","status":"publish","type":"page","link":"https:\/\/www.sl-soft.de\/en\/swiftletsmoveit\/","title":{"rendered":"Swift &#8211; LetsMoveIt"},"content":{"rendered":"<div data-elementor-type=\"wp-page\" data-elementor-id=\"1172\" class=\"elementor elementor-1172\">\n\t\t\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-484ee6b elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"484ee6b\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-59bed11\" data-id=\"59bed11\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-643d0ea elementor-widget-divider--view-line elementor-widget elementor-widget-divider\" data-id=\"643d0ea\" data-element_type=\"widget\" data-widget_type=\"divider.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-divider\">\n\t\t\t<span class=\"elementor-divider-separator\">\n\t\t\t\t\t\t<\/span>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-6076002 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"6076002\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-2a0c7ef\" data-id=\"2a0c7ef\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-deaae3e elementor-widget elementor-widget-heading\" data-id=\"deaae3e\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h1 class=\"elementor-heading-title elementor-size-default\">LetsMoveIt<\/h1>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-2a9b5c1 elementor-widget elementor-widget-spacer\" data-id=\"2a9b5c1\" data-element_type=\"widget\" data-widget_type=\"spacer.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-spacer\">\n\t\t\t<div class=\"elementor-spacer-inner\"><\/div>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-c4b3252 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"c4b3252\" data-element_type=\"section\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;,&quot;shape_divider_top&quot;:&quot;triangle&quot;}\">\n\t\t\t\t\t<div class=\"elementor-shape elementor-shape-top\" aria-hidden=\"true\" data-negative=\"false\">\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewbox=\"0 0 1000 100\" preserveaspectratio=\"none\">\n\t<path class=\"elementor-shape-fill\" d=\"M500,98.9L0,6.1V0h1000v6.1L500,98.9z\"\/>\n<\/svg>\t\t<\/div>\n\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-930633c\" data-id=\"930633c\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-56d2cf8 elementor-widget elementor-widget-text-editor\" data-id=\"56d2cf8\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>There is already a similar <a href=\"https:\/\/github.com\/potionfactory\/LetsMove\" target=\"_blank\" rel=\"noopener\">Project<\/a> but I wanted a solution that can be implemented with pure on-board resources and does not require the installation of an extra framework. The result is \u201cLetsMoveIt\u201d. You only need to create a Swift file (in my case \u201cLetsMoveIt.swift\u201d) with the following content in your project. Of course you can place the \u201cToApps ()\u201d function in any other document, but I find a separate class somehow more elegant. But as is so often the case, it's a matter of taste and of course it's up to everyone to do it differently. (-:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-4c2d05d elementor-widget elementor-widget-code-block-for-elementor\" data-id=\"4c2d05d\" data-element_type=\"widget\" data-widget_type=\"code-block-for-elementor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<pre class='line-numbers theme-twilight' data-show-toolbar='yes'><code class='language-swift'>\/\/\n\/\/  LetsMoveIt.swift\n\/\/\n\/\/  Created by Sascha Lamprecht 04.06.2021\n\/\/\n\nimport Cocoa\n\nclass LetsMoveIt: NSViewController {\n    \n    func ToApps() {\n\n        let url = URL(fileURLWithPath: Bundle.main.resourcePath!)\n        var LaunchPath = url.deletingLastPathComponent().deletingLastPathComponent().absoluteString.replacingOccurrences(of: &quot;file:\/\/&quot;, with: &quot;&quot;).replacingOccurrences(of: &quot;%20&quot;, with: &quot; &quot;)\n        LaunchPath.removeLast()\n        let RealAppName = URL(fileURLWithPath: LaunchPath).lastPathComponent\n        \n        if LaunchPath.contains(&quot;\/Applications\/&quot;) {\n            return\n        }\n        if UserDefaults.standard.bool(forKey: &quot;Supress&quot;) {\n            return\n        }\n        \n        let alert = NSAlert()\n        alert.messageText = NSLocalizedString(&quot;Move to Applications folder?&quot;, comment: &quot;&quot;)\n        alert.informativeText = NSLocalizedString(&quot;I can move myself to the Applications folder if you&#039;d like. This will keep your Downloads folder uncluttered.&quot;, comment: &quot;&quot;)\n        alert.alertStyle = .informational\n        alert.showsSuppressionButton = true\n        let Button = NSLocalizedString(&quot;Do Not Move&quot;, comment: &quot;&quot;)\n        alert.addButton(withTitle: Button)\n        let CancelButtonText = NSLocalizedString(&quot;Move to Applications Folder&quot;, comment: &quot;&quot;)\n        alert.addButton(withTitle: CancelButtonText)\n\n        if alert.runModal() == .alertFirstButtonReturn {\n            if let supress = alert.suppressionButton {\n                let state = supress.state\n                switch state {\n                case NSControl.StateValue.on:\n                UserDefaults.standard.set(true, forKey: &quot;Supress&quot;)\n                default: break\n                }\n            }\n            return\n        }\n\n        let admin_check = &quot;user=$( id -un ); admin_check=$( groups \\&quot;$user\\&quot; | grep -w -q admin ); echo \\&quot;$admin_check\\&quot;&quot;\n        let process            = Process()\n        process.launchPath     = &quot;\/bin\/bash&quot;\n        process.arguments      = [&quot;-c&quot;, admin_check]\n        process.launch()\n        process.waitUntilExit()\n        \n        let fileManager = FileManager.default\n        let path = &quot;\/Applications\/&quot; + RealAppName\n            if admin_check.contains(&quot; admin &quot;) {\n                do {\n                    if fileManager.fileExists(atPath: path) {\n                        try fileManager.removeItem(atPath: path)\n                    }\n                    try fileManager.copyItem(atPath: LaunchPath, toPath: path)\n                    try fileManager.removeItem(atPath: LaunchPath)\n                } catch {\n                    return\n                }\n            } else {\n                let move_to_apps = &quot;osascript -e &#039;do shell script \\&quot;rm -rf \/Applications\/&quot; + RealAppName + &quot;; cp -r \\\\\\&quot;&quot; + LaunchPath + &quot;\\\\\\&quot; \/Applications\/; chown -R &quot; + NSUserName() + &quot;:staff \\\\\\&quot;\/Applications\/&quot; + RealAppName + &quot;\\\\\\&quot;; rm -r \\\\\\&quot;&quot; + LaunchPath + &quot;\\\\\\&quot;\\&quot; with administrator privileges&#039;&quot;\n                let process            = Process()\n                process.launchPath     = &quot;\/bin\/bash&quot;\n                process.arguments      = [&quot;-c&quot;, move_to_apps]\n                process.launch()\n                process.waitUntilExit()\n            }\n        let task = Process()\n        task.launchPath = &quot;\/usr\/bin\/open&quot;\n        task.arguments = [path]\n        task.launch()\n        exit(0)\n    }\n}<\/code><\/pre>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-3bdaecc elementor-widget elementor-widget-text-editor\" data-id=\"3bdaecc\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>The function can now be called from anywhere in the project using the following syntax. For example from AppDelegate.swift:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-4547206 elementor-widget elementor-widget-code-block-for-elementor\" data-id=\"4547206\" data-element_type=\"widget\" data-widget_type=\"code-block-for-elementor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<pre class='line-numbers theme-okaidia' data-show-toolbar='yes'><code class='language-javascript'>func applicationDidFinishLaunching(_ aNotification: Notification) {\n    LetsMoveIt().ToApps()\n}<\/code><\/pre>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-49377d3 elementor-widget elementor-widget-text-editor\" data-id=\"49377d3\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>The following dialog then opens if the application is not yet in \u201c\/ Applications\u201d:<br><\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-1fc91b0 elementor-widget elementor-widget-image\" data-id=\"1fc91b0\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img fetchpriority=\"high\" decoding=\"async\" width=\"674\" height=\"290\" src=\"https:\/\/www.sl-soft.de\/wp-content\/uploads\/2021\/06\/Bildschirmfoto-2021-06-05-um-13.47.18.png\" class=\"attachment-large size-large wp-image-1317\" alt=\"\" srcset=\"https:\/\/www.sl-soft.de\/wp-content\/uploads\/2021\/06\/Bildschirmfoto-2021-06-05-um-13.47.18.png 574w, https:\/\/www.sl-soft.de\/wp-content\/uploads\/2021\/06\/Bildschirmfoto-2021-06-05-um-13.47.18-16x8.png 16w, https:\/\/www.sl-soft.de\/wp-content\/uploads\/2021\/06\/Bildschirmfoto-2021-06-05-um-13.47.18-300x151.png 300w\" sizes=\"(max-width: 674px) 100vw, 674px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-21948cb elementor-widget elementor-widget-text-editor\" data-id=\"21948cb\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>You now have the option to move the application there.<br \/>If LetsMoveIt should also contain German, here are the corresponding strings:<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-b1a709c elementor-widget elementor-widget-code-block-for-elementor\" data-id=\"b1a709c\" data-element_type=\"widget\" data-widget_type=\"code-block-for-elementor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<pre class='line-numbers theme-okaidia' data-show-toolbar='yes'><code class='language-javascript'>\/* No comment provided by engineer. *\/\n&quot;Do Not Move&quot; = &quot;Nicht verschieben&quot;;\n\n\/* No comment provided by engineer. *\/\n&quot;I can move myself to the Applications folder if you&#039;d like. This will keep your Downloads folder uncluttered.&quot; = &quot;Ich kann mich selbst in den Programme-Ordner verschieben wenn Du m&ouml;chtest. Somit bleibt Dein Download-Ordner aufger&auml;umt.&quot;;\n\n\/* No comment provided by engineer. *\/\n&quot;Move to Applications Folder&quot; = &quot;In den Programme-Ordner verschieben&quot;;\n\n\/* No comment provided by engineer. *\/\n&quot;Move to Applications folder?&quot; = &quot;In den Programme-Ordner verschieben?&quot;;\n<\/code><\/pre>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<\/div>","protected":false},"excerpt":{"rendered":"<p>LetsMoveIt Es gibt zwar bereits schon ein \u00e4hnliches Projekt aber ich wollte eine L\u00f6sung die mit reinen Bordmitteln realisiert werden kann und keine Installation von einem extra Framework bedingt. Das Ergebnis ist &#8222;LetsMoveIt&#8220;. Man braucht lediglich nur eine eine Swift-Datei (in meinem Fall &#8222;LetsMoveIt.swift&#8220;) mit nachfolgendem Inhalt in seinem Projekt anlegen. Nat\u00fcrlich kann man die&hellip;&nbsp;<a href=\"https:\/\/www.sl-soft.de\/en\/swiftletsmoveit\/\" class=\"\" rel=\"bookmark\">Read More &raquo;<span class=\"screen-reader-text\">Swift &#8211; LetsMoveIt<\/span><\/a><\/p>","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"page-templates\/template-pagebuilder-full-width.php","meta":{"footnotes":""},"class_list":["post-1172","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.sl-soft.de\/en\/wp-json\/wp\/v2\/pages\/1172","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.sl-soft.de\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.sl-soft.de\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.sl-soft.de\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.sl-soft.de\/en\/wp-json\/wp\/v2\/comments?post=1172"}],"version-history":[{"count":130,"href":"https:\/\/www.sl-soft.de\/en\/wp-json\/wp\/v2\/pages\/1172\/revisions"}],"predecessor-version":[{"id":2102,"href":"https:\/\/www.sl-soft.de\/en\/wp-json\/wp\/v2\/pages\/1172\/revisions\/2102"}],"wp:attachment":[{"href":"https:\/\/www.sl-soft.de\/en\/wp-json\/wp\/v2\/media?parent=1172"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}