Authenticate GameKit local player using swift - authentication

Im looking to migrate a game over to swift, the only trouble I am having is with blocks/closures. It's the syntax I just don't understand, whereas in Objective C I would use:
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
localPlayer.authenticateHandler = ^(UIViewController *viewController, NSError *error){
if (viewController != nil) {
[self presentViewController:viewController animated:YES completion:nil];
}
}
etc.etc. but I'm not sure how to go about doing the same in Swift. I know it's simple but I just can't get it to work, even after reading the Swift book and googling answers myself. I'm only a hobbyist programmer so I'm far from perfect at all this.
Any Help would be appreciated.

This is how you would do it in Swift:
var localPlayer = CGLocalPlayer.localPlayer()
localPlayer.authenticateHandler = {(viewController : UIViewController!, error : NSError!) -> Void in
//handle authentication
}
The documentation for closures can be found here.

This is how you authenticate in Swift using Xcode 6.1 +:
var localPlayer = GKLocalPlayer.localPlayer()
localPlayer.authenticateHandler = {(viewController : UIViewController!, error : NSError!) -> Void in
if ((viewController) != nil) {
self.presentViewController(viewController, animated: true, completion: nil)
}else{
println((GKLocalPlayer.localPlayer().authenticated))
}
}

Related

app broke after Xcode update

I have a Swift app, with some Objective-C code mixed in. It was working yesterday, but this morning I updated XCode and now everything had gone to hell!
Firstly, after updating, I clicked the XCode popup box to allow it to upgrade my app to Swift4. This is where the problems started.
I have a Swift class called RestClient with the following 4 functions (among others):
class func getInstance() -> RestClient {
if (gRestClient == nil) {
let prefs:UserDefaults = UserDefaults.standard
return RestClient(username: prefs.string(forKey: "username")!, password: prefs.string(forKey: "password")!)
}
return gRestClient!
}
class func getUsername() -> String {
if (gUsername == nil) {
let prefs:UserDefaults = UserDefaults.standard
gUsername = prefs.string(forKey: "username")!
}
return gUsername!
}
class func getPassword() -> String {
if (gPassword == nil) {
let prefs:UserDefaults = UserDefaults.standard
gPassword = prefs.string(forKey: "password")!
}
return gPassword!
}
public func getServer() -> String {
return MAIN_SERVER;
}
Then in my /Objective-C/ folder, I have some more files, once of which is called RestClientObj.m. In here, I have this lines of code:
NSString* url = [NSString stringWithFormat:#"%#/receipt/email/%#/%#/", [[RestClient getInstance] getServer], rrn, emailAddress];
NSString *authStr = [NSString stringWithFormat:#"%#:%#", [RestClient getUsername], [RestClient getPassword]];
So as you can see, I'm calling the RestClient.swift from here. The RestClientObj.h is as follows:
#ifndef RestClientObj_h
#define RestClientObj_h
#endif /* ResClientObj_h */
#interface RestClientObj : NSObject {
}
+(BOOL) sendSMS:(NSString *)rrn mn:(NSString *)mobileNumber;
+(BOOL) sendEmail:(NSString *)rrn mn:(NSString *)emailAddress;
#end
This whole upgrade is causing other problems too. I have another class with the following error:
No visible #interface for 'AppDelegate' declares the selector 'managedObjectContext'
on the line:
appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext]; <-ERROR
Can anyone shed any light on this?
EDIT: Here's some code from the AppDelegate class:
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
if coordinator == nil {
return nil
}
var managedObjectContext = NSManagedObjectContext()
managedObjectContext.persistentStoreCoordinator = coordinator
return managedObjectContext
}()
Just to close this off.
The issue was missing the #obj identifier before the variable declaration to make it visible to my objective-c code, in combination with the XCode Swift Upgrade wizard renaming some functions.

ABAddressBookRequestAccessWithCompletion crashes on iOS 10

