How to initiate email on xcode for mac app - macos

i'm developing a mac app that requires email access
here's the code i've tried on ios
-(IBAction)Contact us:(id)sender {
//Email Subject
NSString *emailTitle = #"";
//Email Content
NSString *messageBody = #"";
//Email Address
NSArray *toRecipients =[NSArray arrayWithObject:#"info#mandarin-espeak.com"];
MFMailComposeViewController *mc = [[MFMailComposeViewController alloc] init];
mc.mailComposeDelegate = self;
[mc setSubject:emailTitle];
[mc setMessageBody:messageBody isHTML:YES];
[mc setToRecipients:toRecipients];
}
how can i do it on a mac app to open default email client

In MacOS you can easily send e-mails like this:
class SendEmail: NSObject {
static func send() {
let service = NSSharingService(named: NSSharingServiceNameComposeEmail)!
service.recipients = ["abc#dom.com"]
service.subject = "Vea software"
service.performWithItems(["This is an email for auto testing through code."])
}
}
Usage:
SendEmail.send()

I ended up going with an AppleScript solution. This is a one off app, not for the store, so I turned sandboxing off. I also added Privacy - AppleEvents Sending Usage Description to the info.plist and in the Hardened Runtime under Signing and Capabilities checked Apple Events
My email code, shouldn't be too hard to pan out my unique stuff:
func emailUser(_ thisUser:NSManagedObject) {
let dictSIPResponse = checkSIPforAppIdentifier("com.microsoft.Outlook")
if let bIsSIPEnabled = dictSIPResponse["isSIPEnabled"] as? Bool, let strSIPMessage = dictSIPResponse["sipMessage"] as? String{
if bIsSIPEnabled {
if let thisWriter = thisUser as? Writer, let strEmailAddress = thisWriter.email {
let outlookScript = """
if application "Outlook" is running then
tell application "Outlook"
set newMessage to make new outgoing message with properties {subject:"Hooray for automation"}
make new recipient at newMessage with properties {email address:{name:"Steve Suranie", address:"steven.suranie#xandr.com"}}
send newMessage
end tell
end if
"""
var out: NSAppleEventDescriptor?
if let scriptObject = NSAppleScript(source: outlookScript) {
var errorDict: NSDictionary? = nil
out = scriptObject.executeAndReturnError(&errorDict)
if let error = errorDict {
print(error)
}
}
}
} else {
print(strSIPMessage)
}
}
}
Before trying to email with the AppleScript I check to ensure the permissions have been set:
func checkSIPforAppIdentifier(_ sipIdentifier:String) -> Dictionary<String, Any> {
var dictSIPResponse = [String:Any]()
var targetAppEventDescriptor = NSAppleEventDescriptor(bundleIdentifier: sipIdentifier)
var status = AEDeterminePermissionToAutomateTarget(targetAppEventDescriptor.aeDesc, typeWildCard, typeWildCard, true);
switch (status) {
case -600: //procNotFound
dictSIPResponse["isSIPEnabled"] = false
dictSIPResponse["sipMessage"] = "Not running app with id \(sipIdentifier)"
break;
case 0: // noErr
dictSIPResponse["isSIPEnabled"] = true
dictSIPResponse["sipMessage"] = "SIP check successfull for app with id \(sipIdentifier)"
break;
case -1744: // errAEEventWouldRequireUserConsent
// This only appears if you send false for askUserIfNeeded
dictSIPResponse["isSIPEnabled"] = false
dictSIPResponse["sipMessage"] = "User consent required for app with id \(sipIdentifier)"
break;
case -1743: //errAEEventNotPermitted
dictSIPResponse["isSIPEnabled"] = false
dictSIPResponse["sipMessage"] = "User didn't allow usage for app with id \(sipIdentifier)"
// Here you should present a dialog with a tutorial on how to activate it manually
// This can be something like
// Go to system preferences > security > privacy
// Choose automation and active [APPNAME] for [APPNAME]
default:
break;
}
return dictSIPResponse
}

Related

SwiftUI trigger function when notification is sent?

I currently have a system that can send notifications to the phone in my app. I would like to perform a function every time that notification is sent? Any help is appreciated.
My current code for creating a notification.
static func addNotification(sub: SubscriptionItem){
let center = UNUserNotificationCenter.current()
let addRequest = {
let content = UNMutableNotificationContent()
content.title = "\(sub.name)"
content.subtitle = "€\(sub.price) due in \(sub.daysBefore) day(s)"
content.sound = UNNotificationSound.default
var dateComponents = DateComponents()
dateComponents.day = Calendar.current.dateComponents([.day], from: sub.nextpayment).day
let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
let request = UNNotificationRequest(identifier: sub.id, content: content, trigger: trigger)
center.add(request)
}
center.getNotificationSettings { settings in
if settings.authorizationStatus == .authorized{
addRequest()
}
else{
center.requestAuthorization(options: [.alert, .badge, .sound]) { success, error in
if success{
addRequest()
}
}
}
}
}

Xcode Apple Watch project, local notification not being presented?

I am trying to present a local notification on an Apple Watch simulator with a button. This is the code:
#IBAction func buttonOne() {
print("button one pressed")
let content = UNMutableNotificationContent()
content.title = NSString.localizedUserNotificationString(forKey: "Notified!", arguments: nil)
content.body = NSString.localizedUserNotificationString(forKey: "This is a notification appearing!", arguments: nil)
// Deliver the notification in five seconds.
content.sound = UNNotificationSound.default()
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5,
repeats: false)
// Schedule the notification.
let request = UNNotificationRequest(identifier: "Notify", content: content, trigger: trigger)
center.add(request) { (error : Error?) in
if let theError = error {
print(theError.localizedDescription)
} else {
print("successful notification")
}
}
}
The console is successfully printing "successful notification," but the notification never appears on the watch simulator. I have no idea why this is
1) Before scheduling a notification, request permissions. Use requestAuthorization method, for example:
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options: [.alert, .sound]) { (granted, error) in
// Enable or disable features based on authorization
}
2) Notifications will not appear on watch face if the application is running in foreground. Considering this you may use cmd + H to hide the app.

