If I put an NSURL in a class declaration and set it to something in a method, when the method finishes the object it's pointing to is gone. Is there a way to have a non pointer version of an object in the declaration like you can in C++? XCode doesn't seem to want to let me.
Is there a way to have a non pointer version of an object in the declaration like you can in C++? XCode doesn't seem to want to let me.
NSObject types don't support this. Even creating your own root objc class is not supported with Clang (you could do it with GCC if you were geeky enough). Thus, the short answer is "No, you can't declare a NSObject type by value".
But that's not really important; the right solution is to figure out why your member is cleared -- using ref counted pointers works for everybody else.
Related
I have an NSMutableArray in which i want to add those objects which conforms the ObjectType. Is there any way i can get the ObjectType declared using light weight generics so when adding an object i can check whether the object is about to insert is ObjectType; if yes insert it else just forget it.
Thanks.
In Objective-C all type analysis is done at runtime and only at runtime. (The compiler gives warnings at compile time, but the produced code is bit-identical to code with any other object type.) The lightweight generics are for Swift. We didn't need that in the past 30 years. (Wow, this is really long in computer sciences.)
So, any code related to the mutable array with or without type specifier is identical. For Objective-C a static type information is the wrong thing. Even there would be a way to do that, it would be anticonceptual.
So: No.
Why do you want to do that? Don't do it.
I am using a 3rd party Obj-C static library for and API in a RubyMotion project and one of the classes in the library defines some public instance variables in the interface section in the API header file. Here is the code as it's pretty short:
#interface TransporterFile : NSObject
{
#public
NSString *name;
TransporterFileType type;
NSDate *modifyTime;
NSDate *createTime;
unsigned long long size;
}
- (BOOL) isFolder;
- (BOOL) isShared;
#end
In ObjC, these values can be reached like this:
name = transporterFile->name
but there is no getter defined so you can't use dot notation.
In RubyMotion, probably because there is no getter, there is no instance variable exposed to me. I have tried using the .instance_variables method and it returns an empty array. I also tried the instance_variable_get('#name') method but that doesn't work either. I am able to call the two methods isFolder and isShared and they work as expected.
Update: I tried doing a similar thing in the Swift language and it had similar problems and that led me to a suggestion to use the valueForKeyPath('name') method to access the 'name' instance variable. That worked in Swift and led me to check if a similar method was available to RubyMotion. The good news is that this works but is a bit clunky so I'll leave this question open for now in the hope that a better answer is available.
I realise the 3rd party library is not following best practice and I will recommend to the vendor that they define some properties instead if using instance variables directly but for now I need a workaround.
Can anyone please suggest a way to access these public instance variables from RubyMotion or perhaps by wrapping the vendor's library in another ObjC library. I've never written an ObjC library (wrapper or not) so would appreciate some advice before I embark on this option.
The full API can be seen here: https://secure.connecteddata.com/developer
Note that I'm using Mac OS X 10.10 with Xcode 6.1.1 and the latest version of RubyMotion. The Mac OS X API download from the above site is missing the header file so I used the header from the iOS download.
Many thanks,
Craig.
I updated my question to explain that I found the following method allows me to access the public instance variables.
obj.valueForKeyPath('name')
However, I'd be happy to hear of any better ways to do this as it's a bit clunky.
ps. Why is it that I can spend hours trying to find a solution to a problem then within minutes of posting the question on an open forum, I find a potential answer? Grr... :)
I suppose the default scope for ivars is #protected.
I declared a variable like this in the header file of a class:
{
int _test1;
}
But I could print this variable _test1 using NSLog in a totally unrelated object.
NSLog(#"%d", _test1);
Why is _test1 available to the second object?
Where can I find the latest ivars scope rules?
Thanks in advance.
If you are talking objective-c v1, then you are correct... unless otherwise defined (by using the #public, #private, or #packaged keywords), ivars will default to #protected.
You're not showing your code, so I can't be certain, but I wonder if you have the same "issue" as described in this other post: Objective-C - Private vs Protected vs Public
For objective-c 2 this is kind of "deprecated". This article pretty much describes how to do this now: http://robsprogramknowledge.blogspot.com/2011/08/objective-c-property.html
The best place to go for the latest objective-c documentation is probably developer.apple.com... Here's a link to the latest programming manual: https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/Introduction/Introduction.html
I have a lot question marks tolling above my head.
What I don't get is before xcode 4.3 I needed to declare forward declarations (for private methods) in my implementation file.
Like in my .m file:
// deleting this with xcode 4.3 the below code still does work
// in previous versions i had to put this because otherwise the compiler can't find methodFirst
#interface DetailViewController ()
- (void)methodFirst;
- (void)methodSecond;
#end
#implementation DetailViewController
- (void) methodSecond
{
// if i delete the forward declaration now adays i dont get a compiler error that he cant find method first
[self methodFirst];
}
- (void) methodFirst
{
}
#end
Now it seems I don't need to do that anymore? Did Apple update the compiler so that it isn't needed anymore to put forward declarations?
I can't find any reference to an official Apple source about this change. I wonder what other people have encountered in their new environment.
As of the LLVM Compiler version shipped with Xcode 4.3, if you try to call a method that the compiler has not previously seen, it will look in the rest of the current #implementation block to see if that method has been declared later. If so, then it uses that, and you don't get a warning. Hence, as of Xcode 4.3, there's much less need to pre-declare your internal methods. Clearly, you still need to declare methods that are publicly exposed to other classes.
This change was noted in the release notes of some of the Xcode 4.3 betas, but apparently didn't make it into the "What's New in Xcode 4.3" final documentation.
Unlike has been suggested in other answers, this is not just an "Undeclared Selector" warning that has been turned off by default. In fact, if you're using ARC, unrecognized selectors are still hard errors. Try calling [self myNonexistentMethod] and you'll see; the compiler still complains.
There aren't any private methods in Objective-C. What you're thinking of is the class continuation, the "nameless" category interface you can declare in your .m file to declare methods that will be in the class implementation, but that aren't in the public interface.
There's never been a requirement to declare methods before they're used. However, it's always been a good idea, and the compiler has a warning flag to indicate when methods that haven't been seen are used. The reason is to do with the operating system's calling convention for functions. Different types, such as structures, floating point numbers, integer numbers, and pointers, can all be handled in different ways when they are the arguments to or return values from functions. Indeed, on different computers and in different operating systems, they are handled in different ways. To know how to handle the arguments and return values for an Objective-C method, the compiler needs to know the signature for that method: how many arguments of what types it takes, and what type it returns.
If it hasn't seen a declaration of the method, then the compiler will need to make a guess. If that guess is incorrect, then it can end up putting the wrong values into the arguments, or interpreting the return value incorrectly, or trying to take something off the stack that doesn't exist.
In the Modern Objective-C runtime, you can do something like this:
#interface MyClass : NSObject {
}
#property NSString *stringProperty;
#end
#implementation MyClass
#synthesize stringProperty;
#end
It is my understanding with the modern runtime this will not only synthesize the accessors for my property, but also the instance variable itself, so I could then say in one of this class's methods [stringProperty length]; and it would work just as if I'd declared an instance variable.
I've started using this in all my code now, because, well it's one less thing I have to write over and over again. And I've heard with the clang 2.0 compiler, I'll even be able to skip the #synthesize (but that's another matter). But I've been wondering, what are some of the downsides to doing this? When might I truly need an instance variable in addition to my properties?
I know there are sometimes when I want to keep a variable private and not give access to it externally (but then I usually just declare the property in my private class extension, or I don't create a property for it at all, if I don't need accessors for it).
Are there any times when I wouldn't want to do this?
One possible reason why it might be advisable to not use synthesized instance variables is they are a bit more of a pain to debug in the current version of Xcode (3.2.5). They don't seem to show up in the live debugger view when running code through GDB, the only way to get at them is through the gdb console like po [0xOBJ_ADDRESS propertyName]. Not exactly as nice as a standard, non-synthesized ivar.
Maybe Xcode 4 fixes this but I don't have enough experience with it to say (and it's still under NDA).
More info on this SO question: Seeing the value of a synthesized property in the Xcode debugger when there is no backing variable
You may want to provide many properties for a single instance variable, e.g., :
for accessing an angle value both in degrees and radians
for accessing coordinates both in rectangular and in polar systems
In these cases, you don't want to synthesize instance variables (it already exist) nor accessor methods (you want to provide them for doing conversions).
Anytime you need to make a conversion (unless someone knows a better way) in a class you need to serialize. For example if you have a class that has a numeric value. You cannot serialize an integer so you store it as a NSNumber in the class but the property is a integer type.
Another example is if you code as Apple recommends when working with CoreData. They say you should create a custom class derived from NSManagedObject as the Class for your managed object and use a property for each attribute. Then you would use #dynamic instead of #synthesize and no iVar is needed at all.
But I've been wondering, what are some of the downsides to doing this? When might I truly need an instance variable in addition to my properties?
Possible reasons:
it allows you to change the instance variable in init and dealloc without tripping over subclass overrides or KVO.
the app will compile and run in 32 bit mode on Mac OS X. There are still some Intel Macs out there that don't support 64 bit.
I'm not sure how valid the first point really is. There may be other ways around the issues. The second point is game over though if you need to support older Macs.
One other reason is to avoid shortcuts to direct variable access.
I try to follow the personal coding convention:
- object variable: prefix with underscore '_xxx'
- property: named without underscore 'xxx'
This ensure that I never write unintentionally something like
xxx = value;
or
[xxx someMessage];
I want to always use the getter/setter.
self.xxx = value;
[self.xxx someMessage];
This is particularly useful when you are using lazy init for object variables...