Creating a exported method library class in iOS - ios

I'm sure my verbiage is what is stopping me from finding the right answer here.
I want to create an "Common" class that all of my other classes can use in xCode. This Common class will contain universal methods i use frequently by several different classes. I know one way that works is to put a "+" sign at the beginning of my method definitions and include my "Common.h" in each class. IS this the best way for memory management, efficiency, good practice? Or do you recommend a different solution.
//Inside Common.h
+(NSString*)SayHello;
//Inside Common.m
+(NSString*)SayHello{
return #"Hi";
}
//Inside AppDelegate.m
#import "Common.h"
//then later
NSLog(#"Common said %#",[Common SayHello]);

I prefer to make it C-style for the utility classes:
.h
NSString *ResourcesPath();
.m
NSString *ResourcesPath() {
NSString* resourcePath = [[NSBundle mainBundle] resourcePath];
return resourcePath;
}
usage
import .h
call with
NSString * resPath = ResourcesPath();

The + sign denotes a class method over an instance method. As far as good practice it definitely depends. As far as memory management if you're using ARC you shouldn't have to worry to much. If you're using MRC you just need to be aware of objects you're creating and returning in the class methods same as you should be for instance methods.
Another thing to consider is whether or not you need a Singleton to do this type of work. Not knowing your exact goals thats hard to determine but chances are you could probably use one.

Related

subclassing NSDictionary like so: #implementation NSDictionary (weather)

I am looking at the Ray Wenderlich AFNetworking tutorial, and I have come across a way of subclassing NSDictionary that I have not seen before:
first:
#implementation NSDictionary (weather)
then in another file:
#implementation NSDictionary (weather_package)
This seems to just "work" in another file where it's included. What's most puzzling is that the NSDictionary defined in a class that uses these seems to match the "weather_package" version and within that container the "weather" version.
Can someone point me to the name of what's going on here? I am not entirely clear on how this works from reviewing the code, particularly how the compiler decides what to apply where since no explicit reference is made to these files apart from including them in the header.
Thank you for any help.
This is not subclassing. This is extending the class using categories. This is used to bring new functionality into existing classes without subclassing them.
A category can be declared for any class, even if you don’t have the original implementation source code (such as for standard Cocoa or Cocoa Touch classes). Any methods that you declare in a category will be available to all instances of the original class, as well as any subclasses of the original class. At runtime, there’s no difference between a method added by a category and one that is implemented by the original class.
A category can be defined like
#interface ClassName (CategoryName)
#end
#implementation ClassName (CategoryName)
#end
For more information read https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/CustomizingExistingClasses/CustomizingExistingClasses.html#//apple_ref/doc/uid/TP40011210-CH6-SW1
It's not subclassing, it's more extending existing implementation with new methods, so called categories:
https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/CustomizingExistingClasses/CustomizingExistingClasses.html

How to create an ObjC function outside a class in Xcode?

I am new to Obj-C and to Xcode. I have been surfing different tutorials for a few days now but there is one question I can't get straight:
I want to write a function to generate a dictionary from a long string before parsing the information to the rest of my iOS app. I imagine a small function on the side would do and I don't see how to justify defining a class with .h and .m files.
If I want to write a small function in Obj-C (and not C) in Xcode outside of a class, how do I do it?
Thank you!
Apart from just creating a C function somewhere, you could also add a category to NSString, which would probably be more in keeping with the Objective-C philosophy. That would make it possible to perform the operation on any NSString in your program.
Note, however, that the overhead is pretty much the same as creating a class, although that should not deter you from using this approach.
Use plain C methods, for example:
// .h file
NSNumber *sum(NSNumber *x, NSNumber *y);
// .m file
NSNumber *sum(NSNumber *x, NSNumber *y) {
return #(x.intValue + y.intValue);
}
Objective C does not have functions, it only has methods.
If you want to write function use plain C.

"Proper" way to define a class - Properties vs Methods

This is an observation and a question:
I am loading some json data into a class (json already converted into an NSDictionary). The values will be read-only from the outside:
#interface Checklist
-(id)initWithJSON:(NSDictionary *)json;
-(NSInteger)checklist_id;
-(NSString *)checklist_name;
etc....
#end
With the corresponding method bodies in the .m file.
As a test, I created a class for another data element:
#interface ChecklistItem
-(id)initWithJSON:(NSDictionary *)json;
#property (readonly) NSInteger item_id;
#property (readonly) NSString *item_name;
#end
Functionally, the two classes have similar methods in the #implementation. In both cases they basically pull the appropriate value from the json and return the result. And as far as the rest of the program was concerned, the two approaches seem to be interchangeable.
So my question is:
Which approach is the best one to use?
I find either way equally readable and so far I can not find any code-reason to prefer one way over the other. I can kind of see the second option as nice since it kind-of documents the json.
You should use properties, they come in handy once you use KVO.
Also you can define public readonly properties and overwrite them in a class extension with a readwrite property that is only usable in the same class. If you try to achieve something similar you will have to deal with private helper methods — the code gets ugly.
-(NSInteger)checklist_id;
-(NSString *)checklist_name;
This isn't standard Objective-C naming. If you want to do things properly, follow the platform conventions. Apple document this in their coding guidelines documentation.
Which approach is the best one to use?
They are equivalent as far as Objective-C is concerned. The property syntax expresses your intent at a higher level than manually creating the methods, so I would prefer that approach. It's also less code.
This is less important now that ARC will clean up memory which would have been managed
inside the setter but this is still very much best practice. The performance overhead of
calling a setter method is also negligible compared to the safety gained from always
going through the setter.
this is a subjective question and you'll get nothing but opinions back, but here is mine:
the read only properties will just write the getters for you. if you don't write a private read write propertly in your .m file or wherever and just set the ivar's directly you don't even get the will/did change value for key calls and will have to call those yourself also.
#interface ChecklistItem ()
#property (readwrite) NSInteger item_id;
#property (readwrite) NSString *item_name;
#end
To access them KVO complient inside the object you'll have to do:
self.item_id = 13;
And not:
_item_id = 13;
Of course you could just have getter methods:
-(NSInteger)checklist_id;
-(NSString *)checklist_name;
And just wrap all changes in in your KVO methods:
[self willChangeValueForKey:#"checklist_id"];
_item_id = 13;
[self didChangeValueForKey:#"checklist_id"];
it's just a coding style choice, and sometimes leveraging what the compiler will write for you. but either option works the same.
If the values are read only, I'd think you'd want them as methods rather than as read-only properties to avoid any confusion that the values might be able to be set. Unless of course you want the subscribers to be able to use the dot notation for accessing the properties, but if you're just returning the values in the NSDictionary, the method form would be better as you're not keeping around another copy of the data.

Move from old-fashioned struct to class

I know this could be a noob question but I am a bit stucked here. I usualy makes the following to access app data in different ViewControllers: First I declare a global.h module like this
global.h
typedef struct {
NSString *appName
NSString *appVersion;
bool mode;
} structApp;
extern structApp app;
After that I declare in MainViewController.h the struct so that I can access data
#implementation ViewController
structApp app;
- (void)viewDidLoad
{
app.appVersion = #"v1.02";
}
#end
And then I include "global.h" in every ViewController.h
This way I can access globally. As far I can see this is a good implementation and I have used it in more than 20 apps. Problem starts when this struct grows in size. In those cases I see corrupted memory, nil variables that were previously loaded with data, etc.
There is a better way of making data available in all ViewController? Please give me some examples if you can.
You have two options
Use a singleton class - Refer Objective C Singleton
Declare properties in App delegate - Refer SO
You can access the app delegate from any class using:
AppDelegate *appDel = [[UIApplication sharedApplication] delegate];
As you were using extern in your structure, any object updating the same value.
In OOPS, global variables are never said Good, so you need to use a singleton pattern.
Create a singleton/shared class having all those stuffs in your structure and use it.
You should deal with struct only if you deal with primitive data (if you are in a OOP way).
app.appVersion = #"v1.02";
Make your struct pointing on dangling pointer, since you are pointing a data in a function scope (app.appVersion is only holding the pointer, not the data). So you must retain all those object values in order to make it content safe, but i must admit it is still a Q&D approach.
If you need global access to data, you can use a singleton, only if you really need strong encapsulation and control to data.
How to make a singleton
What should my Objective-C singleton look like?
You can use macro too, that way you'll can use constants string without worrying data persistency, since they will always be available into the scope you are dealing with.
If you only want to read the data and you dont need any complex data structure you can also use a settings file like
Settings.h
#define appName #"blabla"
#define appVersion #"1.01"
#define mode 1
In General using struct should work fine. There is nothing wrong with using them. If you observe weird values caused by overlapping memory or illegal re-use of it or so then your problem is somewhere else but not in using structs in principle. The extern statement could lead to such an issue.
A class is not much more than a struct too, from a memory usage perspective. If I were you I would design a class with properties where ever you have members when using a struct. And make use of them in pretty the same way.
For "global variables" I apply a singleton pattern. That is basically a class with a class method (the leading + instead of -) that makes the one and only instance of the class available. Within that method I check if the class (a class internal static reference to the same class) is already available (!= nil) and instantiate it. Sometimes I use the initialize method for that. Initialize is an objective-c typical thing. It is called only once for each class, even subclassed ones, when or before the class is used for the first time. A very good place for instantiating class variables as singletons but not portable to other programming languages.

Objective-C singleton pattern in iOS 5+

I've been reading a lot of threads and blog articles about how to implement a singleton in objective-c, several of them maybe being a bit deprecated (year 2010 or earlier), and it seems like people have different opinions regarding this issue... Does Apple have documentation about implementing a singleton? I couldn't find it. If so, could somebody tell me where?
I need a singleton for a class that has some both public and private variables. Currently, this is the implementation I have for such class:
#interface MySingleton ()
#property (strong, nonatomic) NSString *state;
#end
#implementation MySingleton
#synthesize state = _state;
#synthesize count = _count;
static MySingleton *sharedObject = nil;
+ (MySingleton *)sharedInstance
{
static dispatch_once_t _singletonPredicate;
dispatch_once(&_singletonPredicate, ^{
sharedObject = [[super allocWithZone:nil] init];
});
return sharedObject;
}
+ (id)allocWithZone:(NSZone *)zone
{
return [self sharedInstance];
}
Should be this the recommended way? And how should I initialize the instance variables, public and private?
Another issue I'd like to make clear about singleton is: will this generate a memory leak? Is the use of singletons actually recommended in iOS?
Thanks
The above is correct, along with #miho's comment about includng the static object inside of the sharedInstance method. But there is no reason to override +allocWithZone:. Singletons in ObjC are generally "shared," not forced. You're free to create other instances of a "singleton." If it's illegal to create other instances, then you should make init perform an NSAssert rather than fooling the caller in +allocWithZone:. If your singleton is mutable (and most are), you absolutely should not override +allocWithZone: this way.
Another issue I'd like to make clear about singleton is: will this generate a memory leak?
No. This object will never be released, but it will always be accessible. That is not a leak.
Is the use of singletons actually recommended in iOS?
Yes, and it is a very common pattern, used all over the Cocoa frameworks. That said, there are various other patterns that have started to recently become somewhat popular among developers. Dependency Injection is getting some interest, though I don't see it in practice very often. Reducing your reliance on singletons can improve testability, and I have been experimenting recently with how to eliminate some of them in my code with some success. But they have a long, proud history in Cocoa, and I do not consider them a problem.
EDIT: you have one actual bug in your code. You should be calling [[self alloc] init], not [[super alloc] init]. There's no reason to ever call +allocWithZone:, just use +alloc. (The time when ...WithZone: methods were useful has long passed.)
In Xcode, under 'Search Documentation' enter Creating a Singleton Instance. There are lots of results (but the link above, at the bottom of the page, has example code).
Yes, this is the recommended way. There is only one small difference of how I use it: I define the sharedObject as static variable inside the + (MySingleton *)sharedInstance method, because it shouldn't be possible to access the variable from anywhere else then from the getter method.
And no, you won't create a memory leak. When your app is terminated all reserved memory used by your app will be released anyway and there is no other situation where a static shared instance should get released. In pre-ARC area it even was common to override the release method do prevent accidentally releasing of the object.
A bit of warning using gcd for singletons:
dispatch_once(&_singletonPredicate, ^{
sharedObject = [[super allocWithZone:nil] init];
});
if the init method for some reason addresses the singleton object directly or indirectly, there will be a deadlock. For this reason I believe that the more appropriate way to write a singleton is through the
+ (void) initialize
method
I am still using the singleton header thingy from CocoaWithLove - may be a bit dated but still works like a charm. It basically does the same as described here referring to Apples documentation and I would assume at least Apple's documentation (bottom of this page) is still valid. There are people assuming it will stay valid indefinitely sine it is the official solution Apple suggested.

Resources