Objective-C –Setting network indicator to visible after application is launched - objective-c

Is it possible to set [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES]; in - application:didFinishLaunchingWithOptions:
It doesn't seem to work for me.

It works for me, check if you turn it down at some place later.

Check if it gets turned off as wcrane suggested but also make sure you don't have some other 3rd party library in your project that possibly does that. Also, try calling it after a delay of, say, 0.5s or something. E.g.
[self performSelector:#selector(turnOnNetworkIndicator) withObject:nil afterDelay:0.5]

Related

NSUserNotificationCenter defaultNotificationcenter returns nil

I feel like I am going insane here.
I'm making a little command-line tool to let me know when a Twitch channel I like goes live. So far, everything works. There's only one, small issue: [NSUserNotificationCenter defaultUserNotificationCenter] is consistently returning nil, no matter where I call it in the program. This is a bit of a problem, since I need to be able to send notifications.
After a solid hour of googling, I can't figure out what's going on. Something like [[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:myDelegate] doesn't crash, but I'm pretty sure that's because you can send messages to nil in Obj-C. Similarly, I can do something like [[NSUserNotificationCenter defaultNotificationCenter] deliverNotification: mynote], but nothing is displayed onscreen (and this is with the delegate for [NSUserNotificationCenter defaultUserNotificationCenter] set to return YES for the userNotificationCenter:(NSUserNotificationCenter *)center shouldPresentNotification:(NSUserNotification *)method.)
Additionally, all notifications presented via deliverNotification do not have their delivered property set to YES.
The only thing I can think of is that the usage of NSUserNotificationCenter only works if you're running an NSApplication, but I cannot find that documented anywhere. I'm running a simple command-line tool, which is pretty much a main function, an #autoreleasepool, and some method calls.
Is there anything obvious that can cause [NSUserNotificationCenter defaultUserNotificationCenter] to return nil?
The only thing I can think of is that the usage of NSUserNotificationCenter only works if you're running an NSApplication, but I cannot find that documented anywhere.
I don't think it would be easy to find it explicitly documented somewhere, but if your app is a simple command line tool, i.e., it is not using a NSRunLoop, I doubt that features like notifications can work at all. They intrinsically require your program to have a run loop that sits there waiting for events (e.g., a notification coming in, a click, a touch) and dispatching them to whomever should handle them.
You might try starting and NSRunLoop from you main function, but it would cease to be a simple command-line tool, I guess.

prevent windows from opening (windowless application)

I want to make a windowless application. The problem is that I'm using a framework that shows some alert boxes sometimes, and I'm not able to suppress them (at least not without a crash).
I've set LSBackgroundOnly to 1 (in the info.plist app file), but this doesn't seem to work. Any chance I'm missing something here (maybe some other settings that I need to set)?
I've also tried creating a category for NSWindow:
Overwritten alloc and allocWithZone: so that no window gets created. This works on some situations, but starting a modal session throws exception (because sending a nil parameter to beginModalSessionForWindow:).
Tried overwriting NSApplication's beginModalSessionForWindow: and returned nil everytime, but this leads to EXC_BADACCESS somewhere in the framework (runModalSession: and endModalSession: were also overwritten, but the crash is before any of them being called).
Any other ideas will be welcome.
In case it helps, the framework that I'm using is Twain.Framework, so if instead anyone knows a way to block all UI from twain (this includes error alerts shown when a device is not connected) it would be great if you share.
It's not clear what you're hoping for. Are you hoping for an app that doesn't normally display windows but does allow the third-party framework to show its alerts? Or are you hoping to find a way to prevent the framework from showing its alerts so your app absolutely never has any windows?
If it's the former, you're probably looking for LSUIElement. That's an app which can have some UI elements, but doesn't show in the Dock or the Command-Tab application switcher and doesn't have a menu bar.
I managed to make it 'windowless' (some windows are still shown, but at least they're not visible, and they're automatically closed). I only handled modal windows, since these where shown in my situation.
I made a category for NSWindow, so that all windows are invisible, and can't become key or main windows:
-(BOOL)canBecomeKeyWindow{
[self setOpaque:NO];
self.alphaValue = 0;
return NO;
}
-(BOOL)canBecomeMainWindow{
[self setOpaque:NO];
self.alphaValue = 0;
return NO;
}
Subclassed NSApplication:
-(NSInteger)runModalForWindow:(NSWindow *)aWindow{
return NSCancelButton;
}
-(NSModalSession)beginModalSessionForWindow:(NSWindow *)aWindow{
NSModalSession session = [super beginModalSessionForWindow:aWindow];
[aWindow performSelector:#selector(close) withObject:nil afterDelay:1];
return session;
}
However, this didn't help much. In case of runModalForWindow: everything was good, since the owner of the window received a response. In case of beginModalSessionForWindow: the application got stuck, most probably because the window's owner was waiting for a specific event (e.g. button click) which it never received.

Upgrading app from IOS4 to IOS5

I have an IOS5 app which uses following function
[self.presentingViewController dismissModalViewControllerAnimated:YES];
and who works perfectly on IOS4 but suddenly I discovered that this function doesn't exists on IOS5 so I had to use this other equivalent one
[self.parentViewController dismissModalViewControllerAnimated:YES]
Now I've got the following issue: IOS4 users are not able to install my app due to this non existing function in IOS4 and what is even worse, the app is available on Apple's App Store but is only functional of IOS5 users. Another related issue us that the app suddenly stopped working on iPads equipped with Wifi, those connected to 3G networks operate normal.
Is there anything I missed trying to compile this new app version?
Thanks in advance!
You can check for existence of the property like this:
if([self respondsToSelector:#selector(presentingViewController)])
[self.presentingViewController dismissModalViewControllerAnimated:YES];
else
[self.parentViewController dismissModalViewControllerAnimated:YES];
Code it this way:
if ([self respondsToSelector:#selector(parentViewController)])
[self.parentViewController ...];
else
[self.presentingViewController ...];
(This is uncompiled, untested, etc.)
The point is that you can (and should) test for capabilities, and then act accordingly. In this case, if the iOS5 method is available, use that one. If not, use the old one, which also means its a pre-iOS5 device.
The way to go is twofold:
compiling your app against the latest SDK version, but also set the deployment target to the oldest version that you want to support; this will ensure that the app is listed properly in the App Store;
checking before using any method/feature that is only available on a later version; this will ensure that you app will not crash and can be done by means of conditional compilation, e.g.:
k
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 40000
if ([[UIApplication sharedApplication] respondsToSelector:#selector(beginBackgroundTaskWithExpirationHandler:)])
{
UIBackgroundTaskIdentifier bgTask = [[UIApplication sharedApplication] eginBackgroundTaskWithExpirationHandler:^{}];
// Perform work that should be allowed to continue in background
[[UIApplication sharedApplication] endBackgroundTask:bgTask];
}
#endif
this is quite convoluted if you have to do it in many places. You may have a look at this very good post to learn how to improve upon that example.
I have built a category that add presentingViewController on iOS 4.
(It disables itself on iOS 5.)
It works seamlessly; Just include 2 files.
Please see backward-modal.
I hope this benefits you as much as it does to me; It makes your code more clean!

Why did UIAlertView dismissAnimated: work at all?

I was just trying to dismiss a UIAlertView using the following call:
[serverConnectionClosedAlertView dismissAnimated:YES];
I did some testing and everything worked nicely. When I got back to the Xcode window I saw the warning, "UIAlertView may not respond to '-dismissAnimated'. I looked up the documentation and noticed that this method is indeed not defined on UIAlertView or even UIView. The correct call should have been
[serverConnectionClosedAlertView dismissWithClickedButtonIndex:0 animated:YES];
So, I am wondering
Why did Xcode suggest the original method name (I had pressed ESC to get the list of suggestions and just picked the method above; old Eclipse/Java habit, I guess), and
Why did the code work at all? It actually did dismiss the UIAlertView without any crashes or log entries.
It was in fact called dismissAnimated: in previous versions of the SDK. It has since either been deprecated or made a private API in favor of dismissWithClickedButtonIndex:animated:, but it'll still work if you call it.

Can I disable UIPickerView scroll sound?

I want to disable the annoying clicks that the UIPickerView generates upon scrolling up and down. Is there a way to do this? I want to play short sounds for each item that the picker view lands upon. It gets ruined by the built in sound.
I understand that the picker sounds can be turned off globally by switching off the keyboard sounds in iPhone/iPod settings. But is there a way to programatically do this?
Any help will be much appreciated!
Thanks
I've been struggling with a UIPickerView sound issue, and even though it's only partially relevant to the original question, I'm posting the problem/solution here because this topic keeps coming up in my search results so I think anyone else in the same boat may end up here too…
I needed to initialize a UIPickerView to restore the currently selected row from saved data. Simple, right? In viewDidLoad, just call the selectRow:inComponent:animated method of UIPickerView:
[myPicker selectRow:currentRowIndex inComponent:0 animated:NO];
This works as expected, but has a side effect that it generates a single "click" sound as if the user had scrolled the control. The click sound only occurs when running on a device (not the simulator), and only if the device has iOS 3.x installed (I tested with 3.1.3 and 3.2). This was apparently a bug in iOS that was fixed starting with iOS 4.0. But if you need to target Gen1 iPhone, you're stuck with iOS 3.1.3 where this problem is present.
I discussed the issue with Apple DTS, but they were unable to suggest any workaround other than upgrading to 4.0. I asked if they would make an exception and permit the use of the undocumented setSoundsEnabled mentioned above (which does actually solve the problem). The answer was, "There are no exceptions."
After some additional detective work, I discovered that you can prevent the sound from occurring by temporarily removing the UIPickerView from the superview, call selectRow, then re-add it to the superview. For example, in viewDidLoad:
UIView *superview = [myPicker superview];
[myPicker removeFromSuperview];
[myPicker reloadAllComponents];
[myPicker selectRow:currentRowIndex inComponent:0 animated:NO];
[superview addSubview:myPicker];
This gets rid of the extraneous click sound without using undocumented/private APIs so should pass Apple's approval process.
After using this specific undocumented api for over a year on the App Store Apple finally asked me to remove it from my App. It is very frustrating for audio apps to have that damn click sound. The best advice is to share with users that the picker sound can be disabled globally in the settings application under "Sounds" and setting "Keyboard Clicks" to "Off". I also strongly recommend visiting https://bugreport.apple.com/ and filing a bug for UIPickerView, as it can cause distortion in audio applications when the picker click is played.
they have just rejected an app of mine because the use of undocumented api's...thats one of them.
Someone I know says he got this past the App Store review just last week:
// Hide private API call from Apple static analyzer
SEL sse = NSSelectorFromString([NSString stringWithFormat:#"%#%#%#", #"set",#"Sounds",#"Enabled:"]);
if ([UIPickerView instancesRespondToSelector:sse]) {
IMP sseimp = [UIPickerView instanceMethodForSelector:sse];
sseimp(self.thePicker, sse, NO);
}
There is an undocumented way (I'm actually not sure if it is still available in iphone 3.0) but here it is any way
#import <UIKit/UIKit.h>
#interface SilintUIPickerView: UIPickerView
{ }
- (void) setSoundsEnabled: (BOOL) enabled;
#end
use this subclass instead and call [view setSoundsEnabled: NO]
I'm interested in knowing how it goes in the latest SDK, give it a shot and let us know.
Could this trick work? Someone was able to suppress the camera shutter sound effect by playing an inverted copy of the sound at the same moment: https://stackoverflow.com/a/23758876/214070
Maybe this not the answer for this particular question, but I had a similar problem - set minimumDate for datePicker, and I wanted set it without annoying "click" sound. After some time found very simple solution:
datePickerCustomTime.minimumDate = [[NSDate date] dateByAddingTimeInterval:300]// min time to set = now + 5 min
[datePickerCustomTime setDate:[[NSDate date] dateByAddingTimeInterval:300] animated:NO];
I found small quickie solution for this try below
UIPickerView *pickerView = [[UIPickerView alloc] initWithFrame:CGRectMake(0, yPickerView, VIEW_WIDTH, PICKERVIEW_HEIGHT)];
pickerView.delegate = self;
pickerView.dataSource = self;
pickerView.showsSelectionIndicator = YES;
pickerView.alpha = 0.8f;
pickerView.tag = fieldTag;
[pickerView selectRow:pickerViewSelectedIndex inComponent:0 animated:NO];
set the animated:NO for selectRow: method