did afnetworking cancel task can ensure code execution order? [closed] - ios

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 days ago.
Improve this question
I have two classes, one is a player , the other one is a viewcontroller.
the player has two public methods as below
- (void)playRoomId:(NSSting *)roomId
- (void)stop
the viewcontroller call it's methods, first call
playroomId:
then user pressed a button, call stop
stop
all code as below
//***********player.m*********
// use afnetworking to request
- (void)playRoomId:(NSSting *)roomId {
__weak typeof(self) ws = self;
self.task = [self reqeust:roomId successBlock:^{
[ws rellayPlay]; /// succes callBack
} failure:^{reBlock:^{
}
}
- (void)stop {
[self.task cancel]; /// cancelRequest
[self reallyStop]; /// reallystop
}
//***********player.m*********
/// ****viewController.m****
- (void)viewDidLoad {
[self.player playRoomId:#"2234"];
}
// button did touch
- (void)buttonAction {
[self.player stop];
}
/// ****viewController.m****
For above code,is it possible that it execute in this order?
[self.task cancel]
[self reallyStop]
[ws rellayPlay]
I worry some error might happen in this situation.
For example, when the network data is just returned and submitted to the main queue, the button is clicked. Since the submission to the main queue is an asynchronous submission, the button click method will be executed firstly. Since the network data has been received, the task might not be cancelled succssfully.
I tried many times in this situation, and no error is found, but I still worry it might happen.

Related

iOS Swift - Singleton data persistance [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I am developping an application that saves informations about the logged-in user in CoreData and singleton class. After the user log-in, I'm fetching data from coredata and set the variables from the singleton.
My question:
If the app receives memory warning issue, and the data from the singleton will be released, my app will crash. What can I do in this situation?
Thanks!
Let's say you have a local property named NSArray *myArray in singleton's .m file where you store all the needed data. All you need to do is to add a method in header file which returns that array if is not nil, and in case of nil make it reload from storage and return.
Also override - (void)didReceiveMemoryWarning method and save the data in case of memory warning.
Here is a sample code written in objective-c:
//Singleton.h file
- (NSArray *)storedData;
//Singleton.m file
#property NSArray *myArray;
...
- (NSArray *)storedData
{
if (_myArray == nil)
_myArray = [self fetchMyArrayFromLocalStorage];
return _myArray;
}
- (NSArray *)fetchMyArrayFromLocalStorage
{
//Some code to fetch data from local storage
}
- (void)saveMyArrayToLocalStorage
{
//Code to save _myArray to local storage
}
- (void)didReceiveMemoryWarning
{
[self saveMyArrayToLocalStorage];
_myArray = nil; //Remove array if is needed
[super didReceiveMemoryWarning];
}
Now you'll always get the data you needed simply by calling method:
[[mySingleton sharedInstance] storedData]
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
Your ViewController would have this method by default, and before your app crash, this method will execute automatically, you should write some code in this method to make sure your data can be saved in device, and then release it.

How to load interstitial ads when Navigation Back Button Pressed and Some Click Event? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I am new to iOS development. I am adding an interstitial ads when ViewDidLoad but I want to show interstitial ads when an user clicks ten times in my application, is that possible? If it is possible then please help me finding a solution. My Application contains HMSegmentedControll and it has ten different UITableView. And I also want to display these ads when NavigationBar back button is pressed. Could anyone help me with this?
It is Possible like as SharedPreference in Android
Make One Global Variable NSObject like as
GlobalVariable.h File
#property (assign) int touchCount;
+ (TouchCount *)getInstance;
#end
and GlobalVariable.m File
#synthesize touchCount;
static TouchCount *instance = nil;
+(TouchCount *)getInstance
{
#synchronized(self)
{
if(instance==nil)
{
instance= [TouchCount new];
}
if (instance.touchCount ==10)
{
instance.touchCount=0;
instance= [TouchCount new];
}
}
return instance;
}
And Use this Instance when You Want to Touch Count import GLobalVariable.hlike as
TouchCount *obj=[TouchCount getInstance];
Whell u can add some global value than counts "back taps"
in GlobalVariables.h file something like this:
extern int PRJ_back_touches_count;
.m:
int PRJ_back_touches_count;
Than e.g. in viewWillDisappear method PRJ_back_touches_count++
On viewDidAppear u can handle the PRJ_back_touches_count actual value

iOS App freezing with NSConditionLock

I'm having this wierd problem with the app freezing at a certain point. I'm guessing its got to do with how I'm using NSConditionLock.
Theres a library I have been given to use, which consists of a series of survey questions, but it works in such a way that it races directly to the last question without accepting answers, hence the need to pause the thread and accept input from the user.
I haven't used it before so maybe someone could help if I'm implementing it wrongly?
Please let me know if the code provided is insufficient.
- (void)viewDidLoad
{
[super viewDidLoad];
//INITIALISE CONDITION LOCK WITH CONDITION 0
condition=[[NSConditionLock alloc]initWithCondition: 0];
}
- (IBAction)startPressed:(UIButton*)sender {
if (sender.tag == 1) {
//START BACKGROUND THREAD
surveyThread = [[NSThread alloc] initWithTarget:self selector:#selector(runProjecttest) object:nil];
[surveyThread start];
}
else
{
//DO SOME STUFF AND THEN UNLOCK
[condition unlockWithCondition:1];
}
}
- (void) runProjecttest:(AbstractTask *)rendertask
{
// DO STUFF AND SHOW UI ON MAIN THREAD, THEN LOCK
[self performSelectorOnMainThread:#selector(showUI:) withObject:task waitUntilDone:YES];
[condition lockWhenCondition: 1];
}
EDIT: In short, I want the Objc equivalent of this java snippet...
this.runOnUiThread(showUI);
try
{
//SLEEP
Thread.sleep(1000*60*60*24*365*10);
}
catch (InterruptedException e)
{
//WAKE
setResponse(at,showUI);
}
EDIT 2: ShowUI method on Paul's request.
[self removePreviousSubViews];
switch ([task getType]) {
case SingleChoiceType:
{
NSLog(#"SingleChoiceType");
isMultipleChoice = NO;
[self addSingleChoiceView:nil];
break;
}
case TextType:
{
NSLog(#"TextType");
self.txtTextType.keyboardType=UIKeyboardTypeDefault;
[self addTextTypeView:nil];
break;
}
...more cases
}
-(void)addTextTypeView:(NSSet *)objects
{
self.txtTextType.text = #"";
CGRect frame = self.txtQuestionType.frame;
// frame.size = [self.txtQuestionType sizeThatFits: CGSizeMake(self.txtQuestionType.frame.size.width, FLT_MAX)];
frame.size.height = [self textViewHeightForAttributedText:self.txtQuestionType.text andWidth:self.txtQuestionType.frame.size.width andTextView:self.txtQuestionType];
self.txtQuestionType.frame=frame;
self.textTypeView.frame = CGRectMake((self.view.frame.size.width - self.textTypeView.frame.size.width)/2, ( self.txtQuestionType.frame.origin.y+self.txtQuestionType.frame.size.height), self.textTypeView.frame.size.width, self.textTypeView.frame.size.height);
[self.view addSubview: self.textTypeView];
}
I agree with BryanChen, I think you may have another issue. Without details on the survey library, it is impossible to confirm, but assuming that it is a UIViewController than accepts touch inputs to progress through a series of questions, it is hard to see why it is a threading issue - it simply shouldn't advance without user interaction.
That aside, your use of NSCondtionLock doesn't look right either.
Essentially an NSConditionLock has an NSInteger that represents the current 'condition', but just think of it of a number. There are then two basic operations you can perform -
lockWhenCondition:x will block the current thread until the 'condition' is 'x' and the lock is available. It will then claim the lock.
unlockWithCondition:y releases the lock and sets the condition to 'y'
There are also methods to set timeouts (lockBeforeDate) and try to claim the lock without blocking (tryLock, tryLockWhenCondition).
To synchronise two threads, the general pattern is
Initialise Lock to condition 'x'
Thread 1 lockWhenCondition:x -This thread can claim the lock because it is x
Thread 2 lockWhenCondition:y - This thread will block because the lock is x
Thread 1 completes work, unlockWithCondition:y - This will enable Thread 2 to claim the lock and unblock that thread
Your code looks strange, because you are starting a thread in your if clause but unlocking in an else clause. I would have thought you would have something like -
-(IBAction)startPressed:(UIButton*)sender {
if (sender.tag == 1) {
//START BACKGROUND THREAD
surveyThread = [[NSThread alloc] initWithTarget:self selector:#selector(runProjecttest) object:nil];
[surveyThread start];
[condition:lockWithCondition:1]; // This will block until survey thread completes
[condition:unlockWithCondition:0]; // Unlock and ready for next time
}
}
- (void) runProjecttest:(AbstractTask *)rendertask
{
// DO STUFF AND SHOW UI ON MAIN THREAD, THEN LOCK
[condition lockWhenCondition: 0];
[self performSelectorOnMainThread:#selector(showUI:) withObject:task waitUntilDone:YES];
[condition unlockWithCondition:1];
}
BUT This looks like a recipe for deadlock to me, because you are performing the showUI selector on the main thread that is blocked waiting for the survey thread to complete.
Which brings us back to the question, what does showUI do and why is it skipping directly to the end?

How to make a play again method? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I have a game where when it ends, a gameover image (gameoverscreen.png) is visible (formerly hidden), and a button appears to play again. What I tried doing was creating a IBAction for it, then in that action, reloading the viewDidLoad.
example:
-(IBAction)restartGame:(id)sender{
[self viewDidLoad]; //to reload the screen
gameoverscreen.hidden = YES;
replayButton.hidden = YES;
}
I thought this would reload the screen, but it simply appears for half a second, then the gameoverscreen is visible again. I thought it had something to do with my NSTimer, but the timer is invalidated when the gameoverscreen.hidden = NO; so its not that.. Any reason on why it won't reload the screen properly, and allow the user to play again?
Well I can't answer the question per se but I can give advice... this is what I imagine your starting code looks like...
-(void)viewDidLoad
{
NSTimer *t = [some timer code to start the loop and process events]
//init some other state stuff, arrays of rects etc.
}
-(IBAction)restartGame:(id)sender{
[self viewDidLoad]; //to reload the screen
gameoverscreen.hidden = YES;
replayButton.hidden = YES;
}
this is what your code should look like:
-(void)viewDidLoad
{
[self restartGame];
}
- (void)setUpInitalGameState
{
//init some other state stuff, arrays of rects etc.
}
- (void)start
{
NSTimer *t = [some timer code to start the loop and process events]
}
-(IBAction)restartGame:(id)sender{
[self setUpInitialGameState];
[self start];
}
You should not be calling viewDidLoad to reset your game to a starting state. Let viewDidLoad only be called once automatically when the application launches, and then manually reset the variables and positions in your game. In viewDidLoad, you should load any images, audio, and initialize variables used in your games. Handle your game reset in a separate function with a format similar to the one below:
(IBAction)resetGame:(id)sender{
// Set positions of all images to a starting state.
// Change image visibilities as desired.
// Reset all game variables to the initial state.
}
My iOS game SlothDrop only calls viewDidLoad once. When the game ends, all objects are animated off screen and are repositioned, where they are later animated back on screen. At no time is the view loaded again, all objects are just moved around. You can see how I reset the game in the free version here: https://itunes.apple.com/us/app/slothdrop-free/id789603341?mt=8&uo=4
In this way you need wholly re-init your controller and then push it to the screen.

Don't work dispatch_async in iOS 7 like in iOS 6 [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
There is a part of the program:
dispatch_sync (dispatch_get_main_queue (), ^ {
[startBtn setTitle: # "Loading ..." forState: UIControlStateNormal];
[self loadImages]; / / loading images - AssesLibrary
});
[self makeCollage];
NSLog (# "Albums found:% lu", (unsigned long) [assetGroups count]);
from the block dispatch_sync program comes out, and I need to initially perform the functions of [self loadImages] (filled array of data), and then later performed [self makeCollage].
If no dispatch_sync - then just [self makeCollage] starts filled without further processing array and gives an error.
Advise how to be
added :
dispatch_queue_t currentQueue=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(currentQueue, ^{
__block UIImage *image=nil;
dispatch_sync(currentQueue, ^{
//download the image here
image = [self loadImages];
});
dispatch_sync(dispatch_get_main_queue(), ^{
//handle the image to the user here on the main queue
if (image != nil){
[self makeCollage];
} else
{
NSLog(#"Image isn't downloaded. Nothing to do.");
}
});
});
Try this:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, NULL), ^{
// Do your stuff
});
As Gabriele stated you are causing a dead lock. You got two options:
Create a new sync queue, but it seems that you are using UIKit in the block. UIKit for the most isn't thread safe particularly for part that has influence on the display
Instead on using a dispatch_sync, use a dispatch_async on the main queue
If you want to send work on a background thread you should organize your logic differently.

Resources