How to access NSApplicationLaunchUserNotificationKey in Swift? - objective-c

I am trying to translate the following from Objective-C to Swift, but I'm stuck!
See https://developer.apple.com/documentation/appkit/nsapplicationlaunchusernotificationkey
NSUserNotification *userNotification = [[myNotification userInfo]
objectForKey:NSApplicationLaunchUserNotificationKey];
if (userNotification) {
// The app was launched by a user selection from Notification Center.
}

The objective-c syntax in your question is fine.
But the Notification it refers to is the one belonging to -applicationDidFinishLaunching:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
NSUserNotification *userNotification = aNotification.userInfo[NSApplicationLaunchUserNotificationKey];
if (userNotification) {
// The app was launched by a user selection from Notification Center.
}
}
but the API is deprecated.
So it in swift it will look like..
func applicationDidFinishLaunching(_ notification: Notification)
if let response = notification.userInfo?[NSApplication.launchUserNotificationUserInfoKey] as? UNNotificationResponse {
// evaluate response.notification.request.content
}
}

Related

Detect in MacOS opening/closure laptops's lid [duplicate]

I am developing an app in Xcode on Mac and would like to know the event which is fired when the mac gets back from sleep.
AwakeFromNib doesn't seem to work.
For swift 3:
func onWakeNote(note: NSNotification) {
print("Received wake note: \(note.name)")
}
func onSleepNote(note: NSNotification) {
print("Received sleep note: \(note.name)")
}
func fileNotifications() {
NSWorkspace.shared().notificationCenter.addObserver(
self, selector: #selector(onWakeNote(note:)),
name: Notification.Name.NSWorkspaceDidWake, object: nil)
NSWorkspace.shared().notificationCenter.addObserver(
self, selector: #selector(onSleepNote(note:)),
name: Notification.Name.NSWorkspaceWillSleep, object: nil)
}
For swift 4:
#objc func onWakeNote(note: NSNotification) {
...
}
#objc func onSleepNote(note: NSNotification) {
...
}
func fileNotifications() {
NSWorkspace.shared.notificationCenter.addObserver(
self, selector: #selector(onWakeNote(note:)),
name: NSWorkspace.didWakeNotification, object: nil)
NSWorkspace.shared.notificationCenter.addObserver(
self, selector: #selector(onSleepNote(note:)),
name: NSWorkspace.willSleepNotification, object: nil)
}
Just found it:
- (void) receiveWakeNote: (NSNotification*) note
{
NSLog(#"receiveSleepNote: %#", [note name]);
}
- (void) fileNotifications
{
//These notifications are filed on NSWorkspace's notification center, not the default
// notification center. You will not receive sleep/wake notifications if you file
//with the default notification center.
[[[NSWorkspace sharedWorkspace] notificationCenter] addObserver: self
selector: #selector(receiveWakeNote:)
name: NSWorkspaceDidWakeNotification object: NULL];
}
You can use IORegisterForSystemPower().
Connects the caller to the Root Power Domain IOService for the purpose
of receiving sleep & wake notifications for the system. Does not
provide system shutdown and restart notifications.
io_connect_t IORegisterForSystemPower (
void *refcon,
IONotificationPortRef *thePortRef,
IOServiceInterestCallback callback,
io_object_t *notifier ) ;
Take a look at Q:How can my application get notified when the computer is going to sleep or waking from sleep? How to I prevent sleep?

How to use Objective C selectors as arguments when subscribing to NSNotifications? [duplicate]

This question already has answers here:
How to write Keyboard notifications in Swift 3
(12 answers)
Closed 6 years ago.
I have the following subscription in swift. I need to know when the keyboard will show to move the view up. It compiles and works as expected but I don't know how to get rid of this warning. "No method declared with Objective-C selector'keyboardWillShow'"
// Subscribing class to recieve the notification
func subscribeToKeyboardNotifications() {
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillShow", name: UIKeyboardWillShowNotification, object: nil)
}
// Shifting view's frame up
func keyboardWillShow(notification: NSNotification) {
view.frame.origin.y -= getKeyboardHeight(notification)
}
// Getting keyboard height
func getKeyboardHeight(notification: NSNotification) -> CGFloat {
let userInfo = notification.userInfo
let keyboardSize = userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue // of CGRect
return keyboardSize.CGRectValue().height
}
Thanks in advance for any suggestions!
Use #selector:
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(keyboardWillShow(_:)), name: UIKeyboardWillShowNotification, object: nil)

