I am trying to define an instance variable which is a block
i have 2 classes as follows
#interface ClassA:NSObject
typedef void (^ABlock)(void);
#end
#import "ClassA.h"
#interface ClassB :NSObject
-(void)someMethodWithABlock:(ABlock)block;
#end
in class B the "ABlock" type is not recognized unless it is written right above the "someMethodWithABlock"
How can I fix it?
you want this?
typedef void (^blockA)(void);
#import <Foundation/Foundation.h>
#interface ClassA : NSObject
{
blockA classAblockA;
}
#end
#interface ClassB : NSObject
{
blockA classBblockA;
}
#end
hope this will help you
You want to pass a block as an argument of a method
so instead of writing this
- (void) someMethodWithABlock:(void (^)(void)) blockA;
you want to use typedef to make it more presentable
typedef void (^ABlock)(void);
now you can use it as
- (void) someMethodWithABlock:(ABlock) blockA;
Now You want to use above typedef to someWhere else for it you need to import this
.h file where you want to use this typedef(If you are already done it , you must have problem in your global file where you are importing it).
Related
As is known that in ObjC property declared in .h file is the interface "visible outside", while property declared in .m file (class extension) can be only accessed in .m, kind of "private" or "hidden". But in practice code as follows can be compiled.
ClassA.h
#interface ClassA : NSObject
+ (void)foo;
#end
ClassA.m
#import "ClassA.h"
#interface ClassA ()
#property (nonatomic) NSInteger aInt;
#end
#implementation ClassA
+ (void)foo {
ClassA *aObj = [ClassA new];
aObj.aInt = 2; //?
}
#end
#interface _ClassB : NSObject //Some private class defined in the same .m file...
#end
#implementation _ClassB
+ (void)bar {
ClassA* aObj = [ClassA new];
aObj.aInt = 2; //?
}
#end
The fact is, not only ClassA *aObj defined in ClassA's own method can access class extension property aInt, but ClassA *aObj defined in another _ClassB while in the same ClassA.m file can also access aInt.
As far as I understand, aObj defined in class method foo has no difference with any ClassA * type variable defined in another class and separate .m file. But by no means will the latter access 'aInt', say
ClassC.m
#import "ClassA.h"
...
- (void)fun {
ClassA *aObj = [ClassA new];
NSLog("%d", aObj.aInt); //Error! Property aInt not found on object of type 'ClassA*'
}
Why is this happening? Can this be explained with ObjC runtime mechanism or something?
It has nothing to do with the Objective C runtime. In fact, if you use key value coding, you can access any property and/or method from any class from any source file you want, may it be declared private or not, or in an extension or directly. This is how some people (forbiddenly) use private APIs of Apple.
Objective C, like C, just needs to know the declarations of your class. This is done by importing the header files. The header file says "Look, there is something like ClassA, it has these methods and those properties", and then you can use them.
Anything that is declared in a .m file is not visible to other source files, because you typically do not import .m files (although, technically, it works). Nevertheless, the declaration still exist - just the compiler does not know of it when compiling the other file.
You could create a dummy header file:
// FakeClassAExtension.h
// ...
#interface ClassA (Fake)
#property (nonatomic) NSInteger aInt;
#end
and then use it in your ClassC:
// ClassC.m
#import "ClassA.h"
#import "FakeClassAExtension.h"
//...
- (void)fun {
ClassA *aObj = [ClassA new];
NSLog("%d", aObj.aInt); //Fine
}
When compiling ClassC.m, the compiler get's to know that someting like aInt exists in ClassA. The linker - as the final step - then checks if this really is true, e.g. if one (and only one) of the compiled source files contained the definition of aInt.
Try this: Just declare a property that is not defined anywhere:
// FakeClassAExtension2.h
// ...
#interface ClassA (Fake2)
#property (nonatomic) NSInteger oopsDoesItExist;
#end
and then use it:
// ClassC.m
#import "ClassA.h"
#import "FakeClassAExtension2.h"
//...
- (void)fun {
ClassA *aObj = [ClassA new];
NSLog("%d", aObj.oopsDoesItExist); //Compiler is fine here
}
The compiler will compile the code, but the linker then will say that there is no definition of oopsDoesItExist
Just a final remark: You can define iVars or synthesize properties only in class extensions (anonymous categories) within an .m file. See https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/CustomizingExistingClasses/CustomizingExistingClasses.html
When I define my block in my .h file, there comes an issue:
Unknown type name NSString
My code is below:
typedef void(^CancelBlock)();
typedef void(^ConfirmBlck)(NSString *); // this line comes the error
#import <UIKit/UIKit.h>
#interface LMLUpspringView : UIView
#property (nonatomic, copy) CancelBlock cancelBlock;
#property (nonatomic, copy) ConfirmBlck confirmBlock;
#end
But, why is my first block ok and the second report's an error?
You define block above the #import <UIKit/UIKit.h> (in the .h file), so there did not import the NSString, you should cut the #import <UIKit/UIKit.h> above the block define.
you need to declare block as below
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
typedef void(^ConfirmBlck)(NSString * string);
In latest versions of xcode you can simply specify
#import <Foundation/NSString.h>
any NS Foundation class can be imported as needed.
position declaration uikit import then follow:
// declare
#property(nonatomic,strong)void(^ConfirmBlck)(NSString * string);
// define
[self setConfirmBlck:^(NSString *indexpVal) { }];
// call
if (self.ConfirmBlck) {
self.ConfirmBlck(selectedVal);
}
i've worked with delegation before. i know how to create delegation from a superview to a subview class. however, i'm trying to do it the opposite way using the same approach but it's not working! is delegation meant only to work one way or is there a way/trick to use it as a two way communication between the classes? I'm receiving an error at the parent/superview .h class which is:
Cannot find protocol definition for 'SubViewControllerDelegate'
my code goes like this:
subview.h
#import <UIKit/UIKit.h>
#import "SuperViewController.h"
#protocol SubViewControllerDelegate <NSObject>
- (void)someMethod:(NSData *)data;
#end
#interface SubViewController : UIViewController
#property (weak, nonatomic) id <SubViewControllerDelegate> delegate;
#end
subview.m:
[self.delegate someMethod:data];
SuperView.h
#import <UIKit/UIKit.h>
#import "SubViewController.h"
#interface SuperViewController : UIViewController <SubViewControllerDelegate>
#end
SuperView.m:
#pragma mark - SubView Controller Delegate Methods
- (void)someMethod:(NSData *)data{
NSLog(#"%#", data);
}
am i doing anything wrong or missing out anything?
You have an "import-cycle", because "SuperViewController.h" imports "SubViewController.h" and vice versa.
Removing the #import "SuperViewController.h" in "SubViewController.h"
should solve the problem.
If you really need that class to be declared in "SubViewController.h", use
#class SuperViewController; to avoid the import-cycle.
Remark: The <SubViewControllerDelegate> protocol declaration is probably not
needed in the public interface "SuperViewController.h" at all.
In "SuperViewController.h", declare the class as
#interface SuperViewController : UIViewController
In "SuperViewController.m", define a class extension with the protocol:
#interface SuperViewController () <SubViewControllerDelegate>
#end
I want to use a custom method in a custom class in my viewcontroller
//Viewcontroller.h
#import "Class1.h"
//Class1.h
//#import "Class1+Category.h" // Deemed unnecessary in comments below.
#interface Class1: NSObject
-(void)doSomething;
#end
//Class1.m
#import "Class1.h"
#implementation Class1
-(void)doSomething{
NSLog("In doSomething");
}
#end
Now I want a category method of Class1.
//Class1+Category1.h
#import "Class1.h"
#interface Class1 (Category1) // ERROR : Cannot find interface declaration
-(void)doAnotherThing;
#end
//Class1+Category1.m
#import "Class1+Category.h"
#implementation Class1 (Category1)
-(void)doAnotherThing{
NSLog(#"Did Another thing");
}
#end
Finally - in my viewcontroller.m I see the doSomething method, but not the doAnother thing
//viewcontroller.m
Class1 *myClass1 = [[Class1 alloc]init];
[Class1 doSomething]; //Works great!
[Class1 doAnotherThing]; //Not recognized
I have added the -all_load to my target settings. I am out of ideas..do I use the #class? I get 'Cannot find interface declaration' error
Your class and category seems correct at first glance but your controller needs to import Class1+Category.h. Perhaps that's what you missed?
I have started new iOS project and have added only one property in ViewControler header file. but it gives me error:
expected specifier-qualifier-list before 'property'
here is the code:
#import <UIKit/UIKit.h>
#interface QuoteGenViewController : UIViewController {
#property (retain) NSArray *myQuotes;
}
#end
Here the general structure of a class interface
#interface Class : Superclass
{
// Instance variable declarations.
// Theirs definition could be omitted since you can declare them
// in the implementation block or synthesize them using declared properties.
}
// Method and property declarations.
#end
Since a property provides a simple way to declare and implement an object’s accessor methods (getter/setter), you need to put them in the Method and property declarations section.
I really suggest to read ocDefiningClasses doc for this.
Hope that helps.
Your code should look like this:
#import <UIKit/UIKit.h>
#interface QuoteGenViewController : UIViewController {
}
#property (retain) NSArray *myQuotes;
#end