What is the objc_selector implementation? [duplicate] - ios

This question already has answers here:
How do SEL and #selector work? [duplicate]
(2 answers)
Closed 8 years ago.
I've found that the SEL type has the next definition:
typedef struct objc_selector *SEL;
But I can't find how is objc_selector implemented.
Okay, if we have the next code
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
SEL mySelector = NSSelectorFromString(#"mySelector");
return 0;
}
, then mySelector is just a pointer. Following the address which it contains, we see the C-string, which can be presented like:
const char* mySelector = "mySelector";
But objc_selector is not a C-string, it is structure and it can contain something else. So I want to know how objc_selector structure is implemented.

This might help you:
Now this one is fun and interesting. SEL is the type of a "selector" which identifies the name of a method (not the implementation). So, for example, the methods -[Foo count] and -[Bar count] both share a selector, namely the selector "count". A SEL is a pointer to a struct objc_selector, but what the heck is an objc_selector? Well, it's defined differently depending on if you're using the GNU Objective-C runtime, or the NeXT Objective-C Runtime (like Mac OS X). Well, it ends up that Mac OS X maps SELs to simple C strings. For example, if we define a Foo class with a - (int)blah method, the code NSLog(#"SEL = %s", #selector(blah)); would output SEL = blah.
Taken from: here

Related

Override a static constant int in .h file in Objective-C?

I'm trying to build an app in OC and have a constant in .h file like this that defines how many columns should be on a menu:
// cellManager.h
static int const cellNumberPerRow = 4;
Now in my view manager file(.m), I need to change the number of columns to 3 when the font size changes. So far I have tried:
// menuManagerView.m
if ([self isBigFontSize]) {
// ....
cellNumberPerRow = 3;
// ...
But this gives me an error Cannot assign to variable 'cellNumberPerRow' with const-qualified type 'const int'; And when I tried to add identifier before like this:
static int const cellNumberPerRow = 3;
There is a warning Unused variable 'cellNumberPerRow' and the column number remains 4;
I feel like there should be an elegant way to do this but couldn't find it anywhere. I'm really new to iOS dev so would appreciate anyone's input, Thanks!
UPDATE
I defined a new integer variable, assigned the value of const variable to it, and replaced all old cellNumberPerRoe with the new variable in the .m file. Now it worked. But I wonder if there's any better way to do this?
static int newCellNumberPerRow = cellNumberPerRow;
If you want to change the value of a constant under some circumstances it implies it's no longer a constant. You could circumvent the const compiler check by using a pointer, but that's counterproductive. It'd be much easier to just drop const from definition altogether.
What I would suggest as an alternative is a computed property in your file manager class defined like this:
typedef NS_ENUM(int, CellNumberPerRow) {
defaultCellNumberPerRow = 4,
smallerCellNumberPerRow = 3,
};
#interface YourManager: NSObject
#property(readonly,nonatomic) int currentCellNumberPerRow;
#end
#implementation DocumentItem
-(int)currentCellNumberPerRow {
if ([self isBigFontSize]) {
return smallerCellNumberPerRow;
}
return defaultCellNumberPerRow;
}
#end
Now to get the appropriate cell number per row you would use currentCellNumberPerRow property instead.
Perhaps making the currentCellNumberPerRow a class property #property(class,...) instead of instance property could also turn out convenient.

Callback identification in superpowered

I'm trying to extend a piece of code that uses the SuperPowered audio library in an iOS application. In particular, I'm interested in the void playerEventCallback(void *clientData, SuperpoweredAdvancedAudioPlayerEvent event, void *value)callback, which gets passed a pointer to the managing SuperPowered object when the audio player is created:
SuperpoweredAdvancedAudioPlayer(void *clientData, SuperpoweredAdvancedAudioPlayerCallback callback, unsigned int sampleRate, unsigned char cachedPointCount, unsigned int internalBufferSizeSeconds = 2, unsigned int negativeSeconds = 0);
If I understand the code right, nothing prevents me from modifying this situation for my own purpose, passing, for example, a pointer to an object in an array, which would identify the player that is/was running, instead of the managing SuperPowered object.
Can I do that, or is there a consequence I should be aware of?
I ended up doing exactly that, passing an instance of a struct defined as follows:
struct AudioPlayerWithIndex {
int index;
SuperpoweredAdvancedAudioPlayer* player;
Superpowered* superpoweredInstance;
AudioPlayerWithIndex(int index, SuperpoweredAdvancedAudioPlayer* player, Superpowered* superpoweredInstance) : index(index), player(player), superpoweredInstance(superpoweredInstance) {}
};

Hash Define in objective C and usage in swift [duplicate]

I am migrating a UIViewController class to train a bit with Swift. I am successfully using Objective-C code via the bridging header but I have the need of importing a constants file that contains #define directives.
I have seen in Using Swift with Cocoa and Objective-C (Simple macros) the following:
Simple Macros
Where you typically used the #define directive to define a primitive constant in C and Objective-C, in Swift you use a global constant instead. For example, the constant definition #define FADE_ANIMATION_DURATION 0.35 can be better expressed in Swift with let FADE_ANIMATION_DURATION = 0.35. Because simple constant-like macros map directly to Swift global variables, the compiler automatically imports simple macros defined in C and Objective-C source files.
So, it seems it's possible. I have imported the file containing my constants into the bridging header, but I have no visibility from my .swift file, cannot be resolved.
What should I do to make my constants visible to Swift?
UPDATE:
It seems working with NSString constants, but not with booleans:
#define kSTRING_CONSTANT #"a_string_constant" // resolved from swift
#define kBOOL_CONSTANT YES // unresolved from swift
At the moment, some #defines are converted and some aren't. More specifically:
#define A 1
...becomes:
var A: CInt { get }
Or:
#define B #"b"
...becomes:
var B: String { get }
Unfortunately, YES and NO aren't recognized and converted on the fly by the Swift compiler.
I suggest you convert your #defines to actual constants, which is better than #defines anyway.
.h:
extern NSString* const kSTRING_CONSTANT;
extern const BOOL kBOOL_CONSTANT;
.m
NSString* const kSTRING_CONSTANT = #"a_string_constant";
const BOOL kBOOL_CONSTANT = YES;
And then Swift will see:
var kSTRING_CONSTANT: NSString!
var kBOOL_CONSTANT: ObjCBool
Another option would be to change your BOOL defines to
#define kBOOL_CONSTANT 1
Faster. But not as good as actual constants.
Just a quick clarification on a few things from above.
Swift Constant are expressed using the keywordlet
For Example:
let kStringConstant:String = "a_string_constant"
Also, only in a protocol definition can you use { get }, example:
protocol MyExampleProtocol {
var B:String { get }
}
In swift you can declare an enum, variable or function outside of any class or function and it will be available in all your classes (globally)(without the need to import a specific file).
import Foundation
import MapKit
let kStringConstant:String = "monitoredRegions"
class UserLocationData : NSObject {
class func getAllMonitoredRegions()->[String]{
defaults.dictionaryForKey(kStringConstant)
}
simple swift language don't need an macros
all #define directives.
will be let
and complex macros should convert to be func
The alternative for macro can be global variable . We can declare global variable outside the class and access those without using class. Please find example below
import Foundation
let BASE_URL = "www.google.com"
class test {
}

How can I view the contents of an objective C Protocol?

If I have access to an objective-C Protocol and trying to figure out how to look inside it to see what methods it contains, including their signatures, etc.
I've tried NSLog and looking in the object in the debugger, as well as on the internet, and cannot find any way to do this.
I checked out the methods in objc/runtime.h after seeing the answers to this SO post: List selectors for Objective-C object and found a way to NSLog a protocol's method signatures
#import <objc/runtime.h>
Protocol *protocol = #protocol(UITableViewDelegate);
BOOL showRequiredMethods = NO;
BOOL showInstanceMethods = YES;
unsigned int methodCount = 0;
struct objc_method_description *methods = protocol_copyMethodDescriptionList(protocol, showrequiredMethods, showInstanceMethods, &methodCount);
NSLog(#"%d required instance methods found:", methodCount);
for (int i = 0; i < methodCount; i++)
{
struct objc_method_description methodDescription = methods[i];
NSLog(#"Method #%d: %#", i, NSStringFromSelector(methodDescription.name));
}
free(methods)
The only catch is that in protocol_copyMethodDescriptionList you need to specify whether you want required vs. non-required methods and whether you want class vs. instance methods. So to cover all four cases, you would need to call protocol_copyMethodDescriptionList four times and print the results for each list.

Declare public static variable in objective c [duplicate]

This question already has answers here:
Objective-C: how to declare a static member that is visible to subclasses?
(3 answers)
Closed 8 years ago.
I want a static varibale in .h of a class and want it to be inherited to its child class.
#interface :UIViewController
static bool isSearchWindowOpen ; //something like this.
#end
If i write like :
static bool isSearchWindowOpen ;
#interface :UIViewController
#end
it works fine but cannot be inherited by child classes.
pls suggest.
This sounds a bit like you are confusing this with some other programming language, like C++. In Objective-C, just like C, a static variable is a variable with file scope. If you declare a static variable in a header file, then any source file including that header file has its own copy of the static variable.
You'd probably want a class method
+ (BOOL)isSearchWindowOpen
with implementation
static BOOL sSearchWindowOpen;
+ (void)setSearchWindowOpen:(BOOL)open { sSearchWindowOpen = open; }
+ (BOOL)isSearchWindowOpen { return sSearchWindowOpen; }
Probably even better to write code that checks whether the search window is open, instead of relying on a static variable that you have to track correctly all the time.
The variable as declared has nothing to do with the class. It’s a global static in the “C sense”: only code in the same file can access it. (See Wikipedia for details.) You can write class accessors:
static BOOL foo;
+ (void) setFoo: (BOOL) newFoo
{
foo = newFoo;
}
That way the class descendants can access the variable, too. But it’s not a good idea anyway. What problem are you trying to solve?

Resources