Kategorien-Archiv Xcode Swift DE

VonTobias Stephan

Swift random Zufallszahl ermitteln

Mit dieser einfachen Zeile ermittelst Du eine Zufallszahl zwischen 0 und 100

let number = Int.random(in: 0 ... 100)
VonTobias Stephan

SwiftUI Lokalisierung mit mehreren Sprachen

Datei > Neu > File ->> Strings File erstellen > Name kann z.B.: Localizeable.Strings heissen.

Als nächstes im Fileinspector auf die neu erstellte Datei klicken und rechts im Bildschirm den Button Localizeable anklicken.

Syntax der Übersetzungen:
„welcometitle“ = „Welcome“;

…ganz wichtig, Semikolon am Ende nicht vergessen

Wenn man nun ein schreibt:

Text(„welcometitle“) – so wird der Text aus der Lokalisierung genommen.

Um eine Variable zu lokalisieren, verwendet man:

NSLocalizedString(sStringVar, comment: "")

Damit weitere Lokalisierungen hinzugefügt werden können, Die Lokalisierungsdatei links anklicken und rechts die Sprache auswählen.

Wie schon beschrieben kann man unter Swift UI zum Beispiel einfach

Text("lokalisierteVariable")

schreiben. Manchmal möchte man aber an mehreren Stellen Strings zusammensbauen. Dabei hilft

Text(NSLocalizedString("lokalisierteVariable", comment: ""))
VonTobias Stephan

Swift url validation – gültige URL mit regex prüfen

Mit dieser einfachen kleinen Funktion kannst Du prüfen ob eine URL valide ist.

    func isValidUrl(urlString: String) -> Bool {
        let pat = "((https|http)://)((\\w|-)+)(([.]|[/])((\\w|-)+))+"
        let regex = try! NSRegularExpression(pattern: pat, options: [])
        
        let matches = regex.numberOfMatches(in: urlString, options: [], range: NSMakeRange(0,urlString.utf16.count))
        if (matches == 1 ) {
            return true
        }
        else {
            return false
        }
    }
VonTobias Stephan

Firebase Invalid Key Type Error 401

Herrjeh, was ein Kampf! Eine halbe Ewigkeit habe ich nach der Lösung gesucht. Es muss einfach der richtige Serverschlüssel verwendet werden. Die im Titel erwähnte Fehlermeldung ereilte mich bei der Entwicklung einer C# Anwendung zum Verteilen von Push-Notifications auf IOS-Devices.

Über die Prejkteinstellungen gelangt man auf die korrekte Seite. Projekteinstellungen der entsprechenden App und dann auf Cloud Messaging.

VonTobias Stephan

Swift Leerzeichen aus String entfernen

So entfernst Du die Leerzeichen am Anfang und Ende eines Strings.

let str = "  Remove whitepaces  "
let trimmed = str.trimmingCharacters(in: .whitespaces)
print(trimmed)

Bei diesem Beispiel wird aus “ Remove whitepaces “ einfach nur „Remove Whitespaces“. Das Leerzeichen zwischen Remove und whitespaces bleibt dabei natürlich erhalten. .whitepaces ist eines der möglichen Charactersets.

VonTobias Stephan

SwiftUI Get Screen Width and Height Breite und Höhe

Wie kann man die Bildschirmbreite ermitteln. Füge die Extension in Dein SwiftUI File ein und Du hast eine einfach Möglichkeit um Elemente in optimaler Grösse zu platzieren. Schließlich sind die Breiten abhängig vom jeweiligen Device, iPhone, iPad und da die jeweiligen Modelle. Natürlich ist es innvoll alle Angaben relativ zu halten. So funktioniert Deine App auch auf künftigen Devices.

extension UIScreen{
   static let screenWidth = UIScreen.main.bounds.size.width
   static let screenHeight = UIScreen.main.bounds.size.height
   static let screenSize = UIScreen.main.bounds.size
}
VonTobias Stephan

SwiftUI Rectangle Circle Ellipse Capsule RoundedRectangle

SwiftUI bietet uns fünf integrierte Formen, die häufig verwendet werden: Rechteck, abgerundetes Rechteck, Kreis, Ellipse und Kapsel. Insbesondere die letzten drei unterscheiden sich in ihrem Verhalten je nach den von Ihnen bereitgestellten Größen, aber wir können alle Optionen an einem Beispiel demonstrieren:

struct ContentView: View {
    var body: some View {
        ZStack {
            Rectangle()
                .fill(Color.black)
                .frame(width: 200, height: 200)

            RoundedRectangle(cornerRadius: 25, style: .continuous)
                .fill(Color.red)
                .frame(width: 200, height: 200)

            Capsule()
                .fill(Color.green)
                .frame(width: 100, height: 50)

            Ellipse()
                .fill(Color.blue)
                .frame(width: 100, height: 50)

            Circle()
                .fill(Color.white)
                .frame(width: 100, height: 50)
        }
    }
}