Core Data Error: "Can't find model for source store"

I just deleted an attribute of my entity inside CoreData and after that this error appears:
2016-02-02 21:37:54.499 toRep_Management[32110:4679391] CoreData: error: -addPersistentStoreWithType:XML configuration:(null) URL:file:///Users/Tom/Library/Application%20Support/de.toEducate.toRep_Management/CocoaAppCD.storedata options:{
NSInferMappingModelAutomaticallyOption = 1;
NSMigratePersistentStoresAutomaticallyOption = 1;
} ... returned error Error Domain=NSCocoaErrorDomain Code=134130 "Persistent store migration failed, missing source managed object model." UserInfo={URL=file:///Users/Tom/Library/Application%20Support/de.toEducate.toRep_Management/CocoaAppCD.storedata, metadata={type = immutable dict, count = 6,
entries =>
0 : {contents = "NSStoreUUID"} = {contents = "A3FD787E-495C-493D-A3B9-2E7F7925EF7C"}
3 : {contents = "NSStoreModelVersionIdentifiers"} = (
""
)
4 : {contents = "NSStoreType"} = {contents = "XML"}
10 : {contents = "NSPersistenceFrameworkVersion"} = {value = +641, type = kCFNumberSInt64Type}
11 : {contents = "NSStoreModelVersionHashes"} = {type = mutable dict, count = 1,
entries =>
0 : Notice = {length = 32, capacity = 32, bytes = 0xd22eaaf9bb53e406e8914544584e0e72 ... 0899bacb36b735bd}
}
12 : {contents = "NSStoreModelVersionHashesVersion"} = {value = +3, type = kCFNumberSInt64Type}
}
, reason=Can't find model for source store} with userInfo dictionary {
URL = "file:///Users/Tom/Library/Application%20Support/de.toEducate.toRep_Management/CocoaAppCD.storedata";
metadata = {
NSPersistenceFrameworkVersion = 641;
NSStoreModelVersionHashes = {
Notice = ;
};
NSStoreModelVersionHashesVersion = 3;
NSStoreModelVersionIdentifiers = (
""
);
NSStoreType = XML;
NSStoreUUID = "A3FD787E-495C-493D-A3B9-2E7F7925EF7C";
};
reason = "Can't find model for source store";
}
2016-02-02 21:37:54.499 toRep_Management[32110:4679391] CoreData: annotation: NSPersistentStoreCoordinator's current model hashes are {
Notice = <2465d170 cdc5f276 8e769b4d 25c03a0d 8efb193b 6707ab4d 46419c42 17733df1>;
}
I thought I implemented a lightweight migration correctly but now I´m not sure anymore.
My AppDelegate:
func applicationDidFinishLaunching(aNotification: NSNotification) {
// Insert code here to initialize your application
}
func applicationWillTerminate(aNotification: NSNotification) {
// Insert code here to tear down your application
}
// MARK: - Core Data stack
lazy var applicationDocumentsDirectory: NSURL = {
// The directory the application uses to store the Core Data store file. This code uses a directory named "de.toEducate.toRep_Management" in the user's Application Support directory.
let urls = NSFileManager.defaultManager().URLsForDirectory(.ApplicationSupportDirectory, inDomains: .UserDomainMask)
let appSupportURL = urls[urls.count - 1]
return appSupportURL.URLByAppendingPathComponent("de.toEducate.toRep_Management")
}()
lazy var managedObjectModel: NSManagedObjectModel = {
// The managed object model for the application. This property is not optional. It is a fatal error for the application not to be able to find and load its model.
let modelURL = NSBundle.mainBundle().URLForResource("toRep_Management", withExtension: "momd")!
return NSManagedObjectModel(contentsOfURL: modelURL)!
}()
lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {
// The persistent store coordinator for the application. This implementation creates and returns a coordinator, having added the store for the application to it. (The directory for the store is created, if necessary.) This property is optional since there are legitimate error conditions that could cause the creation of the store to fail.
let fileManager = NSFileManager.defaultManager()
var failError: NSError? = nil
var shouldFail = false
var failureReason = "There was an error creating or loading the application's saved data."
// Make sure the application files directory is there
do {
let properties = try self.applicationDocumentsDirectory.resourceValuesForKeys([NSURLIsDirectoryKey])
if !properties[NSURLIsDirectoryKey]!.boolValue {
failureReason = "Expected a folder to store application data, found a file \(self.applicationDocumentsDirectory.path)."
shouldFail = true
}
} catch {
let nserror = error as NSError
if nserror.code == NSFileReadNoSuchFileError {
do {
try fileManager.createDirectoryAtPath(self.applicationDocumentsDirectory.path!, withIntermediateDirectories: true, attributes: nil)
} catch {
failError = nserror
}
} else {
failError = nserror
}
}
// Create the coordinator and store
var coordinator: NSPersistentStoreCoordinator? = nil
let migrateOptions = [NSMigratePersistentStoresAutomaticallyOption: true, NSInferMappingModelAutomaticallyOption: true]
if failError == nil {
coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("CocoaAppCD.storedata")
do {
try coordinator!.addPersistentStoreWithType(NSXMLStoreType, configuration: nil, URL: url, options: migrateOptions)
} catch {
failError = error as NSError
}
}
if shouldFail || (failError != nil) {
// Report any error we got.
var dict = [String: AnyObject]()
dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data"
dict[NSLocalizedFailureReasonErrorKey] = failureReason
if failError != nil {
dict[NSUnderlyingErrorKey] = failError
}
let error = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
NSApplication.sharedApplication().presentError(error)
abort()
} else {
return coordinator!
}
}()
lazy var managedObjectContext: NSManagedObjectContext = {
// Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) This property is optional since there are legitimate error conditions that could cause the creation of the context to fail.
let coordinator = self.persistentStoreCoordinator
var managedObjectContext = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
managedObjectContext.persistentStoreCoordinator = coordinator
return managedObjectContext
}()
// MARK: - Core Data Saving and Undo support
#IBAction func saveAction(sender: AnyObject!) {
// Performs the save action for the application, which is to send the save: message to the application's managed object context. Any encountered errors are presented to the user.
if !managedObjectContext.commitEditing() {
NSLog("\(NSStringFromClass(self.dynamicType)) unable to commit editing before saving")
}
if managedObjectContext.hasChanges {
do {
try managedObjectContext.save()
} catch {
let nserror = error as NSError
NSApplication.sharedApplication().presentError(nserror)
}
}
}
func windowWillReturnUndoManager(window: NSWindow) -> NSUndoManager? {
// Returns the NSUndoManager for the application. In this case, the manager returned is that of the managed object context for the application.
return managedObjectContext.undoManager
}
func applicationShouldTerminate(sender: NSApplication) -> NSApplicationTerminateReply {
// Save changes in the application's managed object context before the application terminates.
if !managedObjectContext.commitEditing() {
NSLog("\(NSStringFromClass(self.dynamicType)) unable to commit editing to terminate")
return .TerminateCancel
}
if !managedObjectContext.hasChanges {
return .TerminateNow
}
do {
try managedObjectContext.save()
} catch {
let nserror = error as NSError
// Customize this code block to include application-specific recovery steps.
let result = sender.presentError(nserror)
if (result) {
return .TerminateCancel
}
let question = NSLocalizedString("Could not save changes while quitting. Quit anyway?", comment: "Quit without saves error question message")
let info = NSLocalizedString("Quitting now will lose any changes you have made since the last successful save", comment: "Quit without saves error question info");
let quitButton = NSLocalizedString("Quit anyway", comment: "Quit anyway button title")
let cancelButton = NSLocalizedString("Cancel", comment: "Cancel button title")
let alert = NSAlert()
alert.messageText = question
alert.informativeText = info
alert.addButtonWithTitle(quitButton)
alert.addButtonWithTitle(cancelButton)
let answer = alert.runModal()
if answer == NSAlertFirstButtonReturn {
return .TerminateCancel
}
}
// If we got here, it is time to quit.
return .TerminateNow
}
Could anybody help with the error and how can I handle this in future with a better migration?
"Can't find model for source store" means that you're trying to do a model migration but that Core Data can't find the old version of the data model. For migration to work, you need to have both the old version and the new version. The error suggests that you only have the new version.
When you're going to change a data model and migrate data, you need to create a new version of the model in your project. You'd do this by selecting the model file in Xcode and using "Editor" menu --> "Add Model Version". Then you'd make your changes to the new version while leaving the old one in place.
You need to restore the old model. The best way to do that is to just look back through your SCM (git, probably) commits and get it.

