1 module objc.runtime; 2 3 version(D_ObjectiveC): 4 5 private bool isValidObjectiveCNumber(T)() 6 { 7 return is(T == BOOL) || is(T == byte) || is(T == ubyte) || 8 is(T == short) || is(T == ushort) || 9 is(T == int) || is(T == uint) || 10 is(T == long) || is(T == ulong); 11 } 12 13 ////ns Helper Section//// 14 /** 15 * .ns can be used as a postfix to convert almost any type to its Objective-C representation. 16 * Currently it supports: 17 - string 18 - numbers 19 - associative arrays 20 - identity (used on any object that extends NSObject will return itself) 21 */ 22 23 NSString ns(string str) 24 { 25 import core.memory; 26 str~= '\0'; 27 // scope(exit) GC.free(cast(void*)str.ptr); 28 return NSString.alloc.initWithUTF8String(str.ptr); 29 } 30 ///Identity. Always return the object itself if it inherits from NSObject 31 T ns(T)(T value) if(is(T : NSObject)){return value;} 32 33 NSMutableDictionaryD!(K, V) ns(K, V)(V[K] aa){return NSMutableDictionaryD!(K, V)(aa);} 34 35 NSNumberD!T ns(T)(T value) if(isValidObjectiveCNumber!T) 36 { 37 return NSNumberD!T(value); 38 } 39 40 ////End ns Helper Section//// 41 42 43 44 extern(Objective-C): 45 46 47 public import core.attribute:selector; 48 alias BOOL = bool; 49 enum YES = true; 50 enum NO = false; 51 52 ///Type used to represent elapsed time in seconds. 53 alias CFTimeInterval = double; 54 55 version(watchOS) 56 { 57 alias NSUInteger = uint; 58 alias NSInteger = int; 59 } 60 else 61 { 62 alias NSInteger = long; 63 alias NSUInteger = ulong; 64 } 65 extern class NSObject 66 { 67 static NSObject alloc() @selector("alloc"); 68 NSObject initialize() @selector("init"); 69 ///Increments the receiver’s reference count. 70 NSObject retain() @selector("retain"); 71 ///Allocates a new instance of the receiving class, sends it an init message, and returns the initialized object. 72 NSObject new_() @selector("new"); 73 ///Decrements the receiver’s reference count. 74 void release() @selector("release"); 75 ///Deallocates the memory occupied by the receiver. 76 void dealloc() @selector("dealloc"); 77 ///Decrements the receiver’s retain count at the end of the current autorelease pool block. 78 NSObject autorelease() @selector("autorelease"); 79 80 } 81 82 ///A simple container for a single C or Objective-C data item. 83 extern class NSValue : NSObject 84 { 85 86 } 87 88 private void* _D4objc7runtime8NSNumber7__ClassZ = null; 89 ///An object wrapper for primitive scalar numeric values. 90 extern class NSNumber : NSValue 91 { 92 @selector("numberWithBool:") static NSNumber opCall(BOOL); 93 @selector("numberWithChar:") static NSNumber opCall(byte); 94 @selector("numberWithDouble:") static NSNumber opCall(double); 95 @selector("numberWithFloat:") static NSNumber opCall(float); 96 @selector("numberWithInt:") static NSNumber opCall(int); 97 @selector("numberWithLongLong:") static NSNumber opCall(long); 98 @selector("numberWithShort:") static NSNumber opCall(short); 99 @selector("numberWithUnsignedChar:") static NSNumber opCall(ubyte); 100 @selector("numberWithUnsignedInt:") static NSNumber opCall(uint); 101 @selector("numberWithUnsignedLongLong:") static NSNumber opCall(ulong); 102 @selector("numberWithUnsignedShort:") static NSNumber opCall(ushort); 103 104 @selector("boolValue") BOOL boolValue(); 105 @selector("charValue") byte charValue(); 106 @selector("doubleValue") double doubleValue(); 107 @selector("floatValue") float floatValue(); 108 @selector("intValue") int intValue(); 109 @selector("longLongValue") long longValue(); 110 @selector("shortValue") short shortValue(); 111 @selector("unsignedCharValue") ubyte ubyteValue(); 112 @selector("unsignedIntValue") uint uintValue(); 113 @selector("unsignedLongLongValue") ulong ulongValue(); 114 @selector("unsignedShortValue") ushort ushortValue(); 115 } 116 struct NSNumberD(T) if(isValidObjectiveCNumber!T) 117 { 118 NSNumber num; 119 this(T t){num = NSNumber(t);} 120 alias num this; 121 } 122 123 /** 124 * Used for NSObjects. It will define a new 125 * alloc, init and an opCall for that. 126 */ 127 mixin template ObjectiveCOpCall() 128 { 129 extern(Objective-C) 130 { 131 override static typeof(this) alloc() @selector("alloc"); 132 override typeof(this) initialize() @selector("init"); 133 } 134 extern(D) final static typeof(this) opCall() 135 { 136 return alloc.initialize; 137 } 138 } 139 140 extern(C) void NSLog(NSString str, ...); 141 142 extern class NSString 143 { 144 static NSString alloc() @selector("alloc"); 145 NSString initWithUTF8String(in char* str) @selector("initWithUTF8String:"); 146 147 @selector("stringWithCString:encoding:") 148 static NSString stringWithCString(const(char)* stringWithCString, size_t encoding); 149 150 ///Returns a string created by copying the data from a given C array of UTF8-encoded bytes. 151 @selector("stringWithUTF8String:") 152 static NSString stringWithUTF8String(const(char)* nullTerminatedCString); 153 154 ///A null-terminated UTF8 representation of the string. 155 @selector("UTF8String") 156 immutable(char)* UTF8String() @nogc const; 157 158 159 static size_t defaultCStringEncoding(); 160 void release() @selector("release"); 161 162 extern(D) final string toString() @nogc const 163 { 164 immutable(char)* ret = UTF8String(); 165 size_t i = 0; while(ret[i++] != '\0'){} 166 if(i > 0) return ret[0..i-1]; 167 return null; 168 } 169 } 170 171 private extern(C) void* _D4objc7runtime7NSArray7__ClassZ = null; 172 extern class NSArray : NSObject 173 { 174 NSArray init() @selector("init"); 175 ///Creates and returns an empty array. 176 @selector("array") 177 static NSArray array(); 178 179 ///Creates and returns an array containing the objects in another given array. 180 @selector("arrayWithArray:") 181 static NSArray array(NSArray array); 182 183 ///Creates and returns an array containing a given object. 184 @selector("arrayWithObject:") 185 static NSArray array(NSObject object); 186 187 ///Creates and returns an array containing the objects in the argument list. 188 @selector("arrayWithObjects:") 189 static NSArray array(NSObject objects, ...); 190 191 ///Creates and returns an array that includes a given number of objects from a given C array. 192 @selector("arrayWithObjects:count:") 193 static NSArray array(NSObject* objects, NSUInteger count); 194 195 ///The number of objects in the array. 196 @selector("count") 197 NSUInteger count(); 198 alias length = count; 199 200 ///Returns the object located at the specified index. 201 @selector("objectAtIndex:") 202 NSObject objectAtIndex(NSUInteger index); 203 } 204 205 alias NSArray_(T) = NSArray; 206 207 struct NSArrayD(T) 208 { 209 NSArray arr = void; 210 alias arr this; 211 212 auto opAssign(NSArray arr) 213 { 214 this.arr = arr; 215 return this; 216 } 217 218 extern(D) pragma(inline, true) T opIndex(size_t index) 219 { 220 return cast(T)cast(void*)arr.objectAtIndex(index); 221 } 222 extern(D) final int opApply(scope int delegate(T) dg) 223 { 224 int result = 0; 225 NSUInteger l = arr.count; 226 for(int i = 0; i < l; i++) 227 { 228 T item = opIndex(i); 229 result = dg(item); 230 if (result) 231 break; 232 } 233 return result; 234 } 235 } 236 237 extern class NSDictionary : NSObject 238 { 239 ///Creates an empty dictionary. 240 @selector("dictionary") 241 static NSDictionary dictionary(); 242 243 ///The number of entries in the dictionary. 244 @selector("count") 245 NSUInteger count(); 246 247 ///A new array containing the dictionary’s keys, or an empty array if the dictionary has no entries. 248 @selector("allKeys") 249 NSArray allKeys(); 250 251 ///A new array containing the dictionary’s values, or an empty array if the dictionary has no entries. 252 @selector("allValues") 253 NSArray allValues(); 254 255 ///Returns the value associated with a given key. 256 @selector("objectForKey:") 257 NSObject objectForKey(NSObject); 258 259 ///Returns the value associated with a given key. 260 @selector("valueForKey:") 261 NSObject valueForKey(NSString); 262 } 263 264 265 private void* _D4objc7runtime19NSMutableDictionary7__ClassZ = null; 266 ///A dynamic collection of objects associated with unique keys. 267 extern class NSMutableDictionary : NSDictionary 268 { 269 @selector("dictionary") 270 override static NSMutableDictionary dictionary(); 271 272 ///Creates and returns a mutable dictionary, initially giving it enough allocated memory to hold a given number of entries. 273 @selector("dictionaryWithCapacity:") 274 static NSMutableDictionary dictionaryWithCapacity(NSUInteger); 275 276 ///Adds a given key-value pair to the dictionary. 277 @selector("setObject:forKey:") 278 void setObject(NSObject, NSObject); 279 280 ///Adds a given key-value pair to the dictionary. 281 @selector("setValue:forKey:") 282 void setValue(NSObject, NSString); 283 } 284 285 struct NSMutableDictionaryD(Key, Value) 286 { 287 static if(isValidObjectiveCNumber!Value) 288 alias RealValue = NSNumber; 289 else static if(is(Value == string)) 290 alias RealValue = NSString; 291 else 292 { 293 static assert(is(Value : NSObject), "Unknown object of type ", Value, " receive"); 294 alias RealValue = Value; 295 } 296 297 NSMutableDictionary dictionary; 298 this(NSMutableDictionary d){dictionary = d;} 299 this(scope Value[Key] kv) 300 { 301 dictionary = NSMutableDictionary.dictionaryWithCapacity(32); 302 foreach(key, value; kv) 303 opIndexAssign(value, key); 304 } 305 306 void opIndexAssign(Value v, Key k) 307 { 308 static if(is(Key == string) || is(Key == NSString)) 309 dictionary.setValue(v.ns, k.ns); 310 else 311 dictionary.setObject(v.ns, k.ns); 312 } 313 314 RealValue opIndex(Key k) 315 { 316 static if(is(Key == string) || is(Key == NSString)) 317 return cast(RealValue)cast(void*)dictionary.valueForKey(k.ns); 318 else 319 return cast(RealValue)cast(void*)dictionary.objectForKey(k.ns); 320 } 321 322 alias dictionary this; 323 } 324 325 alias NSErrorDomain = NSString; 326 327 extern class NSError 328 { 329 ///The error code 330 @selector("code") 331 NSInteger code(); 332 333 ///A string containing the error domain. 334 @selector("domain") 335 NSErrorDomain domain(); 336 337 338 ///A string containing the localized description of the error. 339 @selector("localizedDescription") 340 NSString localizedDescription(); 341 342 ///An array containing the localized titles of buttons appropriate for displaying in an alert panel. 343 @selector("localizedRecoveryOptions") 344 NSArray_!NSString _localizedRecoveryOptions(); 345 346 extern(D) final NSArrayD!NSString localizedRecoveryOptions() 347 { 348 return NSArrayD!NSString(_localizedRecoveryOptions); 349 } 350 351 ///A string containing the localized recovery suggestion for the error. 352 @selector("localizedRecoverySuggestion") 353 NSString localizedRecoverySuggestion(); 354 355 ///A string containing the localized explanation of the reason for the error. 356 @selector("localizedFailureReason") 357 NSString localizedFailureReason(); 358 359 360 extern(D) final void print() 361 { 362 NSLog("Objective-C Error: %@".ns, this); 363 } 364 } 365 struct NSRange 366 { 367 NSUInteger length; 368 NSUInteger location; 369 } 370 extern class NSData : NSObject{}