I do not know how to convert the following Objective-C code into swift. How should I do ?
Objective-c
if (operations) {
if ([operations isKindOfClass:[NSArray class]]) {
for (id <MyOperation> operation in operations) {
if (operation) {
[operation cancel];
}
}
} else if ([operations conformsToProtocol:#protocol(MyOperation)]){
[(id<MyOperation>) operations cancel];
}
[operationDictionary removeObjectForKey:key];
}
swift
if operations != nil {
// doto .......
}
Try this code:
if operations != nil {
// doto .......
if (operations?.isKindOfClass(NSArray) != nil){
for operation in operations as! [MyOperation]{
operation.cancle()
}
} else if operations?.conformsToProtocol(MyOperation){
(operations as MyOperation).cancle()
}
operationDictionary.removeObjectForKey(key)
}
I didn't test it so may be you have to make little bit changes into this code.
Hope this will help.
I usually don't help people with complete conversions, but...
if let operations: AnyObject = operations {
if operations is NSArray {
for operation in operations as! [MyOperation] {
operation.cancel()
}
}
else if let operation = operations as? MyOperation {
operation.cancel()
}
operationDictionary.removeObjectForKey(key)
}
Related
I've got a function with completion block, and which in some cases calls itself recursively until has the expected result.
I'm getting errors in release, probably because it has different memory management in release.
Anyway I'm asking what should I do to make it work in release as in debug.
I've found some links about declaring a block variable weak, and another one strong, and then assign the block to both of them. However I'm in difficulty to understand well how to apply it to my code.
Here's the code:
-(void) getBitmapFromXObject: (OCPdfXObject *) xobj completion:(void(^)(NSData * data))completion{
__block BOOL hasAlreadyCompleted = false;
if (xobj.type == OCPdfXObjectType_Form) {
OCPdfXObjectForm * formxboj = (OCPdfXObjectForm *)xobj;
OCPdfDictionary * res = formxboj.resources.xObject;
if (res != nil) {
for (CBKeyValuePair * key in res) {
OCPdfXObject* childXObjc = [OCPdfXObject createFromObject:key.value];
if (!childXObjc) {
continue;
}
[self getBitmapFromXObject:childXObjc completion:^(NSData *data) {
if (data != nil) {
hasAlreadyCompleted = true;
}
}];
}
}
}
if (xobj.type == OCPdfXObjectType_Image) {
OCPdfImage* imagexobj = (OCPdfImage *)xobj;
if (imagexobj.colorSpace != OCPdfColorSpace_DeviceRGB) {
completion(nil);
hasAlreadyCompleted = true;
}
[self getBitmapFromImage:imagexobj withCompletion:^(NSData *data) {
NSData *uiImage = data;
completion(uiImage);
hasAlreadyCompleted = true;
}];
}
if (!hasAlreadyCompleted) {
completion(nil);
}
}
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)")
}
}
}
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
}
}
}
I am trying to re-write an app in swift which is currently in Objective-C. How would I change this single line into Swift, as my current attempt does not prove correct
Tabata *tabata = [notification object];
Here is the entire function:
- (void)stateChanged:(NSNotification*)notification
{
if (enabled)
{
Tabata *tabata = [notification object];
switch (tabata.getState) {
case EXERCISE:
case RELAXATION:
[player play];
break;
default:
break;
}
}
}
And here is what I've converted into Swift:
func stateChanged(notifcation: NSNotification) {
if enabled {
var tabata: Tabata! = notification.object //error "Use of unresolved identifier 'notification'"
switch tabata.getState() {
case .EXERCISE: fallthrough
case .RELAXATION:
player.play()
break
default:
break
}
}
}
In Swift you have to downcast objects of type AnyObject rather then declare the type
var tabata = notification.object as! Tabata
func stateChanged(notification: NSNotification) {
if(enabled) {
var tabata: Tabata = notification.object as! Tabata
switch tabata.getState() {
case .EXERCISE:
fallthrough
case .RELAXATION:
player.play()
break
default:
break
}
}
}
Hope this helps!
I have these declarations in header file:
Note: I won't explain the whole code, I think it is easy to understand
typedef void (^loopCell)(id cell);
-(id)allCells:(loopCell)cell;
And allCells function implementation:
-(id)allCells:(loopCell)cell
{
for (AAFormSection *section in listSections)
{
for (id _cell in section.fields) {
cell(_cell);
}
}
return nil;
}
The usage of allCells function:
-(void)setFieldValue:(NSString *)value withID:(int)rowID
{
[self allCells:^(id cell) {
if([cell isKindOfClass:[AAFormField class]]) {
AAFormField *_cell = (AAFormField *)cell;
if(_cell.rowID == rowID) {
_cell.value = value;
//return; Here I want to terminate loop
}
}
}];
}
My problem is, I can't terminate allCells loop in the middle (actually when I found object I need in the loop, I don't want iterate through other objects)
How can I stop allCells loop in the middle?
Look at the docs for NSArray enumerateObjectsUsingBlock:. They setup the block signature to take a BOOL pointer. Set the stop BOOL to YES to cause the iteration to stop.
typedef void (^loopCell)(id cell, BOOL *stop);
-(id)allCells:(loopCell)cell {
BOOL stop = NO;
for (AAFormSection *section in listSections) {
for (id _cell in section.fields) {
cell(_cell, &stop);
if (stop) {
break;
}
}
if (stop) {
break;
}
}
return nil;
}
-(void)setFieldValue:(NSString *)value withID:(int)rowID {
[self allCells:^(id cell, BOOL *stop) {
if([cell isKindOfClass:[AAFormField class]]) {
AAFormField *_cell = (AAFormField *)cell;
if(_cell.rowID == rowID) {
_cell.value = value;
if (stop) {
*stop = YES;
}
}
}
}];
}
You can't break from setFieldValue, but you can from allCells.
It's up to the method you're using that calls the block — allCells in this case — to provide a mechanism for stopping the loop. Usually, it's a parameter to the block.
If allCells is yours and you don't mind modifying it, you modify the block signature to take a pointer to a BOOL, initialized to YES, and check if the block modified it to NO.
(Note: You can break from a for in loop.)