ARC forbids Objective-C objects in structs or unions despite marking the file -fno-objc-arc - iphone

ARC forbids Objective-C objects in structs or unions despite marking the file -fno-objc-arc?
Why is this so?
I had the assumption that if you mark it -fno-objc-arc you don't have this restriction.

If you got this message try __unsafe_unretained. It is only safe, if the objects in the struct are unretained.
Example: If you use OpenFeint with ARC the Class OFBragDelegateStrings says this error in a struct.
typedef struct OFBragDelegateStrings
{
NSString* prepopulatedText;
NSString* originalMessage;
} OFBragDelegateStrings;
to
typedef struct OFBragDelegateStrings
{
__unsafe_unretained NSString* prepopulatedText;
__unsafe_unretained NSString* originalMessage;
} OFBragDelegateStrings;

Rather than using a struct, you can create an Objective-C class to manage the data instead.

That is because arc can't track objects in structs or unions (since they are at that point plain C pointers).
Even though you marked the file/class in question with -fno-objc-arc you might still pass an object controlled by arc to it as parameter, which would most likely result in a memory leak.

Looks like this now works without errors, probably after this change.
i.e., You can put normal (strong) pointers to Objective-C objects in a C struct. It is managed by ARC e.g., it is unretained when the struct is destructed. Verified with:
$ clang --version
Apple LLVM version 10.0.0 (clang-1000.11.45.2)

Related

how to use __unsafe_unretained in Structure [duplicate]

This question already has answers here:
ARC forbids Objective-C objects in structs or unions despite marking the file -fno-objc-arc
(4 answers)
Closed 9 years ago.
I am converting my project to ARC
I am using structure in my project.
It is giving me error while converting into ARC
ARC forbids Objective-C objects in structs or unionsrk - type definition for struct
I search in SO and I found out that using __unsafe_unretained.It will solve the issue. So I used it in my sturcture.
typedef struct Grade{
__unsafe_unretained NSString *Table,
*RowId,
*ScheduleID,
*Level,
*Label,
*Thershold;
char *CreateStmt;
} grade;
It is working but now it is showing the same error in next line at *RowId. My question is Should I put the __unsafe_unretained before all the variable. Is It safe to do that? or there is another way to fix this.
ARC can not work with object in structs, there is a technical reason for it but I always forget it, you can disable ARC for the those element in a struct using the __unsafe_unretained modifier but then you have no memory management whats so every, even your own. There are some private functions to retain and release object but they are private so you can't depend on them, you may run into trouble with apples app store. The best way to handle this is to turn of ARC for the .m files that have structs with object elements, (use -fno-objc-arc on those files) and then do all of the memory management manually for everything in that file. You could use categories to reduce the amount of code that is needed to do manually reference counting, you can have ARC off for the class file and then ARC on for one of its categories for example.

When to write "NSString *str" or "NSString str"?

I'm learning Objective C to program on iOS.
I know it has something to do with pointers, which I fail to understand.
I don't know what's the difference of creating a string (or any NSObject) like this:
NSString place = ...;
or
NSString *place = ...;
Thanks for the help!!
You never write NSString str. Period. All Obj-C objects are actually C pointers.
NSString is a class and as such instances of the class declared as NSString *str must always be declared as a pointer (since object instances can only be accessed via a pointer to the objects structure). Therefore this declaration is illegal: NSString str
Objective-C is, in some sense, more like a scripting language. Class definitions are maintained during runtime and can be modified. There is a C interface to the class definition system in objc.h. Even system classes can be modified, though it is not a good idea to do so. Because of this, all Objective-C objects must be created at runtime and accessed via pointers. To put it another way, there is no way for the compiler to know what an object should look like at compile time. This is also why "object may not respond to selector" is a warning, not an error and has the word "may" in it.

What is the strong property attribute

I am using the Xcode beta for developers, and am noticing some subtle differences. Among them is a new attribute for declared properties.
#property(strong)IBOutlet NSArrayController *arrayControl;
My question is: what does the strong attribute mean?? Does it replace some older one, or is it something entirely new? I have searched through google and the developer documentation and havent been able to find anything. Until i know what it is i am hesitant to use it.
Thanks in advance
It's a replacement for the retain attribute, as part of Objective-C Automated Reference Counting (ARC). In non-ARC code it's just a synonym for retain.
A strong reference is a reference to an object that stops it from being deallocated. In other words it creates a owner relationship. Whereas previously you would do this:
**// Non-ARC Compliant Declaration
#property(retain) NSObject *obj;**
Under ARC we do the following to ensure a class instance takes an ownership interest a referenced object (i.e. so it cannot be deallocated until the owner is).
**// ARC Compliant Declaration
#property(strong) NSObject *obj;**
As we know, we cannot release any object in an ARC-based project in iOS 5.
So when we want to retain any object for further use at a later stage and don't want ARC to remove the object from memory, then we set the property for the object as "Strong".

Objective-C, properties for references

