I'm trying to access this custom obj-C category in Swift file:
#import "NSString+UUID.h"
#implementation NSString (UUIDCategory)
+ (NSString*)stringWithUUID
{
CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault);
NSString *string = (NSString*)CFMakeCollectable(CFUUIDCreateString(kCFAllocatorDefault, uuid));
CFRelease(uuid);
return [string autorelease];
}
#end
So, I added :
#import "NSString+UUID.h"
in my bridging header, but can't find a solution to use it.
var string = NSString.stringWithUUID()
EDIT: the code seems to work now (the problem was I didn't include #import Foundation/Foundation.h in my bridging header before importing my categories.
This is a factory method and Swift will create an initializer for you automatically!
You should be able to use it like this:
let string = NSString(UUID:uuid)
Off topic, but you should really adopt ARC :]
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.
I have a few custom UIViewControllers in my app which need to know the string returned of an NSDate. I could copy and paste the same code between these classes, but that's obviously terrible practise. It's also probably not good to put it in 1 class as a method, then have another class add this class to take advantage of it's method. It seems like a messy thing to do. So what would you recommend i do?
To clarify - I need a method which is given an NSDate and returns a string, for use in several other classes.
Sounds like you either need a function, rather than a method:
//Helpers.h
#import <Foundation/Foundation.h>
NSString * makeAStringFromThisDateSomehow(NSDate * d);
//Helpers.m
#import "Helpers.h"
NSString * makeAStringFromThisDateSomehow(NSDate * d)
{
// Body
// of
// your
// function
}
Or to make a category on NSDate to do what you need:
//NSDate+AndrewsCategory.h
#import <Foundation/Foundation.h>
#interface NSDate(AndrewsCategory)
- (NSString *)Andrew_MakeAStringSomehow;
#end
//NSDate+AndrewsCategory.m
#import "NSDate+AndrewsCategory.h"
#implementation NSDate(AndrewsCategory)
- (NSString *)Andrew_MakeAStringSomehow {
// Body
// of
// your
// method
}
#end
Note the stupid prefix on the method name. That's important to keep your method names from colliding with other method names on framework classes. Usually you would use initials: your company's, yours, or the project's.
In either case, just import the relevant header where you need to use the function or method, and you should be hunky-dory.
I'd consider writing a category on NSDate. Categories let you extend the functionality of existing classes with additional methods without having to mess with the existing implementation of the class. So you can add yourMethod to NSDate, and in the future just be able to call [yourDate yourMethod].
To do this in Xcode, just hit ⌘N to create a new file, and choose Objective-C category, then give it some name and make it a category on NSDate.
Then set up your header:
#interface NSDate (YourCategory)
- (NSString *) yourMethod;
#end
And your implementation:
#implementation NSDate (YourCategory)
- (NSString *) yourMethod {
return [NSString stringWithFormat:#"yourMethod on this date: ", [self description]]; // for example
}
#end
Then just include "NSDate+YourCategory.h" in any file where you want to use yourMethod.
i'd recommend adding the method to a catagory and then adding the header to your projects pch file
#ifdef __OBJC__
#import "yourHeader.h"
#endif
if you google for NSDate+Helper that should give you an idea of the implementation.
Nik
It's probably good to put it in 1 class as a method, then have another class add this class to take advantage of it's method.
simple 1 or 2 methods NSObject subclasses won't make slightest differences in execution
I have a small function which I want to rewrite, so that function is valid for every class.
At the moment I have 10 of the same functions which all work same but every function is for another class.
I know, that I have to do it with reflections, but I am not so sure how to do it.
I already read this link:
http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html
The functions I am talking about are:
-(NSCountedSet *)MissionGetReferecedNested:(id)modelObject
{
setOfObjects = [[NSCountedSet alloc]initWithArray:modelObject.MissionSectionList];
return setOfObjects;
}
-(NSCountedSet *)MissionGetSectionReferecedNested:(id)modelObject
{
setOfObjects = [[NSCountedSet alloc]initWithArray:modelObject.DamageAccountList];
return setOfObjects;
}
MissionSectionList and DamageAccountList are both NSMutableArrays from two different classes.
Is it possible to see if a class consists a NSMutableArray and if yes then it should call the .... modelObject.MyMutableArray?
You can use reflection like this:
- (NSCountedSet *)MissionGet:(id)modelObject
{
SEL propertySelector = NULL;
if ([modelObject respondsToSelector:#selector(MissionSectionList)]) {
propertySelector = #selector(MissionSectionList);
} else if ([modelObject respondsToSelector:#selector(DamageAccountList)]) {
propertySelector = #selector(DamageAccountList);
}
if (!propertySelector) {
[NSException raise:#"Invalid modelObject value" format:#"Model object %# does not contain any recognised selectors", modelObject];
}
return [[NSCountedSet alloc] initWithArray:[modelObject performSelector:propertySelector]];
}
But a more common technique among cocoa programmers would be:
- (NSCountedSet *)MissionGet:(id <MyCustomProtocol>)modelObject
{
return [[NSCountedSet alloc] initWithArray:[modelObject missionArray]];
}
Where you would accept any object which confirms to the protocol MyCustomProtocol. The protocol is defined in a header files somewhere, using:
#protocol MyCustomProtocol
#property (readonly) NSArray *missionArray;
#end
And then in each of your classes, declare it as implementing the protocol:
#interface MissionSectionListClass <MyCustomProtocol>
And add a method implementation:
#implementation MissionSectionListClass <MyCustomProtocol>
- (NSArray *)missionArray
{
return self.MissionSectionList;
}
#end
Using protocols is a bit more code, but it's the "right" way to go. It allows you to add support for new classes, without any change to your MissiongGet... method.
More info about protocols: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProtocols.html
EDIT : Cleared all my answer to this :
I think it's not possible to check if a class has a member variable of specified type. You can only check if a class has a specified method.
So, in this case it will be best if you make all your NSMutableArray list the same name, and then create a declared property for this list, and then do a respondsToSelector in your ...GetReferencedNested method.
So, for example, in all of your class create this property :
#property (nonatomic, retain) NSMutableArray * list;
and then in the ..MissionGetReferencedNested method :
if ([modelObject respondsToSelector:#selector(list)])
...
Correct me if i'm wrong...
In terms of style I'd also follow Abhi's suggestion.
But if you really want to inspect a class that you are stuck with and, for example build a NSCountedSet with the first NSMutableArray variable you can find, you could do it like this:
#import "Utilities.h"
#import <Foundation/Foundation.h>
#import <objc/objc-runtime.h>
#implementation Utilities
+ (NSCountedSet*)initCountedSetWithFirstArrayinObject:(id)someObject {
unsigned int c;
Ivar *ivar_arr = class_copyIvarList([someObject class], &c);
for (unsigned int i = 0; i < c; i++) {
if ([#"#\"NSMutableArray\"" isEqualToString:
[NSString stringWithCString:ivar_getTypeEncoding(ivar_arr[i]) encoding:NSUTF8StringEncoding]
]) {
return [[NSCountedSet alloc] initWithArray:object_getIvar(someObject, ivar_arr[i])];
}
}
return nil;
}
#end
Of course this has very limited real world use because it depends on you knowing that the first array will be the one you're interested in.
I think I have to go with the runtime type editing.(http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html)
The idea with the protocols was good but there I have to change a lot of things in the classes.(which is not possible/allowed) for me. My intension was only to change the functions so that I have only one function for all classes.
I think with the runtime type editing I can check what classes and attributes I have (?) Am I right?
Did somebody already work with runtime type editing?
why does this code not work for referencing a const from a class?
Background: I want to be able to reference a constant value from a class in a class variable type approach, as this is where it makes sense to source. Trying find the best way to effectively have the class offer up an exposed constant. I tried the below but it doesn't seem to work, I get "ERROR: property 'titleLablePrefix' not found on object of type 'DetailedAppointCell'"
#interface DetailedAppointCell : UITableViewCell {
}
extern NSString * const titleLablePrefix;
#end
#import "DetailedAppointCell.h"
#implementation DetailedAppointCell
NSString * const titleLablePrefix = #"TITLE: ";
#end
// usage from another class which imports
NSString *str = DetailedAppointCell.titleLablePrefix; // ERROR: property 'titleLablePrefix' not found on object of type 'DetailedAppointCell'
You can use directly as NSString *str = titleLablePrefix; if your external linkages are proper.
Objective C doesn't support class variables/constants, but it supports class methods. You can use the following solution:
#interface DetailedAppointCell : UITableViewCell {
}
+ (NSString*)titleLablePrefix;
#end
#import "DetailedAppointCell.h"
#implementation DetailedAppointCell
+ (NSString*)titleLablePrefix {
return #"TITLE: ";
}
#end
// usage from another class which imports
NSString *str = [DetailedAppointCell titleLablePrefix];
p.s. Dot syntax is used for instance properties. You can learn more about Objective C here: http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocObjectsClasses.html
I want to use a protocol, how can we implement it in iPhone.
///In POCViewController.h
#import
#protocol BasicAPI
-(NSString*)hello;
#end
#interface HessianPOCViewController : UIViewController
{
idbasicAPI;
}
#end
///
// In POCViewController.m
// In Some method
NSURL* url = [NSURL
URLWithString#"http://www.caucho.com/hessian/test/basic"];
id proxy =
(id)[CWHessianConnection
proxyWithURL:url
protocol:#protocol(basicAPI)];
NSLog(#"hello: %#", [proxy hello]);
////
Please help me how I can implement above code?
In the above code snippet - the #protocol block goes in your header file, underneath the #end declaration that's already there. Common use case is something like:
#interface MyClass
// properties, method definitions, etc
#end
#protocol BasicAPI
-(NSString*)hello;
#end
Then in some method body in your implementation file, MyClass.m
-(void)myMethod {
NSURL* url = [NSURL URLWithString#"http://www.caucho.com/hessian/test/basic"];
id proxy = (id)[CWHessianConnection proxyWithURL:url protocol:#protocol(basicAPI)];
NSLog(#"hello: %#", [proxy hello]);
}
I see that the example you give is taken from the documentation for the Hessian Objective-C implementation. It's showing you how to interact with a Hessian web service from an Objective-C client.
Do you have an existing Hessian web service that you're trying to talk to? If so, you need to declare in your #protocol block the interface to that service. The answers to this question give some good examples of how this works on both the client & server side.