Using Webview within Class Method - iphone

Basically I have a class method which I am calling to call a web-service call as in dispatch mechanism, and when I get the response, I send the response in NSDictionary in sync mode.
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(queue, ^{
NSDictionary *_pD= [HttpRequest Details:#"Type" :#"guest" :[Description valueForKey:#"number"]];
dispatch_sync(dispatch_get_main_queue(), ^{
DLog(#"%#",[_D description]);
[self mapObjects:_D];
});
});
However, in this call I need to also invoke WebView, and wait for a javascript to get invoked from webview, hence I am just curious if that is possible to do also in Class method? Since in class method, anytime I assigned a delegate, it generates an error that I cant assign it to self.
Thanks.

You can have a static instance of your class being the delegate, and handle the entire thing from there.
Also remember to set the UIWebViewDelegate protocol in your .h
+ (YourClass *)getInstance {
static YourClass *instance = nil;
if (!instance) {
instance = [YourClass new];
}
return instance;
}
- (void)callWebService {
... do your thing
}
and call like this:
[[YourClass getInstance] callWebService];
If you want to get picky on the getInstance method, the proper way to do it is this (I didn't want to confuse you with weird code):
+ (YourClass *)getInstance {
static dispatch_once_t pred;
static YourClass *instance = nil;
dispatch_once(&pred, ^{
instance = [[[self class] alloc] init];
});
return instance;
}

Since in class method, anytime I assigned a delegate, it generates an
error that I cant assign it to self.
Just a quick thought. Why don't you write a new class and assign its object as the delegate instead of self?

Related

Overriding alloc init for singleton class [duplicate]

This question already has answers here:
How to properly implement ARC compatible and `alloc init` safe Singleton class? [duplicate]
(3 answers)
Closed 8 years ago.
I am writing some singleton class in my framework and I do not want other developer to call init and alloc on those singleton classes so I have override those methods but since I am using ARC, so my code for singleton class is:
+(MFSingletonClass*) sharedInstance
{
static dispatch_once_t pred = 0;
dispatch_once(&pred, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
and following are alloc and init methods:
+ (id)alloc {
static dispatch_once_t pred = 0;
dispatch_once(&pred, ^{
sharedInstance = [super alloc];
});
return sharedInstance;
}
- (id)init {
__weak typeof(self) weakSelf = self;
static dispatch_once_t pred = 0;
dispatch_once(&pred, ^{
static BOOL init = NO;
if (!init) {
init = YES;
typeof(self) strongSelf = weakSelf;
strongSelf = [super init];
}
});
return weakSelf;
}
I wanted to know whether my implementation of alloc and init method is proper or not?
Thanks in advance!
You ask whether your "implementation of alloc and init method is proper or not?"
Depends on how you define "proper"...
Your code is not incorrect as far as it goes, in that it usually does work, but the init is, let's say, over-cautious and a little incorrect, and there is a trick or two you missed.
Looking at the init you double up checking whether the initialisation has been run:
dispatch_once; and
a BOOL flag init.
The block passed to dispatch_once will be executed at most once, and at that time init will be NO. Overkill. Removing that you get:
- (id)init
{
__weak typeof(self) weakSelf = self;
static dispatch_once_t pred = 0;
dispatch_once(&pred,
^{
typeof(self) strongSelf = weakSelf;
strongSelf = [super init];
});
return weakSelf;
}
Now consider [super init], this is a method call on the current instance, that is though it is not explicit this expression references self. Given that your efforts to avoid a retain cycle are wasted. Furthermore in those efforts you assigned the result of [super init] to a block-local variable strongSelf while init returns weakSelf - this is the reason for the "usually does work" remark above, most calls to [super init] do actually return the same object, but the need not. If we remove the use of weak references we solve both these issues at once:
- (id)init
{
static dispatch_once_t pred = 0;
dispatch_once(&pred,
^{
self = [super init];
});
return self;
}
Bot doesn't this leave us with a retain cycle? No, the object referenced by self does not keep a reference to the block, so the block having a reference back to the object doesn't matter.
The "as far as it goes" remark above
The default alloc method just calls allocWithZone:, the latter takes a memory zone - something which is no longer used but exists for historical reasons. Therefore you should really implement allocWithZone: rather than alloc to catch all allocations - the code would follow the same algorithm as your alloc.
Then there is the copy and copyWithZone: pair. If you want a singleton you don't copies of it, so you should implement copyWithZone: (which copy just calls as will alloc/allocWithZone:) and return self:
- (id) copyWithZone:(NSZone *)zone
{
return self;
}
The missed trick
So your code works as far as it goes, apart from the case where [super init] returns a different object, but was overcomplicated; clean up init to address that.
However if you dig up Apple's now deprecated Cocoa Objects documentation you'll find Apple's old recommendation for producing a true singleton. Under ARC you can ignore the MRC overrides, and you can add the use of GCD as you have done to ensure concurrent correctness, and that will leave you with one trick: Apple implement allocWithZone: by calling sharedManager (your sharedInstance) and having that in turn call allocWithZone on super. With your code that would be:
+ (MFSingletonClass*) sharedInstance
{
static MFSingletonClass *sharedInstance = nil;
static dispatch_once_t pred = 0;
dispatch_once(&pred,
^{
sharedInstance = [[super allocWithZone:NULL] init];
});
return sharedInstance;
}
+ (id)allocWithZone:(NSZone *)ignore
{
return [self sharedInstance];
}
Which is a little cleaner, but your approach works fine as well.
And kudos for knowing the difference between a true singleton and just a shared instance!
HTH
With singletons, you have two choices: Write the very simple sharedInstance method and be done with it, or try to do all kinds of ingenious tricks to keep people from instantiating more objects. Trying to instantiate the singleton through any call other than sharedInstance is a programming error. You don't write complicated code to prevent programming errors. And you'll never get it right anyway :-)

Objective C Singleton Class [duplicate]

This question already has answers here:
Using a singleton to create an array accessible by multiple views
(2 answers)
Closed 9 years ago.
I have created a singleton class in Objective C. Like the one below:
#interface SingletonClass : NSObject{
NSMutableArray *instanceArray;
}
#property(nonatomic,retain)NSMutableArray *instanceArray;
+(SingletonClass*)sharedInstance;
#end
#implementation SingletonClass
#synthesize instanceArray;
static SingletonClass *sharedInstance =nil;
+(SingletonClass*)sharedInstance
{
if(sharedInstance==nil){
sharedInstance=[[super allocWithZone:NULL]init];
}
return sharedInstance;
}
-(id)init{
self=[super init];
if(self){
instanceArray=[[NSMutableArray alloc]init];
[instanceArray addObject:#"One"];
[instanceArray addObject:#"Two"];
}
return self;
}
+(id)allocWithZone:(NSZone *)zone{
return [self sharedInstance];
}
#end
I know it can be accessed from anywhere with the following piece of code:
SingletonClass *singletonObject=[SingletonClass sharedInstance];
And the instanceArray can be accessed anywhere by singletonObject.instanceArray.
Now my question is, is is possible to modify the array by adding new objects to it ? Will that be persisted ? Because i tried to add an object from one class
[singletonObject.instanceArray addObject:#"Three"];
When i checked the array contents from another class, the array consisted of only two values which are initialized by default. The value which i added from another class didnt show up.
What could be the problem ? Am I missing something here ? Please help.
Drop the allocWithZone: implementation entirely. It is prone to error and a distinctly odd thing to do. The reality is that if you have code that is using your singleton class and not going through sharedInstance then that code is broken. Attempting to hide that brokenness is just going to cause pain later.
Just do this one:
+(instancetype)sharedInstance
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[SingletonClass alloc] init];
});
return sharedInstance;
}
If you aren't seeing updates to the array in your other class, then there is some other bug.
Your implementation of allocWithZone: is never called because you are calling the [super allocWithZone:], also i don't think you need this method.
i would change your class method with this:
+(instancetype)sharedInstance
{
if(sharedInstance==nil){
sharedInstance = [[SingletonClass alloc]init];
}
return sharedInstance;
}
and if you want to be more secure that you are not going to create another instance of your object use dispatch_once:
+(instancetype)sharedInstance
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[SingletonClass alloc] init];
}
return sharedInstance;
}
I think that you forgot the ! before self in init method :
-(id)init {
self = [super init];
if(!self) {
instanceArray=[[NSMutableArray alloc]init];
[instanceArray addObject:#"One"];
[instanceArray addObject:#"Two"];
}
return self;
}
That's why each time you get a new instance of your singleton

Is self release, released actual object?

I have a singleton class which is allocation object only one time in whole project. Few code line is below..
declaration...
....
MyClassName *classObject = nil
In the init method, the code is like below..
-(id) init(){
self = [super init];
if(classObject == nil){
1. Allocate object code here
2. classObject = self;
3. return classObject
} else {
return classObject;
}
}
But my problem is that how will I dealloc this object. I am calling this init method from all the class and it is returning classObject reference every time.
My approach....
From the dealloc method in appdelegate.m, I am calling a function (releaseObject)which is defined in MyClassName . Here is the definition of function body...
-(void) releaseObject {
[self release]; // Confusion: Will it dealloc classObject reference?
[super release];
}
Is this good idea dealloc this object? My problem is that I don't have to dealloc object until application is not being closed.
The answer is don't bother ever to release the singleton. It is supposed to last the lifetime of the application anyway and will go away automatically along with everything else when the process terminates. You may find that the dealloc method on your app delegate never gets called for the same reason.
If you have clean up to do on application close, it's probably better to move that into a separate method and just call that when the application is about to terminate.
a simpler pattern for a singleton IMO is to have a class method to return the singleton instance and not mess about with releasing stuff in init.
+(MyClass*) sharedInstance
{
static MyClass* theInstance = nil;
static dispatch_once_t pred;
dispatch_once(&pred, ^{ theInstance = [[MyClass alloc] init]});
return theInstance;
}
The above uses dispatch_once to ensure the initialising block only happens once in the lifetime of the application. You can still create other instances by calling init directly but that is advantageous IMO.
I'd recommend to make an extra class method in your singleton:
static MyClassName *classObject = nil;
...
+ (MyClassName *)sharedInstance {
...
}
+ (void)releaseSharedInstance {
[classObject release];
classObject = nil;
}
If your class is a singleton, in AppDelegete dealloc just call
[[YourClass instance] release];
Here is workaround via Objective C++:
class StaticOwner {
private:
id<NSObject> object;
public:
StaticOwner(id<NSObject> obj) { object = [obj retain]; }
~StaticOwner() { [object release]; }
id<NSObject> instance() {return object;}
};
Usage example:
+ (MySingleton*) sharedInstance {
static StaticOwner owner = StaticOwner([[[MySingleton alloc] init] autorelease]);
return owner.instance();
}

how to make static variable initialized

I want to save the "dataFilePath" as a static variable so that it can be initialized when first time use "Constants" and no need to instantiate the Class , for example [Constants SDataFilePath]. But the trues is that the init method is not called. How can I do to meet my request? (In Java the construct method will be called the fist time to access the Class).
#implementation Constants
static NSString *dataFilePath;
-(id)init
{
NSLog(#"init!");
if(self = [super init]) {
dataFilePath = [self getDataFilePathWithArg:dbfile];
}
return self;
}
+(NSString *)SDataFilePath {
return dataFilePath;
}
....
#end
Well you could make Constants a singleton. Leave your code how it is and add this method to the .m:
+ (Constants *)sharedConstants
{
static Constants *_sharedConstants = nil;
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
_sharedConstants = [[self alloc] init];
});
return _sharedConstants;
}
And the method declaration to the .h:
+ (Constants *)sharedConstants;
Then access your variable like this:
[[Constants sharedConstants] SDataFilePath]
That will force an init the first time you access [Constants sharedConstants] (and only the first time). Also, you'll need to change +(NSString *)SDataFilePath to an instance method, not class method:
-(NSString *)SDataFilePath
This cannot be done this way. Any reason why you want this path to be static? You might want to look into setting dataFilePath with a getter, but no setter and instantiating the class as a singleton. That way you can set the path by some internal method and share the instance as a singleton. See here

iPhone check if user is logged in throughout application

For learning iOS programming I'm developing an iPhone application for sharing images. The application is the client for a website.
In the method didFinishLaunchingWithOptions I check if the user is already logged in.
If the user isn't logged in he can still see all parts of the applications but for example he wouldn't see option button for editing profile, comment on images, etc.
How can I share the logged/or not status throughout all view controllers?
Update: If giving this advice today, I would say use a shared instance:
#interface SomeClass: NSObject
{
+(SomeClass *)shared;
}
#implementation SomeClass
{
+(SomeClass *)shared {
static SomeClass *shared;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
shared = [SomeClass new];
});
return shared;
}
}
Then it is auto-instantiated for you on first use, and available throughout your app:
[[SomeClass shared] doSomething];
You can use a singleton - a global, shared instance of an object.
#interface SomeClassSingleton : NSObject {
}
+(SomeClass*)sharedSomeClass;
+(void)setSharedSomeClass:(SomeClass*)someObject;
#end
#implementation SomeClassSingleton
static SomeClass* _someObject = nil;
+(SomeClass*)sharedSomeClass
{
return _someObject;
}
+(void)setSharedSomeClass:(SomeClass*)someObject
{
#syncrhonized(self)
{
_someObject = someObject;
}
}
#end
Then, when you need to access your object in another source file, you import the header file for your singleton in the other header, like you would for any other reference.
Create a singleton:
SomeClass* someObject = [[SomeClass alloc] init];
[SomeClassSingleton setSharedSomeClass:someObject]; // write to save your singleton
Use/read a singleton:
[[SomeClass sharedSomeClass] someSharedClassMessage];
// OR
SomeClass* someObject = [SomeClass sharedSomeClass];
Or, you can create a singleton implementation that auto-inits the first time you access it:
#implementation SomeClassSingleton
static SomeClass* _someObject = nil;
+(SomeClass*)sharedSomeClass
{
#synchronized(self) {
if (_someObject == nil) {
_someObject = [[SomeClass alloc] init];
}
}
return _someObject;
}
#end
Put it in a singleton like the application delegate or as a transient value in a model object (like user data) that everything can see.
If you add an assigned BOOL property to your application delegate, you can get to it like this:
myApplicationDelegate *myDelegate = (myApplicationDelegate*)[[UIApplication sharedApplication] delegate];
myDelegate.userLoggedIn = YES;