I have a Owners class defined that is used just fine in existing classes.
I tried to add another class, and no matter what I do (deleted, recreated new class, copied other class files over and renamed, cleaned all targets, howled at the moon), I cannot use this particular class in any new files I create.
The class is simple with a singleton definition of an array.
Here it is in use in another class (just fine):
#import "OwnersSchema.h"
#import "Owners.h"
#import "Constants.h"
#implementation OwnersViewController
#synthesize mid,imageStore;
- (OwnersSchema *)OwnersForIndexPath:(NSIndexPath *)indexPath {
return [[Owners sharedOwners].ownersArray objectAtIndex:indexPath.row];
}
So I make an exact copy of the above header and make files, just rename interface, etc. and add the same exact code, and it claims Owners is undeclared: First use in function.
I can add other class definitions to the new file and it sees them just fine.
Here is the Owners class:
#import <UIKit/UIKit.h>
#import "URLConnection.h"
#class OwnersSchema;
#interface Owners : NSObject <URLCacheConnectionDelegate> {
NSMutableArray *ownersArray;
NSString *lastUpdated;
NSString *url;
NSString *dbpath;
}
#property (nonatomic,retain) NSString *dbpath;
#property (nonatomic,retain) NSMutableArray *ownersArray;
#property (nonatomic,retain) NSString *lastUpdated;
#property (nonatomic,retain) NSString *url;
-(void)saveOwnersArray;
+ (Owners *)sharedOwners;
#end
I don't get it. I just want to create another viewcontroller. Is there some limitation on the number of files or class inclusions (actually, I use this Owners class in only a few places). And why does it work everywhere else except for the new class I'm trying to create?
Try a clean and rebuild?
OK, I cleaned all targets again, then ran clean caches, then restarted, and the class is usable again.
Related
You can declare a variable like this.
Case1:
#interface MyClass : NSObject
{
NSString *str;
}
#end
Also, if you want to set its property, you can do
Case2:
#interface MyClass : NSObject
{
NSString *str;
}
#property (nonatomic, strong) NSString *str;
#end
And in the .m,
#synthesize str;
My understanding with the difference between Case 1 and Case 2 is that synthesized and propertied variables in Case 2 can be accessed from another class when this another class instantiates this class.
What are other differences between Case 1 and 2? Say when these variables are just used only in its .m file. The fact that you are setting 'str' properties probably makes a difference, but how? If you don't set property, how are they going to be released with ARC?
The differences are fairly confusing in this case because of the way it is set up.
Also it is using what is now old practises.
The new suggested way of doing this (suggested by Apple) is to do this...
MyClass.h
#interface MyClass : NSObject
#property (nonatomic, strong) NSString *str;
#end
MyClass.m
#import "MyClass.h"
#implementation MyClass
#end
You no longer need the #synthesize as Xcode (since 4.5) will auto generate these for you.
Doing this sets up the property called str and an iVar called _str.
You now no longer need to worry about defining multiple ivars and properties etc... Just use the property and that's it done.
An example setter method for the property str would look like this...
- (void)setStr:(NSString*)str
{
_str = str;
}
I can build the following code for debug, but not for release for an OS X target in xcode:
myclass.h:
#interface myclass : NSObject
#property (nonatomic,copy) NSString *name;
#end
myclass.m:
#implementation myclass {
NSString *_name;
}
#synthesize name = _name;
#end
Any ideas why? On iOS it builds for both release and debug.
I understand that moving the instance variable declaration to the .h will work, but my intention is to hide the implementation details (of course the real class is more complex than this example). I've tried this on the latest xcode version (4.6, build 4H127) on Mountain Lion when building 64-bit apps.
One approach is to use a class extension. In your .m file, write
#interface myclass ()
{
NSString *_name;
}
#end
above your #implementation for myclass.
On the other hand, you don't actually need to declare the instance variable which is backing your property. If you just write
#property (nonatomic, copy) NSString *name;
in your class declaration (the code beginning with #interface myclass : NSObject and ending with #end), a backing NSString * ivar _name will be generated for you automatically, and you'll be able to access this ivar inside the instance methods of myclass. You don't even need to write #synthesize name = _name;. Furthermore, if you want to use a variable name other than _name to back your property name, you needn't declare the ivar; instead you can just use #synthesize
#synthesize name = m_Name;
inside your class' #implementation block.
Instance variables in the implementation block requires the modern Objective-C runtime. See Objective-C Feature Availability Index. It could be that the release is targeting a version of OS X which does not support the modern runtime.
you have not specified object type of the property "name" here:
#property (nonatomic,copy) name;
use this
#property (nonatomic,copy) NSString *name;
Here's my question.
Let's say I have a class called WebServiceBase.h. And I need to add a iVar in to that class called NSString *requestData. But I don't need to add that iVar in to the header file and make it visible to the external people. (If I'm distributing this as a class library)
Also I need to be able to access this requestData iVar, within the other classes that is extended from the WebServiceBase.h. (These extended classes are written by me. Not from the external people)
I tried with declaring the requestData iVar within the class extensions. But then it's not visible to the extended classes.
Any solution for this? I need to protect my data and make it hide from the external world.
You can define your ivars as protected via the #protected keyword, meaning that your class and all subclasses can access it without any problem, but the compiler won't allow this for other classes which don't inherit from your base class:
#interface Foo : NSObject
{
#protected
NSObject *a;
}
Its as simple as that and already gives you all the safety you can get from Objective-C.
You can have an ivar definition block in the #implementation block.
there are 2 ways , you can choose one you like.
1).h file
#interface YourClass
{
}
.m file
#interface YourClass ()
#property (nonatomic, retain) NSString *title;
#end
#implementation YourClass
#synthesize title;
//your method
2) .h flie
#interface YourClass
{
}
.m file
#implementation YourClass
{
NSString *title;
}
//your method
Declare a class extension that defines the ivar in another .h file. Call it something like myclass-private.h. Then import that header in both your main class your subclasses.
So what is actually the difference between these two versions:
#interface Foo : NSObject
// A guy walks into a bar.
#property(nonatomic, copy) NSString *bar;
#end
// Implementation file
#interface Foo ()
#property(nonatomic, retain) NSArray *baz;
#end
and
#interface Foo : NSObject
// A guy walks into a bar.
#public
#property(nonatomic, copy) NSString *bar;
#private
#property(nonatomic, retain) NSArray *baz;
#end
As far as my understanding goes, putting the #property in the .m basically means that it is private. Correct me if I am wrong? Also which is the best implementation then? Is it just a coding style/practice?
The compiler can warn you about things that it knows about.
When I import your header the compiler can see that Foo has a method called bar and setBar:. This means I can use them both
[instanceOfFoo setBar:#"some string"];
NSLog(#"%#", [instanceOfFoo bar]);
whereas because I only imported the header - the compiler can only see the header it is not aware that there are also methods baz and setBaz: available, so doing the following will cause the compiler to barf
[instanceOfFoo setBaz:#"some string"];
NSLog(#"%#", [instanceOfFoo baz]);
I can however still access these properties if I know they exist by using KVC like this without the compiler barfing
[instanceOfFoo setValue:#"some string" forKey:#"baz"];
NSLog(#"%#", [instanceOfFoo valueForKey:#"baz"]);
You are correct in your understanding. Putting the #property in an #interface in the .m is making it "private". What that means is you'll get compiler warnings if you try to access that property from another class that includes the .h that doesn't include the #property declaration. This doesn't mean that you can't access the property, just that the compiler will yell at you.
As for best, neither one is best. You should implement the one that makes sense for you object, which could include items in both the .h and .m (read only proper in .h with full property in .m). Basically if the #property shouldn't ever be accessed outside of your class put it in the .m.
Hey all i have been trying to figure out why i am getting this warning:
'TxtAppDelegate' may not respond to '-TCN'
'TxtAppDelegate' may not respond to '-TID'
when i try to use this code:
// .h file
#interface RootViewController : UITableViewController <UIActionSheetDelegate> {
NSString *theCompanyName;
NSString *theID;
}
#property (nonatomic, retain)NSString *theCompanyName;
#property (nonatomic, retain)NSString *theID;
// .m
NSString *theCompanyName;
NSString *theID;
#synthesize theCompanyName;
#synthesize theID;
TxtAppDelegate *customObjInstance = [[TxtAppDelegate alloc] init];
theCompanyName = [customObjInstance TCN];
theID = [customObjInstance TID];
I've added the header for the .h file that has the two functions in them. The code works but i really would like to solve the warning problem.
Any help would be great to solve this problem of mine :)
David
While it would have been more helpful to see the header file where TxtAppDelegate is declared, I'm guessing the method declarations must be off. They should look like this:
- (NSString *)TCN;
- (NSString *)TID;
If this is not the cause of the problem, please post the header file here so we can examine it.
How are declared these two functions in your header?
They should belong to a category of TxtAppDelegate class or to a protocol. If you choose the protocol, TxtAppDelegate interface should mention that it conforms to that protocol.