How to print the current local network name in swift - swift

I am creating an iOS app which displays the current local network name at the top of the screen, and so forth. I am trouble-shooting different ways to display this but I can't manage the current program. Can someone help me out?
I've looked at several GitHub, stack overflow, and youtube comments about this, but nome of them worked.
In the current Xcode I'm using which is Xcode(10.4.2) I'm using a label(correct me if I should use something else) to display the current Wifi named --> (WiFi: ......)

Please don't test on the simulator, use the iphone for testing.
Import SystemConfiguration :
import SystemConfiguration.CaptiveNetwork
In ViewDidLoad :
let wifiName = getWiFiName()
print("Wifi: \(String(describing: wifiName))")
Function :
func getWiFiName() -> String? {
var serviceSetIdentifier:String?
if let interfaces = CNCopySupportedInterfaces() as Array? {
interfaces.forEach { interface in
guard let interfaceInfo = CNCopyCurrentNetworkInfo(interface as! CFString) as NSDictionary? else { return }
serviceSetIdentifier = interfaceInfo[kCNNetworkInfoKeySSID as String] as? String
}
}
return serviceSetIdentifier
}

Related

Better way to get the frontmost window of an Application - Swift

its not hard to get a specified application by name
NSWorkspace.shared.runningApplications.filter{$0.localizedName == "Safari"}.first
but how to get the first window of this application, and perform miniaturize with this window?
something similar with this
let app = NSWorkspace.shared.runningApplications.filter{$0.localizedName == "Safari"}.first
app.frontmostWindow.miniaturize()
You can do this using the ScriptingBridge
import ScriptingBridge
let safari = SBApplication(bundleIdentifier: "com.apple.Safari")
let windowClass = appleEvent(keyword: "cwin")
let miniaturized = appleEvent(keyword: "pmnd")
let windows = safari?.elementArray(withCode: windowClass)
let frontMostWindow = (windows?.firstObject as? SBObject)?.get() as? SBObject
frontMostWindow?.property(withCode: miniaturized).setTo(true)
func appleEvent(keyword: StaticString) -> AEKeyword {
keyword
.utf8Start
.withMemoryRebound(to: DescType.self, capacity: 1, \.pointee)
.bigEndian
}
To be able to run this code you will need a code signed app with the com.apple.security.automation.apple-events entitlement set to true (which allows posting of AppleEvents to other applications)

RealmSwift number of existing object is always 4, at start of program

I am using RealmSwift to create a PIN code screen for an app. I have a manager class that has a few functions, including checkForExistingPin() which is intended to be used to check whether a pin exists (as the name suggests).
When I create an instance of the manager class and call the checkForExistingPin() function, it always tells me that there are 4 (It prints: "Optional(4)"), even though I have not created a pin yet.
Can anyone explain why this might be doing this and how I might get the correct output from the code?
Here is the class:
import Foundation
import RealmSwift
class pinCode: Object {
#objc dynamic var pin = ""
}
protocol pinCodeManager {
func checkForExistingPin() -> Bool
func enterNewPin(newPin:String)
func checkPin(pin:String) -> Bool
}
class manager:pinCodeManager {
let realm = try! Realm()
func checkForExistingPin() -> Bool {
let existingCode = realm.objects(pinCode.self).first?.pin
print("\n\nNumber of existing PINs: ", existingCode?.count as Any, "\n\n") // Number of existing PINs: Optional(4)
if existingCode?.count == 0 {
return false
}
else {
return true
}
}
func enterNewPin(newPin:String) {
if checkForExistingPin() {
let oldCode = realm.objects(pinCode.self).first
try! realm.write {
oldCode!.pin = newPin
}
}
let newPinObject = pinCode()
newPinObject.pin = newPin
realm.add(newPinObject)
}
func checkPin(pin:String) -> Bool {
if checkForExistingPin() {
print ("Realm object first: ", realm.objects(pinCode.self).first?.pin as Any)
if pin == realm.objects(pinCode.self).first?.pin {
print ("Pin Correct")
return true
}
else {
print ("Pin Incorrect")
return false
}
}
print ("No existing pin")
return false
}
}
And here is the relevant code snippet of the ViewController:
class InitialViewController: UIViewController {
let myPin = pinCode()
let myManager = manager()
let realm = try! Realm()
#IBAction func NewUserButton(_ sender: Any) {
print("No existing PINs: ", self.myManager.checkForExistingPin())
}
The output is : Number of existing PINs: Optional(4)
You must have created a pinCode object (or multiple of them). "Optional(4) doesn't mean you have created 4 pins. You are counting String. It means that the object you retrieved has a 4 digit pin. If you haven't created any pinCode object, you should get nil. Or if you have created one without assigning a pin, you should get 0.
I recommend your looking at your realm file. You should be able to print out its location this way:
print(Realm.Configuration.defaultConfiguration.fileURL!)
You can then open the file with Realm Studio and verify what is in there.
You have a few things going on here:
Although this is not really in the scope of the question, here's a tip for the future. Your types' names should be capitalized (following CamelCase standard), as per Swift API Design Guidelines. Thus, your pinCodes and manager classes and pinCodeManager protocol should be called PinCode, Manager and PinCodeManager respectively.
Assuming you renamed your types and as other users pointed out, you're not counting instances of PinCode. You're counting the length of the pin member of PinCode class. Refactoring your checkForExistingPin() function:
func checkForExistingPin() -> Bool {
return realm.objects(pinCode.self).count > 0
}
In your enterNewPin(newPin:) function, in the case you already have a PinCode object stored, note that you are actually updating the old PinCode and adding a new one with the same pin. For instance, if you previously have a PinCode object stored with pin=1234. After calling enterNewPin(newPin: "5678") you will have two such objects stored with the pin=5678. You might want to refactor that as well:
func enterNewPin(newPin:String) {
if checkForExistingPin() {
let oldCode = realm.objects(pinCode.self).first
try! realm.write {
oldCode!.pin = newPin
}
} else {
let newPinObject = pinCode()
newPinObject.pin = newPin
try! realm.write {
realm.add(newPinObject)
}
}
}
Before trying to do any debugging in your app. I recommend you first uninstalling and then reinstalling the app wherever you running (simulator or actual device). If things keep behaving weird, that's probably something related with your configuration if you're overriding the default one (i.e. I noticed that you just used try! Realm() for retrieving a Realm, but you might have overridden Realm.Configuration.defaultConfiguration somewhere else).
Hope that helps!

