How would I translate this Swift to Obj-C? - ios

This is probably simple enough, but Im not a regular iOS dev but have a decent understanding of Obj-C and Xcode however not so much with Swift yet.
I am playing around with a mapping SDK called Skobbler and downloaded both Swift and iOS examples.
The Swift example gives me some useful text/console logs of directions turn by turn however the Obj-C doesn't and having a tough time exposing them.
The Swift example looks like this
let advices: Array<SKRouteAdvice> = SKRoutingService.sharedInstance().routeAdviceListWithDistanceFormat(SKDistanceFormat.Metric) as! Array<SKRouteAdvice>
for advice: SKRouteAdvice in advices
{
let instructions = advice.adviceInstruction
print(instructions)
}

NSArray<SKRouteAdvice *> *advices = [[SKRoutingService sharedInstance] routeAdviceListWIthDistanceFormat:SKDistanceFormat.Metric];
for (SKRouteAdvice *advice in advices)
{
NSLog(#"%#", instructions);
}

NSArray *advices = [[SKRoutingService sharedInstance]routeAdviceListWithDistanceFormat:SKDistanceFormat.Metric];
for (SKRouteAdvice *advice in advices) {
NSLog(#"%#", [advice adviceInstruction]);
}

as! doesn't need translating - the compiler will just believe you (you might want to add an assert for identical behaviour). The print is replaced with NSLog (#"%#", instructions).

Related

Handling Windows Hebrew Encoding in Objective-c

I am working on an ancient iOS app for a program that runs off VB6. It is passing strings over in a non unicode format including Hebrew characters which once they are parsed are displayed as "àáðø ãøåøé"
I am assuming it is being encoded in Windows Hebrew.
I can't seem to find anything in the apple documentation that explains how to handle this case. And most searches bring up solutions in Swift, no Obj-C. I tried this:
NSString *hebrewPickup = [pickupText stringByApplyingTransform:NSStringTransformLatinToHebrew reverse:false];
But that just gave me this:
"ðø ַ̃øַ̊øֵ"
I am stumped.
EDIT: Based on JosefZ's comment I have tried to encode back using CP1252, but the issue is that CP1255 is not in the list of NSStringEncodings. But seems like it would solve my issue.
NSData *pickupdata = [pickupText dataUsingEncoding:NSWindowsCP1252StringEncoding];
NSString *convPick = [[NSString alloc] initWithData:pickupdata encoding:NSWindowsCP1254StringEncoding];
NSString *hebrewPickup = [convPick stringByApplyingTransform:NSStringTransformLatinToHebrew reverse:false];
Ok, if any poor soul ends up here, this is how I ended up fixing it. I needed to add some Swift into my Obj-C code. (If only I could magically just rebuild the whole project in Swift instead.)
Here is the info on that: https://developer.apple.com/documentation/swift/imported_c_and_objective-c_apis/importing_swift_into_objective-c
Making use of this Swift Package: https://github.com/Cosmo/ISO8859
I added the following code to a new swift file.
#objc class ConvertString: NSObject {
#objc func convertToHebrew(str:String) -> NSString {
let strData = str.data(using: .windowsCP1252);
let bytes: Data = strData!;
if let test = String(bytes, iso8859Encoding: ISO8859.part8) {
return test as NSString;
}
let test = "";
return test as NSString;
}
}
Then in the Obj-C project I was able to call it like so:
ConvertString *stringConverter = [ConvertString new];
NSString *pickupTextFixed = [stringConverter convertToHebrewWithStr:pickupText];
NSString *deliverTextFixed = [stringConverter convertToHebrewWithStr:deliverText];

"'isDeveloperModeEnabled' is deprecated: This no longer needs to be set during development. " What is isDeveloperModeEnabled used for

