Checking and Remedying Null Objects Efficiently - objective-c

Has anyone found a more efficient way of checking if a variable is nil, then instantiating it? I know the classic way is to write:
if (myObject == nil) {
//instantiate and do other stuff
}
Or
if (!myobect) {
//do stuff
}
Which seems too boiler-plate-esque for my liking, especially if I have to do it many times.
EDIT: Having had a stroke of inspiration, would something like this work?
-(id)instantiateIfObjectIsNull:(id)object withClass:(Class*)class {
if (object == nil) {
object = [[Class alloc]init];
}
return object;
}

If you're using ObjC++, you could approach it from this angle:
#import <Foundation/Foundation.h>
template < typename T >
void InitIfNil(T*& obj) {
if (nil == obj)
obj = [T new];
}
template < typename T >
void TryIt() {
T * obj(nil);
NSLog(#"before: %#", obj);
InitIfNil(obj);
NSLog(#"after: %s : %#", object_getClassName(obj), obj);
[obj release];
}
int main(int argc, const char* argv[]) {
#autoreleasepool {
TryIt<NSArray>();
TryIt<NSString>();
TryIt<NSMutableSet>();
}
return 0;
}
This could also be done with a macro... I don't think this helps readability though.
A third option would be C11 generics - when your compiler supports them.

well it is essentially the same thing but
if (!myobject) {
.....
}

Related

Recursive function with block in Objective C

I've got a function with completion block, and which in some cases calls itself recursively until has the expected result.
I'm getting errors in release, probably because it has different memory management in release.
Anyway I'm asking what should I do to make it work in release as in debug.
I've found some links about declaring a block variable weak, and another one strong, and then assign the block to both of them. However I'm in difficulty to understand well how to apply it to my code.
Here's the code:
-(void) getBitmapFromXObject: (OCPdfXObject *) xobj completion:(void(^)(NSData * data))completion{
__block BOOL hasAlreadyCompleted = false;
if (xobj.type == OCPdfXObjectType_Form) {
OCPdfXObjectForm * formxboj = (OCPdfXObjectForm *)xobj;
OCPdfDictionary * res = formxboj.resources.xObject;
if (res != nil) {
for (CBKeyValuePair * key in res) {
OCPdfXObject* childXObjc = [OCPdfXObject createFromObject:key.value];
if (!childXObjc) {
continue;
}
[self getBitmapFromXObject:childXObjc completion:^(NSData *data) {
if (data != nil) {
hasAlreadyCompleted = true;
}
}];
}
}
}
if (xobj.type == OCPdfXObjectType_Image) {
OCPdfImage* imagexobj = (OCPdfImage *)xobj;
if (imagexobj.colorSpace != OCPdfColorSpace_DeviceRGB) {
completion(nil);
hasAlreadyCompleted = true;
}
[self getBitmapFromImage:imagexobj withCompletion:^(NSData *data) {
NSData *uiImage = data;
completion(uiImage);
hasAlreadyCompleted = true;
}];
}
if (!hasAlreadyCompleted) {
completion(nil);
}
}

When are C++ objects destroyed in Objective-C++?

I am trying to expose a C++ object by creating an Objective-C++ class to wrap it.
Ultimately, in Swift, I'm trying to write this:
print(JSApplication.eval("'TKTK'")?.toString() ?? "")
print(JSApplication.eval("x = {a: 42}; x")?.toString() ?? "")
print(JSApplication.eval("x")?.get("a")?.toString() ?? "nope");
print(JSApplication.eval("1 + 2")?.toInt32() ?? 0)
However, when I try to call JSApplication.eval("x")?.get("a")?.toString(), Objective-C calls dealloc on my class after .get("a") but before .toString().
Normally in dealloc I would call .reset() on the shared pointer that the class contains. But since the dealloc is firing too early, this would clear out my V8 result before .toString() could be called on it.
This raises a general question: How does Swift / Objective-C decide when to call dealloc on a temporary object? For something like foo()?.bar()?.baz(), where foo and bar return temporary objects, is it correct that both temp objects are receiving a dealloc message before baz is called? That's what I'm seeing.
If that's the correct behavior, then what's the proper way to extend the lifetime of a temporary object to the scope where the function is being called, like C++? Is that possible?
Here's my Objective-C++ binding. (I notice that no "Destroy 0x..." messages are being printed out at all, so C++ destructors don't seem to be firing. Am I supposed to call those manually?)
// Extracts a C string from a V8 Utf8Value.
const char* ToCString(const v8::String::Utf8Value& value) {
return *value ? *value : "<string conversion failed>";
}
#interface NJSValue (V8)
- (instancetype)init;
- (instancetype)initWithValue:(Local<Value>)value;
#end
struct NJSRef
{
std::shared_ptr<Nan::Persistent<Value>> _ref;
~NJSRef()
{
printf("Destroy 0x%08x\n", (unsigned int)(size_t)_ref.get());
}
};
#implementation NJSValue (V8)
NJSRef m;
- (instancetype)init
{
self = [super init];
return self;
}
- (instancetype)initWithValue:(Local<Value>)value
{
self = [super init];
Nan::HandleScope scope;
Nan::EscapableHandleScope escape;
m._ref.reset(new Nan::Persistent<Value>(escape.Escape(value)));
printf("Alloc 0x%08x\n", (unsigned int)(size_t)m._ref.get());
return self;
}
#end
#implementation NJSValue
- (void)dealloc
{
printf("Dealloc 0x%08x\n", (unsigned int)(size_t)m._ref.get());
//m_ref.reset();
}
- ( NSString * _Nonnull )toString
{
if (m._ref != nullptr) {
Nan::HandleScope scope;
Local<Value> value(Nan::New(*m._ref));
v8::String::Utf8Value str(JS_ISOLATE(), value);
const char* cstr = ToCString(str);
return NJSStringToNSString(JS_STR(cstr));
} else {
return #"undefined";
}
}
- (NSNumber *)toInt32
{
if (m._ref != nullptr) {
Nan::HandleScope scope;
Local<Value> value(Nan::New(*m._ref));
if (!value->IsInt32()) return nullptr;
return [NSNumber numberWithInt:TO_INT32(value)];
} else {
return nullptr;
}
}
- (NSNumber *)toNumber
{
if (m._ref != nullptr) {
Nan::HandleScope scope;
Local<Value> value(Nan::New(*m._ref));
if (!value->IsNumber()) return nullptr;
return [NSNumber numberWithDouble:TO_DOUBLE(value)];
} else {
return nullptr;
}
}
- (NJSValue * _Nullable __strong)get:(NSString * _Nonnull)key CF_RETURNS_RETAINED
{
if (m._ref == nullptr) return nullptr;
v8::HandleScope scope(JS_ISOLATE());
v8::EscapableHandleScope handle_scope(JS_ISOLATE());
Local<Value> value(Nan::New(*m._ref));
if (!value->IsObject()) return nullptr;
Local<Object> obj(JS_OBJ(value));
Local<Value> jsKey(JS_STR([key UTF8String]));
if (!obj->Has(JS_CONTEXT(), jsKey).FromJust()) return nullptr;
Local<Value> result(obj->Get(jsKey));
v8::String::Utf8Value str(JS_ISOLATE(), result);
const char* cstr = ToCString(str);
printf("got %s\n", cstr);
NJSValue* ret = [[NJSValue alloc] initWithValue:handle_scope.Escape(result)];
// [self associateValue:ret withKey:key];
return ret;
}
#end
#implementation JSApplication
- (instancetype)init
{
self = [super init];
if (self) {
}
return self;
}
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super init];
if (self) {
self.frame = frame;
}
return self;
}
// Executes a string within the current v8 context.
v8::Local<v8::Value>
ExecuteString(v8::Isolate* isolate, v8::Local<v8::String> source,
v8::Local<v8::Value> name, bool print_result,
bool report_exceptions) {
v8::EscapableHandleScope handle_scope(isolate);
v8::TryCatch try_catch(isolate);
v8::ScriptOrigin origin(name);
v8::Local<v8::Context> context(isolate->GetCurrentContext());
v8::Local<v8::Script> script;
if (!v8::Script::Compile(context, source, &origin).ToLocal(&script)) {
// Print errors that happened during compilation.
if (report_exceptions)
ReportException(isolate, &try_catch);
return handle_scope.Escape(v8::Undefined(isolate));
} else {
v8::Local<v8::Value> result;
if (!script->Run(context).ToLocal(&result)) {
assert(try_catch.HasCaught());
// Print errors that happened during execution.
if (report_exceptions)
ReportException(isolate, &try_catch);
return handle_scope.Escape(v8::Undefined(isolate));
} else {
assert(!try_catch.HasCaught());
if (print_result && !result->IsUndefined()) {
// If all went well and the result wasn't undefined then print
// the returned value.
v8::String::Utf8Value str(isolate, result);
const char* cstr = ToCString(str);
printf("eval result: %s\n", cstr);
}
return handle_scope.Escape(result);
}
}
}
void ReportException(v8::Isolate* isolate, v8::TryCatch* try_catch) {
v8::HandleScope handle_scope(isolate);
v8::String::Utf8Value exception(isolate, try_catch->Exception());
const char* exception_string = ToCString(exception);
v8::Local<v8::Message> message = try_catch->Message();
if (message.IsEmpty()) {
// V8 didn't provide any extra information about this error; just
// print the exception.
fprintf(stderr, "%s\n", exception_string);
} else {
// Print (filename):(line number): (message).
v8::String::Utf8Value filename(isolate,
message->GetScriptOrigin().ResourceName());
v8::Local<v8::Context> context(isolate->GetCurrentContext());
const char* filename_string = ToCString(filename);
int linenum = message->GetLineNumber(context).FromJust();
fprintf(stderr, "%s:%i: %s\n", filename_string, linenum, exception_string);
// Print line of source code.
v8::String::Utf8Value sourceline(
isolate, message->GetSourceLine(context).ToLocalChecked());
const char* sourceline_string = ToCString(sourceline);
fprintf(stderr, "%s\n", sourceline_string);
// Print wavy underline (GetUnderline is deprecated).
int start = message->GetStartColumn(context).FromJust();
for (int i = 0; i < start; i++) {
fprintf(stderr, " ");
}
int end = message->GetEndColumn(context).FromJust();
for (int i = start; i < end; i++) {
fprintf(stderr, "^");
}
fprintf(stderr, "\n");
v8::Local<v8::Value> stack_trace_string;
if (try_catch->StackTrace(context).ToLocal(&stack_trace_string) &&
stack_trace_string->IsString() &&
v8::Local<v8::String>::Cast(stack_trace_string)->Length() > 0) {
v8::String::Utf8Value stack_trace(isolate, stack_trace_string);
const char* stack_trace_string = ToCString(stack_trace);
fprintf(stderr, "%s\n", stack_trace_string);
}
}
}
+ (NJSValue *)Eval:(NSString *)string __attribute((ns_returns_retained))
{
Isolate* isolate = Isolate::GetCurrent();
v8::HandleScope handle_scope(isolate);
Local<Context> context = isolate->GetCurrentContext();
v8::Context::Scope context_scope(context);
const char* str = [string UTF8String];
Local<Value> result = ExecuteString(
context->GetIsolate(),
v8::String::NewFromUtf8(context->GetIsolate(), str,
v8::NewStringType::kNormal).ToLocalChecked(),
JS_STR("JSApplication.Eval"), false, true);
return [[NJSValue alloc] initWithValue:result];
}
#end
Here's the output I get for the Swift code at the top of this question:
TKTK
Alloc 0x81d34230
Dealloc 0x81d34230
Alloc 0x81d34270
Dealloc 0x81d34270
TKTK
Alloc 0x81d38230
Dealloc 0x81d38230
[object Object]
Alloc 0x81d38250
got 42
Alloc 0x81d38240
Dealloc 0x81d38240
Dealloc 0x81d38240
42
Alloc 0x81d38250
Dealloc 0x81d38250
3
A big part of your problem is that your declaration of NJSRef m; is not declaring an instance variable, even though it's inside an #implementation. It's just a file-scope global. There's just one, and it's being shared (and clobbered) by all of your instances of NJSValue. You would have to enclose it in curly braces {...} to make it an instance variable.
That explains why it's never destroyed, at least. Probably a lot of the other symptoms, too, but it's hard to tell given the external types you're using that I'm not familiar with.

