Can someone please explain what #ifdef..#else..#endif does in this piece of code? It's from an open-source iphone twitter client.
#ifdef ENABLE_OAUTH
#interface NTLNTwitterClient : NTLNOAuthHttpClient {
#else
#interface NTLNTwitterClient : NTLNHttpClient {
#endif
int requestPage;
NSString *screenNameForUserTimeline;
BOOL parseResultXML;
NSObject<NTLNTwitterClientDelegate> *delegate;
BOOL requestForTimeline;
BOOL requestForDirectMessage;
NTLNTwitterXMLParser *xmlParser;
}
If ENABLE_OAUTH is defined somewhere else, then the class NTLNTwitterClient will be a subclass of NTLNOAuthHttpClient.
If ENABLE_OAUTH is not defined, then the class NTLNTwitterClient will be a subclass of NTLNHttpClient.
Related
I have a scenario where I am trying to create a generic C++ class (across platforms) that can operate on an Array . This C++ class is meant to be portable across OS's such that it can leverage the native Array support.
For example, it'll use NSArray when running on Mac OS / iOS, or an MFC array class in Windows. My goal is to make this array management class generic.
#ifndef __MixTest__ArrayUser__
#define __MixTest__ArrayUser__
#if defined _MAC_OS
typedef void * ARRAY_HANDLE;
//#elif defined _WINDOWS
#endif
class ArrayUser
{
public:
ArrayUser() { }
virtual ~ArrayUser() { }
void assignArray(ARRAY_HANDLE handle)
{
m_array_handle = handle;
}
void UseArray();
private:
ARRAY_HANDLE m_array_handle;
};
#endif /* defined(__MixTest__ArrayUser__) */
// ArrayUser.cpp
// MixTest
#include "ArrayUser.h"
#import <Cocoa/Cocoa.h>
void ArrayUser::UseArray()
{
NSArray *array = (__bridge NSArray *) m_array_handle;
for (NSString *str in array)
{
NSLog(#"Array - %#",str);
}
}
Now my goal is to run this on Mac OS and I do the following in my barebones Mac OS project
#import <Cocoa/Cocoa.h>
#interface AppDelegate : NSObject <NSApplicationDelegate>
#property (assign) IBOutlet NSWindow *window;
#property (strong) NSArray *arrayItems;
#end
Implementation
#import "AppDelegate.h"
#include "ArrayUser.h"
#interface AppDelegate ()
{
ArrayUser arrayUser;
}
#end
#implementation AppDelegate
-(id) init
{
if([super init] !=nil)
{
_arrayItems = #[#"Planes",#"Trains",#"Automobiles"];
arrayUser.assignArray((__bridge ARRAY_HANDLE)_arrayItems);
arrayUser.UseArray();
}
return self;
}
Questions
Is this transfer appropriate ?
arrayUser.assignArray((__bridge ARRAY_HANDLE)_arrayItems);
The expectation is that _arrayItems being strong and is expected to be controlled via the AppDelegate.
If _arrayItems weren't defined as being strong, then what is the
right way to bridge such that the object cannot be destroyed
(because ArrayUser needs it ) ?
Should the bridging be the same irrespective of whether or not
_arrayItems is strong or weak? The fact that ArrayUser needs it, should indicate to ARC that the object cannot be deallocated. What
is the bridging in this case ?
Sometimes I declare an ivar but after a while I am no longer using it. I would like to remove this sort of cruft from my code, but I cannot find a warning that will show me my unused ivars.
Is there a tool or built in feature of Xcode that will allow me to find all of my unused ivars?
I see that the static analyzer has CLANG_ANALYZER_OBJC_UNUSED_IVARS, but it does not seem to do anything.
#implementation AppDelegate
{
#private
BOOL _foo; // Never read or written to
}
Runing the analyzer in Xcode 5 with CLANG_ANALYZER_OBJC_UNUSED_IVARS (unused ivars) set to YES never produces a warning.
Based on the relevant Clang source code and a couple of quick tests, it seems that the analyzer does not look at ivars that are not both declared in the #interface and marked #private.
#interface Igloo : NSObject
{
NSString * address; // No warning
#private
NSInteger radius; // Warning
}
#end
#implementation Igloo
{
NSInteger numWindows; // No warning
#private // Has no real effect, of course; just testing
NSString * doormatText; // No warning
}
#end
I suggest filing a bug/submitting a patch.
It appears that the static analyzer option only works if you declare the ivar in the header file.
This generates the analyzer warning correctly:
// AppDelegate.h
#interface AppDelegate : NSObject <UIApplicationDelegate>
{
BOOL _foo; // never read or written
}
#end
Neither of these generates any sort of analyzer warning:
// AppDelegate.m
#interface AppDelegate ()
{
#private
BOOL _goo; // never read or written
}
#end
#implementation AppDelegate
{
#private
BOOL _hoo; // never read or written
}
#end
So it looks like you cannot use the modern syntax to keep ivars in the .m file if you want to check for unused ivars.
In Xcode from product menu click on analyze... It will show you unused variables. This will also tell you about dead code.
I'm new to Objective-C and trying to figure out enums. Is there a way to scope an enum to a class so that the values could be used by another class? Something like this:
#interface ClassA {
typedef enum {
ACCEPTED,
REJECTED
} ClassAStatus;
}
#end
#interface ClassB {
typedef enum {
ACCEPTED,
REJECTED
} ClassBStatus;
}
#end
Though that does not work, obviously. Or is there a better way to do enums altogether?
Edit: I guess my wording wasn't clear, but I'm not asking how to declare enums. I'm aware that putting them at the top of the file works. I'm asking if there's a way to scope them so the values aren't global to the entire file.
You have to prefix your public enums. Simply put the enum definition in the header of your class.
// ClassA.h
typedef enum {
ClassAStatusAccepted,
ClassAStatusRejected
} ClassAStatus;
#interface ClassA {
ClassAStatus status;
}
#end
// ClassB.h
typedef enum {
ClassBStatusAccepted,
ClassBStatusRejected
} ClassBStatus;
#interface ClassB {
ClassBStatus status;
}
#end
This is how Apple does it.
Or you could use the new style:
// UIView.h
typedef NS_ENUM(NSInteger, UIViewAnimationCurve) {
UIViewAnimationCurveEaseInOut, // slow at beginning and end
UIViewAnimationCurveEaseIn, // slow at beginning
UIViewAnimationCurveEaseOut, // slow at end
UIViewAnimationCurveLinear
};
Just put the enum right at the top of your .h, like Apple does in UITableView.h, for example:
//
// UITableView.h
// UIKit
//
// Copyright (c) 2005-2012, Apple Inc. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <CoreGraphics/CoreGraphics.h>
#import <UIKit/UIScrollView.h>
#import <UIKit/UISwipeGestureRecognizer.h>
#import <UIKit/UITableViewCell.h>
#import <UIKit/UIKitDefines.h>
typedef NS_ENUM(NSInteger, UITableViewStyle) {
UITableViewStylePlain, // regular table view
UITableViewStyleGrouped // preferences style table view
};
typedef NS_ENUM(NSInteger, UITableViewScrollPosition) {
UITableViewScrollPositionNone,
UITableViewScrollPositionTop,
UITableViewScrollPositionMiddle,
UITableViewScrollPositionBottom
}; // scroll so row of interest is completely visible at top/center/bottom of view
typedef NS_ENUM(NSInteger, UITableViewRowAnimation) {
UITableViewRowAnimationFade,
UITableViewRowAnimationRight, // slide in from right (or out to right)
UITableViewRowAnimationLeft,
UITableViewRowAnimationTop,
UITableViewRowAnimationBottom,
UITableViewRowAnimationNone, // available in iOS 3.0
UITableViewRowAnimationMiddle, // available in iOS 3.2. attempts to keep cell centered in the space it will/did occupy
UITableViewRowAnimationAutomatic = 100 // available in iOS 5.0. chooses an appropriate animation style for you
};
You probably recognize some of these name, but you may not have been aware they were actually apart of a public enum in Apple's header files.
Just want to add to #DrummerB's answer that I usually write like this. The namespace in camelCase, and then the constant in upper case.
typedef enum {
ClassAStatus_ACCEPTED,
ClassAStatus_REJECTED
} ClassAStatus;
First post and I am really hoping this is not a repetitive or solved question. I tried searching here and Google and while I have found similar Expected identifier or '(' errors none of the solutions work for me.
Basically I'm trying to learn Design patterns and as I used to know a bit of java I am trying to use it as an opportunity to learn objective-c so I have a java program that works and an xCode project that I get the error Expected identifier or '(' in my header file just before the #interface
this is my java solution (very simple I know):
public class Duck {
public void quack(){
System.out.print("Quack!");
}
public void swim(){
System.out.print("swimming duck!");
}
public void display(){
quack();
swim();
}
}
public class mainClass {
public static void main(String[] args){
Duck duck = new Duck();
duck.display();
}
}
and this is my objective-c version.
//duck.h
#include <CoreFoundation/CoreFoundation.h>
#interface Duck : NSObject{ //Expected identifier or '('
}
#end
// Duck.m
#include "Duck.h"
#implementation Duck
-(void)quack{
printf("Quack!");
}
-(void)swim{
printf("swimming duck!");
}
-(void)display{
[self quack];
[self swim];
}
#end
// main.c
#include <CoreFoundation/CoreFoundation.h>
#include "Duck.m"
int main(int argc, const char * argv[])
{
Duck *duck = [[Duck alloc] init];
[duck display];
return 0;
}
If any one can help I would greatly appreciate it, and again sorry if this is a duplicate post
The compiler doesn't know what NSObject is. If you look at the reference, you'll see that it's part of the Foundation framework, not CoreFoundation, so:
#import <Foundation/Foundation.h>
instead of:
#import <CoreFoundation/CoreFoundation.h>
//duck.h
//#include <CoreFoundation/CoreFoundation.h>
#import <Foundation/Foundation.h> // or Cocoa/Cocoa.h
#interface Duck : NSObject//{ //Expected identifier or '('
//} not necessary if there are no instance fields
- (void)quack;
- (void)swim;
- (void)display;
#end
// Duck.m
//#include "Duck.h"
#import "Duck.h"
#implementation Duck
-(void)quack{
printf("Quack!");
}
-(void)swim{
printf("swimming duck!");
}
-(void)display{
[self quack];
[self swim];
}
#end
// main.c SHOULD BE ~main.m~ if using ObjC!!!
//#include <CoreFoundation/CoreFoundation.h>
//#include "Duck.m"
#import "Duck.h"
Additionally, get in to the habit of using NSString literals; #"example" for if/and when you decide to advance into Cocoa. Good luck with your studies.
It could be that you don't really need curly brackets on your empty interface:
#interface Duck : NSObject
#end
Try using import instead of include. Also, make sure that the CoreFoundation framework is actually part of your project.
Dear wisdom of the internet,
in the header-file (Objective-C)
myTestClass.h
#import <Foundation/Foundation.h>
#interface myTestClass : NSObject {
typedef int pixel;
}
- (id) initWithPic: (NSString*) picFileName;
- (void) dealloc;
- (void) doSomething;
#end
At the line typedef int pixel;xCode complains like
( ! ) "Expected specifier-qualifier-list before
'typedef'" ( 3 )
This err-msg seems pretty popular but given solutions (missing #import) do not work for me.
Also the hints I found do not explain what is going wrong here.
I do not understand this err-msg
Can someone explain it to me?
I do appreciate any tips.
Not sure what you are trying to do, put your should just put the typedef before your interface.
Inside the braces is the place for iVars.
If you want an integer variable, then you do not need the typedef:
#interface MyClass
{
int myPixel;
}
#end
Typedefs are used to create a new type, based on another. For instance:
typedef int pixel;
#interface MyClass
{
pixel myPixel;
}
#end
So when you use the pixelpseudo-type, the int type will be used.