There is an iOS sample project for the Dropbox Datastore API available here: https://www.dropbox.com/developers/datastore/sdks/ios
Inside that project's main class (TasksController.m), it has some API-related properties:
#property (nonatomic, readonly) DBAccountManager *accountManager;
#property (nonatomic, readonly) DBAccount *account;
#property (nonatomic, retain) DBDatastore *store;
...as well as some private methods:
- (DBAccountManager *)accountManager {
return [DBAccountManager sharedManager];
}
- (DBAccount *)account {
return self.accountManager.linkedAccount;
}
- (DBDatastore *)store {
if (!_store && self.account) {
_store = [DBDatastore openDefaultStoreForAccount:self.account error:nil];
}
return _store;
}
There aren't any code comments describing these. Why is this class structured this way? Do all classes working with the API need to use a similar structure?
For example, can I just declare DBAccount *account in viewDidLoad or should I be using the read-only property somehow?
I guess it depends on what scope you want. If you don't need the DBAcccount outside of viewDidLoad, then feel free to just declare it there. For the DBDatastore, however, you need to make sure it stays in scope for the lifetime of your app (or at least as long as you care about it syncing with Dropbox). As soon as it goes out of scope, it will also stop syncing changes to and from the server.
Related
I'm trying to use this project which is a synthesizer for Objective-C for an iPhone application I'm building. However, I'm having trouble with the MHAudioBufferPlayer class.
In the MHAudioBufferPlayer.m class, I'm getting a bunch of Use of undeclared identifier errors for _gain, _playing, and _audioFormat. This makes sense, as those identifiers are never declared with an underscore in front of them. However, they are declared in the MHAudioBufferPlayer.h class without the underscores.
I'm sort of confused by this as I'm new to Objective-C. Does an underscore denote a special action to be taken? Is it supposed to be translated into self.gain, self.playing, etc.? How can I fix this? Or is this code just buggy?
- (id)initWithSampleRate:(Float64)sampleRate channels:(UInt32)channels bitsPerChannel:(UInt32)bitsPerChannel packetsPerBuffer:(UInt32)packetsPerBuffer
{
if ((self = [super init]))
{
_playing = NO;
_playQueue = NULL;
_gain = 1.0;
_audioFormat.mFormatID = kAudioFormatLinearPCM;
_audioFormat.mSampleRate = sampleRate;
_audioFormat.mChannelsPerFrame = channels;
_audioFormat.mBitsPerChannel = bitsPerChannel;
_audioFormat.mFramesPerPacket = 1; // uncompressed audio
_audioFormat.mBytesPerFrame = _audioFormat.mChannelsPerFrame * _audioFormat.mBitsPerChannel/8;
_audioFormat.mBytesPerPacket = _audioFormat.mBytesPerFrame * _audioFormat.mFramesPerPacket;
_audioFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
_packetsPerBuffer = packetsPerBuffer;
_bytesPerBuffer = _packetsPerBuffer * _audioFormat.mBytesPerPacket;
[self setUpAudio];
}
return self;
}
If you are using new compiler that comes with Xcode4.4 onwards, then for each of your property it creates an automatic synthesize with _(underscore) as prefix.
Like, if you have created #property.... playing;
then the compiler creates #synthesize playing=_playing;
If you are in older versions of Xcode, this need to be done manually.
#synthesize generated by Xcode => 4.4 as the default. The generated private instance variable, ivar, created for you by Xcode has a leading underscore '' if you don't explicitly create your own #synthesize statement. You MUST include the leading '' when sending messages to this
property (typically UI element as an outlet from your controller.m file).
That is
#property textField;
[_textField setStringValue: #"foo"]; if you DON'T write the '#synthesize'.
The compiler's done this for you, and has made a private instance variable by synthesizing the getter/setters. The convention is to make the private ivar the name of the property prepended by the leading underscore.
OR
#synthesize textField;
#property textField;
[textField setStringValue: #"foo"]; if you DO write your own '#synthesize' or are < Xcode 4.4.
Here, the complier has NOT done it for you, your ivar name/property name are the same and can be used w/o the leading '_'.
Good luck.
Depending on what version of XCode you are using, and compiler there are different ways of doing it. I don't know how familiar you are with OOP, if you are not I suggest you read up a bit on setters and getters and objects as it is the basis of almost everything you will do from now on.
Some examples, Old school style, will create an ivar. In your .h:
#interface TheViewController : UIViewController{
NSString *theString;
}
A bit new style, will create setter and getter In your .h.
#interface TheViewController : UIViewController
#property (nonatomic, weak) NSString *theString;
In your .m file:
#implementation TheViewController
#synthesize theString = _theString;
Can be accessed by _theString or self.theString
The new way of doing it. In your .h file:
#property (nonatomic, weak) NSString *theString;
The compiler Will create everything the above way did.
Hope that helps you a bit.
Apparently it's not possible to use #synthesize when overwriting an atomic property accessor. Xcode 4 will produce a warning.
Now, is there another way of using lazy initialization of atomic properties while still letting Xcode synthesize both getter and setter automatically, without overwriting any of them?
What you need to do is write both the setter and the getter. You can still #synthesize to get the storage. e.g.:
//.h
#property (strong) id x;
//.m
#synthesize x = _x;
- (id)x
{
#synchronized(self)
{
if (!_x)
{
_x = [[MyX alloc] init];
}
return _x;
}
}
- (void)setX:(id)x
{
#synchronized(self)
{
_x = x;
}
}
You may need to do additional memory management without ARC and may want to create a different lock (instead of self) or use a different synchronisation method, but it'll give you the gist.
Icon is set as #property (nonatomic, retain) AHGridIcon *icon;
Usually i just do:
-(void)setIcon:(AHGridIcon *)iconLocal {
icon = iconLocal;
}
But i read a guide to getters setters and properties online which has lead me to believe that instead, this is right:
-(void)setIcon:(AHGridIcon *)iconLocal {
if (iconLocal != self.icon)
{
NSLog(#"local: %#", iconLocal);
NSLog(#"self.icon 1: %#", self.icon);
[iconLocal retain];
[icon release];
icon = iconLocal;
NSLog(#"self.icon 2: %#", self.icon);
}
}
The problem is, the original icon is staying put, it's not being replaced with the new icon. What am i doing wrong? Should i just revert to the usual way i do it?
You should use '#synthesize' unless you really need custom setter behavior.
like I posted in my comment:
the best way is to use #synthesize which will create a getter and a setter to with respect to the properties you wrote in your property (nonatomic, retain) => not threadsafe but fast getter and setter and a retaining (and also releasing) setter. If you dont need sophisticating stuff to do in your setter then you should not override the setter.
.h:
#property (nonatomic, retain) AHGridIcon *icon;
.m:
#implementation Something
#synthesize icon;
...
#end
The code you posted in your setter is nearly the same as the compiler would produce when only using synthesize.
Your usual way is not really nice because in your header is defined (in your property) that the setter is retaining but in your implementation you are overriding that correct setter which doesn't retain. It is nearly the same as the compiler would produce with an (nonatomic, assign) property.
But if you want to override your setter then it should look like the same as you wrote. For me it is working fine.
first retaining the new object
then releasing the old one
then assigning the local pointer to your new object
you can even omit your if but then it is really important that you first retain the new and then release the old objects (like you did - just want to mention that).
For solving your problem with an overriten setter: Your setter looks ok in my eyes. Have you also overriten the getter? If yes then post it here (you use it by calling self.icon in your log-call).
I've done a small test-program
#synthesize str;
- (void)setStr:(NSString *)localStr
{
if(str != localStr)
{
NSLog(#"old : %#", self.str);
NSLog(#"new1: %#", localStr);
[localStr retain];
[str release];
str = localStr;
NSLog(#"new2: %#", self.str);
}
}
and the output is fine:
old : (null)
new1: Hello
new2: Hello
old : Hello
new1: World
new2: World
So, I thought consulting you guys about my design, cause I sense there might be a better way of doing it.
I need to implement game bonuses mechanism in my app.
Currently there are 9 bonuses available, each one is based of different param of the MainGame Object.
What I had in mind was at app startup to initialize 9 objects of GameBonus while each one will have different SEL (shouldBonus) which will be responsible for checking if the bonus is valid.
So, every end of game I will just run over the bonuses array and call the isBonusValid() function with the MainGame object(which is different after every game).
How's that sound ?
The only issue I have currently, is that I need to make sure that if some bonuses are accepted some other won't (inner stuff)... any advice how to do that and still maintain generic implementation ?
#interface GameBonus : NSObject {
int bonusId;
NSString* name;
NSString* description;
UIImage* img;
SEL shouldBonus;
}
#implementation GameBonus
-(BOOL) isBonusValid(MainGame*)mainGame
{
[self shouldBonus:mainGame];
}
#end
Sounds ok, the only change I would consider is perhaps removing a bonus from the array should it be acepted. That way it is not checked in the future. This would also work for bonus that for other reason should no longer be available.
Whether or not the player can obtain a particular bonus according to the rules of your game isn't something the individual bonuses would know about. This is something the game itself would know. For example, you may have one game that allows bonuses A and B together, but another game that wouldn't.
So the logic to grant or deny a bonus should be in the MainGame object. I would organize it so that GameBonus is a plain bit bucket class and the logic is all in the MainGame. MainGame would be a superclass of any other custom games that might want to override the bonus logic.
A starting point:
typedef enum {
BonusTypeA, BonusTypeB, BonusTypeC
} BonusId;
#interface GameBonus : NSObject {
BonusId bonusId;
NSString *name;
NSString *description;
UIImage *img;
}
#property (nonatomic,assign) BonusId bonusId;
#property (nonatomic,retain) NSString *name;
#property (nonatomic,retain) NSString *description;
#property (nonatomic,retain) NSString *img;
#end
#interface MainGame : NSObject {
NSMutableSet *activeBonuses;
}
-(BOOL) tryToSetBonus:(BonusId)bonus; // tries to set, returns YES if successful.
-(BOOL) isBonusValid:(BonusId)bonus; // has no side effect, just check validity.
#end
When should I be using the self expression in my iphone development applications? say i have 2 fields: UITextField *text1; and NSString *str1; retained and synthesized.
when i am accessing either of these 2 fields, when should i and when should i not use self.text1 and self.str1 ?
self is not a keyword, it is an expression. Additionally, you use it any time you want to refer to a method or property on yourself, or yourself directly. By "yourself" I am of course, referring to the instance of the class you are operating in.
There are certain circumstances where it's generally discouraged to use the self.-expression to access a property. Normally you always use self for any access of a property. It's the most secure and uncomplicated way. Especially if you used retain, then memory management will be done for you.
The two exceptions from this rule:
Any init method.
In dealloc.
In both cases you are dealing with an partially initialized object. There are some side effects that may occur when using setters or getters here -- because they are methods and hence may be overridden.
For example, take a class A with a property foo that has been subclassed by class B. The subclass B adds an property bar and overrode the setter for foo. Now your init-method calls setFoo:, because you used self.foo = ... with some initial value. The subclass, however, also accesses the value of bar in this setter. But in this case, it may happen that bar has never been initialized and points at some arbitrary data. Calling a setter in init my cause crashes, although the probability may not be too high in your own code.
In your example you aren't directly accessing instance variables when you use self, instead you're accessing the properties you've defined.
Consider this example:
#interface Foo : NSObject {
NSString *_bar;
}
#property (nonatomic, retain) NSString *bar;
#end
#implementation Foo
#synthesize bar = _bar;
-(void)baz {
_bar = #"ivar"; //accessing the ivar
self.bar = #"property"; //accessing the ivar via the property
}
#end
In general if you're using properties, there's little reason to utilize the ivar. This has the added benefit of automatically retaining & releasing values for you.
But other cases exist when your properties will have a readonly modifier. In these cases it's necessary to directly access your ivars in order to set their values.
It's also a good idea to use self within a method call sometimes if you have a custom getter. The managedContext object within a Core Data-using application is a good example. If you refer to it by self.managedContext, you can override and set the object to what it needs to be if it's nil. Refer to the code generated by XCode when creating an application that uses Core Data.
Here is an example of the code generated by XCode, actually:
#interface YourAppDelegate : NSObject <UIApplicationDelegate>
{
#private
NSManagedObjectContext *managedObjectContext_;
}
#property (nonatomic, retain, readonly) NSManagedObjectContext *managedObjectContext;
#implementation ContractionTimerAppDelegate
/**
Returns the managed object context for the application.
If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.
*/
- (NSManagedObjectContext *)managedObjectContext {
if (managedObjectContext_ != nil) {
return managedObjectContext_;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
managedObjectContext_ = [[NSManagedObjectContext alloc] init];
[managedObjectContext_ setPersistentStoreCoordinator:coordinator];
}
return managedObjectContext_;
}
#end
if you "synthesize" the variable, you should "self." the variable. little rule of thumb
I don't know anything about objective-c, but this looks a lot like this keyword from other languages (like C++, C#, Java, PHP, and others). If so, then my advice is to use it always. That way, if you ever (accidentally) define a local variable with the same name, your code won't break.
However, I must also add, that this is somewhat of a religious debate with a history of flamewars in programmer communities. So take this advice with a grain of salt and use whatever seems to make most sense to you. Just be consistent about it.