Das zeichnet alle fünf Formen: zwei im Format 200×200 und drei im Format 100×50. Da das Zeichenverhalten der Formen jedoch unterschiedlich ist, Du wirst alle fünf Formen in der Ausgabe sehen:

  • Rechteck zeichnet einen Kasten in genau den von Ihnen angegebenen Abmessungen
  • RoundedRectangle macht dasselbe, nur dass Sie jetzt die Ecken um einen bestimmten Betrag runden können. Der zweite Parameter, der Stil, bestimmt, ob Sie die klassischen abgerundeten Ecken (.circular) oder Apples etwas glattere Alternative (.continuous) wünschen.
  • Die Kapsel zeichnet einen Kasten, bei dem eine Kantenachse vollständig abgerundet ist, je nachdem, ob die Höhe oder die Breite am größten ist. Unsere Form ist 100×50, so dass sie links und rechts abgerundete Kanten hat, während sie am oberen und unteren Rand gerade ist.
  • Ellipse zeichnet eine Ellipse in genau den angegebenen Abmessungen.
  • Der Kreis zeichnet eine Ellipse, bei der Höhe und Breite gleich sind. Wenn wir also 100×50 für den Raum zur Verfügung stellen, erhalten wir tatsächlich 50×50.
VonTobias Stephan

swiftui imagepicker camera oder library

Du siehst hier ein komplettes Demo-Projekt, dass leicht wiederverwertbar ist. Einfach ein neues XCode Projekt anlegen und mit Copy-Paste in die Datei ContentView.Swift alles einfügen bzw. den vorhandenen standardmässig erstellten Code ersetzen. Ganz wichtig ist jedoch Deine erste Tat im neuen Projekt. Füge folgende Zeilen in die Info.plist ein.

NSCameraUsageDescription
Take Pictures
NSPhotoLibraryUsageDescription
Take Pictures

Wenn Du mit der rechten Maustaste auf Deine Info.plist klickst kannst du im Kontextmenü auf „Open as Source“ klicken. Diese Eigentschaften sind erforderlich, damit Deine App die erforderliche Berechtigung erhält auf die Photolibrary bzw. auf die Kamera zuzugreifen. Apple möchte dem User eine Begründung für den Zugriff nennen können. Sinnvolle Entscheidung. Vergisst man diesen Eintrag, kann das gleich zu einem Crash Deiner app führen.

//
//  ContentView.swift
//  PhototestII
//
//  Created by T. Stephan on 08.03.20.
//  Copyright © 2020 eCommerce - Tobias Stephan. All rights reserved.
//

import SwiftUI

struct ContentView: View {
    @State private var image: Image?
    
    @State private var showingImagePicker = false
    @State private var inputImage: UIImage?
    
    @State var ImagePickerSource: UIImagePickerController.SourceType = .photoLibrary
    
    var body: some View {
        NavigationView{
            VStack{
                ZStack{
                    Rectangle()
                        .fill(Color.secondary)
                    if image != nil {
                        image?
                            .resizable()
                            .scaledToFit()
                    } else {
                        Text("Tap to take photo!")
                            .foregroundColor(.white)
                            .font(.headline)
                    }
                }
                .onTapGesture {
                    self.showingImagePicker = true
                    self.ImagePickerSource = .camera
                }
                
                Button(action: {
                    self.showingImagePicker = true
                    self.ImagePickerSource = .photoLibrary
                })
                { Text("Library")}
                
                
            }
        }
        .padding([.horizontal, .bottom])
        .navigationBarTitle("Filter")
        .sheet(isPresented: $showingImagePicker, onDismiss: loadImage) {
            
            //   ImagePicker(image: self.$inputImage)
            ImagePicker(image: self.$inputImage, ImagePickerSource: self.ImagePickerSource)
            
        }
    }
    
    func loadImage() {
        guard let inputImage = inputImage else { return }
        image = Image(uiImage: inputImage)
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}


struct ImagePicker: UIViewControllerRepresentable {
    @Environment(\.presentationMode) var presentationMode
    @Binding var image: UIImage?
    @State var ImagePickerSource: UIImagePickerController.SourceType = .photoLibrary
    
    class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
        let parent: ImagePicker
        
        init(_ parent: ImagePicker) {
            self.parent = parent
            
        }
        
        func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
            
            if let uiImage = info[.originalImage] as? UIImage {
                parent.image = uiImage
            }
            
