I want to check whether the UIALertView is present on the screen or not, though I have done it by using the following method:
-(BOOL) isAlertShowing
{
for (UIWindow* window in [UIApplication sharedApplication].windows) {
NSArray* subviews = window.subviews;
if ([subviews count] > 0)
if ([[subviews objectAtIndex:0] isKindOfClass:[UIAlertView class]])
return YES;
}
return NO;
}
but I came to know that it is undocumented one. So, please tell me authenticate way of doing it.
In an app I submitted (and is approved), I have used a similar approach (see iPhone: detecting if a UIAlert/UIActionSheet are open)...
I don't see why you think it's not a valid method - I'd try it.
Related
my app has around 200 UITableView rows, when i use simulator on xcode to filter data through UISearchBar, it filters and shows result instantly however, when i run my app in my iphone (iphone4, iOS 5.1.1), it hangs for couple of seconds before showing any search result. I'm using this code to filter data...
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText{
[self.filteredData removeAllObjects];
if ([searchText length] > 0) {
self.isSearching = YES;
for (AClass *filteredData in self.allData) {
NSRange titleResultRange = [filteredData.name rangeOfString:self.searchBar.text options:NSCaseInsensitiveSearch];
if (titleResultRange.location != NSNotFound) {
[self.filteredData addObject:filteredData];
}
}
}
else self.isSearching = NO;
[self.tableView reloadData];}
I believe my code is okay since it's working perfectly fine on the simulator, is there anything i need to do to make it work faster on iphone?
btw, my iPhone is working perfectly fine, i use other apps, they work fine for me..
The reason your device is taking longer than the simulator is due to the amount of memory available. As a general rule, don't use the performance of your app in the simulator to judge your app's performance.
If you are filtering a very large data set in the way you describe, I would suggest using dispatch queues to perform your search instead of doing it all in the main queue. You can read about them here: http://developer.apple.com/library/ios/#documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html
In case you don't want to read the entire documentation, here's an example of what this would look like with your code.
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText{
[self.filteredData removeAllObjects];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
if ([searchText length] > 0) {
self.isSearching = YES;
for (AClass *filteredData in self.allData) {
NSRange titleResultRange = [filteredData.name rangeOfString:self.searchBar.text options:NSCaseInsensitiveSearch];
if (titleResultRange.location != NSNotFound) {
[self.filteredData addObject:filteredData];
}
}
}
else self.isSearching = NO;
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
});
}
Please note that the example I am giving you is not thread safe... you will need to make sure that only one search is being performed at any given time or this code will crash, since the same array will be referenced across multiple queues. If you need more assistance, leave a comment and I'll try to get to it.
I have an iPhone application in which I am testing in the applicationDidBecomeActive: that if the selected viewcontroller's rootview is there, then I want to call one webservice, otherwise not when I am coming from background to foreground I am taking the stack and checking it. But now even if I am in the rootview the webservice is not getting called. Can anybody help me on this?
Here is my code snippet:
- (void)applicationDidBecomeActive:(UIApplication *)application{
NSLog(#"applicationWilssnd");
if(tabBarController.selectedIndex==0)
{
NSArray *mycontrollers = self.tabBarController.viewControllers;
NSLog(#"%#",mycontrollers);
///if([mycontrollers objectAtIndex:0]!=)
///[[mycontrollers objectAtIndex:0] popToRootViewControllerAnimated:NO];
PinBoardViewController *pinvc=(PinBoardViewController*)[[mycontrollers objectAtIndex:0]topViewController] ;
if([mycontrollers objectAtIndex:0]!=pinvc)
{
}
else
{
[pinvc merchantnews];
}
mycontrollers = nil;
tabBarController.selectedIndex = 0;
}
}
`here the merchantnews is not getting called.
PinBoardViewController *pinvc=(PinBoardViewController*)[[mycontrollers objectAtIndex:0]topViewController] ;
if([mycontrollers objectAtIndex:0]!=pinvc)
Instead of this, try this
PinBoardViewController *pinvc=(PinBoardViewController*)[[mycontrollers objectAtIndex:0]topViewController] ;
if(pinvc isKindOfClass:[PinBoardViewController class]){
// Do ur stuff
}
Ok, so this has been driving me mad for a while, but it occasionally self corrects so I've dealt with it, but it's time to fix it!
Situation is as follows:
View created in Interface Builder for iOS. Contains a UIButton referenced as 'banana015'
Method in my implementation .m as follows:
- (IBAction)draggedOut: (id)sender withEvent: (UIEvent *) event {
if ([[NSUserDefaults standardUserDefaults] integerForKey:#"edittingmode"] == 3) {
UIButton *selected = (UIButton *)sender;
selected.center = [[[event allTouches] anyObject] locationInView:self.view];
if ([[NSUserDefaults standardUserDefaults] integerForKey:#"changeskin"] == 1) {
[self scifiTempSave];
}
else if ([[NSUserDefaults standardUserDefaults] integerForKey:#"changeskin"] == 2) {
[self bananaTempSave];
}
else if ([[NSUserDefaults standardUserDefaults] integerForKey:#"changeskin"] == 3) {
[self orangeTempSave];
}
}
else{}
}
And declared in my .h Header as
-(IBAction)draggedOut:(id)sender;
Now, when I connect the button to the 'draggedOut:' method in Interface Builder using the Touch Drag Inside event, I can drag the button around when I build and run the project (expected behaviour) however when I release the app crashes.
In the past I've been able to connect to a method that appears as "draggedout: withevent" which works beautifully. This evening I've connected some 50 items up to this 'draggedout: withevent' option and it works beautifully for each one - I have however got two UIButtons (identical in almost every way (different referencing outlets) that I have yet to connect to it, and I'll be damned if it'll let me.
Can anyone help? This has been infuriating for some time. The option disappears, yet all those that I previously connected to it still work perfectly, I just can't hook anything new up to it...or the old ones if I disconnect them.
The one problem I can see is that your method declaration in the header is not the same as your implementation. The header declaration should be the first line of the method in the implementation plus a semicolon:
- (IBAction)draggedOut: (id)sender withEvent: (UIEvent *) event;
To get more info on the crash, you should try setting NSZombieEnabled to true.
To answer your question in the comment, I don't know why you would get the option of a draggedout: method in addition to the one including withEvent if it's not declared in your code.
I want to get a pointer reference to UIKeyboard *keyboard to the keyboard on screen so that I can add a transparent subview to it, covering it completely, to achieve the effect of disabling the UIKeyboard without hiding it.
In doing this, can I assume that there's only one UIKeyboard on the screen at a time? I.e., is it a singleton? Where's the method [UIKeyboard sharedInstance]. Brownie points if you implement that method via a category. Or, even more brownie points if you convince me why it's a bad idea to assume only one keyboard and give me a better solution.
Try this:
// my func
- (void) findKeyboard {
// Locate non-UIWindow.
UIWindow *keyboardWindow = nil;
for (UIWindow *testWindow in [[UIApplication sharedApplication] windows]) {
if (![[testWindow class] isEqual:[UIWindow class]]) {
keyboardWindow = testWindow;
break;
}
}
// Locate UIKeyboard.
UIView *foundKeyboard = nil;
for (UIView *possibleKeyboard in [keyboardWindow subviews]) {
// iOS 4 sticks the UIKeyboard inside a UIPeripheralHostView.
if ([[possibleKeyboard description] hasPrefix:#"<UIPeripheralHostView"]) {
possibleKeyboard = [[possibleKeyboard subviews] objectAtIndex:0];
}
if ([[possibleKeyboard description] hasPrefix:#"<UIKeyboard"]) {
foundKeyboard = possibleKeyboard;
break;
}
}
}
How about using -[UIApplication beginIgnoringInteractionEvents]?
Also, another trick to get the view containing the keyboard is to initialize a dummy view with CGRectZero and set it as the inputAccessoryView of your UITextField or UITextView. Then, get its superview. Still, such shenanigans is private/undocumented, but I've heard of apps doing that and getting accepted anyhow. I mean, how else would Instagram be able to make their comment keyboard interactive (dismiss on swipe) like the Messages keyboard?
I found that developerdoug's answer wasn't working on iOS 7, but by modifying things slightly I managed to get access to what I needed. Here's the code I used:
-(UIView*)findKeyboard
{
UIView *keyboard = nil;
for (UIWindow* window in [UIApplication sharedApplication].windows)
{
for (UIView *possibleKeyboard in window.subviews)
{
if ([[possibleKeyboard description] hasPrefix:#"<UIPeripheralHostView"])
{
keyboard = possibleKeyboard;
break;
}
}
}
return keyboard;
}
From what I could make out, in iOS 7 the keyboard is composed of a UIPeripheralHostView containing two subviews: a UIKBInputBackdropView (which provides the blur effect on whatever's underneath the keyboard) and a UIKeyboardAutomatic (which provides the character keys). Manipulating the UIPeripheralHostView seems to be equivalent to manipulating the entire keyboard.
Discaimer: I have no idea whether Apple will accept an app that uses this technique, nor whether it will still work in future SDKs.
Be aware, Apple has made it clear that applications which modify private view hierarchies without explicit approval beforehand will be rejected. Take a look in the Apple Developer Forums for various developers' experience on the issue.
If you're just trying to disable the keyboard (prevent it from receiving touches), you might try adding a transparent UIView that is the full size of the screen for the current orientation. If you add it as a subview of the main window, it might work. Apple hasn't made any public method of disabling the keyboard that I'm aware of - you might want to use one of your support incidents with Apple, maybe they will let you in on the solution.
For an app I am currently developing I am using a really quick and easy method:
Add this in the header file:
// Add in interface
UIWindow * _window;
// Add as property
#property (strong, nonatomic) IBOutlet UIView * _keyboard;
Then add this code in the bottom of the keyboardWillShow function:
-(void) keyboardWillShow: (NSNotification *) notification {
.... // other keyboard will show code //
_window = [UIApplication sharedApplication].windows.lastObject;
[NSTimer scheduledTimerWithTimeInterval:0.05
target:self
selector:#selector(allocateKeyboard)
userInfo:nil
repeats:NO];
}
This code look for when the keyboard is raised and then allocates the current window. I have then added a timer to allocate the keyboard as there were some issues when allocated immediately.
- (void)allocateKeyboard {
if (!_keyboard) {
if (_window.subviews.count) {
// The keyboard is always the 0th subview
_keyboard = _window.subviews[0];
}
}
}
We now have the keyboard allocated which gives you direct "access" to the keyboard as the question asks.
Hope this helps
Under iOS 8 it appears you have to jump down the chain more than in the past. The following works for me to get the keyboard, although with custom keyboards available and such I wouldn't rely on this working unless you're running in a controlled environment.
- (UIView *)findKeyboard {
for (UIWindow* window in [UIApplication sharedApplication].windows) {
UIView *inputSetContainer = [self viewWithPrefix:#"<UIInputSetContainerView" inView:window];
if (inputSetContainer) {
UIView *inputSetHost = [self viewWithPrefix:#"<UIInputSetHostView" inView:inputSetContainer];
if (inputSetHost) {
UIView *kbinputbackdrop = [self viewWithPrefix:#"<_UIKBCompatInput" inView:inputSetHost];
if (kbinputbackdrop) {
UIView *theKeyboard = [self viewWithPrefix:#"<UIKeyboard" inView:kbinputbackdrop];
return theKeyboard;
}
}
}
}
return nil;
}
- (UIView *)viewWithPrefix:(NSString *)prefix inView:(UIView *)view {
for (UIView *subview in view.subviews) {
if ([[subview description] hasPrefix:prefix]) {
return subview;
}
}
return nil;
}
Does Apple not allow developers to add an icon into a status bar?
I followed code from a book. The code is simple:
#interface UIApplication (extended)
- (void) addStatusBarImageNamed:(NSString *)aName;
- (void) removeStatusBarImageNamed:(NSString *)aName;
#end
- (void)performAction{
if (xxx) {
[[UIApplication sharedApplication]addStatusBarImageNamed:#"Default_EN.png"];
}
else {
[[UIApplication sharedApplication]addStatusBarImageNamed:#"Default_EC.png"];
}
}
But it gives the following feedback :
-addStatusBarImageNamed: is deprecated. Doing nothing.
What can I do?
To my best knowledge, this isn't permitted within the SDK, but there could be the possibilities that they could have some private API to do so but so far they haven't exposed those, I think you are'nt able to add icon in status bar. If someone know please correct me .
In Classes/YourViewController.m, the addStatusBarImageNamed:removeOnExit: method needs to be overwritten with this.
- (void) addStatusBarImageNamed:(NSString*)image removeOnExit: (BOOL) remove {
if(_statusbarimage!=nil && _responds) {
if ([[[NSUserDefaults standardUserDefaults] objectForKey:#"statusBarEnabled"] integerValue] == 1)
[self removeStatusBarImageNamed:_statusbarimage];
statusbarimage=image;
}
if (_responds) {
if ([[[NSUserDefaults standardUserDefaults] objectForKey:#"statusBarEnabled"] integerValue] == 1)
[super addStatusBarImageNamed:image removeOnExit: remove];
}
}
See if it works fine.