19

I have two projects open in Xcode 6.4. Both use the follow declaration:

- (void)startService
{
    __weak typeof(self) weakSelf = self;
    [self.messageOperationQueue addOperationWithBlock:^{
        NSDictionary *storedMessages = [mySettings get:kStorageName withDefault:@{} storageType:kMySettingsStorageTypeDiskMapped];
        [weakSelf.messages addEntriesFromDictionary:storedMessages];
    }];
}

However, in one project there are no errors, and in the other project I get a compiler error:

Expected ';' at end of declaration

It wants me to put a semi-colon after __weak typeof(self). I have suspicion that I'm just doing something really dumb, but I'm having trouble figuring out what. Also, I know I could replace the typeof(self) with myClass *.

Ben Flynn
  • 18,524
  • 20
  • 97
  • 142
  • Trying to remove this line and rewrite it. – Bannings Aug 21 '15 at 16:39
  • @Bannings Tried that. Also cleaned and rebuilt. Also restarted Xcode. When I clean, it flashes the error on and off like it can't decide what's going on, ultimately deciding its an error. – Ben Flynn Aug 21 '15 at 16:43
  • What's in the next line? – matt Aug 21 '15 at 16:43
  • @matt Added the method. This fails in other places with other methods as well in this project. When I replaced them all with `myClass *` it compiles fine. – Ben Flynn Aug 21 '15 at 16:47
  • This is not relevant to your question, but you do realize, don't you, that you're not doing the weak-strong dance properly and that you can crash when you say `weakSelf.messages`? – matt Aug 21 '15 at 16:48
  • Are you using ARC with this project? If not, try using `__block` instead of `__weak`. – musical_coder Aug 21 '15 at 16:49
  • @LeoNatan `__typeof` worked. Why? – Ben Flynn Aug 21 '15 at 16:52
  • Was just typing an answer with an explanation when you posted your comment. Good. – Léo Natan Aug 21 '15 at 16:54
  • @matt Since weakSelf is weak, it should be nil-ed when it goes out of memory and sending a message to nil should be safe, yes? – Ben Flynn Aug 21 '15 at 16:54
  • `weakSelf.message` will not crash. `weakSelf->message` will, which is one of the few reasons why properties are preferred over ivars. – Léo Natan Aug 21 '15 at 16:55
  • @matt "Fetching" a property is actually calling the getter method of the property. Calling that method on a nil objects results in a nil result, not a crash. – Léo Natan Aug 21 '15 at 16:56
  • @LeoNatan Ah, okay. One less thing to worry about. Still, I was taught to assign `weakSelf` to a strong reference first thing and proceed only if this is not `nil`. (It's been a while since I did this; I live in Swift these days...) – matt Aug 21 '15 at 16:56
  • @matt This is for another reason. If you have several code lines accessing the same weak variable, it may be released in the middle, causing undefined behaviour in your code. This way, you hold it strongly for the duration of scope. – Léo Natan Aug 21 '15 at 16:57
  • @matt Aside from different semantics of Swift, properties are implemented exactly the same way. Internally, the Swift runtime is calling all the ObjC runtime functions we love. `;)` – Léo Natan Aug 21 '15 at 17:01
  • @LeoNatan Yes, but my point is that Swift makes it much easier to get the dance right. It basically twists your arm and forces you to do so. :) – matt Aug 21 '15 at 17:04
  • @matt Which I am not necessarily fond of. But to be honest, ARC did a most things right. If Apple were to go a little step further and provide a hint system to tell the compiler/runtime how to capture scoped objects, it would have been perfect in ObjC long before Swift. Let's admit it, `__weak __typeof(self) weakSelf = self;` is ugly. – Léo Natan Aug 21 '15 at 17:06

2 Answers2

36

Use __typeof instead of typeof.

This is because both __typeof and typeof are extensions to C, but typeof is only enabled in Clang when the language is a GNUXX variant of C, but not for CXX.

Léo Natan
  • 56,823
  • 9
  • 150
  • 195
6

I had a similar error. @Leo Natan is right and if you want, you can change the C dialect to GNU like this:

In the Project Navigator go to Project -> Target -> Build Settings

There look for C Language Dialect and change it from c11 or c99 to GNU99 and it will solve the problem. Now you can use typeof()

I hope it helps :)

Ricardo Anjos
  • 1,417
  • 18
  • 22