Mit dieser einfachen Zeile ermittelst Du eine Zufallszahl zwischen 0 und 100
let number = Int.random(in: 0 ... 100)
Mit dieser einfachen Zeile ermittelst Du eine Zufallszahl zwischen 0 und 100
let number = Int.random(in: 0 ... 100)
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: ""))
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 } }
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.
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.
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 }
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:
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:
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] ] ] }
Kurzes Snippet zum Öffnen eines Links in Safari in Swift.
if let url = URL(string: "https://www.exoda.de") { UIApplication.shared.open(url) }