Jump to content

LelandLong

Moderators
  • Content Count

    77
  • Joined

  • Last visited

Community Reputation

0 Neutral

About LelandLong

  • Rank
    developer

Profile Information

  • Title
    Senior Developer
  • Industry
    Flooring
  • Gender
    Male
  • Location
    Charleston, SC

Contact Methods

  • Website URL
    http://www.kellerinteriors.com

FileMaker Experience

  • Skill Level
    Expert
  • FM Application
    18

Platform Environment

  • OS Platform
    Mac
  • OS Version
    Mojave

FileMaker Partner

  • Certification
    Not Certified
  • Membership
    FileMaker TechNet

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. Adding Preferences (via the iOS Settings App) to a FIAS project How to create and utilize native iOS Preferences functionality (in the Apple-provided Settings App) and share those preferences with the FIAS solution database, using the AppDelegate in a FileMaker iOS App SDK (FIAS) project (v18). What You'll Learn How to add native App Settings functionality to a FIAS project in Xcode. How to share/pass the App Settings data with the FIAS solution database. What This Post Is Not A tutorial on FIAS A tutorial on Xcode A tutorial on Objective-C Requirements iOS App SDK 18+ (not tested on v17, but may work just fine) Xcode 10+ What We're Going To Do Add an Objective-C App Delegate class Verify the App Delegate class Implement App Delegate Methods to communicate with FileMaker database Add a 'Settings bundle' file that defines the preferences to display Verify the Settings data is accessible by the App Delegate Verify the Settings data can be shared with a FileMaker script Your FIAS Project Either open up and existing FIAS project or create a new one. Make sure you can build it and run it, either in the iOS Simulator or on your own device. Xcode: Add an Objective-C App Delegate class Bring up your existing App Delegate class in the Xcode editor or create a New File, using the file type 'Objective-C File' as the document type. Be sure to save this new file into your existing 'Custom Application Resources' directory. Note: If you are adding this App Delegate class to your project for the first time, be sure to follow the instructions in the iOS SDK Documentation for modifying the 'configFile.txt' file so that applicationDelegateClass = MyAppDelegate Use the following code in your App Delegate file as a starting point. #import <Foundation/Foundation.h> #import <UIKit/UIKit.h> #import "FMX_Exports.h" #define kUserNameKey @"username_preference" #define kPasswordKey @"password_preference" #define kDatasourceKey @"datasource_preference" @interface MyAppDelegate : UIResponder <UIApplicationDelegate> { } @property (strong, nonatomic) UIWindow *window; @end @implementation MyAppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSLog(@"MyAppDelegate: %s", __func__); return true; } @end Verify the App Delegate Class Build the project (Command-B). You shouldn't have any errors. Run the project (Command-R). When it runs the console should display the NSLog string from inside the function 'didFinishLaunchingWithOptions': MyAppDelegate: -[MyAppDelegate application:didFinishLaunchingWithOptions:] Note: to show the Console, type Command + Shift + c FileMaker: Create a FileMaker Script Open your FIAS database locally in FileMaker Pro. Create a new Script, using any naming convention you wish. For the following examples we will use the script name 'AppDelegate_didFinishLaunchingWithOptions'. #======================================== # Purpose: FIAS AppDelegate - triggered by delegate method # Returns: none # Parameters: scriptParameter (optional) # iOS variables (optional) # Called from: (FIAS) didFinishLaunchingWithOptions # Author: Leland Long # Notes: none # History: 2019-07-29 Leland Long - created #======================================== Allow User Abort [ Off ] Set Error Capture [ On ] Set Variable [ $param; Value:Get ( ScriptParameter ) ] Show Custom Dialog [ Title: "AppDelegate"; Message: "Script triggered in db: " & Get ( ScriptName ) & "¶" & "Param: " & $param; Default Button: "Excellent", Commit: “Yes” ] Close the database in FileMaker Pro and return to Xcode. Xcode: Trigger the FileMaker Script in your FIAS project Modify your existing AppDelegate file to match the following, replacing with the actual name of your database filename, not including the extension '.fmp12': - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSLog(@"MyAppDelegate: %s", __func__); if (FMX_Queue_Script(@"<myFMdbName>", @"AppDelegate_didFinishLaunchingWithOptions", kFMXT_Pause, @"A script param from Xcode", nil)) { NSLog(@"MyAppDelegate: FMX_Queue_Script AppDelegate_didFinishLaunchingWithOptions Succeeded"); } else { NSLog(@"MyAppDelegate: FMX_Queue_Script AppDelegate_didFinishLaunchingWithOptions Failed"); } return true; } Build and run the project. When it runs the console should display the 2 NSLog entries from inside the function 'didFinishLaunchingWithOptions': MyAppDelegate: -[MyAppDelegate application:didFinishLaunchingWithOptions:] MyAppDelegate: FMX_Queue_Script appDelegate_didFinishLaunchingWithOptions Failed Notice: the script failed to be triggered. How? What? Why? Create a NSTimer Class Object To Fix Our Script Issue I won't pretend to know the answer as to why this failed, but I can provide an educated guess. The FileMaker framework handles all of the UIWindow, UIViewController, and UIView pieces and parts. This all takes time. My assumption is that when this function is triggered in our AppDelegate, the FileMaker database is not yet quite ready to receive and run our script request, so it quietly fails. Going on this assumption, I decided to play around with adding a slight delay in our code to see if that might solve this dilemma. It does solve it, but is not the best solution. The reason I mention this is because you will notice slight differences with the length of delay required to successfully fire off this script request, between trying this solution on the iOS Simulator and actual iOS devices (iPhones and iPads). But let's give it a try to see what your experience is in your environment. Modify your existing AppDelegate methods to match the following: - (void)triggerScript_didFinishLaunchingWithOptions:(NSTimer *)timer { NSLog(@"MyAppDelegate: %s", __func__); if (FMX_Queue_Script(@"<myFMdbName>", @"AppDelegate_didFinishLaunchingWithOptions", kFMXT_Pause, @"A script param from Xcode", nil)) { NSLog(@"MyAppDelegate: FMX_Queue_Script AppDelegate_didFinishLaunchingWithOptions Succeeded"); } else { NSLog(@"MyAppDelegate: FMX_Queue_Script AppDelegate_didFinishLaunchingWithOptions Failed"); } } - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSLog(@"MyAppDelegate: %s", __func__); NSLog(@"didFinishLaunchingWithOptions: creating a timer to launch script 'AppDelegate_didFinishLaunchingWithOptions'"); // FIAS needs a little time to begin responding to script requests, so add a slight delay // simulator is fairly quick (2 seconds works fine) but iOS device seems to take longer, at least with debugger, needing 10 seconds [NSTimer scheduledTimerWithTimeInterval: 2.0 target: self selector: @selector(triggerScript_didFinishLaunchingWithOptions:) userInfo: nil repeats: NO]; return true; } Build and run the project. When it runs the console should display the 2 NSLog entries from inside the function 'didFinishLaunchingWithOptions': If it runs successfully you will see the success message in the Console and you will also see the Custom Dialog appear in your App, that you added previously in your Script. You should also see that your Script Parameter was successfully passed to the Script. didFinishLaunching script If it still did not trigger successfully, try increasing the TimeInterval value from 2.0 to 4.0, or 6.0, or whatever you want to try , in order to determine the sweet spot of a small enough value to work every time. My own experience has resulted in a 2.0 second delay for the Simulator and a 10.0 second delay in my iPhone XSMax running on iOS v13 beta. If it still does not trigger, or if the Console shows that it triggered successfully, but your App does not present the expected Custom Dialog, be sure to refer back to the iOS SDK installation instructions regarding copying the solution file (database) into the iOS project. This is a setting you can adjust in the configFile.txt file. During development I would recommend selecting always so that it copies the database every time you run the project. Xcode: Optional Additional AppDelegate Script Trigger Methods All of the following code is optional. You can pick and choose which ones to add to your project. Most, if not all of these, will not need a NSTimer delay in order to successfully trigger a FileMaker Script to be run. I would highly recommend having each and every additional FileMaker Script that you add for any of these methods to contain a ShowCustomDialogscript step so that you can get a feel for how each of these methods actually perform while the User is using your App. For instance, the method didChangeStatusBarOrientation seems to be triggered twice in succession for every single time it is triggered by the OS. This is the type of scenario you need to be aware of ahead of time while you develop your project, so that you can plan your process flow accordingly. - (void)applicationDidBecomeActive:(UIApplication *)application { NSLog(@"MyAppDelegate: %s", __func__); if (FMX_Queue_Script(@"<myFMdbName>", @"appDelegate_applicationDidBecomeActive", kFMXT_Pause, @"A script param", nil)) { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_applicationDidBecomeActive Succeeded"); } else { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_applicationDidBecomeActive Failed"); } } - (void)completedReturnToForegroundActive { NSLog(@"MyAppDelegate: %s", __func__); if (FMX_Queue_Script(@"<myFMdbName>", @"appDelegate_completedReturnToForegroundActive", kFMXT_Pause, @"A script param", nil)) { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_completedReturnToForegroundActive Succeeded"); } else { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_completedReturnToForegroundActive Failed"); } } - (void)applicationWillTerminate:(UIApplication *)application { NSLog(@"MyAppDelegate: %s", __func__); if (FMX_Queue_Script(@"<myFMdbName>", @"appDelegate_applicationWillTerminate", kFMXT_Pause, @"A script param", nil)) { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_applicationWillTerminate Succeeded"); } else { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_applicationWillTerminate Failed"); } } - (void)applicationWillResignActive:(UIApplication *)application { NSLog(@"MyAppDelegate: %s", __func__); if (FMX_Queue_Script(@"<myFMdbName>", @"appDelegate_applicationWillResignActive", kFMXT_Pause, @"A script param", nil)) { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_applicationWillResignActive Succeeded"); } else { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_applicationWillResignActive Failed"); } } - (void)applicationDidEnterBackground:(UIApplication *)application { NSLog(@"MyAppDelegate: %s", __func__); if (FMX_Queue_Script(@"<myFMdbName>", @"appDelegate_applicationDidEnterBackground", kFMXT_Pause, @"A script param", nil)) { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_applicationDidEnterBackground Succeeded"); } else { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_applicationDidEnterBackground Failed"); } } - (void)applicationWillEnterForeground:(UIApplication *)application { NSLog(@"MyAppDelegate: %s", __func__); if (FMX_Queue_Script(@"<myFMdbName>", @"appDelegate_applicationWillEnterForeground", kFMXT_Pause, @"A script param", nil)) { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_applicationWillEnterForeground Succeeded"); } else { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_applicationWillEnterForeground Failed"); } } - (void)applicationSignificantTimeChange:(UIApplication *)application { NSLog(@"MyAppDelegate: %s", __func__); if (FMX_Queue_Script(@"<myFMdbName>", @"appDelegate_applicationSignificantTimeChange", kFMXT_Pause, @"A script param", nil)) { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_applicationSignificantTimeChange Succeeded"); } else { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_applicationSignificantTimeChange Failed"); } } - (void)applicationDidReceiveMemoryWarning:(UIApplication *)application { NSLog(@"MyAppDelegate: %s", __func__); if (FMX_Queue_Script(@"<myFMdbName>", @"appDelegate_applicationDidReceiveMemoryWarning", kFMXT_Pause, @"A script param", nil)) { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_applicationDidReceiveMemoryWarning Succeeded"); } else { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_applicationDidReceiveMemoryWarning Failed"); } } - (void)application:(UIApplication *)application didChangeStatusBarOrientation: (UIInterfaceOrientation)oldStatusBarOrientation { // seems to trigger twice every time NSLog(@"MyAppDelegate: %s Calling FMX_Queue_Script appDelegate_didChangeStatusBarOrientation", __func__); if (FMX_Queue_Script(@"<myFMdbName>", @"appDelegate_didChangeStatusBarOrientation", kFMXT_Pause, @"A script param", nil)) { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_didChangeStatusBarOrientation Succeeded"); } else { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_didChangeStatusBarOrientation Failed"); } } Passing Multiple Script Parameters Sometimes you want to pass multiple script parameters to a script, and the SDK has a very nice and easy process for doing so. Modify your existing AppDelegate methods to match the following: - (void)triggerScript_didFinishLaunchingWithOptions:(NSTimer *)timer { NSLog(@"MyAppDelegate: %s", __func__); NSDictionary<NSString *, NSString *> *variables = @ { @"$a": @"Value of $a", @"$z": @"Value of $z" }; if (FMX_Queue_Script(@"<myFMdbName>", @"appDelegate_didFinishLaunchingWithOptions", kFMXT_Pause, @"ima script param", variables)) { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_didFinishLaunchingWithOptions Succeeded"); } else { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_didFinishLaunchingWithOptions Failed"); } } - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSLog(@"MyAppDelegate: %s Calling FMX_Queue_Script appDelegate_didFinishLaunchingWithOptions", __func__); // FIAS needs a little time to begin responding to script requests, so add a slight delay [NSTimer scheduledTimerWithTimeInterval: 10.0 target: self selector: @selector(triggerScript_didFinishLaunchingWithOptions:) userInfo: nil repeats: NO]; return true; } Now modify your existing FileMaker Script AppDelegate_didFinishLaunchingWithOptions to match the following: #======================================== # Purpose: FIAS AppDelegate - triggered by delegate method # Returns: none # Parameters: scriptParameter (optional) # iOS variables (optional) # Called from: (FIAS) didFinishLaunchingWithOptions # Author: Leland Long # Notes: none # History: 2019-07-29 Leland Long - created #======================================== Allow User Abort [ Off ] Set Error Capture [ On ] Set Variable [ $param; Value:Get ( ScriptParameter ) ] Show Custom Dialog [ Title: "AppDelegate"; Message: "Script triggered in db: " & Get ( ScriptName ) & "¶" & "Param: " & $param & "¶" & "sdk_$a: " & $a & "¶" & "sdk_$z: " & $z Default Button: "Excellent", Commit: “Yes” ] Build and run the project. When it runs you should see a Custom Dialog confirming that these 2 variables were successfully passed into your Script. I have not tested this, but this code snippet leads me to believe that many multiple parameters can be passed into a FileMaker Script by simply following the code structure and syntax of the NSDictionary object we just added. I have no idea how many or what limits there are, but I would suppose that you would be able to pass in just about whatever you desire to pass in and it would just work. As an example, here would be the adjustment to that NSDictionary code in order to pass in 4 additional parameters, instead of the 2 we passed earlier: NSDictionary<NSString *, NSString *> *variables = @ { @"$a": @"Value of $a", @"$z": @"Value of $z", @"$anotherCoolScriptParameter": @"$1,234,567.99", @"$dontForgetAboutMeParameter": @"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc tincidunt hendrerit tellus, id vestibulum odio venenatis et. Integer arcu est, efficitur sed cursus vitae, efficitur quis nisl." }; The iOS Settings App First off, here is a quote from Apple's Human Interface Guidelines, regarding the Settings App and it's intended purpose: So, with that in mind, let us create a file (called Settings.bundle) that will be automatically installed by Xcode, that will generate our own custom settings into the Settings.app. Then later we will add code to interact with the data our Users will enter into the Settings.app. Create a New File from the File menu, select Settings Bundle from the iOS Resource section, leave the default filename as Settings.bundle, and be sure to select Custom Application Resources in the Group drop-down menu of your project. Look for your newly created file in the left pane of Xcode (Project navigator) and click the disclosure arrow on the left side of the filename to expand it's contents. You should see 2 items: a folder titled en.lproj and a file named Root.plist. Right-click on the file Root.plist and select OpenAs->SourceCode. Note: once you have created this file using the XML Source Code editor, you can go back and look at this same code in the Property List editor. It can be a bit tricky adding these various fields, dividers, sections, etc. in the Property List editor, so in this guide I will just have you copy and paste the complete code block in the easier Source Code editor. Replace the code with the following: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>PreferenceSpecifiers</key> <array> <dict> <key>Title</key> <string>Access Credientials</string> <key>Type</key> <string>PSGroupSpecifier</string> </dict> <dict> <key>Type</key> <string>PSTextFieldSpecifier</string> <key>Title</key> <string>UserName</string> <key>Key</key> <string>username_preference</string> <key>KeyboardType</key> <string>Alphabet</string> <key>IsSecure</key> <false/> <key>AutocorrectionType</key> <string>No</string> <key>AutocapitalizationType</key> <string>None</string> </dict> <dict> <key>Type</key> <string>PSTextFieldSpecifier</string> <key>Title</key> <string>Password</string> <key>Key</key> <string>password_preference</string> <key>IsSecure</key> <false/> <key>AutocorrectionType</key> <string>No</string> <key>AutocapitalizationType</key> <string>None</string> </dict> <dict> <key>Type</key> <string>PSGroupSpecifier</string> <key>Title</key> <string>Datasource</string> </dict> <dict> <key>Type</key> <string>PSTextFieldSpecifier</string> <key>Title</key> <string>URL</string> <key>Key</key> <string>datasource_preference</string> <key>KeyboardType</key> <string>Alphabet</string> <key>IsSecure</key> <false/> <key>AutocorrectionType</key> <string>No</string> <key>AutocapitalizationType</key> <string>None</string> </dict> </array> <key>StringsTable</key> <string>Root</string> </dict> </plist> Run the Project. Nothing will look different at this stage. Now Quit the App, either in the Simulator or on the device. Find the Settings.app and Open it. Scroll down to the bottom of the list of Settings, and you should now see your App listed. Tap on your App. Custom App Settings And look at that, several fields for you to enter Settings, or Preferences, or whatever you wish to have the User enter in this Settings.app. Now if you go back to Xcode and look at the Root.plist file using the Property List editor, and expand all the disclosure arrows, you should see the required format for creating whatever fields you desire to use. The field option that is key to Xcode being able to communicate with these fields is labeled Identifier. Whatever you enter into this Identifierfield is the name of the variable you will use to pass the user-entered data into your code, and eventually into FileMaker as a parameter. Settings.bundle Root.plist Extracting the Settings.app User Data Into Xcode AppDelegate Modify your existing AppDelegate code (the interface section near the top of the file) to match the following: @interface MyAppDelegate : UIResponder <UIApplicationDelegate> { NSString *settingsUsername; NSString *settingsPassword; NSString *settingsDatasource; } @property (strong, nonatomic) UIWindow *window; @end Then modify your existing triggerScript_didFinishLaunchingWithOptions method to match the following: - (void)triggerScript_didFinishLaunchingWithOptions:(NSTimer *)timer { NSLog(@"MyAppDelegate: %s", __func__); if (settingsUsername == nil) { settingsUsername = @""; } if (settingsPassword == nil) { settingsPassword = @""; } if (settingsDatasource == nil) { settingsDatasource = @"<invalid>"; } NSDictionary<NSString *, NSString *> *variables = @ { @"$username": settingsUsername, @"$password": settingsPassword }; if (FMX_Queue_Script(@"<myFMdbName>", @"appDelegate_didFinishLaunchingWithOptions", kFMXT_Pause, settingsDatasource, variables)) { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_didFinishLaunchingWithOptions Succeeded"); } else { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_didFinishLaunchingWithOptions Failed"); } } Now modify your didFinishLaunchingWithOptions method to match the following: - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSLog(@"MyAppDelegate: %s", __func__); // FIAS needs a little time to begin responding to script requests, so add a slight delay [NSTimer scheduledTimerWithTimeInterval: 10.0 target: self selector: @selector(triggerScript_didFinishLaunchingWithOptions:) userInfo: nil repeats: NO]; // Pulling data from Settings NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; settingsUsername = [defaults objectForKey:kUserNameKey]; settingsPassword = [defaults objectForKey:kPasswordKey]; settingsDatasource = [defaults objectForKey:kDatasourceKey]; NSLog(@"MyAppDelegate - standardUserDefaults - username: %@", settingsUsername); NSLog(@"MyAppDelegate - standardUserDefaults - password: %@", settingsPassword); NSLog(@"MyAppDelegate - standardUserDefaults - datasource: %@", settingsDatasource); return true; } Then modify your FileMaker Script AppDelegate_didFinishLaunchingWithOptions to match the following: #======================================== # Purpose: FIAS AppDelegate - triggered by delegate method # Returns: none # Parameters: scriptParameter (optional) # iOS variables (optional) # Called from: (FIAS) didFinishLaunchingWithOptions # Author: Leland Long # Notes: none # History: 2019-07-29 Leland Long - created #======================================== Allow User Abort [ Off ] Set Error Capture [ On ] Set Variable [ $param; Value:Get ( ScriptParameter ) ] Show Custom Dialog [ Title: "AppDelegate"; Message: "Script triggered in db: " & Get ( ScriptName ) & "¶" & "Param: " & $param & "¶" & "sdk_$username: " & $username & "¶" & "sdk_$password: " & $password Default Button: "Excellent", Commit: “Yes” ] Before running your app, go back into the Settings.app and enter in some random values into those 3 fields so that they are not blank. Then close the Settings.app and return to Xcode. Now Run your project. If all went well you should have seen the user-entered Settings values show up in the Console and inside the Custom Dialog in the App itself. Conclusion You now should have completed what we set out to do. There are several ways you can customize these examples to match what you would like to do in your own app. Hopefully this has been a helpful and in-depth guide on putting the AppDelegate to work for you in a useful and meaningful way. Happy FileMaking. Further Reading You can read more about the various AppDelegate Methods here: https://developer.apple.com/documentation/uikit/uiapplicationdelegate A Future Feature Request It would be great to have a way to communicate between the database solution file and the AppDelegate Methods. Maybe with a pre-determined standard global variable; something like $$SDK.SHARED.DATA. I'm not sure what everyone would use it for, but here is an idea I have come up with for helping to solve to delay issue we dealt with earlier in this project. Instead of statically creating a delay of 2.0 - 10.0 seconds, it would be a much better solution to create a loop in the Delegate code, maybe with a 0.5 - 1.0 second delay between iterations, to check for the existence of a certain value in this proposed global variable. For example: @interface MyAppDelegate : UIResponder <UIApplicationDelegate> { NSTimer *myTimer; NSString *sdk_shared_data; } @property (strong, nonatomic) UIWindow *window; @end @implementation MyAppDelegate - (void)triggerScript_didFinishLaunchingWithOptions:(NSTimer *)timer { NSString *fmpVariable = sdk_shared_data; if ([fmpVariable isEqual: @"helloFromFileMakerGlobalVariable"]) { [myTimer invalidate]; myTimer = nil; if (FMX_Queue_Script(@"<myFMdbName>", @"appDelegate_didFinishLaunchingWithOptions", kFMXT_Pause, @"none", nil)) { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_didFinishLaunchingWithOptions Succeeded"); } else { NSLog(@"MyAppDelegate: FMX_Queue_Script appDelegate_didFinishLaunchingWithOptions Failed"); } } } - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSLog(@"MyAppDelegate: %s", __func__); myTimer = [NSTimer scheduledTimerWithTimeInterval: 1.0 target: self selector: @selector(triggerScript_didFinishLaunchingWithOptions:) userInfo: nil repeats: YES]; return true; }
  2. I read that the new 3.01 version does not require Java. When I run FMPAv16 on my Mac (10.11.6) and use the sample Email database it works just fine and I see nothing related to Java. I had the older v2.12 plugin installed on here and have just updated to v3.01 today. When I run FMPAv16 on a different Mac (10.11.6) and install the v3.01 plugin (never had the plugin installed on this machine before today) and run the sample database a Java App runs without any windows, Just visible in the lower right dock and its single menu is titled "Java" Any ideas as to this oddity? Leland Long
  3. Keller Interiors (http://www.kellerinteriors.com) is looking to hire an I.T. Support Specialist with an interest in FileMaker database development. We are a 25+ year steadily growing flooring installation/construction company based in Charleston, SC with many other offices throughout the South, Southeast, and Midwest. We are looking to add a highly motivated, positive-minded, service oriented, and experienced individual that is looking to support and help to expand the needs of our I.T. Department. Daily work will primarily consist of supporting our existing I.T. infrastructure along with aiding in the planning, development and implementation of current and future projects. Responsibilities: • Setup, upgrading, and maintaining hardware and software • Providing basic employee service support • Training and troubleshooting of both hardware and software • Preparing reference for users by writing operating instructions and procedures • Contributing to the team effort of improving I.T. Department goals and requests • Team involvement in FileMaker Pro database development Requirements: • 1-2 years of FileMaker experience • 1-2 years of I.T. related job experience • Expertise in both Mac and PC hardware and software • Ability to work well with people at all levels, including non-technical staff • Ability to work effectively in a changing environment • Ability to coordinate tasks with prioritization. Optional Skills: • PHP • Obj-C • Swift • HTML/CSS/Javascript Benefits include: • Paid vacation, holidays, and sick time • 401K • Health benefits • Bonus potential • Salary range is based on experience Please communicate via email with: lelandlong@kellerinteriors.com
  4. I have finally, FINALLY stumbled across the solution to my problem I was also having with the agonizingly-slow InsertFile script step. In my case, working on a hosted database, the secret was in the External Data Source management !! I was using two databases, one local and one remotely hosted on another machine, with the local database using the remote database as an External Data Source. Original File Path List that allowed access to external data just fine yet caused MAJOR slowness using Insert File Script Step: fmnet:/www.mydomain.com/RelatedDatabaseName Modified File Path List that solved the problem: file:RelatedDatabaseName fmnet:/192.168.1.108/RelatedDatabaseName fmnet:/www.mydomain.com/RelatedDatabaseName I needed all three because it will be used here locally (where the FMServer is located) as well as externally by other clients using the domain name. Now the script takes less than 1 second, as it well should, where before it was taking 20-30 seconds each time it ran, causing the spinning beach ball-of-death and lots of finger tapping while uttering vocabulary not fit for fellow workmates...
  5. Mac OS X Server v10.6.8 FileMaker Server 12.0.1.178 During a daily scheduled backup in which it's set to keep a maximum of 14 backups, once there are 14 folders as expected I am receiving error messages stating: FMServer Error 685 Error occurred while deleting backup folder... When I look at the folder(s) in question it has successfully deleted all the database copies, only leaving the externally stored container files. All of them. And their folders. I looked at the permissions for each folder and they were all identical; all having fmserver/fmsadmin with Read & Write priv's. Thoughts, suggestions ?!
  6. Try this in your script: If ( PatternCount ( Get ( ApplicationVersion ) ; "web" ) > 0 This will be true when the user is connected via IWP.
  7. LelandLong

    services wanted FM Developer Charleston SC

    Company Certified by the federal government, LifePoint is the designated Organ Procurement Organization (OPO) for organ recovery services in South Carolina, except Aiken and Edgefield counties. LifePoint actively provides organ, tissue and ocular donor services to 62 hospitals throughout the state. Position We are looking to hire another experienced FileMaker Developer. We are particularly interested in someone with experience connecting FileMaker to the Web through a variety of methods, though this is not a requirement for this position. Our main office is in Charleston, SC, and this position requires the candidate to reside nearby. Qualifications total dedication to customer service development experience in a related field familiarity with current versions of FileMaker Pro strong understanding of relational database design creativity to design innovative solutions that eliminate problems ability to quickly conceptualize, evaluate and troubleshoot complex problems ability to quickly familiarize yourself with systems written by other developers excellent communication skills a positive attitude proven reliability FileMaker Certification is a plus familiarity with web connectivity and web programming ability to enthusiastically perform job functions with a minimum of structure and supervision Compensation Compensation is dependent upon skills brought to the table. To apply If you are interested and available, please follow these instructions to be considered. Email lifepoint_inc@me.com with the following: - Use “FileMaker developer” as Subject line. - In the email itself or on a cover letter, please rate yourself from 0 to 10 on the following traits/skills (not all are required for the position) C++ Java Javascript JDBC HTML CSS Flash PHP Ruby on Rails SQL XML XSLT Cocoa / Cocoa Touch Applescript Photoshop/Illustrator Office suite (Word/Excel/Powerpoint) UNIX command line competency Mac OS X Windows knowledge of relational databases development with current versions of FileMaker Pro experience developing using current methods of FileMaker-to-Web integration knowledge of IT environments working with specifications object oriented programming UI development Windows application development Mac application development iPhone/iPad application development formal computer science education clear communication good-with-people skills ability to manage your own tasks and time sense of humor ninja skills computer hacking skills - Attach your resume (text or PDF only) - Attach 2-4 professional references with emails and phone contacts for each - Answer the following questions: What is your availability? (How many hours per week, starting when?) What hourly rate / salary would you require? Is most of your experience with full-time employment or freelance work? What are some of the most interesting projects you have worked on? Do you work better alone or in a team? What is your strongest asset? What do you do when you are having a difficult time solving a problem? - Attach three different code samples and/or links. We look forward to hearing from you. No calls please.
  8. To handle no-occurrences I modified the code to: Let ( [ fieldNameStart = "Nation|" ; fieldNameClose = "" ; fieldNameLength = Length ( fieldNameStart ) ; dataBegin = Position ( YourXMPfield ; fieldNameStart ; 1 ; 1 ) ; dataEnd = Position ( YourXMPfield ; fieldNameClose ; dataBegin ; 1 ) ; dataLength = dataEnd - dataBegin - fieldNameLength ] ; Case ( dataBegin > 0 ; Middle ( YourXMPfield ; dataBegin + fieldNameLength ; dataLength ) ; "" ) ) To handle multiple occurrences of 'Nation' and/or others, you have a couple options. 1) if you have Advanced you could create a recursive function to handle all instances of 'Nation' 2) if no FMPAdvanced, you'll need a field for every possibility. ie for up to 5 possible Nations you'll need 5 fields. Use the above code for each field. Change the Position code in each field to match the occurrence. * Nation3 would replace the position function parameters to 'Position(YourXMPfield;fieldNameStart;1;[color:red]3)'
  9. I've done a lot of XML scraping This should work for each field you want to scrape by modifying just the first variable 'fieldNameStart'. Here's the formula I like to use for each field (modified for your example - hopefully didn't create an error with modifying my code to match your needs): Let ( [ fieldNameStart = "Nation|" ; fieldNameClose = "" ; fieldNameLength = Length ( fieldNameStart ) ; dataBegin = Position ( YourXMPfield ; fieldNameStart ; 1 ; 1 ) ; dataEnd = Position ( YourXMPfield ; fieldNameClose ; dataBegin ; 1 ) ; dataLength = dataEnd - dataBegin - fieldNameLength ] ; Middle ( YourXMPfield ; dataBegin + fieldNameLength ; dataLength ) )
  10. First flight from Charleston to Atlanta cancelled Sunday afternoon. The pair of us got on the next flight out via Standby In Atlanta next flight was delayed due to weather. Then delayed again. And again. And then again. Now we get on the plane (3 hours later-could have been worse.) Still at the gate 15 minutes after everyone on board. Pilot gets on the P.A. "Flight has been cancelled". Long lines everywhere! May be sleeping in the airport tonight. Possibility of a Delta provided hotel, if you can get through the crawling line. Next flight out is Monday am. Arriving in Phoenix: 9:30ish! Guess we're missing out on the awesome welcoming keynote. >: The best-laid plans of mice and men... Wish someone there could record the keynote : Wishing we were there already....hope everyone else's travels have had a better result.
  11. Actually, the way you phrased it may be wrong... Test it. Run your test on a machine that has the ethernet cable unplugged, or aircard off, or whatever to guarantee no internet. Now run your test. Reason I say this, with no internet connection the webviewer may still load an error page. If so, your variable may still not be empty. Instead of a blank page, maybe have a success message that you can look for...
  12. I have successfully synced data between runtimes and served files for some time now. It works great in limited applications. Absolutely perfect in single user instances such as yours where you just want data to be sent from the runtime to the server as new records or edits. So if you just want log data to be sent to the server via a button/script in the runtime, then that is what I'm referring to...it can be done. A few requirements: 1) hosted file on a FM server (or equivalent [client copy v6 has this]) with XML capability 2) custom php web pages hosted on any web server
  13. Yes, load a common, almost always available webpage (google, fmforums, etc) in a webviewer. If the user doesn't need to see it make it 1 pixel tall. Use GetLayoutObjectAttribute in a calc to pull the html source data. Create a script loop that will find PatternCount ( [theHTMLsource] ; "
  14. I've had wonderful success with runtimes working with hosted databases. Not sure how my solutions would work in your situation however, except possibly sending the log data back to the production studio automatically without needing a separate file and/or email. Sounds to me like a solution would be the opener script in the runtime. If the video is inserted into its subfolder, as long as it had the same path to use every time (at least at the same level and name), the runtime opener script could handle what you are wanting the hosted database to do in your description. Unless I misunderstood you...
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.