Where to put a global macro/function in iOS application - ios

In some apple documentation i've seen, they suggest using a macro to check for the current version of iOS installed which could be used across your project. It looks something like this:
NSUInteger MajorVersionInstalled();
NSUInteger MajorVersionInstalled() {
// Call objective-c methods and return NSUInteger
}
#define IS_OLDER_THAN_SIX (MajorVersionInstalled() < 6)
And the idea is that you can use the macro in conditional checks across your project. I'd like to use this idea, but i'm getting a bit confused because its using a c function and i'm not sure where to define it:
Is there a place I should use to define this for use across my project (Prefix.pch ??).
Does the function implementation go in the same place??

Is there a place I should use to define this for use across my project (Prefix.pch ??).
The PCH is not a good place. It's better to put in a separate header and #import where you need it because it is likely that this declaration need not be visible everywhere. Note: The implication by using NSUInteger is also that the function is only usable in objc sources.
Does the function implementation go in the same place??
Unless you have a very specific need, the declaration:
NSUInteger MajorVersionInstalled();
belongs in a header file and the definition:
NSUInteger MajorVersionInstalled() {
// Call objective-c methods and return NSUInteger
}
belongs in an *.m file.
Once you do that, you could also create a function to get rid of #define IS_OLDER_THAN_SIX (MajorVersionInstalled() < 6).
Using the pch, definitions in the header, and foundation everywhere will often slow down your builds and can create larger binaries. It's difficult to detect this in small projects, but quickly becomes an issue in larger bodies of code and libraries.

Related

How to access iOS private APIs in Swift?

How can I call non-public iOS functions and acces non public properies from Swift? Specifically, I would like to use one non-public class in QuartzCore framework.
One solution that came to my mind is to create "bridging" Objective-C project that would wrap this non-public APIs into public ones and than call this Objective-C functions from Swift. However, my solution is pure Swift now and I would prefer to keep it that way. Is there any more staitforward way? (for example adding something to Objective-C bridging header file)
Note: I know what you are thinking, private APIs are private because they should not be used. I know the risks, I am aware of all the donwsides, app store restrictions etc. After all that carefully considered and lot of research, it unfortunatelly still seems the best way to go in this particular case.
You can do the very same trick that you would do if your project was in
Objective-C.
Create a header file and put the declaration of a category on the class, along with the declaration of the private methods you wish to expose. Then, tell the Swift compiler to import this bridging header.
For demonstration purposes, I'm going to poke around in the internals of NSBigMutableString, a private subclass of NSMutableString, and I will call its _isMarkedAsImmutable method.
Note that here, the entire class itself is private, hence I have to declare it as a subclass of its real superclass first. Because of this, I could have as well declared the method right in the declaration of the class itself; that, however, wouldn't have demonstrated the usage of the (Private) trick-category.
If your class is public, then obviously you will only need the category, and you won't need to (re-)declare the class itself.
Bridge.h:
#import <Foundation/Foundation.h>
#interface NSMutableString (Private)
- (BOOL)_isMarkedAsImmutable; // this is a lie
#end
#interface NSBigMutableString : NSMutableString
#end
s.swift:
let s = NSBigMutableString()
println(s._isMarkedAsImmutable())
Compile and run:
$ xcrun -sdk macosx swiftc -o foo -import-objc-header Bridge.h s.swift
$ ./foo
false
$
You can get private classes using NSClassFromString: and interact with them using performSelector.

Any smarter way to define constants in bulk?

