I want to put an annotation on every grocery store within a specific area. I already have my mkmapview working and tracking my current location.
Thanks in advance!
Give it a try, unfortunately I'm not in situation to test it right now, but this piece of code should serve your requirement:
let request = MKLocalSearchRequest()
request.naturalLanguageQuery = "Groceries"
request.region = mapView.region
let search = MKLocalSearch(request: request)
search.start(completionHandler: {(response, error) in
if error != nil {
print("Error occured in search:
\(error!.localizedDescription)")
} else if response!.mapItems.count == 0 {
print("No matches found")
} else {
print("Matches found")
for item in response!.mapItems {
print("Name = \(item.name)")
print("Phone = \(item.phoneNumber)")
}
}
})
In Swift 2 the following code was working:
let request = NSFetchRequest(entityName: String)
but in Swift 3 it gives error:
Generic parameter "ResultType" could not be inferred
because NSFetchRequest is now a generic type. In their documents they wrote this:
let request: NSFetchRequest<Animal> = Animal.fetchRequest
so if my result class is for example Level how should I request correctly?
Because this not working:
let request: NSFetchRequest<Level> = Level.fetchRequest
let request: NSFetchRequest<NSFetchRequestResult> = Level.fetchRequest()
or
let request: NSFetchRequest<Level> = Level.fetchRequest()
depending which version you want.
You have to specify the generic type because otherwise the method call is ambiguous.
The first version is defined for NSManagedObject, the second version is generated automatically for every object using an extension, e.g:
extension Level {
#nonobjc class func fetchRequest() -> NSFetchRequest<Level> {
return NSFetchRequest<Level>(entityName: "Level");
}
#NSManaged var timeStamp: NSDate?
}
The whole point is to remove the usage of String constants.
I think i got it working by doing this:
let request:NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "Level")
at least it saves and loads data from DataBase.
But it feels like it is not a proper solution, but it works for now.
The simplest structure I found that works in 3.0 is as follows:
let request = NSFetchRequest<Country>(entityName: "Country")
where the data entity Type is Country.
When trying to create a Core Data BatchDeleteRequest, however, I found that this definition does not work and it seems that you'll need to go with the form:
let request: NSFetchRequest<NSFetchRequestResult> = Country.fetchRequest()
even though the ManagedObject and FetchRequestResult formats are supposed to be equivalent.
Here are some generic CoreData methods that might answer your question:
import Foundation
import Cocoa
func addRecord<T: NSManagedObject>(_ type : T.Type) -> T
{
let entityName = T.description()
let context = app.managedObjectContext
let entity = NSEntityDescription.entity(forEntityName: entityName, in: context)
let record = T(entity: entity!, insertInto: context)
return record
}
func recordsInTable<T: NSManagedObject>(_ type : T.Type) -> Int
{
let recs = allRecords(T.self)
return recs.count
}
func allRecords<T: NSManagedObject>(_ type : T.Type, sort: NSSortDescriptor? = nil) -> [T]
{
let context = app.managedObjectContext
let request = T.fetchRequest()
do
{
let results = try context.fetch(request)
return results as! [T]
}
catch
{
print("Error with request: \(error)")
return []
}
}
func query<T: NSManagedObject>(_ type : T.Type, search: NSPredicate?, sort: NSSortDescriptor? = nil, multiSort: [NSSortDescriptor]? = nil) -> [T]
{
let context = app.managedObjectContext
let request = T.fetchRequest()
if let predicate = search
{
request.predicate = predicate
}
if let sortDescriptors = multiSort
{
request.sortDescriptors = sortDescriptors
}
else if let sortDescriptor = sort
{
request.sortDescriptors = [sortDescriptor]
}
do
{
let results = try context.fetch(request)
return results as! [T]
}
catch
{
print("Error with request: \(error)")
return []
}
}
func deleteRecord(_ object: NSManagedObject)
{
let context = app.managedObjectContext
context.delete(object)
}
func deleteRecords<T: NSManagedObject>(_ type : T.Type, search: NSPredicate? = nil)
{
let context = app.managedObjectContext
let results = query(T.self, search: search)
for record in results
{
context.delete(record)
}
}
func saveDatabase()
{
let context = app.managedObjectContext
do
{
try context.save()
}
catch
{
print("Error saving database: \(error)")
}
}
Assuming that there is a NSManagedObject setup for Contact like this:
class Contact: NSManagedObject
{
#NSManaged var contactNo: Int
#NSManaged var contactName: String
}
These methods can be used in the following way:
let name = "John Appleseed"
let newContact = addRecord(Contact.self)
newContact.contactNo = 1
newContact.contactName = name
let contacts = query(Contact.self, search: NSPredicate(format: "contactName == %#", name))
for contact in contacts
{
print ("Contact name = \(contact.contactName), no = \(contact.contactNo)")
}
deleteRecords(Contact.self, search: NSPredicate(format: "contactName == %#", name))
recs = recordsInTable(Contact.self)
print ("Contacts table has \(recs) records")
saveDatabase()
This is the simplest way to migrate to Swift 3.0, just add <Country>
(tested and worked)
let request = NSFetchRequest<Country>(entityName: "Country")
Swift 3.0 This should work.
let request: NSFetchRequest<NSFetchRequestResult> = NSManagedObject.fetchRequest()
request.entity = entityDescription(context)
request.predicate = predicate
I also had "ResultType" could not be inferred errors. They cleared once I rebuilt the data model setting each entity's Codegen to "Class Definition". I did a brief writeup with step by step instructions here:
Looking for a clear tutorial on the revised NSPersistentContainer in Xcode 8 with Swift 3
By "rebuilt" I mean that I created a new model file with new entries and attributes. A little tedious, but it worked!
What worked best for me so far was:
let request = Level.fetchRequest() as! NSFetchRequest<Level>
I had the same issue and I solved it with the following steps:
Select your xcdatamodeld file and go to the Data Model Inspector
Select your first Entity and go to Section class
Make sure that Codegen "Class Definition" is selected.
Remove all your generated Entity files. You don't need them anymore.
After doing that I had to remove/rewrite all occurences of fetchRequest as XCode seem to somehow mix up with the codegenerated version.
HTH
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
func loadItemsCategory() {
let request: NSFetchRequest<Category> = Category.fetchRequest()
do {
categoryArray = try context.fetch(request)
} catch {
print(error)
}
tableView.reloadData()
}
I want to convert the friend list ids that I am getting from facebook as an array to save in parse. My code is as below but I am getting a "unexpectedly found nil while unwrapping an Optional value" error. What should I do to save the result to parse and retrieve it as array when required?
let fbRequest = FBSDKGraphRequest(graphPath:"/me/friends", parameters: nil);
fbRequest.startWithCompletionHandler { (connection : FBSDKGraphRequestConnection!, result : AnyObject!, error : NSError!) -> Void in
if error == nil {
print("Friends are : \(result)")
if let dict = result as? Dictionary<String, AnyObject>{
let profileName:NSArray = dict["name"] as AnyObject? as! NSArray
let facebookID:NSArray = dict["id"] as AnyObject? as! NSArray
print(profileName)
print(facebookID)
}
}
else {
print("Error Getting Friends \(error)");
}
}
When I use the code below in print() I get the result below:
Friends are : {
data = (
{
id = 138495819828848;
name = "Michael";
},
{
id = 1105101471218892;
name = "Johnny";
}
);
The issue is that you are trying to access the name and id elements from the top-level dictionary, where you need to be accessing data.
When you call the FB Graph API for friends it will return an array of dictionaries (one per friend).
Try this:
let fbRequest = FBSDKGraphRequest(graphPath:"/me/friends", parameters: nil)
fbRequest.startWithCompletionHandler { (connection : FBSDKGraphRequestConnection!, result : AnyObject!, error : NSError!) -> Void in
if error == nil {
print("Friends are : \(result)")
if let friendObjects = result["data"] as? [NSDictionary] {
for friendObject in friendObjects {
println(friendObject["id"] as NSString)
println(friendObject["name"] as NSString)
}
}
} else {
print("Error Getting Friends \(error)");
}
}
You should also check out this SO post with more information on the FB Graph API. Here's a brief snippet.
In v2.0 of the Graph API, calling /me/friends returns the person's
friends who also use the app.
In addition, in v2.0, you must request the user_friends permission
from each user. user_friends is no longer included by default in every
login. Each user must grant the user_friends permission in order to
appear in the response to /me/friends. See the Facebook upgrade guide
for more detailed information, or review the summary below.
I'm trying to get the contact details out of the address book on the Mac. I can get the first name and last name fields etc, but I'm struggling with the syntax for ABPersonCopyImageData.
Now according to the documentation ABPersonCopyImageData takes a single parameter of type ABPerson.
Here is my code:
import AddressBook
let thisPerson : ABPerson
let addressBook = ABAddressBook.sharedAddressBook()
rec = addressBook.recordForUniqueId("0005A360-327F-4E12-BBB9-24A842497E12:ABPerson")
let firstName = rec.valueForProperty(kABFirstNameProperty) as! String
let lastName = rec.valueForProperty(kABLastNameProperty) as! String
println("\(firstName) \(lastName)")
let contactImage = ABPersonCopyImageData(thisPerson)
The last line stops the compiler with an error: Cannot invoke 'ABPersonCopyImageData' with an argument list of type (ABPerson). As far as I can tell thisPerson is of type ABPerson. What is going wrong?
I found out how to do this in ElCapitan:
import Contacts
func getContactImage(name:String) -> NSImage?
{
let store = CNContactStore()
do
{
let contacts = try store.unifiedContactsMatchingPredicate(CNContact.predicateForContactsMatchingName(name), keysToFetch:[CNContactImageDataKey])
if contacts.count > 0
{
if let image = contacts[0].imageData
{
return NSImage.init(data: image)
}
}
}
catch
{
}
return nil
}
I couldn't find any info about getting user's location info in swift and xcode 6
I tried
var fbcity = user.objectForKey("location")
var fbcountry = user.objectForKey("country")
But didn't work.
Any idea how to achieve this ?
Perhaps you could supply us with a little more information, e.g. which Facebook SDK you are using and what parameters FBSDKGraphRequest has to return user. Note that there is no specific information about country, the location field in the user node when your send a graph request for the user profile. It will return the subfields: id and name, where name is
With the latest Facebook iOS SDK 4.0 you can do something like:
override func viewDidLoad() {
super.viewDidLoad()
self.loginView.delegate = self
if FBSDKAccessToken.currentAccessToken() != nil {
fetchUserData()
} else {
loginView.readPermissions = ["public_profile", "email", "user_friends"]
}
}
func fetchUserData() {
let graphRequest: FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "me", parameters: nil)
graphRequest.startWithCompletionHandler({ (connection, result, error) -> Void in
if error != nil {
// Process error
println("Error: \(error)")
} else {
let location: NSDictionary! = result.valueForKey("location") as NSDictionary
let city: NSString = location.valueForKey("name") as NSString
}
})
}
More detailed info can be found on Facebook Graph API User page.