            parent.presentationMode.wrappedValue.dismiss()
        }
    }
    
    
    func makeUIViewController(context: UIViewControllerRepresentableContext) -> UIImagePickerController {
        let picker = UIImagePickerController()
        picker.delegate = context.coordinator
        picker.sourceType =  self.ImagePickerSource
        picker.allowsEditing = false
        return picker
    }
    
    func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext) {
        
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    
}

Und so sieht das Ergebnis dann aus:

Imagepicker Demo SwiftUI
ImagePicker Demo from Library or take aphoto
VonTobias Stephan

Swift UI Systemsound abspielen

So lässt sich mit einfachen Mitteln und wenig code ein Systemsound abspielen

// import this
import AVFoundation

// create a sound ID, in this case its the tweet sound.
let systemSoundID: SystemSoundID = 1016

// to play sound
AudioServicesPlaySystemSound (systemSoundID)

Als fertiges SwiftUI Sample:

//
//  ContentView.swift
//  SwiftUIPlaySystemSoundDemo
//
//  Created by T. Stephan on 07.05.20.
//  Copyright © 2020 eCommerce - Tobias Stephan. All rights reserved.
//

import SwiftUI
import AVFoundation


struct ContentView: View {
    var body: some View {

        VStack {
            Button( action: {
                // import this


                // create a sound ID, in this case its the tweet sound.
                let systemSoundID: SystemSoundID = 1016

                // to play sound
                AudioServicesPlaySystemSound (systemSoundID)

            }){
                Text("Play Sound")
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

Hier eine fertige Klasse für die Systemsounds:

//
//  SystemSounds.swift
//  Listory
//
//  Created by T. Stephan on 08.03.20.
//  Copyright © 2020 eCommerce - Tobias Stephan. All rights reserved.
//

import Foundation
import AVFoundation

class SystemSound {
    
    /**Spielt einen Systemsound ab*/
    public func PlaySystemSound(systemSoundID: SystemSoundID) {
        
        AudioServicesPlaySystemSound (systemSoundID)
    }
    


    public let Voicemail : SystemSoundID = 1015
    public let AudioToneBusy : SystemSoundID = 1070
    public let AudioToneError : SystemSoundID = 1073
    public let Telegraph : SystemSoundID = 1033

    var library = ["category" : [
        "-": ["Voicemail.caf": 1015],
        "AudioToneBusy" : ["ct-busy.caf": 1070],
        "AudioToneCallWaiting" : ["ct-call-waiting.caf" : 1074],
        "AudioToneCongestion" : ["ct-congestion.caf": 1071],
        "AudioToneError" : ["ct-error.caf" : 1073],
        "AudioToneKey2" : ["ct-keytone2.caf" : 1075],
        "AudioTonePathAcknowledge" : ["ct-path-ack.caf" : 1072],
        "BeginRecording" : ["begin_record.caf" : 1113],
        "BeginVideoRecording" : ["begin_video_record.caf" : 1117],
        "CalendarAlert" : ["alarm.caf" : 1005],
        "CameraShutter" : ["photoShutter.caf": 1108],
        "ConnectedToPower" : ["beep-beep.caf" : 1106],
        "EndRecording" : ["end_record.caf" : 1114],
        "EndVideoRecording" : ["end_video_record.caf" : 1118],
        "FailedUnlock" : ["-" : 1102],
        "Headset_AnswerCall" : ["short_low_high.caf" : 1256],
        "Headset_CallWaitingActions" : ["short_double_low.caf" : 1258],
        "Headset_EndCall" : ["short_double_low.caf": 1257],
        "Headset_Redial" : ["short_double_high.caf" : 1255],
        "Headset_StartCall" : ["long_low_short_high.caf" : 1254],
        "Headset_TransitionEnd" : ["middle_9_short_double_low.caf" : 1259],
        "JBL_Ambiguous" : ["jbl_ambiguous.caf" : 1115],
        "JBL_Begin" : ["jbl_begin.caf" : 1110],
        "JBL_Cancel" : ["jbl_cancel.caf" : 1112],
        "JBL_Confirm" : ["jbl_confirm.caf" : 1111],
        "JBL_NoMatch" : ["jbl_no_match.caf" : 1116],
        "KeyPressClickPreview" : ["Tock.caf" : 1306],
        "KeyPressed" : ["Tink.caf" : 1103,
                        "Tock.caf" : 1104,
                        "Tock1.caf" : 1105],
        "LowPower" : ["low_power.caf": 1006],
        "MailReceived" : ["new-mail.caf" : 1000],
        "MailSent" : ["mail-sent.caf" : 1001],
        "PINKeyPressed" : ["Tink.caf" : 1057],
        "RingerSwitchIndication" : ["RingerChanged.caf" : 1107],
        "RingerVibeChanged" : ["-" : 1350],
        "ScreenLocked" : ["lock.caf" : 1100],
        "ScreenUnlocked" : ["unlock.caf" : 1101],
        "ShakeToShuffle" : ["shake.caf" : 1109],
        "SilentVibeChanged" : ["-" : 1351],
        "SIMToolkitTone" : ["SIMToolkitCallDropped.caf" : 1051,
                            "SIMToolkitGeneralBeep.caf" : 1052,
                            "SIMToolkitNegativeACK.caf" : 1053,
                            "SIMToolkitPositiveACK.caf" : 1054,
                            "SIMToolkitSMS.caf" : 1055],
        "SMSReceived" : ["ReceivedMessage.caf" : 1003],
        "SMSReceived_Alert" : ["sms-received1.caf" : 1007,
                               "sms-received2.caf" : 1008,
                               "sms-received3.caf" : 1009,
                               "sms-received4.caf" : 1010,
                               "sms-received12.caf" : 1012,
                               "sms-received5.caf" : 1013,
                               "sms-received6.caf" : 1014,
                               "Anticipate.caf" : 1020,
                               "Bloom.caf" : 1021,
                               "Calypso.caf" : 1022,
                               "Choo_Choo.caf" : 1023,
                               "Descent.caf" : 1024,
                               "Fanfare.caf" : 1025,
                               "Ladder.caf" : 1026,
                               "Minuet.caf" : 1027,
                               "News_Flash.caf" : 1028,
                               "Noir.caf" : 1029,
                               "Sherwood_Forest.caf" : 1030,
                               "Spell.caf" : 1031,
                               "Suspense.caf" : 1032,
                               "Telegraph.caf" : 1033,
                               "Tiptoes.caf" : 1034,
                               "Typewriters.caf" : 1035,
                               "Update.caf" : 1036],
        "SMSReceived_Selection" : ["sms-received1.caf" : 1307,
                                   "sms-received2.caf" : 1308,
                                   "sms-received3.caf" : 1309,
                                   "sms-received4.caf" : 1310,
                                   "sms-received1_1.caf" : 1312,
                                   "sms-received5.caf" : 1313,
                                   "sms-received6.caf" : 1314,
                                   "Anticipate.caf" : 1320,
                                   "Bloom.caf" : 1321,
                                   "Calypso.caf" : 1322,
                                   "Choo_Choo.caf" : 1323,
                                   "Descent.caf" : 1324,
                                   "Fanfare.caf" : 1325,
                                   "Ladder.caf" : 1326,
                                   "Minuet.caf" : 1327,
                                   "News_Flash.caf" : 1328,
                                   "Noir.caf" : 1329,
                                   "Sherwood_Forest.caf" : 1330,
                                   "Spell.caf" : 1331,
                                   "Suspense.caf" : 1332,
                                   "Telegraph.caf" : 1333,
                                   "Tiptoes.caf" : 1334,
                                   "Typewriters.caf" : 1335,
                                   "Update.caf" : 1336,
                                   "-" : 1011,
                                   "--" : 1311],
        "SMSSent" : ["SentMessage.caf" : 1004,
                     "tweet_sent.caf" : 1016 ],
        "SystemSoundPreview" : ["Voicemail.caf" : 1300,
                                "ReceivedMessage.caf" : 1301,
                                "new-mail.caf" : 1302,
                                "mail-sent.caf" : 1303,
                                "alarm.caf" : 1304,
                                "lock.caf" : 1305,
                                "Voicemail_1.caf" : 1315],
        "TouchTone" : ["dtmf-0.caf" : 1200,
                       "dtmf-1.caf" : 1201,
                       "dtmf-2.caf" : 1202,
                       "dtmf-3.caf" : 1203,
                       "dtmf-4.caf" : 1204,
                       "dtmf-5.caf" : 1205,
                       "dtmf-6.caf" : 1206,
                       "dtmf-7.caf" : 1207,
                       "dtmf-8.caf" : 1208,
                       "dtmf-9.caf" : 1209,
                       "dtmf-star.caf" : 1210,
                       "dtmf-pound.caf" : 1211],
        "USSDAlert" : ["ussd.caf" : 1050],
        "VCCallUpgrade" : ["vc~ringing.caf" : 1154],
        "VCCallWaiting" : ["ct-call-waiting.caf" : 1153],
        "VCEnded" : ["vc~ended.caf" : 1152],
        "VCInvitationAccepted" : ["vc~invitation-accepted.caf" : 1150],
        "VCRinging" : ["vc~ringing.caf" : 1151],
        "Vibrate" : ["-" : 4095],
        "VoicemailReceived" : ["Voicemail.caf" : 1002]
        
        ]
    ]
}

VonTobias Stephan

Swift UI open Link URL in Safari Browser

Kurzes Snippet zum Öffnen eines Links in Safari in Swift.

if let url = URL(string: "https://www.exoda.de") {
    UIApplication.shared.open(url)
}