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

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.

Related

Typedef NSArray of type in Objective C

It has been a long time since I have worked in Objective C but now I am using it because I need to write something that will remain mostly source compatible for future versions. I want to create an init method that allows me to init my viewController with an array of my custom model object. In Swift I would do it like this:
typealias Stack = [StackBarTabItem]
…
func init(stacks:[Stack])
But how would I typedef an NSArray like that? I am pretty sure I can't do something like typedef NSArray<StackBarTabItem> Stack; so what is the syntax in objective c?
Until iOS 9 and Xcode 7, this isn't officially supported. One way to do this is to subclass NSArray or NSMutableArray and enforce typing in your subclass, but this isn't really recommended. One way to deal with the fact that NSArray can only hold ids is to use respondsToSelector before calling a method on any of the objects in the array.
This solution isn't really a substitute for a good typing system, but it's a common practice to get around this limitation. Thankfully, generic support is getting added soon!
Objective-C is dynamically typed. You simply do not check for it.
Asking the audience on talks and in internet fora, the real danger that code will be shipped with a typing bug is minimal and by far lower than other sources of errors. Simply do not care about this.
Ask yourself: How could that happen without getting a runtime error at the very beginning of your next program run?

Objective-C Swift interoperability with Realm

I'm adding new functionality to an app written in Objective-C with Swift. The new features require a data base so I'm using Realm-Swift. The problem is that the models that have relationships e.g. dynamic var points = List<Point>() don't translate to Objective-C on the {Project}-Swift.h file. I get the error: Type name requires a specifier or qualifier on the line #property (nonatomic) /* List<Point> */ points;
Does anybody know a workaround for this problem?
If you need Objective-C interop, your best bet is to continue using Realm Objective-c. Since List is a generic type, it can't be represented in ObjC at all.

"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.

Creating a exported method library class in 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.

Resources