I use below code to access contacts in my iOS application. It was working fine in iOS<10 but with Xcode 8 and iOS 10 it crashes:
- (void)btcContacts_tap {
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
if (granted) {
_addressBookController = [[ABPeoplePickerNavigationController alloc] init];
[[_addressBookController navigationBar] setBarStyle:UIBarStyleBlack];
_addressBookController.delegate = self;
[_addressBookController setPredicateForEnablingPerson:[NSPredicate predicateWithFormat:#"%K.#count > 0", ABPersonPhoneNumbersProperty]];
[_addressBookController setPeoplePickerDelegate:self];
[self presentViewController:_addressBookController animated:YES completion:nil];
}
else {
dispatch_async(dispatch_get_main_queue(), ^{
[self showMessage:NSLocalizedStringFromTable(#"PLEASE_GRANT_CONTACTS", LIApplicationLanguage(), nil) andAdvertise:#"" andService:nil andTransactionState:kTTTransactionStateInfo];
});
}
});
}
I have set NSSetUncaughtExceptionHandler to a method for logging the crash report but even the exception handler is not calling...
Does someone else faced this problem too?
iOS 10:
You need to put the NSContactsUsageDescription in your plist. Like:
<key>NSContactsUsageDescription</key>
<string>$(PRODUCT_NAME) uses photos</string>
See all usage descriptions here.
Use CNContactStore , ABAddressBookRequestAccessWithCompletion is depreciated.
enter link description here

Objective C static const in swift

How write this Objective C code in Swift?
#import "FFTViewController.h"
//only this part
static vDSP_Length const FFTViewControllerFFTWindowSize = 4096;
#implementation FFTViewController
My idea is
let vDSP: vDSP_Length = 4096
i'm sure that is not correct, but i have no idea.
thanks for help
Update:
I want port this Objective C code to swift
#import "FFTViewController.h"
static vDSP_Length const FFTViewControllerFFTWindowSize = 4096;
#implementation FFTViewController
- (void)viewDidLoad
{
[super viewDidLoad];
//
// Setup the AVAudioSession. EZMicrophone will not work properly on iOS
// if you don't do this!
//
AVAudioSession *session = [AVAudioSession sharedInstance];
NSError *error;
[session setCategory:AVAudioSessionCategoryPlayAndRecord error:&error];
if (error)
{
NSLog(#"Error setting up audio session category: %#", error.localizedDescription);
}
[session setActive:YES error:&error];
if (error)
{
NSLog(#"Error setting up audio session active: %#", error.localizedDescription);
}
//
// Setup time domain audio plot
//
self.audioPlotTime.plotType = EZPlotTypeBuffer;
self.maxFrequencyLabel.numberOfLines = 0;
//
// Setup frequency domain audio plot
//
self.audioPlotFreq.shouldFill = YES;
self.audioPlotFreq.plotType = EZPlotTypeBuffer;
self.audioPlotFreq.shouldCenterYAxis = NO;
//
// Create an instance of the microphone and tell it to use this view controller instance as the delegate
//
self.microphone = [EZMicrophone microphoneWithDelegate:self];
//
// Create an instance of the EZAudioFFTRolling to keep a history of the incoming audio data and calculate the FFT.
//
self.fft = [EZAudioFFTRolling fftWithWindowSize:FFTViewControllerFFTWindowSize
sampleRate:self.microphone.audioStreamBasicDescription.mSampleRate
delegate:self];
//
// Start the mic
//
[self.microphone startFetchingAudio];
}
This is my beginning
import UIKit
import Accelerate
class ViewController: UIViewController, EZMicrophoneDelegate{
var mic: EZMicrophone!
var fft: EZAudioFFTRolling!
private let FFTViewControllerFFTWindowSize: vDSP_Length = 4096
override func loadView() {
super.loadView()
mic = EZMicrophone(delegate: self, startsImmediately: true)
fft = EZAudioFFTRolling(windowSize: FFTViewControllerFFTWindowSize, sampleRate: mic.audioStreamBasicDescription().mSampleRate, delegate: self)
}
}
I becoming the following error:
compile fails with the following error:
"Cannot invoke initializer for type 'EZAudioFFTRolling' with an argument list of type '(windowSize: vDSP_Length, sampleRate: Float64, delegate: ViewController)'"
How is my problem?
Sorry for this question i have no ObjectiveC background, is little challenge this port for me.
Thanks for Help
The problem you're getting an error is in types. When you start typing EZAudioFFTRolling initializer in XCode, autocompletion helps you by displaying specification. It looks like this:
EZAudioFFTRolling(windowSize: vDSP_Length, sampleRate: Float, delegate: EZAudioFFTDelegate!)
If you compare parameters types from specification with actual values you're passing, you will figure out that mic.audioStreamBasicDescription().mSampleRate has Float64 type but should be Float (they're actually not the same) and self is not conforming to EZAudioFFTDelegate protocol. So after changing your line to this
fft = EZAudioFFTRolling(windowSize: FFTViewControllerFFTWindowSize, sampleRate: Float(mic.audioStreamBasicDescription().mSampleRate), delegate: self)
and adding protocol conformance you will be able to build your code.
Swift is type safety in contradistinction to Objective-C, so it's common issues that all Objective-C developers have when start working with Swift. But errors are actually helping you, so read them attentively.

Apple watch communicate with iOS app a new swift project vs to existing obj c project

1) I've managed to communicate from apple watch to iOS app using a complete swift project (iOS app in swift and Apple Watch target in swift)
Code:
In InterfaceController.swift
#IBAction func buttonPressed() {
let watchMessage = ["SiteName" : "Tech-recipes"]
WKInterfaceController.openParentApplication(watchMessage, reply: { (reply:[NSObject : AnyObject]!, error: NSError!) -> Void in
if let message = reply["Message"] as? String{
println(message)
}
})
}
in AppDelegate.swift
func application(application: UIApplication!, handleWatchKitExtensionRequest userInfo: [NSObject : AnyObject]!, reply: (([NSObject : AnyObject]!) -> Void)!) {
if let siteName = userInfo["SiteName"] as? String{
reply(["Message":"Hello from \(siteName)"])
}
}
Output: "Hello from Tech-recipes"
2) However, when I want to integrate the apple watch target in swift to the exiting project in obj-c, it will crash and give me this error: "fatal error: unexpectedly found nil while unwrapping an Optional value"
In InterfaceController.swift
#IBAction func buttonPressed() {
let watchMessage = ["SiteName" : "Tech-recipes"]
WKInterfaceController.openParentApplication(watchMessage, reply: { (reply:[NSObject : AnyObject]!, error: NSError!) -> Void in
if let message = reply["Message"] as? String{ //CRASH HERE!!!!
println(message)
}
})
}
iPhoneAppDelegate.m
- (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *))reply{
// Performs task on phone here
// Sending back a reply
if ([[userInfo valueForKey:#"SiteName"] length]>0) {
//NSMutableDictionary *reply = [[NSMutableDictionary alloc] init];
[reply setValue:[NSString stringWithFormat:#"Hello from %#", [userInfo valueForKey:#"SiteName"]] forKey:#"Message"];
}
}
Update:
--> Noticed that in handleWatchKitExtensionRequest: method the type for userInfo is different in swift and obj-c, in [NSObject : AnyObject]! and NSDictionary respectively. How to solve this?
--> Got an error in error: NSError!: [0] (null) #"NSLocalizedDescription" : #"The UIApplicationDelegate in the iPhone App never called reply() in -[UIApplicationDelegate application:handleWatchKitExtensionRequest:reply:]"
Solved it!
Missed out the reply(aNsdictionary) in the app delegate

Game Center report in iOS 7 (Deprecated)

My IDE show warning "Obsolete: Deprecated in iOS 7.0" this methods:
(GKScore) ReportScore()
(GKAchievement) ReportAchievement()
This methods it works on iOS 7, but use not problem? Exist other methods on iOS 7?
Thanks!
I used this method to report score in game center and it works.
-(void)reportScore
{
if(isIOS7)
{
// Create a GKScore object to assign the score and report it as a NSArray object.
GKScore *score = [[GKScore alloc] initWithLeaderboardIdentifier:_leaderboardIdentifier];
score.value = _score;
[GKScore reportScores:#[score] withCompletionHandler:^(NSError *error) {
if (error != nil) {
NSLog(#"score reporting error : %#", [error localizedDescription]);
}
else
{
NSLog(#"score reported.");
}
}];
}
else
{
GKScore *scoreReporter = [[GKScore alloc] initWithCategory:_leaderboardIdentifier];
scoreReporter.value = _score;
scoreReporter.context = 0;
[scoreReporter reportScoreWithCompletionHandler:^(NSError *error) {
// Do something interesting here.
if (error != nil) {
NSLog(#"score reporting error : %#", [error localizedDescription]);
}
else
{
NSLog(#"score reported.");
}
}];
}
}
Objective-C methods start with a lower-case method. They are not called with rounded brackets. So, I:
opened the documentation for GKScore;
looked for anything deprecated and found -reportScoreWithCompletionHandler:;
saw that +reportScores: withCompletionHandler: isn't deprecated.
And saw pretty much the same thing with the singular instance method being deprecated in favour of the collection class method in GKAchievement.
So: just use the collection methods. Deprecated methods hang around being unsupported for a while and then disappear. You can find out what's currently supported, very very quickly, by reading the documentation.