I'm still learning iOS , just i finish my first application but i want to add some function when the application running , here I'm using did finish launching with option method in appdelegate , i want to change this code , first check if the user have internet or not if not show uialertView also , if there is no internet i need a function can stop the application like
Alert ( this application need internet and you dont have internet right now pls try later ) and the application will exit .
or also in some case maybe the web service out of work
if possible explain me where i should put the if statement and how i can exit the application
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[[UINavigationBar appearance] setBarTintColor:[UIColor lightGrayColor]];
NSFileManager *fileManger=[NSFileManager defaultManager];
NSError *error;
NSArray *pathsArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString *doumentDirectoryPath=[pathsArray objectAtIndex:0];
NSString *destinationPath= [doumentDirectoryPath stringByAppendingPathComponent:#"istudentDatabase.plist"];
// NSLog(#"plist path %#",destinationPath);
//if Plist not exists will copy new one
if ([fileManger fileExistsAtPath:destinationPath]){
NSLog(#"Settings File exists ");
}else{
// Copy New Plist
NSString *sourcePath=[[[NSBundle mainBundle] resourcePath]stringByAppendingPathComponent:#"istudentDatabase.plist"];
[fileManger copyItemAtPath:sourcePath toPath:destinationPath error:&error];
}
settingsClass * settings =[[settingsClass alloc]init];
NSNumber * userid = [settings loadPlist:[NSString stringWithFormat:#"userid"]];
if ([userid intValue] == 0)
{
//NSLog(#"You Dont Have USerid ");
// Send a synchronous request
NSURLRequest * urlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://fahads-macbook-pro.local/ios/newuser.php"]];
NSURLResponse * response = nil;
NSError * error = nil;
NSData * data = [NSURLConnection sendSynchronousRequest:urlRequest
returningResponse:&response
error:&error];
if (error == nil)
{
NSDictionary * mydata = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
[settings saveNewUserId:[mydata[#"userid"] intValue]];
NSLog(#"%#",mydata[#"userid"]);
}else{
NSLog(#"Error please Check Your Connections ");
}
}else{
NSLog(#"You Have Userid : %#",userid);
}
NSMutableDictionary * itemsPlist = [[NSMutableDictionary alloc]initWithContentsOfFile:destinationPath];
NSLog(#"Items : %#",itemsPlist);
return YES;
}
also if there is no way to exit the application , i have view controller and on this view controller there is push button i want to hide this button from appdelegate with If statement for example if no connection hide the start button and show some hint there is no connection.
thanks advance
Related
I am sending database file successfully between iOS devices with the following code:
-(void) doSendDatabase {
UIView *viewTemp = [[UIView alloc] init];
viewTemp.frame = CGRectMake(0.0f, 0.0f, 300, 300);
NSString *currentDatabaseName;
// This is the full path and file name with ext
currentDatabaseName = [self.databases objectAtIndex:[[mainTableView indexPathForSelectedRow] row]];
NSURL *url = [[NSURL alloc] initFileURLWithPath:currentDatabaseName];
UIActivityViewController * airDrop = [[UIActivityViewController alloc]
initWithActivityItems:#[url]
applicationActivities:nil];
airDrop.popoverPresentationController.sourceView = self.view;
[self presentViewController:airDrop
animated:YES
completion:nil];
[url release];
[airDrop release];
[viewTemp release];}
This code works and the database successfully gets sent from the sending iOS device to the receiving device. However, the databases are stored in the Documents/Inbox folder (by design I suppose). I simply want to move the received database files from the Inbox folder up one level into the Documents folder. From what I'm reading I need to handle this in openURL in the App Delegate - but am not sure how to go about this. Any help would be greatly appreciated.
Thank you.
Ok - here's what I did to resolve the problem.
(1) I created a handleInboxItems method in the App Delegate.
-(bool) handleInboxItems {
bool success = YES;
// Get the DBAccess object
DBAccess *dbAccess = [[DBAccess alloc] init];
// Get the Func object
Func *funcObject = [[Func alloc] init];
NSMutableArray *docDatabases;
// get a list of all database files in the Documents/Inbox folder ans store them in the inboxDatabases array
NSMutableArray *inboxDatabases = [[NSMutableArray alloc] init];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *inboxDirectory = [documentsDirectory stringByAppendingPathComponent:#"Inbox"];
NSDirectoryEnumerator *directoryEnumerator = [[NSFileManager defaultManager] enumeratorAtPath:inboxDirectory];
for (NSString *inboxFileAndPath in directoryEnumerator)
{
//check to see if any of the files in the inbox folder end in the database extension - if so then save it in the inboxDatabases array
if ([[inboxFileAndPath pathExtension] isEqualToString:#“dbext”])
{
[inboxDatabases addObject:[inboxDirectory stringByAppendingPathComponent:inboxFileAndPath]];
}
}
// now go through the inboxDatabases array and copy them from the Documents/Inbox folder to the Documents folder
// loop through all inbox database and see if any of the database names already exist in Documents - if so then we need to tack on a sequential number
for (NSString *inboxDatabaseFileAndPath in inboxDatabases)
{
NSString *inboxDatabaseName = [[inboxDatabaseFileAndPath lastPathComponent] stringByDeletingPathExtension];
// Get the databases array from the DBAccess class (from the Documents folder) - need to get each time since we are moving files in there
docDatabases = [dbAccess getAllDatabases];
// does the inbox database already exist in the documents folder?
NSUInteger arrayIndex = [docDatabases indexOfObject:[funcObject databaseNameToFullPathName:allTrim(inboxDatabaseName)]];
int i = 0;
while (arrayIndex != NSNotFound)
{
++i;
NSString *tempDatabaseName = [NSString stringWithFormat:[inboxDatabaseName stringByAppendingString:#" %d"],i];
// see if the database (with sequential number) already exists
arrayIndex = [docDatabases indexOfObject:[funcObject databaseNameToFullPathName:allTrim(tempDatabaseName)]];
if (arrayIndex == NSNotFound)
{
// it does not exist, we can use this name
inboxDatabaseName = tempDatabaseName;
}
}
// give it full path and extension
NSString *docDatabaseFileAndPathToWrite = [funcObject databaseNameToFullPathName:allTrim(inboxDatabaseName)];
NSError *error;
NSFileManager *fileManager = [NSFileManager defaultManager];
success = [fileManager copyItemAtPath:inboxDatabaseFileAndPath toPath:docDatabaseFileAndPathToWrite error:&error];
if (success)
{
// delete the inbox database file
success = [fileManager removeItemAtPath:inboxDatabaseFileAndPath error:&error];
if (!success)
{
NSAssert1(0,#"Failed to delete inbox database:'%#'.",[error localizedDescription]);
}
}
else
{
NSAssert1(0,#"Failed to copy inbox database to documents folder:'%#'.",[error localizedDescription]);
}
}
[dbAccess release];
[funcObject release];
[inboxDatabases release];
return success;}
(2) Added a call to this new method in the didFinishLaunchingWithOptions in the App Delegate just in case there is anything stuck in the inbox upon startup.
(3) I added the openURL method to the App Delegate in order to call handleInboxItems. After done, I send a notification so that I can refresh my database list.
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation{
bool success = [self handleInboxItems];
if (success)
[[NSNotificationCenter defaultCenter] postNotificationName:NOTIF_DATABASE_AIRDROPPED object:self];
return success;}
That's it - works as I need it to.
I'm loading font's remotely by making a url request, creating a CGFontRef from data, and registering it with CTFontManagerRegisterGraphicsFont. If I use the same data and call CTFontManagerCreateFontDescriptorFromData I can get the font name.
If I register for the notification and then try to get the name, I'm not having any luck. I get back that the URL doesn't exist. If I loop through the [UIFont familyNames] I see that it exists, the problem is having prior knowledge to what I'm loading. Can this be done without creating my own notifications or alternative to pass the name around?
lldb: po note
__CFNotification 0xFFFFFFFFFFFF {name = CTFontManagerFontChangedNotification; userInfo = {
CTFontManagerAvailableFontURLsAdded = (
"file://..."
);
}}
- (void)noteHandler:(NSNotification *)note{
NSDictionary *userInfo = [note userInfo];
NSURL *fileURL = (NSURL *)([userInfo objectForKey:#"CTFontManagerAvailableFontURLsAdded"][0]);
CFErrorRef error;
Boolean reachable = CFURLResourceIsReachable((__bridge CFURLRef)(fileURL), &error);
// error says file does not exist.
CFArrayRef descriptors = CTFontManagerCreateFontDescriptorsFromURL((__bridge CFURLRef)(fileURL));
// null
}
I was able to fix this. It's common on stack overflow to talk about using CGDataProviderRef, CGFontCreateWithDataProvider and then registering with CTFontManagerRegisterGraphicsFont. The problem is that the notification doesn't give you a valid URL that you can use for the URL calls within CoreText api's.
The better way to load the font is by writing to a tmp url first, then registering that url. Then the notification passes the tmp url along.
Here's the full example..
NSURL *remoteLocation;
NSData *remoteContent;
...
NSString *path = [NSTemporaryDirectory() stringByAppendingPathComponent:[url.pathComponents componentsJoinedByString:#""]];
NSURL *fileURL = [NSURL fileURLWithPath:path];
NSError *error = nil;
if ([inData writeToURL:fileURL options:NSDataWritingAtomic error:&error]) {
CFErrorRef cferror;
if (CTFontManagerRegisterFontsForURL((__bridge CFURLRef)fileURL, kCTFontManagerScopeProcess, &cferror)) {
// You take it from here..
}
}
Now in the notification assuming all goes well..
[theNoteCenter addObserver:self
selector:#selector(registeredFontChange:)
name:(NSString *)kCTFontManagerRegisteredFontsChangedNotification
object:nil];
- (void)registeredFontChange:(NSNotification *)note {
NSDictionary *userInfo = [note userInfo];
CFURLRef fileURL = (__bridge CFURLRef)([userInfo objectForKey:#"CTFontManagerAvailableFontURLsAdded"][0]);
CFArrayRef allDescriptors = CTFontManagerCreateFontDescriptorsFromURL(fileURL);
// I only happen to get a single descriptor
CTFontDescriptorRef descriptor = CFArrayGetValueAtIndex(allDescriptors, 0);
CFStringRef name = CTFontDescriptorCopyAttribute(descriptor, kCTFontNameAttribute);
// Now you can use this font [UIFont fontWithName:... size:...]
}
I'm doing a shop part for iOS application which has two page (first page for show list of voicePack in shop and second page for show detail of voice inside of voicePack).
when click on any cell in the voicePackList go to next page and in next page exists one button with name : DOWNLOAD that I want when I click on that button the voice downloaded and saved in document folder. this is the code that I made inside the button pressed processing:
- (void)downloadingVoice {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(#"Starting Download ...");
NSString *downloadUrl = #"10.3.1.228:9000/files";
NSURL *url = [NSURL URLWithString:downloadUrl];
NSData *urlData = [NSData dataWithContentsOfURL:url];
if (urlData) {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *voiceDirectory = [paths objectAtIndex:0];
NSString *voicePaths = [NSString stringWithFormat:#"%#%#", voiceDirectory,#"voice.mp3"];
dispatch_async(dispatch_get_main_queue(), ^{
[urlData writeToFile:voicePaths atomically:YES];
NSLog(#"Saved voice files");
});
}
});
}
- (void)btnDownloadClicked:(id)sender {
NSLog(#"Downloading Voice . . .");
[self downloadingVoice];
}
and here are how I put the button below the list of voices:
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
return 60.0f;
}
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
// if(tableView == self.shopTableView) {
UIView *footerView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 320, 40)];
UIButton *download = [UIButton buttonWithType:UIButtonTypeCustom];
[download setTitle:#"Download" forState:UIControlStateNormal];
[download addTarget:self action:#selector(btnDownloadClicked:) forControlEvents:UIControlEventTouchUpInside];
[download setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
download.frame = CGRectMake(0, 0, 130, 30);
[footerView addSubview:download];
return footerView;
}
when I click the button and put some breakpoints, it's end after if (urlData) when I check the urlData and downloadUrl, it says:
2015-09-17 10:53:01.926 Selfie[87197:674517] Starting Download ...
(lldb) po urlData
error: Couldn't materialize: couldn't get the value of variable urlData: no location, value may have been optimized out
Errored out in Execute, couldn't PrepareToExecuteJITExpression
(lldb) po downloadUrl
error: Couldn't materialize: couldn't get the value of variable downloadUrl: variable not available
Errored out in Execute, couldn't PrepareToExecuteJITExpression
anyone please help me to solve this.. I'll be really thank you for your help..
First of all, you are fetching voice data synchronously which is not advisable as this hangs your main thread. You can use your main thread to show the loading overlay and allow user to cancel the download operation if it is taking too much of time. Please use below method to make an Asynchronous call rather.
Secondly, can you please ensure the URL you are pointing to is open on the network you are trying to access the files. If this is a local server, better put localhost rather than IP address.
- (void)fetchFilesAsynchronously {
NSURL *myUrl = [NSURL URLWithString:#"http://10.3.1.228:9000/files"];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:myUrl cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:30.0];
// Add headers as per your need
[urlRequest setValue:#"value" forHTTPHeaderField:#"key"];
// Add body as per your need
NSDictionary *body = #{#"key" : #"value"};
NSData *requestBodyData = [NSJSONSerialization dataWithJSONObject:body options:NSJSONWritingPrettyPrinted error:nil];
[urlRequest setHTTPBody:requestBodyData];
[NSURLConnection sendAsynchronousRequest:urlRequest queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *iResponse, NSData *iData, NSError *iConnectionError) {
// Handle response here
}];
}
Third, for your debugger issue, please take a look at this thread.
I'm developing an app extension for open mode for my document management application. I have already implemented the import mode which is working fine. But in the open mode , when a third party application tries to open any documents from my storage provider, the following methods of file provider is executing multiple times,kind of an inifinite execution and in turn resulting in a memory warning exception.
- (instancetype)init
- (void)startProvidingItemAtURL:(NSURL *)url completionHandler:(void (^)(NSError *))completionHandler
And also for your reference the complete code fo file provider as follows
- (NSFileCoordinator *)fileCoordinator {
NSFileCoordinator *fileCoordinator = [[NSFileCoordinator alloc] init];
[fileCoordinator setPurposeIdentifier:[self providerIdentifier]];
return fileCoordinator;
}
- (instancetype)init {
self = [super init];
if (self) {
[self.fileCoordinator coordinateWritingItemAtURL:[self documentStorageURL] options:0 error:nil byAccessor:^(NSURL *newURL) {
// ensure the documentStorageURL actually exists
NSError *error = nil;
[[NSFileManager defaultManager] createDirectoryAtURL:newURL withIntermediateDirectories:YES attributes:nil error:&error];
}];
}
return self;
}
- (void)providePlaceholderAtURL:(NSURL *)url completionHandler:(void (^)(NSError *error))completionHandler {
// Should call + writePlaceholderAtURL:withMetadata:error: with the placeholder URL, then call the completion handler with the error if applicable.
NSString* fileName = [url lastPathComponent];
NSURL *placeholderURL = [NSFileProviderExtension placeholderURLForURL:[self.documentStorageURL URLByAppendingPathComponent:fileName]];
NSUInteger fileSize = 0;
// TODO: get file size for file at <url> from model
[self.fileCoordinator coordinateWritingItemAtURL:placeholderURL options:0 error:NULL byAccessor:^(NSURL *newURL) {
NSDictionary* metadata = #{ NSURLFileSizeKey : #(fileSize)};
[NSFileProviderExtension writePlaceholderAtURL:placeholderURL withMetadata:metadata error:NULL];
}];
if (completionHandler) {
completionHandler(nil);
}
}
- (void)startProvidingItemAtURL:(NSURL *)url completionHandler:(void (^)(NSError *))completionHandler {
// Should ensure that the actual file is in the position returned by URLForItemWithIdentifier:, then call the completion handler
NSError* error = nil;
__block NSError* fileError = nil;
//getting the actual fiile from the shared container
NSURL *storeURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:#"group.company.test.NBox"];
storeURL = [storeURL URLByAppendingPathComponent:[url.path lastPathComponent]];
NSData* fileData = [NSData dataWithContentsOfFile:[storeURL path]];
// TODO: get the contents of file at <url> from model
//Writing the file data to the documentStorage location
//[self.fileCoordinator coordinateWritingItemAtURL:url options:0 error:&error byAccessor:^(NSURL *newURL) {
[fileData writeToURL:url options:0 error:&fileError];
//}];
if (error!=nil) {
completionHandler(error);
} else {
completionHandler(fileError);
}
}
- (void)itemChangedAtURL:(NSURL *)url {
// Called at some point after the file has changed; the provider may then trigger an upload
// TODO: mark file at <url> as needing an update in the model; kick off update process
NSLog(#"Item changed at URL %#", url);
}
- (void)stopProvidingItemAtURL:(NSURL *)url {
// Called after the last claim to the file has been released. At this point, it is safe for the file provider to remove the content file.
// Care should be taken that the corresponding placeholder file stays behind after the content file has been deleted.
[self.fileCoordinator coordinateWritingItemAtURL:url options:NSFileCoordinatorWritingForDeleting error:NULL byAccessor:^(NSURL *newURL) {
[[NSFileManager defaultManager] removeItemAtURL:newURL error:NULL];
}];
[self providePlaceholderAtURL:url completionHandler:NULL];
}
Thanks,
Vsh
I'm also trying to develop an app extension for open mode. I haven't been successful yet but I don't get the infinite execution. Looking at your code, it's possible that storeURL in startProvidingItemAtURL: points to something inside your container. If so, then the assignment to fileData would trigger an infinite recursion.
As a test, try setting fileData with a test message like this:
NSString *message = [NSString stringWithFormat:#"This is a test."];
NSData *fileData = [NSKeyedArchiver archivedDataWithRootObject:message];
If that works, then it's a problem with storeURL and you'll have to figure out some different location to get the data.
(Incidentally, I noticed that you commented out the file coordinator in startProvidingItemAtURL:. I also ended up doing that to prevent deadlocks and because there's a note in the documentation that says "Do not use file coordination inside this method." But it's very confusing because the template code for file providers puts the file coordinator in that method!)
I'm experiencing a problem with my login system in my app.
When the app first opens, FVC is the main view controller. FVC then checks if I am logged in/if my session key is still valid, and if not, then it makes the LoginViewController pop up over my entire screen, forcing me to login to continue. Once I login with my right username and password, it checks quickly with a JSON file on the web and if it returns no error, it returns a session key. The problem is, I know it is correctly getting the JSON file and parsing it as I did some tests with NSLog but as soon as I login with the correct info, it dismisses the loginView and for half a second, shows the main view, then the loginView pops right back up! Something isn't right and I hope you can find the problem with my code. Michael.
First view controller:
- (void)viewDidAppear:(BOOL)animated
{
//Put login check here.
LoginViewController *login = [self.storyboard instantiateViewControllerWithIdentifier:#"login"];
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
// create the URL we'd like to query
[[NSURLCache sharedURLCache] removeAllCachedResponses];
myURL = [[NSURL alloc]initWithString:[NSString stringWithFormat:#"%#%#", #"https://URL/v1/?get&action=getservers&session_key=", login.sessionKey]];
// we'll receive raw data so we'll create an NSData Object with it
NSData *myData = [[NSData alloc]initWithContentsOfURL:myURL];
// now we'll parse our data using NSJSONSerialization
id myJSON = [NSJSONSerialization JSONObjectWithData:myData options:NSJSONReadingMutableContainers error:nil];
// typecast an array and list its contents
NSDictionary *jsonArray = (NSDictionary *)myJSON;
NSLog(#"%#",[jsonArray objectForKey:#"status"]);
if ([[jsonArray objectForKey:#"status"] isEqualToString:#"ERROR"]) {
[self presentViewController:login animated:NO completion:nil];
}
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}
Login view controller:
- (IBAction)loginAction:(id)sender {
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
// create the URL we'd like to query
NSURL *myURL = [[NSURL alloc]initWithString:[NSString stringWithFormat:#"%#%#%#%#", #"https://URL/v1/?get&action=login&username=", usernameField.text, #"&password=", passwordField.text]];
// we'll receive raw data so we'll create an NSData Object with it
NSData *myData = [[NSData alloc]initWithContentsOfURL:myURL];
// now we'll parse our data using NSJSONSerialization
id myJSON = [NSJSONSerialization JSONObjectWithData:myData options:NSJSONReadingMutableContainers error:nil];
// typecast an array and list its contents
//NSArray *jsonArray = (NSArray *)myJSON;
NSDictionary *jsonArray = (NSDictionary *)myJSON;
NSLog(#"%#",[jsonArray objectForKey:#"status"]);
if ([[jsonArray objectForKey:#"status"] isEqualToString:#"OK"]) {
FirstViewController *dashView = [self.storyboard instantiateViewControllerWithIdentifier:#"dashView"];
sessionKey = [jsonArray objectForKey:#"new_session_key"];
NSLog(#"%#",sessionKey);
[self dismissViewControllerAnimated:YES completion:nil];
} else {
}
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}
I think the problem is the login.sessionKey. Do NSLog on it. It is probably nil. I don't see where you are setting it. That's probably you get an error from your webservice. Check it out.