As a part of upgrading the code base to Swift5, I have updated Firebase pod in my project. After that i started getting warning as below.
isDeveloperModeEnabled is deprecated: This no longer needs to be set during development. Refer to documentation for additional details..
Can somebody explain what is the alternative way to resolve this issue
remoteConfig = RemoteConfig.remoteConfig()
let conSettings = RemoteConfigSettings(developerModeEnabled: true)
if TargetBuild.isProd {
remoteConfig.configSettings = RemoteConfigSettings()
} else if settings.isDeveloperModeEnabled {
remoteConfig.configSettings = conSettings
} else {
print("Could not set config settings")
}
i need to resolve the warning on above code. This was an existing codebase. When i did a global search, i didnt see this value getting used. somebody please help me
Old way:
let remoteConfigSettings = RemoteConfigSettings(developerModeEnabled: true)
New way:
let remoteConfigSettings = RemoteConfigSettings()
remoteConfigSettings.minimumFetchInterval = 0
The iOS documentation does not yet mention that developerModeEnabled is deprecated, but an updated commented example can be found here: https://github.com/firebase/quickstart-ios/blob/master/config/ConfigExample/RemoteConfigViewController.swift#L57 (README here)
That config setting is deprecated.. With a simple google search..
https://firebase.google.com/docs/reference/android/com/google/firebase/remoteconfig/FirebaseRemoteConfigSettings.html#getMinimumFetchIntervalInSeconds()
The docs say to use getMinimumFetchIntervalInSeconds() instead of isDeveloperModeEnabled().
Update -- Android docs say it is deprecated, iOS does not say anything about deprecating isDeveloperModeEnabled
https://firebase.google.com/docs/reference/swift/firebaseremoteconfig/api/reference/Classes/RemoteConfigSettings
If you are using Objective-C, you can solve the issue with:
FIRRemoteConfigSettings *remoteConfigSettings = [[FIRRemoteConfigSettings alloc] init];
[remoteConfigSettings setMinimumFetchInterval:0];

What is the proper syntax for Google Analytics Exception tracking in Swift?

