How to convert Objective-C code to Swift code - errorhandling ,iOS - objective-c

I'm trying to convert this text to swift:
- (void)sendData:(NSData*)data
{
NSError *error;
GameKitHelper *gameKitHelper = [GameKitHelper sharedGameKitHelper];
BOOL success = [gameKitHelper.match
sendDataToAllPlayers:data
withDataMode:GKMatchSendDataReliable
error:&error];
if (!success) {
NSLog(#"Error sending data:%#", error.localizedDescription);
[self matchEnded];
}
}
Now I've gotten so far here:
func sendData(data: NSData) {
var error: NSError?
var gameKitHelper = GameKitHelper.sharedGameKitHelper()
var success = try! gameKitHelper.match.sendDataToAllPlayers(data, withDataMode: GKMatchSendDataReliable)
if !success {
print("Error sending data:\(error.localizedDescription)")
self.matchEnded()
}
}
But It's giving me an error at if (!succes) and I read on apples documentation that the objective-c version of .sendDataToAllPlayers() will return a bool but the swift version won't.
Apple Documentation - GKMatch
So how can I handle the error

The sendDataToAllPlayers function throws an exception if an error occurs. You need a catch block to handle it:
func sendData(data: NSData) {
var gameKitHelper = GameKitHelper.sharedGameKitHelper()
do {
try gameKitHelper.match.sendDataToAllPlayers(data, withDataMode: .Reliable)
}
catch let error as NSError {
print("Error sending data:\(error.localizedDescription)")
self.matchEnded()
}
}

Related

How to use requestGeometryUpdateWithPreferences in Objective C

I have an example in Swift language:
guard let windowScene = view.window?.windowScene else { return }
windowScene.requestGeometryUpdate(.iOS(interfaceOrientations: .portrait)) { error in }
I can't write it in Objective C:
UIWindowScene *windowScene = self.view.window.windowScene;
[windowScene requestGeometryUpdateWithPreferences: UIInterfaceOrientationMaskPortrait errorHandler:nil];
Please tell me how to write correctly I will be grateful for any help.
One way to write that Swift code in Objective-C would be:
UIWindowScene *windowScene = self.view.window.windowScene;
if (!windowScene) { return; }
UIWindowSceneGeometryPreferences *preferences = [[UIWindowSceneGeometryPreferencesIOS alloc] initWithInterfaceOrientations:UIInterfaceOrientationMaskPortrait];
[windowScene requestGeometryUpdateWithPreferences:preferences errorHandler:^(NSError * _Nonnull error) {
// Handle error here
}];

Core data: concurency conflict between save and fetch

These two function calls seem to be conflicting:
MagicalRecord.save({ (localContext) in
let items = NewsItem.staleNewsItems(in: localContext)
if ((items?.count)! > 0){
items?.forEach({ (item) in
if let object = item as? NSManagedObject {
object.mr_deleteEntity(in: localContext)
}
})
}
})
and
- (void) buildAndFetchFRCsInContext:(NSManagedObjectContext*)context {
self.newsItemsFRC = [self buildFetchResultsControllerForClass:[NewsItem class] sortedBy:#"id" withPredicate:nil inContext:context];
[context performBlock:^{
__unused NSDate* start = [NSDate date];
NSError* error;
[self.newsItemsFRC performFetch:&error]; // this line crashes
[self calculateAndBroadcastCounts];
}];
}
Is this save call thread safe? If so what could cause these two functions to cause each-other to crash?
The issue is I'm modifying the news items outside of the context they were created in. So to fix the issue I had to move the code to the main thread. I switched from using magical records save to just performBlockAndWait which is guaranteed to run on the calling thread:
private static func cleanUpNewsItems() -> Void {
let context = NSManagedObjectContext.mr_()
context.performAndWait {
var itemsToDelete = [NSManagedObject]()
if let items = NewsItem.staleNewsItems(in: context) {
items.forEach({ (item) in
itemsToDelete.append(item as! NSManagedObject)
})
}
for item in itemsToDelete {
context.delete(item)
}
do {
try context.save()
} catch let error as NSError {
print("Error While Deleting Note: \(error.userInfo)")
}
}
}

How to get ["error"]["type"] from error.userInfo in Swift?

I am wondering how do we do this in Swift?
I am trying to convert the code below to Swift
FBSDKGraphRequest *request = [[FBSDKGraphRequest alloc] initWithGraphPath:#"me" parameters:nil];
[request startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error) {
if (!error) {
// handle successful response
} else if ([[error userInfo][#"error"][#"type"] isEqualToString: #"OAuthException"]) { // Since the request failed, we can
NSLog(#"The facebook session error");
} else {
NSLog(#"Some other error: %#", error);
}
}];
Here is what I've done.
request.startWithCompletionHandler { (connection: FBSDKGraphRequestConnection!, result: AnyObject!, error: NSError!) -> Void in
if error == nil {
// handle successful response
}
else if error.userInfo["error"]["type"] == "OAuthException" {
//THIS LINE WONT COMPILE
}
else {
println("Some other error");
}
}
But I get a compile error that says could not find member 'subscript' on this line
error.userInfo["error"]["type"] == "OAuthException"
Any ideas please?
Try:
if (error.userInfo?["error"]?["type"] as? String) == "OAuthException" {
userInfo is an optional dictionary of type [NSObject: AnyObject]? so you'll need to unwrap it. Dictionary lookups always return an optional (because the key might not exist) so you have to unwrap it before accessing the key of the nested dictionary. Using a ? instead of ! is optional chaining and it will harmlessly result in nil if the "error" key doesn't exist (instead of crashing if you use a !). Finally, you'll need to cast the result to String (from AnyObject) in order to be able to compare it to "OAuthException".
How about breaking down the error and type as shown below?
else if let errorOAuthException: AnyObject = error.userInfo as? Dictionary<String, AnyObject>{
if errorOAuthException["error"] != nil {
if errorOAuthException["type"] as? String == "OAuthException" {
//Do something for me
}
}
}

Converting Obj-C to Swift

I'm having trouble converting this line to Swift:
(void)authenticateLayerWithUserID:(NSString *)userID completion:(void (^)(BOOL success, NSError * error))completion { }
Here's my line in Swift:
func authenticateLayerWithUserID(userID: NSString) {(success: Bool, error: NSError?) -> Void in }
Anyone have some insight into what I'm not doing correctly?
I would translate this kind of function in Swift with a "completion handler":
func authenticateLayerWithUserID(userID: NSString, completion: (success: Bool, error: NSError?) -> ()) {
if userID == "Jack" {
completion(success: true, error: nil)
}
}
And call it like this:
authenticateLayerWithUserID("Jack", { (success, error) in
println(success) // true
})
EDIT:
Following your comments, here's a new example within a class function, and with an "if else":
class MyClass {
class func authenticateLayerWithUserID(userID: NSString, completion: (success: Bool, error: NSError?) -> ()) {
if userID == "Jack" {
completion(success: true, error: nil)
} else {
completion(success: false, error: nil)
}
}
}
MyClass.authenticateLayerWithUserID("Jack", completion: { (success, error) in
println(success) // true
})
MyClass.authenticateLayerWithUserID("John", completion: { (success, error) in
println(success) // false
})
If you want to make a call to that method, it will look like this in Objective-C (I think you're using this:
[self authenticateLayerWithUserID:userIDString completion:^(BOOL success, NSError *error) {
if (!success) {
NSLog(#"Failed Authenticating Layer Client with error:%#", error);
}
}];
In Swift
var c: MyClass = MyClass()
c.authenticateLayerWithUserID("user", completion: { (boolean, error) -> Void in
})

Check NSURL for UTI / file type

I'm building an app that allows users to drop videos onto it. Given a list of dropped NSURL*s how do I make sure each one conforms to the public.movie UTI type?
If I had an NSOpenPanel, I would just use openPanel.allowedFileTypes = #[#"public.movie"]; and Cocoa would take care of it for me.
Thanks in advance!
This should work:
NSWorkspace *workspace = [NSWorkspace sharedWorkspace];
for (NSURL *url in urls) {
NSString *type;
NSError *error;
if ([url getResourceValue:&type forKey:NSURLTypeIdentifierKey error:&error]) {
if ([workspace type:type conformsToType:#"public.movie"]) {
// the URL points to a movie; do stuff here
}
} else {
// handle error
}
}
(You can also use UTTypeConformsTo() instead of the NSWorkspace method.)
Swift version:
do {
var value: AnyObject?
try url.getResourceValue(&value, forKey:NSURLTypeIdentifierKey)
if let type = value as? String {
if UTTypeConformsTo(type, kUTTypeMovie) {
...
}
}
}
catch {
}
Swift 5 version:
if let resourceValues = try? localUrl.resourceValues(forKeys: [URLResourceKey.typeIdentifierKey]) {
if let typeId = resourceValues.typeIdentifier {
if UTTypeConformsTo(type, kUTTypeMovie) {
...
}
}
}