What happened when block is declared as assign - ios

I have been a while not tweaking blocks. Today I found one interview question about block in Objective-C:
Giving below code:
#interface ViewController ()
#property (weak, nonatomic) IBOutlet UIButton *button;
- (IBAction)buttonClick:(id)sender;
#property(nonatomic, assign) void(^block)();
#end
- (void)viewDidLoad {
[super viewDidLoad];
int value = 10;
void(^blockC)() = ^{
NSLog(#"just a block === %d", value);
};
NSLog(#"%#", blockC);
_block = blockC;
}
- (IBAction)buttonClick:(id)sender {
NSLog(#"Log:%#", _block);
}
What would happen?
Here's the output and some debug value:
If I add a breakpoint at the end of viewDidLoad(), here is the output:
2017-08-03 14:28:49.209 TestApp[23692:1211863] <__NSMallocBlock__: 0x600000055210>
(lldb) po _block
0x00000001026b86c0
And after I click the button and break at NSLog(#"Log:%#", _block);, it shows:
2017-08-03 14:30:57.948 TestApp[23692:1211863] Log:{(
_UILayoutGuide:0x7fc40b70cd10.minY{id: 16}
)}
(lldb) po _block
0x0000000000000003
So I kind of know that since blockC is freed after viewDidLoad(), _block should be pointing to a dirty field and cause memory leak or stack overflow. But what confuses me is that, first, in viewDidLoad(), why the NSLog output is <__NSMallocBlock__: 0x600000055210>, but the _block value is 0x00000001026b86c0? Does this mean whatever on 0x00000001026b86c0 is a pointer pointing to <__NSMallocBlock__: 0x600000055210>?
Secondly, when we click the button, why _block becomes 0x0000000000000003? It's not this value every time, sometimes could be 0x0000000000000001 and even other large numbers(or address value). Also how can NSLog output can be
Log:{(
_UILayoutGuide:0x7fc40b70cd10.minY{id: 16}?
)}
Can someone help explain the whole process? Thank in advance!

Related

Facebook pop kPOPLayerCornerRadius is not working

I have outlet from storyboard and pop animation code inside of IBaction (UIButton) :
#property (strong, nonatomic) IBOutlet UIView *animationView;
...
...
POPBasicAnimation *animationCircle = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerCornerRadius];
animationCircle.toValue = #(self.animationView.layer.cornerRadius/2);
animationCircle.name = #"animacijaCircle";
animationCircle.delegate = self;
[self.animationView pop_addAnimation:animationCircle forKey:#"animacijaCircle"];
My animation is not working and I don't know why...
I have this in my debug area:
2015-03-17 11:28:00.321 customControll[5759:325909] -[UIView cornerRadius]: unrecognized selector sent to instance 0x7fc79ac720c0
and my exception breakpoint os stoped on this part of pop framework:
{kPOPLayerCornerRadius,
^(CALayer *obj, CGFloat values[]) {
values[0] = [obj cornerRadius];// exception breakpoint is on this line here
},
^(CALayer *obj, const CGFloat values[]) {
[obj setCornerRadius:values[0]];
},
kPOPThresholdRadius}
You can also give me example of cornerRadius animation with pop that I can use, I just want to make it work with Facebook pop.
Thank you!
kPOPLayerCornerRadius is a layer property not a view property therefore you need to add the animation to the layer not the view. So this line:
[self.animationView pop_addAnimation:animationCircle forKey:#"animacijaCircle"];
should be:
[self.animationView.layer pop_addAnimation:animationCircle forKey:#"animacijaCircle"];

Why is UITextField text setter giving [UIView text] selector not recognized

I have this code:
- (IBAction)setButtonPressed:(id)sender {
NSUserDefaults *sharedDefaults = [[NSUserDefaults alloc] initWithSuiteName:#"group.TodayExtensionSharingDefaults.santiapps.com"];
NSLog(#"nsuserdef %#", [sharedDefaults objectForKey:#"MyNumberKey"]);
NSLog(#"self.textField.text %#", self.textField.text);
//[sharedDefaults setInteger:[self.textField.text integerValue] forKey:#"MyNumberKey"];
[sharedDefaults synchronize]; // (!!) This is crucial.
NSLog(#"syncd");
}
and for some reason when I tap the button, I get:
-[UIView text]: unrecognized selector sent to instance
but my property is set as:
#property (weak, nonatomic) IBOutlet UITextField *textField;
I get a crash if I uncommment the sharedDefaults setInteger line.
I get a crash if I leave the line where I read the self.textField.text.
I get the final syncd NSLog only if I comment-out the setInteger or self.textField.text NSLog lines.
Why is it thinking textField is a UIView without a text property?
Ok, don't mean to toot my own horn here, but I thought the answer might help someone.
Xcode had incorrectly linked my view controller's UIView to the outlet. And I know some will think I would have done it by being careless, except that I did it as I very seldomly do the connection:
I control dragged from the textfield to the assistant editor's interface where xcode itself created the IBOutlet UITextField for me. So I know it wasn't my mistake. :)
Xcode is buggy. So watch out :-)

Weird EXC_BAD_ACCESS crash related with setter/getter in iOS

Could someone explain why following my code crash? Crash happenes inside the block in foo method.
I've got EXC_BAD_ACCESS or "error for object: double free". And I also got "-[NSObject description]: message sent to deallocated instance" when I set "Enable Zombie Objects" ON.
#interface ViewController ()
#property (nonatomic, strong) NSObject *obj;
#end
#implementation ViewController
// just adding button
- (void)viewDidLoad {
[super viewDidLoad];
UIButton *btn = [UIButton buttonWithType:UIButtonTypeSystem];
[btn setTitle:#"test" forState:UIControlStateNormal];
btn.frame = CGRectMake(100, 100, 100, 100);
[btn addTarget:self action:#selector(btnAction:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
}
// fired by button
- (void)btnAction:(id)sender {
for (int i = 0; i < 100; i++) {
[self foo];
}
}
// I want to understand this method
- (void)foo {
NSLog(#"foo");
self.obj = NSObject.new;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(#"%#", [[self obj] description]); // sometimes crash happenes here with a message "-[NSObject description]: message sent to deallocated instance"
});
}
#end
Looks like self.obj is deallocated between [self obj] and [obj description]. But I'm not sure why.
I think the object from [self obj] should be owned by it's scope and should not be deallocated even if self.obj = NSObject.new is executed at the same time on other threads.
Is my understanding wrong?
I'm testing on iOS 7.0.4 with ARC. Thanks!
You have a for loop that is calling your -foo method, so self.obj is rapidly getting set to new values. Each time this happens, you're executing code asynchronously that is accessing your (nonatomic) property. But even if it is always getting a correct value for that property when being accessed from multiple threads, the main thread is very likely setting the property to a new value before the background thread finishes using the previous value of the property. And once the property gets changed to a new value, it releases the previous object that was assigned to it.
Since you're accessing your property from multiple threads, you want it to be atomic, not nonatomic, so change your property to this:
#property (strong) NSObject *obj;
atomic is the default. It is probably also safer to do the following with your asynchronous block:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSObject *obj = self.obj;
if (self.obj) {
NSLog(#"%#", [obj description]);
}
});
You should no longer see a crash if you do this, because obj will always either be nil or a valid object with a strong reference to it inside the block.
However, you probably won't get the results you expect from this. For each execution of your asynchronous block, it's not guaranteed that you'll get the subsequent instances of NSObject that you're creating. There might be times where it executes your block where obj is the same object both times, and where you never see some of the objects that were created. This is because your asynchronous block isn't getting the instance set immediately before you made the call to invoke the block, it's getting it from the property. If you want this to use the instance set immediately prior, you must do something like the following:
__block NSObject *obj = NSObject.new;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(#"%#", [obj description]);
});
This should always use the instance that you created specifically for that invocation of the asynchronous block.
I suspect the issue is caused by the nonatomic property attribute as you are re-allocating self.obj 100 times I think there is a possibility of the background thread reading a partially reallocated object pointer.
Please try with:
#property (atomic, strong) NSObject *obj;
By the time the background logging is being done, self.obj could be different or in the middle of being changed.
Use a local variable like this:
- (void)foo {
NSLog(#"foo");
NSObject *val = [NSObject new];
self.obj = val;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(#"%#", val);
});
}
This will avoid threading issues and ensure the NSLog logs the proper instance.

Unrecognized selector setting alpha for a UIImageView

I'm getting an unrecognized selector exception trying to set the alpha on a UIImageView, but I don't understand why this should be seeing a UIImageView inherits from UIView and alpha is a property of that.
#property (strong, nonatomic) IBOutlet UIImageView *pulldownTab;
...
self.pulldownTab.alpha = 1.0;
2013-05-21 07:33:32.964 TestControl[655:907] -[__NSCFNumber setAlpha:]: unrecognized selector sent to instance 0x1e587fa0
** UPDATE **
Moral of the story - Solved. be careful with key value coding, a call to this function was being made earlier
- (void) fadeToAlphaValue: (double) alpha forKeyPath: (NSString*) keyPath
{
NSNumber* number = [NSNumber numberWithDouble:alpha];
[UIView animateWithDuration:kFadeAnimationDuration
animations:^ {
[self setValue:number forKeyPath:keyPath];
}];
}
[self fadeToAlphaValue:0.0 forKeyPath:#"self.pulldownTab"];
Are you sure you are assigning the IBOutlet properly in the interface Builder?
The reference is not properly working, when you access to self.pulldownTab is accessing to a NSCFNumber variable in memory.
I had the same problem here. In my case, I was setting myTextView, but not the .text property, earlier in the code, like this:
self.myTextView = #"text";
instead of what I should have been doing:
self.myTextView.text = #"text";
for some reason this didn't throw any errors at this point, but it created an issue later when I tried to set the alpha property on an NSString (which doesn't have such a thing) :)
Anyways, just look for any stupid mistakes like this in your code before the .alpha property is being set - they'll likely be the cause of the problem!

memory management in ios objective c

I am new to iOS and objective-C and although I've been struggling for a while to understand memory management I am disappointed in myself because I still have to get the full picture... My problem is that I do not understand how retaining a property of an object relates with retaining the whole object. Let's take the following code as an example:
#interface TestObject:NSObject { //TestObject declaration
NSNumber *firstNumber;
}
#property (nonatomic, retain) NSNumber *firstNumber;
#end
#synthesize firstNumber;
-(void) dealloc //Use standard synthesized getter and setter, write only custom
//dealloc
{
[firstNumber release];
}
...and the following code that uses it:
-(IBAction) runClicked: (id) sender
{
TestObject *to1=[[TestObject alloc ] init];
to1.firstNumber=[NSNumber numberWithInt:10]; //retain count 1 on firstnumber
NSNumber *num=[to1.firstNumber retain]; //retain count 2 on firstnumber
[to1 release]; //retain count 1 on firstnumber because of 1 release in dealloc
}
I ran an analyze on the code and also ran the program with Leak instrument and no leaks were found by either. Isn't there a leak on firstnumber (accessible by num after main object release) since the number will not be usable by any pointer after *num is also destroyed at the end of function body?
Thank you so much for your time!
Best regards,
Florin.
No, there isn't a leak as first number is an autoreleased object.

Resources