This might be iPhone specific, I'm not sure. The compiler doesn't complain when building for the simulator but when compiling for device it throws some funky errors when I try to set properties for references to objects. Eg,
#property (nonatomic) CGRect &finalFrame;
and the coressponding synthesizer
#synthesize finalFrame;
for a variable declared as
CGRect finalFrame;
Gives the errors
type of property 'finalFrame' does not match type of ivar 'finalFrame'
Unrecognisable insn:
Internal compiler error: Bus error
Internal compiler error: in extract_insn, at recog.c:2904
However I can do it manually without issue, with the following methods:
- (CGRect&)finalFrame;
- (void)setFinalFrame:(CGRect&)aFrame;
Is this a gcc bug? It does compile for the simulator.
Your property is declared as a reference type (CGRect&) but your instance variable is not a reference type (CGRect). They need to be the same to use #synthesize.
Also, it's a little weird to be using C++ reference types as Objective-C properties, but I guess that might work as long as all the files are being compiled as Objective-C++.

Objective-C changes between OS 2.2.1 and OS 3?

When I tried compiling my app for OS 3 I encountered an the following error:
error: type of accessor does not match the type of property
The error was for a property I tried to access that is defined as follows:
NSMutableArray *myArray
#property (readonly,nonatomic) NSArray* myArray;
the property is #synthesized in the implementation file.
This worked just fine in OS 2.2.1 but doesn't is OS 3.0
Writing the getter method myself solved the problem.
Is anyone aware of changes to objective-c between OS 2.2.1 and 3.0?
Is there any documentation for these changes?
The API changes document doesn't appear to contain anything about this issue.
EDIT
the error occurs when you try to access the property e.g.
NSArray *anArray = myClass.myArray;
As I mentioned above I found a workaround for this: writing the getter method myself, however what I'm really after is some kind of documentation from apple explaining this change and any other changes that are not API related.
Thanks for your help
This is a compiler bug.
Though you didn't specify it completely, I expect your code looks like this:
#interface Foo : NSObject {
NSMutableArray *objects;
}
#property (readonly, copy) NSArray *objects;
#end
#implementation Foo
#synthesize objects;
#end
The compiler is, unfortunately, confused between the declaration of the objects property and the declaration of the objects instance variable. Remember that properties and instance variables are different things in Objective-C; a property can be backed by an instance variable, but it's really part of the public interface of a class.
You can work around this by changing your code to clearly separate the definition of the instance variable from the definition of the property, for example by prefixing the name of the instance variable:
#interface Foo : NSObject {
NSMutableArray *_objects;
}
#property (readonly, copy) NSArray *objects;
#end
#implementation Foo
#synthesize objects = _objects;
#end
This way the compiler doesn't get confused about the property versus the instance variable in expressions like self.objects (which it shouldn't anyway, but apparently does).
Just to head off the inevitable response: Apple does not reserve the underbar prefix for instance variables. It's reserved for methods. Regardless, if you dislike the underbar, feel free to use another prefix.
edit: Original answer removed after peer review found it lacking. Please read Chris Hanson's comments on the matter. I'm leaving the rest here because I think it is still valid.
Note that even if you declare the property type to be NSArray, the object returned is still an NSMutableArray, and the mutable methods are defined for it. Declaring the property in this way does not prevent someone from accidentally mutating the array.
If you want to be sure that the returned array is not mutable, you could declare the property as in your original example, and then roll your own accessor:
- (NSArray *)myArray { return [NSArray arrayWithArray:myArray]; }
Note that this would return an unretained NSArray. It would be up to the caller to take ownership of the object if it needed to persist.
You are seeing errors because XCode is now issuing warnings and errors for things it did not previously...
I would argue that it should be at most a warning to do what you are doing, I understand your attempt to present the array as immutable to the outside world but have it mutable inside the class. You may want to consider a different accessor with a different name, built to return the mutable array specifically.
It is still Objective-C 2.0; the compiler is just maybe a little updated with considering this kind of type changing an error. It pretty much should be an error. At least it should warn you that you likely don't mean what you wrote. Then you could cast stuff to make it not warn you, which you can't do with the #synthesize statement.
I just exactly pasted your code and a synthesize statement into my controller and I got no errors or warnings about it. It built fine. Now I set the base SDK to "Simulator 3.0", and the build to "Simulator 3.0 Debug". This project had started in the 2.2.1 SDK and I just installed the 3.0 SDK yesterday; Xcode is version 3.1.3.
Update: Oh I see that actually trying to set the property is where you get the error you mentioned.
self.myArray = [NSArray arrayWithObject:#"foo"];
Clearly you cannot #synthesize this behavior and must write your own accessors.
- (NSArray*)myArray {
return [NSArray arrayWithArray:myArray];
}
- (void)setMyArray:(NSArray*) pMyArray {
myArray = [NSMutableArray arrayWithArray:pMyArray];
}
Filling in these accessors, did not make the message go away, so I had to change the access to:
[self setMyArray:[NSArray arrayWithObject:#"foo"]];
Using the above syntax without custom accessors also did not work.
PS Wow, is anyone else annoyed that you can neither copy message bubbles, or the text in the build results window?
So this is really to do with the #synthesize call that is not happy about exposing a NSMutableArray as an NSArray - why not just implement the getMethod.
Actually thinking about it it must be the set method that is not happy - you wouldn't be able to set an NSArray into an NSMutableArray.
Your questions were:
Is anyone aware of changes to objective-c between OS 2.2.1 and 3.0?
Is there any documentation for these changes?
The definitive answers are:
1) There were no intentional changes to the language specification, but the compiler and other developer tools changed. Chris and his coworkers are the experts on those changes.
2) Probably not, because any changes were unintentional or made to better match behavior with the documentation.
You shouldn't be so quick to dismiss Chris' answer as "a guess." Chris works on Apple's developer tools. You might get another answer you like more, but you won't be getting a more expert answer.