Objective-c Loop in NSThread - objective-c

I want to build a object that can run a loop in thread.
When I run a loop in thread using NSThread, sometimes works fine and sometimes the error message appear :
Uncaught exception NSInvalidArgumentException, reason: Tried to add nil value for key 'NSArgumentDomain' to dictionary.
How do I fix it? Or NSthread tutorial can be helpful.
#import <Foundation/Foundation.h>
#interface ThreadTest: NSObject
-(void) run;
-(void) goThread;
#end
#implementation ThreadTest
-(void) run {
#autoreleasepool {
int i;
for (i = 1; i < 5; i++) {
NSLog (#"Bar");
}
NSLog (#"end of loop");
}
}
-(void) goThread {
[NSThread detachNewThreadSelector: #selector(run)
toTarget: self
withObject: nil];
}
int main(void) {
#autoreleasepool {
ThreadTest *t = [[ThreadTest alloc] init];
[t goThread];
}
return 0;
}

NSDictionary crashes if you try to insert NIL to it. However, you can insert NSNULL argument to it.
So just make a check if your object is nil, insert NSNULL instead.
controlObject != nil ? controlObject : [NSNull null];

Related

How does the Xcode breakpoint system interact with memory management?

Here's a little experiment:
#interface Model : NSObject
#property (copy) NSString *value;
-(instancetype)initWith:(NSString *)value;
#end
#implementation Model
-(instancetype)initWith:(NSString *)value {
self = [super init];
self.value = value;
return self;
}
#end
#import <Foundation/Foundation.h>
#import "Model.h"
void experiment(Model *m);
int main(int argc, const char * argv[]) {
#autoreleasepool {
// insert code here...
NSLog(#"Hello, World!");
Model *ma = [[Model alloc] initWith:[[NSUUID UUID] UUIDString]];
experiment(ma);
NSLog(#"yyy %#", [ma value]);
}
return 0;
}
void experiment(ModelA *m) {
NSString *testValue = nil;
testValue = [m value];
NSLog(#"xxx %#", testValue);
}
When run, this produces the following:
Hello, World!
xxx 6005A7B0-F71C-4755-B1BF-792D6296B716
yyy 6005A7B0-F71C-4755-B1BF-792D6296B716
Program ended with exit code: 0
But suppose I make this line:
testValue = [m value];
part of a breakpoint:
And this changes everything:
Hello, World!
(__NSCFString *) $0 = 0x000000010071e220 #"1C0DCB39-BFBB-4E67-A041-E6B58615BDFD"
xxx 1C0DCB39-BFBB-4E67-A041-E6B58615BDFD
yyy 1C0DCB39-BFBB-4E67-A041-E6B58615BDFD
*** -[CFString release]: message sent to deallocated instance 0x10071e220
And a crash. I see what's happening--the string is released once we exit the function scope, and the second time when the Model object is destroyed, which is an overrelease. But why doesn't the breakpoint (or more precisely, the lldb expression inside the breakpoint) handle the reference count correctly?

Objective-c recursive blocks with threads EXC_BAD_ACCESS

I have some recursive block code in objective-c that is causing a EXC_BAD_ACCESS error.
- (void) doSomethingWithCompletion:(void (^)())completion {
if (completion) {
dispatch_async(dispatch_get_main_queue(), completion);
}
}
- (void) testBlocks {
NSString *testString = #"hello";
__block NSInteger count = 0;
__block __weak void (^weak_block)(NSString *);
void(^strong_block)(NSString *);
weak_block = strong_block = ^(NSString *str) {
[self doSomethingWithCompletion:^{
NSLog(#"number: %zd", count);
if (++count < 10) {
weak_block(str);
}
}];
};
strong_block(testString);
}
The error happens on weak_block(str) which i assume is because it is released when dispatch_async is called. Calling strong_block(str) in it's place when it's declared with __block like so:
__block void(^strong_block)(NSString *);
Causes a warning 'Capturing 'strong_block' strongly in this block is likely to lead to a retain cycle'.
So I changed the testBlock method to not use a weak reference like so:
- (void) testBlocks {
NSString *testString = #"hello";
__block NSInteger count = 0;
__block void (^inner_block)(NSString *);
void(^strong_block)(NSString *);
inner_block = strong_block = ^(NSString *str) {
[self doSomethingWithCompletion:^{
NSLog(#"number: %zd", count);
if (++count < 10) {
inner_block(str);
}
}];
};
strong_block(testString);
}
But I am unsure if this causes a retain cycle or if adding
__block void (^inner_block)(NSString *) = weak_block;
inside the block instead would cause a retain cycle as well. What is the correct way to handle this situation?
It crashes because the block (pointed to by weak_block, strong_block) has already been deallocated by the time the "completion" block runs, and calling a block with a nil block pointer crashes.
The block is deallocated because there are no strong references to it after testBlocks returns.
The second one will have a retain cycle because the block captures inner_block, which holds a strong reference to itself.
The proper way is to make a strong reference from the captured weak reference inside the block, and let the completion block capture that:
- (void) testBlocks {
NSString *testString = #"hello";
__block NSInteger count = 0;
__block __weak void (^weak_block)(NSString *);
void(^strong_block)(NSString *);
weak_block = strong_block = ^(NSString *str) {
void(^inner_block)(NSString *) = weak_block;
[self doSomethingWithCompletion:^{
NSLog(#"number: %zd", count);
if (++count < 10) {
inner_block(str);
}
}];
};
strong_block(testString);
}
Not sure this is proof of either possibility but if you add a weak block property and examine that one after all block stuff has run...
...
#property (weak) void (^true_weak_block)(NSString *);
#property (weak) NSString *weak_string;
...
- (void) testBlocks {
NSString *strong_string = [NSString stringWithFormat:#"%#", #"some string"]; // note that you can not use a string literal in this example..
self.weak_string = strong_string;
NSString *testString = #"hello";
__block NSInteger count = 0;
__block void (^inner_block)(NSString *);
void(^strong_block)(NSString *);
inner_block = strong_block = ^(NSString *str) {
[self doSomethingWithCompletion:^{
NSLog(#"number: %zd", count);
if (++count < 10) {
inner_block(str);
}
}];
};
self.true_week_block = strong_block;
[self test];
strong_block(testString);
}
- (void)test {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(#"%#", self.true_week_block); // not deallocated
NSLog(#"%#", self.weak_string); // deallocated
});
}
In my test the block is never deallocated and also the memory address remains the same over time, even if you change regular assignment of the two strong blocks to use copy instead of the implicitly retained assignment.

Simple addObject to NSMutableArray method gives lldb error

I'm adding objects to a NSMutableArray stack in my model. Here's the interface:
#interface calcModel ()
#property (nonatomic, strong) NSMutableArray *operandStack;
#end
And the implementation:
#implementation calcModel
#synthesize operandStack = _operandStack;
- (NSMutableArray *)operandStack;
{
if (_operandStack == nil) _operandStack = [[NSMutableArray alloc]init];
return _operandStack;
}
This addobject method works fine:
- (void)pushValue:(double)number;
{
[self.operandStack addObject:[NSNumber numberWithDouble:number]];
NSLog(#"Array: %#", self.operandStack);
}
but this one crashes the app and just says 'lldb' in the log:
- (void)pushOperator:(NSString *)operator;
{
[self.operandStack addObject:operator];
NSLog(#"Array: %#", self.operandStack);
}
What's causing this error?
The NSString you're adding is probably nil. Do this:
- (void)pushOperator:(NSString *)operator {
if (operator) {
[self.operandStack addObject:operator];
NSLog(#"Array: %#", self.operandStack);
} else {
NSLog(#"Oh no, it's nil.");
}
}
If that's the case, figure out why it's nil and fix that. Or check it before adding it.
The reason why the first method doesn't crash is, because there is no double value that can't be used to init an NSNumber, so it will never be nil.

NSThread thread-safe implementation of initialize.?

The following code compiles and executes as expected.
#import <objc/objc.h>
#import <Foundation/Foundation.h>
BOOL loopValue = YES;
#interface myThread:NSObject
-(void) enterThread: (NSArray *) elemt count: (NSString *) x;
#end
#implementation myThread
-(void) enterThread : (NSArray *) elemt
{
NSLog (#" Inside mythread ");
NSAutoreleasePool *pool = [[ NSAutoreleasePool alloc] init];
int i;
int cnt =10;
for(i=0; i<cnt; i++) {
NSLog (#"Number of elemennts in array %i ", [elemt count]);
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]];
}
loopValue = NO;
[pool drain];
}
#end
int main ( int argc, char ** argv)
{
NSAutoreleasePool *pool = [[ NSAutoreleasePool alloc] init];
// id tobj = [[myThread alloc] init];
id tobj = [ myThread new ];
NSLog (#"Starting New Thread ");
[NSThread detachNewThreadSelector:#selector(enterThread:) toTarget:tobj withObject:[NSArray arrayWithObjects:#"ram",#"20",nil]];
while(1)
if ( loopValue )
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:2]];
else
break;
NSLog (#".. Exiting.. \n");
[pool drain];
return 0;
}
MY Question:
While compilation i do get the following warnings..
mythread.m:24:1: warning: incomplete implementation of class ‘myThread’ [enabled by default]
mythread.m:24:1: warning: method definition for ‘-enterThread:count:’ not found [enabled by default]
While Execution
WARNING your program is becoming multi-threaded, but you are using an ObjectiveC runtime library .... Removed due to redability]hich does not have a thread-safe implementation of the +initialize method. ......
What am i dong wrong ? how to avoid both warning/runtime errors.
The method you declared is enterThread:count: but the method you implement is enterThread:. Also, that warning you are getting, I'm sure I've only seen that from the old GNUstep runtime… but I guess not.

I am trying to use respondsToSelector but unable to get expected output can anyone find what is wrong in my code?

#import "movie.h"
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// insert code here...
movie *obj = [[movie alloc]init];
[obj findinterestofnum1:(int)200 num2:(int)4 num3:(int)5];
SEL suf = #selector(findinterestofnum1: num2:num3:);
BOOL sul = [obj respondsToSelector:suf];
if(sul)
{
NSLog(#"It is implememted");
}
else
{
NSLog(#" It is not implemented");
}
NSLog(#"Hello, World!");
[pool drain];
return 0;
}
********-----
#interface movie : NSObject {
#private
}
-(void)findinterestofnum1:(int)p num2:(int)n num3:(int)r;
#end
*******-------
#import "movie.h"
#implementation movie
-(void)findinterestofnum1:(int)p num2:(int)n num3:(int)r
{
int a ;
a= (p*n*r/100);
NSLog(#"interest value is =%d",a);
}
- (void)dealloc
{
[super dealloc];
}
#end
i am trying to find whether method is implemented and if it is not it should print it is not implemented
#toddler, respondsToSelector just checks if the corresponding object can respond to that particular method. It doesn't do any checks on whether interface has that definition associated with it since it is a runtime check.
If you had removed the code from the implementation file (.m file) and not the interface, you would have got an error while executing it and you would have found that the BOOL sul is FALSE.