Get data from Firebase and display in TableViewCell as post

I don't know how to get data from Firebase to my UITableView. All tutorials I have been watching used Firebase Authentication, in their videos all worked out fine but while trying to replicate it, I failed.
Here is what I tried:
First there is my Database struct:
And here is my code:
func observePosts(){
let postsRef = Database.database().reference().child("posts")
postsRef.observe(.value, with: { snapshot in
var tempPosts = [Post]()
for child in snapshot.children {
if let childSnapshot = child as? DataSnapshot,
let dict = childSnapshot.value as? [String:Any],
let text = dict["text":""] as? String
{
let post = Post(text: text)
tempPosts.append(post)
}
}
self.posts = tempPosts
self.tableView.reloadData()
})
}
So my question is: How do I get for example the message from a database structure like this?
let text = dict["text":""] as? String {
let post = Post(text: text)
tempPosts.append(post) }
This is wrong. There is nothing like dict["text":""] . First you dont have any data for text keyword , Second you dont write this :""] , you can call as dict["text"].
I think you solution is let text = dict["title"] as? String . But you architecture is wrong. You can declare just one keyword . title 1 , title 2 is wrong. You have to set just title.
If you have followed YouTube tutorials, there's a high chance you did not modify your firebase rules to reflect on non-authenticated users. If you didn't, Firebase ignores every read/write request. To enable this, Edit your firebase rules by:
Set the rules to TRUE
{
"rules": {
".read": true,
".write": true
}
}
However, there's more to it. Don't do it this way unless you're in test mode. Google has some nice docs about it:
Visit https://firebase.google.com/docs/database/security to learn more about security rules.

Swift How do you edit the Metadata (ID3) of a .mp3 file in macOS

