-3

new to objective c here... I am trying to initialize 2 strings and set them later, but I got this error for r1 and r2:

the variable is not assignable (missing _block type specifier)

my code looks like:

    NSMutableString *r1 = [NSMutableString stringWithFormat:@"None"];
    NSMutableString *r2 = [NSMutableString stringWithFormat:@"None"];
    NSURLRequest *request = [client URLRequestWithMethod:@"GET" URL:statusesShowEndpoint parameters:params error:&clientError];

if (request) {
    [client sendTwitterRequest:request completion:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
        if (data) {
            // handle the response data e.g.
            NSError *jsonError;
            NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];
            NSLog(@"ok!");
            for(NSString *key in [json allKeys]) {
                NSLog(@"%@",key);
            }
            r1 = json[@"statuses"][0][@"text"];
            r2 = json[@"statuses"][1][@"text"];

I am confused about if this is the correct way to set strings.... like all i want to do is to initialize a string and set it later.

J.Titor.0
  • 79
  • 12
  • 3
    Your error suggests the code you include does not contain enough context for people to verify your problem. Where *exactly* are those two assignments? Edit your question to provide more context so people can help you better. – CRD Jan 27 '18 at 09:17
  • It's unclear, missing info, but if I was here to guess, I'd say that you have a async call with `NSURLSession` with blocks, you want to retrieve some value into `r1` and `r2`, they are declared before the block, so you need to do `__block NSString *r1` instead. See there: https://stackoverflow.com/questions/7080927/what-does-the-block-keyword-mean Also, the way you define it being mutable, but I'd strongly presume that `json[@"statuses"][0][@"text"]` is not really mutable, being a `NSString` and not a `NSMutableString`. – Larme Jan 27 '18 at 13:43
  • Read this: https://stackoverflow.com/questions/21440388/missing-block-type-specifier-compilation-error-after-refactoring-code-but-ok – Larme Jan 27 '18 at 21:58

1 Answers1

1

Your assignments to your two string variables are inside a block you pass to sendTwitterRequest:completion:. By default a block captures the value of any local variables it uses declared outside the block, in your case r1 and r2, it does not capture the variables themselves, which means it cannot alter the values stored in those variables. Note that if the value captured is a reference to a mutable object, in your case the values are references to mutable strings, then you can mutate the object - doing that does not alter the reference itself.

You can fix your code in two ways:

1) I think the values you are trying to assign are references to immutable strings, NSString *, so I suspect you have only declared the two variables as NSMutableString * in an attempt to fix your problem.

To allow assignment to captured local variables you must annotate the local variable declaration with __block, this changes the behaviour capture so that the variable, rather than its value, is captured. To go this route you just need to change your declarations to:

__block NSString *r1;
__block NSString *r2;

There is no need to give the variables an initial value, they will automatically have the value nil. Your block can now assign directly to r1 and r2, however see the BIG BUT below.

2) If you do require mutable strings, NSMutableString *, then your two declarations are fine and the issue is that you use assignment to the variables (r1 & r2) instead of mutating the strings they reference. You can change the value of a mutable string using setString: (Apple documentation. To do this replace your two assignments with:

[r1 setString:json[@"statuses"][0][@"text"]];
[r2 setString:json[@"statuses"][1][@"text"]];

These two will mutate your strings referenced by variables and those changes will be visible outside your block via the references stored in r1 and r2. However as with the first method above see the following BIG BUT...

BIG BUT

The code fragment you supply suggests you might also be making a common error: assuming values assigned within a block used as an asynchronous handler will be visible after the call taking the block, in your case sendTwitterRequest:completion:. This will normally not be true, the call to sendTwitterRequest:completion: returns before the completion block has run - which is the whole point of asynchronous methods such as sendTwitterRequest:completion:; they schedule the work (accessingTwitter in your case) to run concurrently in the background and then return, later when the asynchronous work is completed the completion block is called.

If you have made this error you need to read up on asynchronous design, you can use Apple's documentation if you wish, you can also search on SO - there are plenty of Q & A on the topic. After that is done you can redesign your code, if you have problems at that point ask a new question.

HTH

CRD
  • 52,522
  • 5
  • 70
  • 86
  • it solves the error I am having... but when I set a label.text to r1 or r2 I got none or null. Does that mean I have to change NSMutableString into NSString? – J.Titor.0 Jan 28 '18 at 18:01
  • I suspect it means you've run afoul of the "big but" and are reading the variable before the asynchronous block has written it. – CRD Jan 28 '18 at 22:03
  • Thanks for helping and clarifying :-) it helps me a lot – J.Titor.0 Jan 30 '18 at 01:25