Created a BOOL *myBool variable in implementation file as below:
#interface myClass ()
{
BOOL *myBool;
}
- (void)viewDidLoad {
[super viewDidLoad];
myBool = false; // no error
}
- (IBAction)myBtnClickd:(UIButton *)sender {
if (!myBool) {
myBool = true; //error: incompatible integer to pointer conversion assigning to BOOL from int.
}
else {
myBool = false;
}
}
why I can not assign true to it and I am not assigning any int as we can see in the code, I do not want to make it a property.
You can't assign true to BOOL, because you are not trying to assign to BOOL, but to BOOL*. A pointer to BOOL. Assigning false to a BOOL* works for some weird reasons deeply hidden in the C standard.
Anyway, this is Objective-C. Why are you using true and false in Objective-C? It's either YES or NO.
Anyway, what is that nonsense code? Just write myBool = ! myBool.
Anyway, what are you doing having instance variables in an Objective-C class that don't start with an underscore, and why are you not using properties? That code should be either
self.myBool = ! self.myBool;
or
_myBool = ! _myBool;
And of course the BOOL* should be a BOOL. BOOL is not a reference type, it's a value type.
Related
Is there a proper way to write a block with no return value in Objective-C? All the examples that I have seen are all with return values. Can someone also please explain the difference between a completion block & a regular block? I know the ^ means that it is a block but doesn't the + before (void) mean it is a block as well?
Here is what a method header would look like if it has a parameter of a block:
- (void)someMethodThatTakesABlock:(returnType (^)(parameterTypes))blockName;
So a block with no return type and no parameters would look something like this:
- (void)someMethodThatTakesABlock:(void (^)(void))blockName;
A regular block is just a set (or group) of code. A completion block is a block that will be executed when the method is completed. A completion block is a regular block, it just is specific to being called at the end of a method.
The ^ signifies a block. The + before a method is a class method.
Other ways to use blocks
As a local variable
returnType (^blockName)(parameterTypes) = ^returnType(parameters) {...};
As a property
#property (nonatomic, copy) returnType (^blockName)(parameterTypes);
As a method parameter
- (void)someMethodThatTakesABlock:(returnType (^)(parameterTypes))blockName;
As an argument to a method call
[someObject someMethodThatTakesABlock:^returnType (parameters) {...}];
As a typedef
typedef returnType (^TypeName)(parameterTypes);
TypeName blockName = ^returnType(parameters) {...};
You would just replace returnType with void.
Here is a demo:
1、no return values and no parameter:
- (void)viewDidLoad {
[super viewDidLoad];
//block
void(^myBlock)(void) = ^(void) {
NSLog(#"This is a block without parameter and returned value");
};
myBlock();
2、no return values and have parameter:
-(void)blockWithParameterButNoReturnData
{
void(^myBlock)(int) = ^(int num) {
NSLog(#"%d",num*100);
};
myBlock(4);
}
3、have retrun values and have parameter:
-(void)blockWithParameterAndReturnValue
{
int (^myBlock)(int) = ^(int num) {
return num * 100;
};
int result = myBlock(2);
NSLog(#"This is a block with parameter and return value :%d",result);
}
PS:for more infomation,see this website:http://www.cnblogs.com/zhanggui/p/4656440.html
Well, this possibly a duplicated question. I've found some questions like this one:
Is there a way to set associated objects in Swift?
However, I want to add an Int property into swift's extension and these answers in the link above doesn't work.
Here's my code:
import ObjectiveC
var xoAssociationKey: UInt8 = 0
extension NSData {
var position: Int {
get {
return objc_getAssociatedObject(self, &xoAssociationKey) as Int
}
set {
objc_setAssociatedObject(self, &xoAssociationKey, newValue, objc_AssociationPolicy(OBJC_ASSOCIATION_RETAIN_NONATOMIC))
}
}
override convenience init() {
self.init()
position = 0
}
}
And I get fatal error: unexpectedly found nil while unwrapping an Optional value everytime I access position
FYI, I did find a solution for this error in Objective C and I'm looking for a swift solution. Here's my code in objective C if you interested:
static char PROPERTY_KEY;
#implementation NSData (Extension)
#dynamic position;
- (NSInteger)position {
return [objc_getAssociatedObject(self, &PROPERTY_KEY) integerValue];
}
- (void)setPosition:(NSInteger)position {
// Must convert to an object for this trick to work
objc_setAssociatedObject(self, &PROPERTY_KEY, #(position), OBJC_ASSOCIATION_COPY);
}
- (instancetype)init {
self = [super init];
if (self) {
self.position = 0;
}
return self;
}
NSData is part of a class cluster, so your custom init method is not necessarily called,
e.g.
let d = NSMutableData()
does not use your init method. The next problem is that your init method calls
itself recursively, therefore
let d = NSData()
crashes with a stack overflow. Note also that the Objective-C code relies on
undefined behaviour, because it replaces a method in a class extension.
So better remove your custom initialization, and change the getter to
return a default value if the associated object has not been set.
This can easily be achieved with an optional cast (as? Int) and the
nil-coalescing operator (??):
extension NSData {
var position: Int {
get {
return objc_getAssociatedObject(self, &xoAssociationKey) as? Int ?? 0
}
set {
objc_setAssociatedObject(self, &xoAssociationKey, newValue, objc_AssociationPolicy(OBJC_ASSOCIATION_RETAIN_NONATOMIC))
}
}
}
I m new for IOS. I have some source code for OS X and java. I was trying to convert to IOS.
In OS X, I have the following.
struct _NoteData {
int number; /** The Midi note number, used to determine the color */
WhiteNote *whitenote; /** The white note location to draw */
NoteDuration duration; /** The duration of the note */
BOOL leftside; /** Whether to draw note to the left or right of the stem */
int accid; /** Used to create the AccidSymbols for the chord */
};
typedef struct _NoteData NoteData;
#interface ChordSymbol : NSObject <MusicSymbol> {
_NoteData notedata[20];/** The notes to draw */
}
_NoteData is like an array and class here. number, whitenote,duration..are instance variable for _noteData.
I was trying to change struct to objective c class:
#interface _NoteData:NSObject{
#property NSInteger number_color;
#property WhiteNote *whitenote;
#property NoteDuration duration;
#property BOOL leftside;
#property NSInteger accid;
};
#interface ChordSymbol : NSObject <MusicSymbol> {
_NoteData notedata[20];/** The notes to draw */
}
In my .m file, it has
+(BOOL)notesOverlap:(_NoteData*)notedata withStart:(int)start andEnd:(int)end {
for (int i = start; i < end; i++) {
if (!notedata[i].leftside) {
return YES;
}
}
return NO;
}
!notedata[i] throw error expected method to read array element. I understand _NoteData is a class, not an array. What should I change?
In java:
private NoteData[] notedata;
NoteData is a class, and notedata is an array which store NoteData.
Same method in java
private static boolean NotesOverlap(NoteData[] notedata, int start, int end) {
for (int i = start; i < end; i++) {
if (!notedata[i].leftside) {
return true;
}
}
return false;
}
I feel all I need is to declare an array with _NoteData object. How can I do that?
Objective-C is a superset of C, so you can use C struct in Objective-C code. You can keep your code in the first paragraph. You need to move the function declaration in ChordSymbol class's header file.
+(BOOL)notesOverlap:(NoteData*)notedata withStart:(int)start andEnd:(int)end;
In another Objective-C class's implementation file, call the Class function like this.
NoteData y[] = {
{ .leftside = YES },
{ .leftside = YES },
{ .leftside = YES },
{ .leftside = YES }
};
BOOL result = [ChordSymbol notesOverlap:y withStart:0 andEnd:3];
NSLog(#"%d",result);
Edit
You can use NSArray for this purpose. You create an array and populate its data with NoteData objects.
NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:20];
NoteData *data1 = [[NoteData alloc] init];
data1.number_color = 1;
[array addObject:data1];
Then you should change (_NoteData*)notedata to (NSArray*)array, and it should work.
The previous version of dart was able to get getters using
cm.getters.values
As is posted in this answer: https://stackoverflow.com/a/14505025/2117440
However actual version was removed that featured and replaced by
cm.declarations.values
The last code gets all attributes, getters, setters, methods, and constructors. I would like to know if there is a way to get only "getters and attributes" without other methods.
The code that I'm using right now is that one:
import "dart:mirrors";
class MyNestedClass {
String name;
}
class MyClass {
int i, j;
MyNestedClass myNestedClass;
int sum() => i + j;
MyClass(this.i, this.j);
}
void main() {
MyClass myClass = new MyClass(3, 5)
..myNestedClass = (new MyNestedClass()..name = "luis");
print(myClass.toString());
InstanceMirror im = reflect(myClass);
ClassMirror cm = im.type;
Map<Symbol, MethodMirror> instanceMembers = cm.instanceMembers;
cm.declarations.forEach((name, declaration) {
if(declaration.simpleName != cm.simpleName) // If is not te constructor
print('${MirrorSystem.getName(name)}:${im.getField(name).reflectee}');
});
}
As you can see in the previous code to check if is not the constructor I need to compare the declaration.simpleName with cm.simpleName. Until I understand is inefficient since we are comparing strings.
In conclusion, I would like to know if there is or will be a better way to solve this problem.
Maybe there is a better way but this should provide what you need
cm.declarations.forEach((name, declaration) {
VariableMirror field;
if(declaration is VariableMirror) field = declaration;
MethodMirror method;
if(declaration is MethodMirror) method = declaration;
if(field != null) {
print('field: ${field.simpleName}');
} else if(method != null && !method.isConstructor){
print('method: ${method.simpleName}');
}
});
After casting to VariableMirror or MethodMirror you can get a lot more properties:
field:
- isConst
- isFinal
- isStatic
method:
- constructorName
- isConstructor
- isConstConstructor
- isFactoryConstructor
- isGenerativeConstructor
- isGetter
- isOperator
- isRedirectingConstructor
- isRegularMethod
- isSetter
- isStatic
- isSynthetic
Im digging for ways to enum objc object such as NSString, I remember there a new feature in a version of Xcode4+ which offering a new way to enum , but not clearly. Anyone know that?
OK, I answered myself. Guess I make a mistake.
This is the new feature I mentioned above:
typedef enum Language : NSUInteger{
ObjectiveC,
Java,
Ruby,
Python,
Erlang
}Language;
It's just a new syntax for enum in Xcode 4.4, but I'm so foolish to think we can exchange "NSUInteger" to "NSString".
So here is the way I found that works:
http://longweekendmobile.com/2010/12/01/not-so-nasty-enums-in-objective-c/
// Place this in your .h file, outside the #interface block
typedef enum {
JPG,
PNG,
GIF,
PVR
} kImageType;
#define kImageTypeArray #"JPEG", #"PNG", #"GIF", #"PowerVR", nil
...
// Place this in the .m file, inside the #implementation block
// A method to convert an enum to string
-(NSString*) imageTypeEnumToString:(kImageType)enumVal
{
NSArray *imageTypeArray = [[NSArray alloc] initWithObjects:kImageTypeArray];
return [imageTypeArray objectAtIndex:enumVal];
}
// A method to retrieve the int value from the NSArray of NSStrings
-(kImageType) imageTypeStringToEnum:(NSString*)strVal
{
NSArray *imageTypeArray = [[NSArray alloc] initWithObjects:kImageTypeArray];
NSUInteger n = [imageTypeArray indexOfObject:strVal];
if(n < 1) n = JPG;
return (kImageType) n;
}
FYI. The original author of the second example code created a category for enum handling. Just the thing for adding to your very own NSArray class definition.
#interface NSArray (EnumExtensions)
- (NSString*) stringWithEnum: (NSUInteger) enumVal;
- (NSUInteger) enumFromString: (NSString*) strVal default: (NSUInteger) def;
- (NSUInteger) enumFromString: (NSString*) strVal;
#end
#implementation NSArray (EnumExtensions)
- (NSString*) stringWithEnum: (NSUInteger) enumVal
{
return [self objectAtIndex:enumVal];
}
- (NSUInteger) enumFromString: (NSString*) strVal default: (NSUInteger) def
{
NSUInteger n = [self indexOfObject:strVal];
if(n == NSNotFound) n = def;
return n;
}
- (NSUInteger) enumFromString: (NSString*) strVal
{
return [self enumFromString:strVal default:0];
}
#end
Alternative way to use struct:
extern const struct AMPlayerStateReadable
{
__unsafe_unretained NSString *ready;
__unsafe_unretained NSString *completed;
__unsafe_unretained NSString *playing;
__unsafe_unretained NSString *paused;
__unsafe_unretained NSString *broken;
} AMPlayerState;
const struct AMPlayerStateReadable AMPlayerState =
{
.ready = #"READY",
.completed = #"COMPLETE",
.playing = #"PLAYING",
.paused = #"PAUSED",
.broken = #"BROKEN"
};
Then you can use like this:
NSString *status = AMPlayerState.ready;
Easy to use, readable.
Would be nice if someone update/edit answer with advantages/disadvantages of this approach.
Recommended way from apple docs:
You use the NS_TYPED_ENUM to group constants with a raw value type that you specify. Use NS_TYPED_ENUM for sets of constants that can't logically have values added in a Swift extension, and use NS_TYPED_EXTENSIBLE_ENUM for sets of constants that can be expanded in an extension.
Apple docs
typedef NSString *MyEnum NS_TYPED_ENUM;
extern MyEnum const MyEnumFirstValue;
extern MyEnum const MyEnumSecondValue;
extern MyEnum const MyEnumThirdValue;
in the .h file. Define your strings in the .m file
MyEnum const MyEnumFirstValue = #"MyEnumFirstValue"
MyEnum const MyEnumSecondValue = #"MyEnumSecondValue";
MyEnum const MyEnumThirdValue = #"MyEnumThirdValue";
Works as expected in both Objective-C
- (void)methodWithMyEnum:(MyEnum)myEnum { }
and Swift
func method(_ myEnum: MyEnum) { }
This will be validated by compiler, so you won't mix up indices accidentally.
NSDictionary *stateStrings =
#{
#(MCSessionStateNotConnected) : #"MCSessionStateNotConnected",
#(MCSessionStateConnecting) : #"MCSessionStateConnecting",
#(MCSessionStateConnected) : #"MCSessionStateConnected",
};
NSString *stateString = [stateStrings objectForKey:#(state)];
<nbsp;>
var stateStrings: [MCSessionState: String] = [
MCSessionState.NotConnected : "MCSessionState.NotConnected",
MCSessionState.Connecting : "MCSessionState.Connecting",
MCSessionState.Connected : "MCSessionState.Connected"
]
var stateString = stateStrings[MCSessionState.Connected]
UPDATE: A more Swifty way is to extend the enum with CustomStringConvertible conformance. Also, this way the compiler will safeguard to implement every new addition to the underlying enum (whereas using arrays does not), as switch statements must be exhaustive.
extension MCSessionState: CustomStringConvertible {
public var description: String {
switch self {
case .notConnected:
return "MCSessionState.notConnected"
case .connecting:
return "MCSessionState.connecting"
case .connected:
return "MCSessionState.connected"
#unknown default:
return "Unknown"
}
}
}
// You can use it like this.
var stateString = MCSessionState.connected.description
// Or this.
var stateString = "\(MCSessionState.connected)"
Update in 2017
Recent down votes drew my attention, and I'd like to add that enum is really easy to work with String now:
enum HTTPMethod: String {
case GET, POST, PUT
}
HTTPMethod.GET.rawValue == "GET" // it's true
Original Answer
Unfortunately I ended up using:
#define HLCSRestMethodGet #"GET"
#define HLCSRestMethodPost #"POST"
#define HLCSRestMethodPut #"PUT"
#define HLCSRestMethodDelete #"DELETE"
typedef NSString* HLCSRestMethod;
I know this is not what OP asked, but writing actual code to implement enum seems to be an overkill to me. I would consider enum as a language feature (from C) and if I have to write code, I would come up with some better classes that does more than enum does.
Update
Swift version seems to be prettier, although the performance can never be as good.
struct LRest {
enum HTTPMethod: String {
case Get = "GET"
case Put = "PUT"
case Post = "POST"
case Delete = "DELETE"
}
struct method {
static let get = HTTPMethod.Get
static let put = HTTPMethod.Put
static let post = HTTPMethod.Post
static let delete = HTTPMethod.Delete
}
}
I think you are looking for the inline array function. eg
#[#"stringone",#"stringtwo",#"stringthree"];
if not, i'm not sure you can enum objects.
you could however have a static array of strings and have the enum reference object at index.
This is how I do it, although it's not perfect. I feel the switch mechanism could be improved... also not positive about hash-collision resistance, don't know what apple uses under the hood.
#define ElementProperty NSString *
#define __ElementPropertiesList #[#"backgroundColor", #"scale", #"alpha"]
#define epBackgroundColor __ElementPropertiesList[0]
#define epScale __ElementPropertiesList[1]
#define epAlpha __ElementPropertiesList[2]
#define switchElementProperty(__ep) switch(__ep.hash)
#define caseElementProperty(__ep) case(__ep.hash)
-(void)setValue:(id)value forElementProperty:(ElementProperty)ep;
[self setValue:#(1.5) forElementProperty:epScale];
//Compiler unfortunately won't warn you if you are missing a case
switchElementProperty(myProperty) {
caseElementProperty(epBackgroundColor):
NSLog(#"bg");
break;
caseElementProperty(epScale):
NSLog(#"s");
break;
caseElementProperty(epAlpha):
NSLog(#"a");
break;
}