Open Window for asking for Password to store in keychain in Swift 2.0

i tried a much, but it doesn't work :-(
I have written a class with a part is this:
if useKeychain {
let server : String = "smb://cloud.amrhein.info"
let user : String = "gerald"
let pwd : String = "password"
let keychain = Keychain(server: server, protocolType: .SMB)
if let output : String = try! keychain.get(user) {
print("Password (if): \(output)")
} else {
print("start Ask4pwd")
var pWindowController : NSWindowController?
if let storyboard : NSStoryboard = NSStoryboard(name: "Main",bundle: nil) as NSStoryboard
{
if let vc = storyboard.instantiateControllerWithIdentifier("passwordViewController") as? passwordViewController
{
let myWindow = NSWindow(contentViewController: vc)
myWindow.makeKeyAndOrderFront(self)
pWindowController = NSWindowController(window: myWindow)
pWindowController!.showWindow(self)
}
}
do {
try keychain
.accessibility(.Always)
.label("\(server) (\(user))")
.comment("Use for Mount Volumes")
.set(pwd, key: user)
} catch let error {
print(error)
}
}
} else {
password = passwordsArray[index!]
}
if password == "" {
print("No password set - break!")
break
}
....
i have settled my environment that no password is found. i see the "start Ask4pwd" print in console!
the class itself is running, but the window for asking the password do not open when no password is fount in keychain!
in the Mainstoryboard i have created a new view controller "passwordViewController" and gave it also the Storyboard ID: passwordViewController
This view controller has no sequel to the Main Window controller!
I do not want that the gui comes up when app starts, i have disabled "is initial controller" on Mainwindowcontroller
i gogoled and viewed youtube videos a lot - i do not reach my goal...
Who can help me?