Swift How do you edit the Metadata (ID3) of a .mp3 file in macOS
I am writing a macOS app and have been trying for some while to change the wording in section of ‘More Info’ in an .mp3 and have done much searching of SO and found 2 snippets of code that will read the metadata but only one actually outputs the existing keys but I don’t understand how to write new data to any of them. I actually want to write data to a .mp3 file I have created and add an image if possible, as a newbie with some knowledge in Swift 3 can anybody help please. The output below is from a test song (Imagine_Test_Song) I have copied to my desktop.
I found this on SO Writing ID3 tags via AVMetaDataItem but I get a compiling error in these lines :-
soundFileMetadata.append(createMetadata(AVMetadataiTunesMetadataKeyArtist, "MyArtist")!) // compiler error here
soundFileMetadata.append(createMetadata(AVMetadataiTunesMetadataKeySongName, "MySong")!)
….
which says :- Missing argument label 'tagKey' in call. The func is this :-
func createMetadata(tagKey: String, _ tagValue: AnyObject?,
keySpace:String = AVMetadataKeySpaceiTunes) -> AVMutableMetadataItem? {
if let tagValue = tagValue {
let tag = AVMutableMetadataItem()
tag.keySpace = keySpace
tag.key = tagKey as NSCopying & NSObjectProtocol
tag.value = (tagValue as? String as! NSCopying & NSObjectProtocol) ?? (tagValue as? Int as! NSCopying & NSObjectProtocol)
return tag
}
return nil
}
Second snippet is my code below which does compile and outputs the various data but how do you edit the text and save the changes. Ideally I would also like to add “artwork” as well, is this possible?
let homeUrl = NSHomeDirectory()
let sourceFilePath = String(format: "%#/Desktop/%#.mp3", homeUrl, " Imagine_Test_Song")
let fileUrl = NSURL(fileURLWithPath: sourceFilePath)
var asset = AVAsset(url: fileUrl as URL) as AVAsset
//using the asset property to get the metadata of file
for metaDataItems in asset.commonMetadata {
//getting the title of the song
if metaDataItems.commonKey == "title" {
let titleData = metaDataItems.value as! NSString
print("title = \(titleData)")
}
//getting the "Artist of the mp3 file"
if metaDataItems.commonKey == "artist" {
let artistData = metaDataItems.value as! NSString
print("artist = \(artistData)")
}
//getting the "creator of the mp3 file"
if metaDataItems.commonKey == "creator" {
let creatorData = metaDataItems.value as! NSString
print("creator = \(creatorData)")
}
//getting the "Album of the mp3 file"
if metaDataItems.commonKey == "albumName" {
let albumNameData = metaDataItems.value as! NSString
print("albumName = \(albumNameData)")
}
Output :-
title = Imagine
creator = John Lennon
type = Singer-Songwriter
albumName = Imagine
Any help would be appreciated, thanks in advance.
After a lot of research on this issue, it seems the ability to modify and save AVMetaDataItems to an MP3 file is impossible using the AVFoundation API calls (even though the mp3 file type is listed as an option) due to licensing issues with MP3 files. So, the only way to do this, as far as I know, is to either roll your own id3 tag editor, or use a library/framework from another author.
I do not personally like using frameworks or libraries from other authors that do not provide the full source code because I have run into problems when the author stops maintaining the project and Apple changes something and the change breaks my apps.
However, I have found ID3TagEditor library by Fabrizio Duroni. Full source is available on github here. It's a straight forward and easy to use library. Fabrizio is actively maintaining the code as of this writing.

How to get e-mail subject from message:// URL in OSX Swift

I have a desktop app that receives e-mail URLs ("message://" scheme) from the drag&drop pasteboard and I want to get the Subject from the relevant message. The only clue I have, so far, is that the QuickLook library might give me an information object where I can retrieve this info from.
Since the QuickLook API seems to be rather in flux at the moment and most examples show how to use it in iOS, I simply cannot find a way to set up my "Preview" object using a URL and get the information from there.
I would like to avoid setting up my project as a QuickLook plugin, or setting up the whole preview pane / view scaffolding; at the moment I just want to get out what QuickLook loads before it starts displaying, but I can't comprehend what paradigm Apple wants me to implement here.
XCode 7.3.1.
It turns out I misinterpreted the contents of draggingInfo.draggingPasteboard().types as a hierarchical list containing only one type of info (URL in this case).
Had to subscribe to dragged event type kUTTypeMessage as String and retrieve the e-mail subject from the pasteboard with stringForType("public.url-name")
EDIT: Note that the current Mail.app will sometimes create a stack of mails when you drag an e-mail thread. Although the method above still works to get the subject of the stack, there is no URL in the dragging info then and since there's no list of Message-IDs available either, I had to resort to scraping the user's mbox directory:
// See if we can resolve e-mail message meta data
if let mboxPath = pboard.stringForType("com.apple.mail.PasteboardTypeMessageTransfer") {
if let automatorPlist = pboard.propertyListForType("com.apple.mail.PasteboardTypeAutomator") {
// Get the latest e-mail in the thread
if let maxID = (automatorPlist.allObjects.flatMap({ $0["id"]! }) as AnyObject).valueForKeyPath("#max.self") as? Int {
// Read its meta data in the background
let emailItem = draggingEmailItem
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
// Find the e-mail file
if let path = Util.findEmlById(searchPath: mboxPath, id: maxID) {
// Read its contents
emailItem.properties = Util.metaDataFromEml(path)
dispatch_async(dispatch_get_main_queue(), {
// Update UI
});
}
}
}
}
}
Util funcs:
/* Searches the given path for <id>.eml[x] and returns its URL if found
*/
static func findEmlById(searchPath searchPath: String, id: Int)-> NSURL? {
let enumerator = NSFileManager.defaultManager().enumeratorAtPath(searchPath)
while let element = enumerator?.nextObject() as? NSString {
switch (element.lastPathComponent, element.pathExtension) {
case (let lpc, "emlx") where lpc.hasPrefix("\(id)"):
return NSURL(fileURLWithPath: searchPath).URLByAppendingPathComponent(element as String)!
case (let lpc, "eml") where lpc.hasPrefix("\(id)"):
return NSURL(fileURLWithPath: searchPath).URLByAppendingPathComponent(element as String)!
default: ()
}
}
return nil
}
/* Reads an eml[x] file and parses it, looking for e-mail meta data
*/
static func metaDataFromEml(path: NSURL)-> Dictionary<String, AnyObject> {
// TODO Support more fields
var properties: Dictionary<String, AnyObject> = [:]
do {
let emlxContent = try String(contentsOfURL: path, encoding: NSUTF8StringEncoding)
// Parse message ID from "...\nMessage-ID: <...>"
let messageIdStrMatches = emlxContent.regexMatches("[\\n\\r].*Message-ID:\\s*<([^\n\r]*)>")
if !messageIdStrMatches.isEmpty {
properties["messageId"] = messageIdStrMatches[0] as String
}
}
catch {
print("ERROR: Failed to open emlx file")
}
return properties
}
Note: If your app is sandboxed you will need the com.apple.security.temporary-exception.files.home-relative-path.read-only entitlement set to an array with one string in it: /Library/