I want to have macros for all constant strings in the project, which I am assigned to maintain.
The format of database fields are like #"first_name", #"last_name", etc.
What I want is like follows:
#define kFirstName #"first_name"
#define kLastName #"last_name" // And so on.
Problem: I have over 3500 unique fields with constant strings. I want each one of them to be defined as macro.
Any smarter way to do this. I am thinking of manually copy, paste & edit each one of them.
Tagging as iOS & Objective-C, as the project itself is an iPad Application.
In general, defining constants like this is the way to go on iOS, so you're on the right track.
You surely won't get around typing out each of the fields at least once.
I would recommend either of two approaches:
use multiple .h-files for the definition of all the constants. you can group the header files according to the definitions that they contain (e.g. all fields related to user data in UserDefinitions.h). that way you at least make sure that you don't have to import all the constants everywhere in your code. working with prefixes will also be helpful in this situation, so prefix all the Macros names with the .h-file that they contain, e.g. kUserFirstName so that you you know at first sight where this constant comes from
define all your constants in one (or multiple) property lists. that makes them easy to maintain. only make sure that you don't load the property file each time you use one of the constants, but rather cache the file once its loaded for the first time.
When using Core Data consider using mogenerator which creates constant values for you that you can reference for all of the attribute and relationship names.
the cleanest way is to make a pair of constants files (header and main). Create a new class (inheriting from whatever, NSObject say) call it constants. Delete the #interface and #implementation, so you have an empty header (except for #import Foundation/Foundation.h) and empty main (except for importing the header.)
then declare each in the header like this
extern NSString *const kFirstName;
and implement each (in the .m file) just like this
NSString *const kFirstName = #"Johnny";
make sure the .m file is added to your target, import the header where need be.

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.

Should Objective-C constants be wrapped by the implementation block?

I have an iOS application I'm writing. I've moved away from #define to create my constant values. I have a few questions regarding the use of these style declarations: NSString *const segueToMainMenu
If I'm using these internally, I'm placing them inside the .m file. However, should I be placing these wrapped around the #implementation block or outside of it or does it matter? I'm thinking inside, because they are specific to the implementation and not global, but I'm not sure. Any details are appreciated.
If I'm creating a more global scope using the extern keyword and I'm using a Constants file pair (Constants.h/Constants.m) do I need to place those in the #interface section and then define them in the #implementation section? What is the benefit of that vs the old way of just using a Constants.h file and including it with other headers? Why do I now need two files?
Is the standard practice still to name the constants with a "k" prefix (e.g. kAnimationDuration) or should I now be doing something like MainMenuViewControllerAnimationDuration? I'm imagining yes and if so, does it matter for the constants from number 1 (i.e. not extern) how I name them? In other words, are those visible outside of my implementation?
Clarification is much appreciated.
Doesn't matter whether you place them inside the implementation block or not—only methods are part of the class implementation, so the scope of constants won't change regardless.
The k prefix is a bit dated now. The usual way is to name constants as <prefix><name>, such as "MDSomeConstant".

Clear Unused Entity Warnings For Static Int In xCode

I have a project, with a file that I call 'Keys.h'
In that file, I declare strings and integers that are used across the project, some of which are integers, some of which are strings.
All of the strings work fine; however, if I use integers, I get an unused variable warning.
For a string, (lfPrefs is a dictionary of user preferences)
static NSString * kUserLFPrefs = #"lfPrefs";
This works fine, and does not produce any errors.
For an integer, (I have integers to define the current mode because it seems a bit snappier than comparing strings all the time).
static int kModeLiveFeed = 1001;
static int kModeEventFeed = 2002;
These work just fine, except that they are showing an unused entity warning.
I'd prefer to use the integers over strings, mostly because I read that comparisons are much faster, takes up less memory, etc.
My question is how can I stop the warnings while still getting access to my integer keys?
(Or, should I just use strings)
I can suggest two different methods.
If you want to keep such variables in .h file, you may prefer using define if you will not be changing the value run time like;
#define kModeLiveFeed 1001
If you will be changing the variable value run time, I suggest keeping them in a .m file instead of in a .h file and creating only one instance of the .m file by using singleton. Then, even if you continue to get a warning from the .m file, you can disable it by the steps below:
Select your project from the left navigator to open project settings view.
Then, select your target.
Go to Build Phases tab and open compile resources area.
Click to the right side of your .m file to add a compiler flag as -w
I hope it helps.
You may be misunderstanding the meaning of static in C/Objective-C (this question should help). You should use const rather than static to define constants, and you should define the value of an integer/string constant in a .m file, with a corresponding declaration in the .h file. Or better yet, use an enum if you have a related set of integer constants.
Here is Apple's documentation on constants, which includes the above information as well as naming recommendations (e.g., PRConstant is preferred over the classic Mac OS-style kConstant).

Resources