Why do i get "program received signal: "EXC_BAD_ACCESS" on NSString veriable

I just recently started learning Objective C, when i run the next program i get error
"program received signal: "EXC_BAD_ACCESS"
For the code line
if([*userChoice isEqualToString:#"yes"])
The full code is:
void initGame (void);
void restartGame(void);
void toGoOn(char *playerChoice);
int guess=-1;
int from=-1;
int to=-1;
bool playStatus=true;
bool gameStatus=true;
int answer=-1;
NSString *userChoice[10];
//if true the game is on
int main (int argc, const char * argv[])
{
#autoreleasepool {
GuessManager *game=GUESS;
NSLog(#"Hello, lets play");
NSLog(#"Please provide a positive range in which you would like to play");
do{
initGame();
[game setnumberToGuess:from :to];
do {
printf("Make you guess:");
scanf("%d", &guess);
[game setUserGuess:guess];
[game checkUserGuess];
if([game getDidIgetIt])
{
playStatus=false;
}
else
{
playStatus=true;
}
} while (playStatus);
restartGame();
}while(gameStatus);
printf("Thanks For Playing PanGogi Games! GoodBye");
}
return 0;
}
void initGame (void)
{
printf("from:");
scanf("%d",&from);
printf("to:");
scanf("%d",&to);
}
void restartGame(void)
{
printf("Would you like to continue?(yes/no)");
scanf("%s",&userChoice);
//scanf("%d",&answer);
// if(answer==1)
if([*userChoice isEqualToString:#"yes"])
{
gameStatus=true;
}
else
{
gameStatus=false;
}
}
I understand that its related to the NSString variable userChoice and how its used in
the if, but what i cant find is what am i doing wrong.
Please help :)
You have 3 errors in the code
1) I think you are getting confused with NSString and C style char array... You just need to use single NSString object to save multi character data..
NSString *userChoice;
2) Since you want to input data using scanf, you need a C style character array. scanf won't work with NSString types.
char tempArray[10];
int count = scanf("%s",&tempArray);
userChoice = [NSString stringWithBytes:tempArray length:count encoding: NSUTF8StringEncoding];
3) Now you can use NSString directly.. No need for pointer like syntax
if( [userChoice isEqualToString: #"yes"]){
.....
.....
}
You're using NSString as if it was char. It's not. It's a class that represents a string.
The scanf function is a C function and needs a char array, not an NSString.
char str[80];
scanf("%s", &str);
You can initialize an NSString object with a char array like this:
NSString *userChoice = [NSString stringWithCString:str encoding:NSASCIIEncoding];
And compare like this:
if ([userChoice isEqualToString:#"yes"]) {
...
} else {
...
}

How to break block loop in Objective - C?

I have these declarations in header file:
Note: I won't explain the whole code, I think it is easy to understand
typedef void (^loopCell)(id cell);
-(id)allCells:(loopCell)cell;
And allCells function implementation:
-(id)allCells:(loopCell)cell
{
for (AAFormSection *section in listSections)
{
for (id _cell in section.fields) {
cell(_cell);
}
}
return nil;
}
The usage of allCells function:
-(void)setFieldValue:(NSString *)value withID:(int)rowID
{
[self allCells:^(id cell) {
if([cell isKindOfClass:[AAFormField class]]) {
AAFormField *_cell = (AAFormField *)cell;
if(_cell.rowID == rowID) {
_cell.value = value;
//return; Here I want to terminate loop
}
}
}];
}
My problem is, I can't terminate allCells loop in the middle (actually when I found object I need in the loop, I don't want iterate through other objects)
How can I stop allCells loop in the middle?
Look at the docs for NSArray enumerateObjectsUsingBlock:. They setup the block signature to take a BOOL pointer. Set the stop BOOL to YES to cause the iteration to stop.
typedef void (^loopCell)(id cell, BOOL *stop);
-(id)allCells:(loopCell)cell {
BOOL stop = NO;
for (AAFormSection *section in listSections) {
for (id _cell in section.fields) {
cell(_cell, &stop);
if (stop) {
break;
}
}
if (stop) {
break;
}
}
return nil;
}
-(void)setFieldValue:(NSString *)value withID:(int)rowID {
[self allCells:^(id cell, BOOL *stop) {
if([cell isKindOfClass:[AAFormField class]]) {
AAFormField *_cell = (AAFormField *)cell;
if(_cell.rowID == rowID) {
_cell.value = value;
if (stop) {
*stop = YES;
}
}
}
}];
}
You can't break from setFieldValue, but you can from allCells.
It's up to the method you're using that calls the block — allCells in this case — to provide a mechanism for stopping the loop. Usually, it's a parameter to the block.
If allCells is yours and you don't mind modifying it, you modify the block signature to take a pointer to a BOOL, initialized to YES, and check if the block modified it to NO.
(Note: You can break from a for in loop.)

List selectors for Objective-C object

I have an object, and I want to list all the selectors to which it responds. It feels like this should be perfectly possible, but I'm having trouble finding the APIs.
This is a solution based on the runtime C functions:
class_copyMethodList returns a list of class methods given a Class object obtainable from an object.
#import <objc/runtime.h>
[..]
SomeClass * t = [[SomeClass alloc] init];
int i=0;
unsigned int mc = 0;
Method * mlist = class_copyMethodList(object_getClass(t), &mc);
NSLog(#"%d methods", mc);
for(i=0;i<mc;i++)
NSLog(#"Method no #%d: %s", i, sel_getName(method_getName(mlist[i])));
/* note mlist needs to be freed */
I think usually you'll want to do that in the console, instead of cluttering your code with debug code. This is how you can do that while debugging in lldb:
(Assuming an object t)
p int $num = 0;
expr Method *$m = (Method *)class_copyMethodList((Class)object_getClass(t), &$num);
expr for(int i=0;i<$num;i++) { (void)NSLog(#"%s",(char *)sel_getName((SEL)method_getName($m[i]))); }
This is also possible with Swift:
let obj = NSObject()
var mc: UInt32 = 0
let mcPointer = withUnsafeMutablePointer(&mc, { $0 })
let mlist = class_copyMethodList(object_getClass(obj), mcPointer)
print("\(mc) methods")
for i in 0...Int(mc) {
print(String(format: "Method #%d: %s", arguments: [i, sel_getName(method_getName(mlist[i]))]))
}
Output:
251 methods
Method #0: hashValue
Method #1: postNotificationWithDescription:
Method #2: okToNotifyFromThisThread
Method #3: fromNotifySafeThreadPerformSelector:withObject:
Method #4: allowSafePerformSelector
Method #5: disallowSafePerformSelector
...
Method #247: isProxy
Method #248: isMemberOfClass:
Method #249: superclass
Method #250: isFault
Method #251: <null selector>
Tested with the 6s simulator running iOS 9.2, Xcode Version 7.2 (7C68).
Taking inspiration from JAL's answer, in Swift you can do:
extension NSObject {
var __methods: [Selector] {
var methodCount: UInt32 = 0
guard
let methodList = class_copyMethodList(type(of: self), &methodCount),
methodCount != 0
else { return [] }
return (0 ..< Int(methodCount))
.flatMap({ method_getName(methodList[$0]) })
}
}
ARC realization
SomeClass *someClass = [[SomeClass alloc] init];
//List of all methods
unsigned int amountMethod = 0;
Method *methods = class_copyMethodList(someClass, &amountMethod);
for (unsigned int i = 0; i < amountMethod; i++) {
Method method = methods[i];
printf("\t method named:'%s' \n", sel_getName(method_getName(method)));
}
free(methods);
Something like this should work (just put it in the object you're curious about). For example if you have an object that's a delegate and want to know what 'hooks' are available this will print out messages to give you that clue:
-(BOOL) respondsToSelector:(SEL)aSelector {
printf("Selector: %s\n", [NSStringFromSelector(aSelector) UTF8String]);
return [super respondsToSelector:aSelector];
}
Note that I discovered this in the iPhone Developer's Cookbook so I can't take credit! For example output I get from a UIViewController that implements the protocols <UITableViewDelegate, UITableViewDataSource>:
Selector: tableView:numberOfRowsInSection:
Selector: tableView:cellForRowAtIndexPath:
Selector: numberOfSectionsInTableView:
Selector: tableView:titleForHeaderInSection:
Selector: tableView:titleForFooterInSection:
Selector: tableView:commitEditingStyle:forRowAtIndexPath:
Selector: sectionIndexTitlesForTableView:
Selector: tableView:sectionForSectionIndexTitle:atIndex:
...
...
etc.,etc.
If you want to also get the selectors for the super classes you can loop through like this:
Class c = [myObject class];
while (c != nil) {
int i = 0;
unsigned int mc = 0;
Method* mlist = class_copyMethodList(c, &mc);
NSLog(#"%d methods for %#", mc, c);
for(i = 0; i < mc; i++) {
const char* selName = sel_getName(method_getName(mlist[i]));
NSLog(#"Method #%d: %s", i, selName);
}
free(mlist);
c = [c superclass];
}