Send data from watchKit to iPhone and got callback without launching iOS App

I want to send a dictionary from WatchKit to iPhone in watchOS 2 and get a reply(callback) from iPhone without launching iPhone app.
In watchOS 1, this is possible by calling openParentApplication method when button tapped in Watch:
#IBAction func btnTapped() {
let dictionary = ["Button":0]
WKInterfaceController.openParentApplication(dictionary, reply: { (replyInfo, error) -> Void in
print(replyInfo["ReturnButton"])
})
}
and in AppDelegate class:
- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void(^)(NSDictionary *replyInfo))reply {
int key = (int)[[userInfo objectForKey:#"Button"] integerValue];
NSMutableDictionary* dict = [[NSMutableDictionary alloc]init];
switch (key){
case 0:
[dict setObject:#"Button1" forKey:#"ReturnButton"];
break;
default:
break;
}
reply(dict);
}
Its goes in handler and print "Button1" without launching iOS app.I don't know this is possible or not for watchOS 2.
Yes it is possible in watchOS 2. They have deprecated the openParent call and replaced it with a new connectivity framework. Documentation in the watchOS 2 transition guide states:
The framework provides options for transferring data in the background
or while both apps are active and replaces the existing
openParentApplication:reply: method of the WKInterfaceController
class.
Connectivity Framework Documentation
The function you should look into is
func transferUserInfo(_ userInfo: [String : AnyObject]) -> WCSessionUserInfoTransfer

Use Block in Objective C to find out if a BOOL has been set?

I'm new to Obj-c. I've got a class which sets a var boolean to YES if it's successful (Game Center login = successful), what it would be great to do, is somehow have a listener to that var that listens to when it is YES and then executes some code. Do I use a block for that? I'm also using the Sparrow framework.
Here's my code in my GameCenter.m file
-(void) setup
{
gameCenterAuthenticationComplete = NO;
if (!isGameCenterAPIAvailable()) {
// Game Center is not available.
NSLog(#"Game Center is not available.");
} else {
NSLog(#"Game Center is available.");
__weak typeof(self) weakSelf = self; // removes retain cycle error
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer]; // localPlayer is the public GKLocalPlayer
__weak GKLocalPlayer *weakPlayer = localPlayer; // removes retain cycle error
weakPlayer.authenticateHandler = ^(UIViewController *viewController, NSError *error)
{
if (viewController != nil)
{
[weakSelf showAuthenticationDialogWhenReasonable:viewController];
}
else if (weakPlayer.isAuthenticated)
{
[weakSelf authenticatedPlayer:weakPlayer];
}
else
{
[weakSelf disableGameCenter];
}
};
}
}
-(void)showAuthenticationDialogWhenReasonable:(UIViewController *)controller
{
[[[[[UIApplication sharedApplication] delegate] window] rootViewController] presentViewController:controller animated:YES completion:nil];
}
-(void)authenticatedPlayer:(GKLocalPlayer *)player
{
NSLog(#"%#,%#,%#",player.playerID,player.displayName, player.alias);
gameCenterAuthenticationComplete = YES;
}
-(void)disableGameCenter
{
}
But I need to know from a different object if that gameCenterAuthenticationComplete equals YES.
You can use a delegate pattern. It's far easier to use than KVO or local notifications and it's used a lot in Obj-C.
Notifications should be used only in specific situations (e.g. when you don't know who wants to listen or when there are more than 1 listeners).
A block would work here but the delegate does exactly the same.
You could use KVO (Key-Value Observing) to watch a property of your object, but I'd rather post a NSNotification in your case.
You'll need to have the objects interested in knowing when Game Center login happened register themselves to NSNotificationCenter, then post the NSNotification in your Game Center handler. Read the Notification Programming Topics for more details !
If there is a single method to execute on a single delegate object, you can simply call it in the setter. Let me give a name to this property:
#property(nonatomic,assign, getter=isLogged) BOOL logged;
It's enough that you implement the setter:
- (void) setLogged: (BOOL) logged
{
_logged=logged;
if(logged)
[_delegate someMethod];
}
Another (suggested) way is to use NSNotificationCenter. With NSNotificationCenter you can notify multiple objects. All objects that want to execute a method when the property is changes to YES have to register:
NSNotificationCenter* center=[NSNotificationCenter defaultCenter];
[center addObserver: self selector: #selector(handleEvent:) name: #"Logged" object: nil];
The handleEvent: selector will be executed every time that logged changes to YES. So post a notification whenever the property changes:
- (void) setLogged: (BOOL) logged
{
_logged=logged;
if(logged)
{
NSNotificationCenter* center=[NSNotificationCenter defaultCenter];
[center postNotificationName: #"Logged" object: self];
}
}

How BarAlarm iOS app is made? [duplicate]

I am developing a non-appstore app for iOS. I want to read the cellular signal strength in my code.
I know Apple doesn't provide any API by which we can achieve this.
Is there any private API that can be used to achieve this? I have gone through the various threads regarding this issue but could not find any relevant info.
It is completely possible because there is an app in the app-store for detecting the carrier's signal strength.
Get signalStreght IOS9:
UIApplication *app = [UIApplication sharedApplication];
NSArray *subviews = [[[app valueForKey:#"statusBar"] valueForKey:#"foregroundView"] subviews];
NSString *dataNetworkItemView = nil;
for (id subview in subviews) {
if([subview isKindOfClass:[NSClassFromString(#"UIStatusBarSignalStrengthItemView") class]])
{
dataNetworkItemView = subview;
break;
}
}
int signalStrength = [[dataNetworkItemView valueForKey:#"signalStrengthRaw"] intValue];
NSLog(#"signal %d", signalStrength);
It is not very hard.
Link CoreTelephony.framework in your Xcode project
Add the following lines where you need it
Code:
int CTGetSignalStrength(); // private method (not in the header) of Core Telephony
- (void)aScanMethod
{
NSLog(#"%d", CTGetSignalStrength()); // or do what you want
}
And you are done.
Update May 2016
Apple removed this opportunity.
I briefly looked at the VAFieldTest project located at Github.
There seems to be getSignalStrength() and register_notification() functions in Classes/VAFieldTestViewController.m that might be interesting to you as they call into CoreTelephony.framework.
I am pretty confident that some of the used calls are undocumented in the CoreTelephony framework documentation from Apple and therefore private - any app in the AppStore must have slipped passed inspection.
To get signal streght in iOS 9 or above in Swift 3, without using the private API from CoreTelephony - CTGetSignalStrength(). Just scouring the statusBar view.
func getSignalStrength() -> Int {
let application = UIApplication.shared
let statusBarView = application.value(forKey: "statusBar") as! UIView
let foregroundView = statusBarView.value(forKey: "foregroundView") as! UIView
let foregroundViewSubviews = foregroundView.subviews
var dataNetworkItemView:UIView!
for subview in foregroundViewSubviews {
if subview.isKind(of: NSClassFromString("UIStatusBarSignalStrengthItemView")!) {
dataNetworkItemView = subview
break
} else {
return 0 //NO SERVICE
}
}
return dataNetworkItemView.value(forKey: "signalStrengthBars") as! Int
}
Attention: If the status bar is hidden, the key "statusBar" will return nil.
I haven't tested it, but apparently this is now a method of CTTelephonyNetworkInfo instead of a global/static function.
The return type is id, so I think you get either a NSDictionary (as the _cachedSignalStrength ivar implies) or an NSNumber (as the old function implies).
id signalStrength = [[CTTelephonyNetworkInfo new] signalStrength];
This changed in iOS 8.3, as you can see from the commit.
Note that this is still not documented! So if your app will go in the App Store, take your precautions.
Here's Lucas' answer converted to Xamarin, and tested on iOS 10.2.1:
var application = UIApplication.SharedApplication;
var statusBarView = application.ValueForKey(new NSString("statusBar")) as UIView;
var foregroundView = statusBarView.ValueForKey(new NSString("foregroundView")) as UIView;
UIView dataNetworkItemView = null;
foreach (UIView subview in foregroundView.Subviews)
{
if ("UIStatusBarSignalStrengthItemView" == subview.Class.Name)
{
dataNetworkItemView = subview;
break;
}
}
if (null == dataNetworkItemView)
return false; //NO SERVICE
int bars = ((NSNumber)dataNetworkItemView.ValueForKey(new NSString("signalStrengthBars"))).Int32Value;