Watchos 2 Beta 5 Dynamic notification not showing,Only static notification interface loaded

I have created apple watch application to show push notificaiton.So I have created different dynamic notification interface with different category.but it's not showing dynamic interface but able to see action button for the respective category.Please help me.Please find the appdelegate push notification registration method
P.S: If run in simulator with payload it's working fine.
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
// Register for Push Notitications, if running iOS 8
if application.respondsToSelector("registerUserNotificationSettings:") {
self.registerSettingsAndCategories()
} else {
// Register for Push Notifications before iOS 8
application.registerForRemoteNotifications()
}
return true
}
func registerSettingsAndCategories() {
let alarmAction = UIMutableUserNotificationAction()
alarmAction.title = NSLocalizedString("Activate Theft Alarm ", comment: "Activate Theft Alarm ")
alarmAction.identifier = "theftAlarm"
alarmAction.activationMode = UIUserNotificationActivationMode.Foreground
alarmAction.authenticationRequired = false
let callCopsAction = UIMutableUserNotificationAction()
callCopsAction.title = NSLocalizedString("Call Near by cops", comment: "Call Near by cops")
callCopsAction.identifier = "callCops"
callCopsAction.activationMode = UIUserNotificationActivationMode.Foreground
callCopsAction.authenticationRequired = false
let callSecAction = UIMutableUserNotificationAction()
callSecAction.title = NSLocalizedString("Call Parking Security ", comment: "Call Parking Security ")
callSecAction.identifier = "callSecurity"
callSecAction.activationMode = UIUserNotificationActivationMode.Foreground
callSecAction.authenticationRequired = false
let navigateToSpotAction = UIMutableUserNotificationAction()
navigateToSpotAction.title = NSLocalizedString("Navigate to Spot", comment: "Navigate to Spot")
navigateToSpotAction.identifier = "navigateToSpot"
navigateToSpotAction.activationMode = UIUserNotificationActivationMode.Foreground
navigateToSpotAction.authenticationRequired = false
let bookappointmentAction = UIMutableUserNotificationAction()
bookappointmentAction.title = NSLocalizedString("Book Appointment", comment: "Book Appointment")
bookappointmentAction.identifier = "bookAppointment"
bookappointmentAction.activationMode = UIUserNotificationActivationMode.Foreground
bookappointmentAction.authenticationRequired = false
let theftCategory = UIMutableUserNotificationCategory()
theftCategory.setActions([alarmAction, callCopsAction,callSecAction],
forContext: UIUserNotificationActionContext.Default)
theftCategory.setActions([callCopsAction,callSecAction], forContext: UIUserNotificationActionContext.Minimal)
theftCategory.identifier = "theftWarning"
let accidentCategory = UIMutableUserNotificationCategory()
accidentCategory.setActions([navigateToSpotAction], forContext: UIUserNotificationActionContext.Default)
accidentCategory.setActions([navigateToSpotAction], forContext: UIUserNotificationActionContext.Minimal)
accidentCategory.identifier = "accident"
let lowOilCategory = UIMutableUserNotificationCategory()
lowOilCategory.setActions([bookappointmentAction], forContext: UIUserNotificationActionContext.Default)
lowOilCategory.setActions([bookappointmentAction], forContext: UIUserNotificationActionContext.Minimal)
lowOilCategory.identifier = "lowOil"
let categories : Set<UIUserNotificationCategory> = [theftCategory, accidentCategory, lowOilCategory]
// Configure other actions and categories and add them to the set...
let settings = UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: categories)
UIApplication.sharedApplication().registerUserNotificationSettings(settings)
UIApplication.sharedApplication().registerForRemoteNotifications()
}
You need to implement didReceiveRemoteNotification:withCompletion: in your subclass of WKUserNotificationInterfaceController.
Then, execute completionHandler.
completionHandler(WKUserNotificationInterfaceType.Custom)
WatchOS 2.0 document:
The completion handler for telling the system what interface to
display. Execute this completion handler at the end of your method
implementation. If you do not execute this block in a timely manner,
the system displays your app’s static notification interface.

Resources