I'm trying to use Exception Tracking for my app in Google Analytics.
https://developers.google.com/analytics/devguides/collection/ios/v3/exceptions
I am just trying to figure out the syntax for this in Swift (not super familiar with Obj-C):
#try {
// Request some scores from the network.
NSArray *highScores = [self getHighScoresFromCloud];
}
#catch (NSException *exception) {
// May return nil if a tracker has not already been initialized with a
// property ID.
id tracker = [[GAI sharedInstance] defaultTracker];
[tracker send:[[GAIDictionaryBuilder
createExceptionWithDescription:#"Connection timout %d: %#", connectionError, errorDescription // Exception description. May be truncated to 100 chars.
withFatal:#NO] build]]; // isFatal (required). NO indicates non-fatal exception.
}
I have set up my tracker okay, and it is working fine saving other data to GA, it is just the syntax calling createExceptionWithDescription() in Swift that I'm not certain of.
There sure doesn't appear to be much in the way of examples / docs for using Swift for Google Analytics... =/ If you know of any, please let me know!
Thanks.
Thanks, David Wong, your post helped a lot to get me on the right track with the syntax.
This post also helped me a lot:
Cannot convert value of type 'NSMutableDictionary' to type '[NSObject: AnyObject]' in coercion for google ios Analytics
This is what ended up working for me:
let tracker = GAI.sharedInstance().defaultTracker
let eventTracker: NSObject = GAIDictionaryBuilder.createExceptionWithDescription("No internet connection.", withFatal: false).build()
tracker.send(eventTracker as! [NSObject : AnyObject])
Thanks again!
I'd imagine its something along the lines of:
let dictionaryToSend = GAIDictionaryBuilder.createExceptionWithDescription("Connection timeout \(connectionError): \(errorDescription)", withFatal: NSNumber(bool: false)).build()
If its a class function in Obj-C written like
[GAIDictionaryBuilder createExceptionWithDescription:...]; // objc
Its written like
GAIDictionaryBuilder.createExceptionWithDescription(...); // swift
Each of the colons in obj-c denotes an argument variable.
// Broken into two lines to make it easier to read
[GAIDictionaryBuilder createExceptionWithDescription: #"String here"
withFatal: #NO];
You can do a similar thing in swift:
//Comma separated
GAIDictionaryBuilder.createExceptionWithDescription("Description String",
withFatal: NSNumber(bool:false));
I suggest you learn a little bit of the ObjC messaging syntax since a lot of iOS code is still in ObjC but don't worry a huge amount about it. Swift is a better language.

SKmaps failed to perform multi level search

I want to make a multi level offline search in my app.
I followed the directions at official Skobbler page and only difference is that l did not download map of France, but map of Wyoming instead.
Offline package code for it is USWY if I am right.
-(void)prepareForSearch{
[SKSearchService sharedInstance].searchServiceDelegate = self;
[SKSearchService sharedInstance].searchResultsNumber = 500;
_listLevel = SKCountryList;
_searchSettings = [SKMultiStepSearchSettings multiStepSearchSettings];
_searchSettings.listLevel = _listLevel;
_searchSettings.offlinePackageCode = #"USWY";
_searchSettings.parentIndex=-1;
}
- (IBAction)searchAction:(UIButton *)sender {
_searchSettings.searchTerm = [NSString stringWithFormat:#"%#",_searchBar.text];
[[SKSearchService sharedInstance]startMultiStepSearchWithSettings:_searchSettings];
}
-(void)searchService:(SKSearchService *)searchService didRetrieveMultiStepSearchResults:(NSArray *)searchResults
{
if ([searchResults count] !=0 && _listLevel<SKInvalidListLevel){
if (_listLevel == SKCountryList) {
_listLevel = SKCityList;
}
else{
_listLevel++;
}
SKSearchResult *searchResult = searchResults[0];
SKMultiStepSearchSettings* multiStepSearchObject = [SKMultiStepSearchSettings multiStepSearchSettings];
multiStepSearchObject.listLevel = _listLevel++;
multiStepSearchObject.offlinePackageCode = _searchSettings.offlinePackageCode;
multiStepSearchObject.searchTerm = _searchBar.text;
multiStepSearchObject.parentIndex = searchResult.identifier;
[[SKSearchService sharedInstance]startMultiStepSearchWithSettings:multiStepSearchObject];
}
}
-(void)searchServiceDidFailToRetrieveMultiStepSearchResults:(SKSearchService *)searchService
{
NSLog(#"Multi Level Search failed");
}
Whatever I put as a searchTerm, I end up with "MultiLevel Search Failed".
from this screenshot, you can see that my map package for Wyoming is included in my SKMaps.bundle:
(Also, if anyone can answer me this: Versioning was different in my app and in the simulator folder in the test app, from where I downloaded an offline package. So, for testing purposes, I made two folders and put Wyoming package in both of them(20140807 and 20140910). Are there any rules regarding this?)
What could be the problem?
Ok, after few days I managed to find the source of the problem.
First, I found out which version I'm using and it's the 20140910.
Second, For some reason, the entire folder containing maps was not recognised. So I took the entire SKMaps.bundle, together with some pre-bundled maps from the demo app, provided by the Skobbler team, and put it in my project and now everything works fine.

is it possible to access pdf outline when developing for iOS

being that PDFKit is not available on iOS, how is it possible to get the outline of a pdf document in that environment? Is commercial libraries like FastPdfKit or PSPDFKit the only solution?
It's not TOO tricky to access the pdf outline. My outline parser has about 420 LOC. I'll post some snippets, so you'll get the idea. I can't post the full code as it's a commercial library.
You basically start like this:
CGPDFDictionaryRef outlineRef;
if(CGPDFDictionaryGetDictionary(pdfDocDictionary, "Outlines", &outlineRef)) {
going down to
NSArray *outlineElements = nil;
CGPDFDictionaryRef firstEntry;
if (CGPDFDictionaryGetDictionary(outlineRef, "First", &firstEntry)) {
NSMutableArray *pageCache = [NSMutableArray arrayWithCapacity:CGPDFDocumentGetNumberOfPages(documentRef)];
outlineElements = [self parseOutlineElements:firstEntry level:0 error:&error documentRef:documentRef cache:pageCache];
}else {
PSPDFLogWarning(#"Error while parsing outline. First entry not found!");
}
you parse single items like this:
// parse title
NSString *outlineTitle = stringFromCGPDFDictionary(outlineElementRef, #"Title");
PSPDFLogVerbose(#"outline title: %#", outlineTitle);
if (!outlineTitle) {
if (error_) {
*error_ = [NSError errorWithDomain:kPSPDFOutlineParserErrorDomain code:1 userInfo:nil];
}
return nil;
}
NSString *namedDestination = nil;
CGPDFObjectRef destinationRef;
if (CGPDFDictionaryGetObject(outlineElementRef, "Dest", &destinationRef)) {
CGPDFObjectType destinationType = CGPDFObjectGetType(destinationRef);
The most annoying thing is that you have Named Destinations in most pdf documents, which need additional steps to resolve. I save those in an array and resolve them later.
It took quite a while to "get it right" as there are LOTS of differences in the PDFs that are around, and even if you implement everything in compliance to the PDF reference, some files won't work until you apply further tweaking. (PDF is a mess!)
It is now possible in iOS 11+.
https://developer.apple.com/documentation/pdfkit
You can get the PDFOutline of a PDFDocument.
The PDFOutline's outlineRoot will return outline items if there are any and NULL if none.

Resources