Ошибка геокодирования что это

  • Methodology
  • Open Access
  • Published:

International Journal of Health Geographics

volume 2, Article number: 10 (2003)
Cite this article

  • 19k Accesses

  • 3 Altmetric

  • Metrics details

Abstract

Background

Public health applications using geographic information system (GIS) technology are steadily increasing. Many of these rely on the ability to locate where people live with respect to areas of exposure from environmental contaminants. Automated geocoding is a method used to assign geographic coordinates to an individual based on their street address. This method often relies on street centerline files as a geographic reference. Such a process introduces positional error in the geocoded point. Our study evaluated the positional error caused during automated geocoding of residential addresses and how this error varies between population densities. We also evaluated an alternative method of geocoding using residential property parcel data.

Results

Positional error was determined for 3,000 residential addresses using the distance between each geocoded point and its true location as determined with aerial imagery. Error was found to increase as population density decreased. In rural areas of an upstate New York study area, 95 percent of the addresses geocoded to within 2,872 m of their true location. Suburban areas revealed less error where 95 percent of the addresses geocoded to within 421 m. Urban areas demonstrated the least error where 95 percent of the addresses geocoded to within 152 m of their true location. As an alternative to using street centerline files for geocoding, we used residential property parcel points to locate the addresses. In the rural areas, 95 percent of the parcel points were within 195 m of the true location. In suburban areas, this distance was 39 m while in urban areas 95 percent of the parcel points were within 21 m of the true location.

Conclusion

Researchers need to determine if the level of error caused by a chosen method of geocoding may affect the results of their project. As an alternative method, property data can be used for geocoding addresses if the error caused by traditional methods is found to be unacceptable.

Background

There has been a dramatic increase in the number of public health applications using GIS. Software and hardware are now more accessible, affordable, and easier to use. Environmental, health and socio-demographic data are readily available through the Internet and optical disk media. Many colleges and universities now offer courses in GIS and spatial analysis. An increase in public awareness of these advances has led to increased demand for studies and maps investigating spatial relationships between health outcome, environmental risk factors and exposure.

Environmental health studies often rely on GIS and geocoding software to help delineate areas of potential exposure and to locate where people live in relation to these areas. A number of studies have used residential locations to determine whether individuals live within defined zones of exposure. Geschwind et al. [1] geocoded congenital malformation cases and controls to estimate an increased risk of living within 1 mile of hazardous waste sites. English et al. [2] used geocoded residential addresses to assess whether there was an elevated odds ratio of childhood asthma hospitalizations in children living within 550 feet (168 m) of roads with heavy traffic in San Diego, California. In a study of breast cancer on Long Island, New York, one-kilometer grid cells were created and cases, controls and chemical facilities were assigned to individual cells through automated geocoding methods. The risk of developing postmenopausal breast cancer was found to increase as the number of chemical facilities sharing the same cells as study subjects increased [3]. More recently, Reynolds et al. [4] geocoded childhood cancer cases to census tracts in California and used USEPA data to assign hazardous air pollutant scores to each tract. There was an increased risk of developing childhood cancer as the exposure level increased. Kitto et al. [5] used GIS to locate nearly 45,000 residential radon screening measurements, which were then associated with surficial geology. The association between surficial geology types and radon measures were used to predict radon levels in towns across New York.

Geocoded health data are also used to map rates of disease in order to determine areas of high or low incidence [6, 7]. Rate maps can be used in conjunction with spatial statistics such as the local Moran’s I [8] or the Spatial Scan Statistic [9] to locate the general areas where the rates are unlikely due to chance. Further investigations or more rigorous epidemiology studies are often needed to clarify the association of risk factors and adverse health outcomes when high rates are detected.

Many GIS software packages provide for street level geocoding. Geocoding software matches residential addresses to street reference files containing geographic centerline coordinates, street numbers, street names and postal codes. Researchers undertaking projects having a geocoding component should be concerned that positional error can be introduced by commonly used algorithms. Of more concern, they need to understand if this error could impact study results. Nondifferential errors with respect to exposure classification will bias the association between a risk factor and the health outcome towards the null, limiting the ability to detect true effects. The capability to detect an association thus depends on the magnitude of this error. However, if the positional error is systematic, it is possible an association may be found between a health outcome and an exposure where none actually exists. In the case of disease surveillance activities, localized high or low rates of disease may appear as an artifact of geocoding errors [10].

The percentage of addresses that geocode is commonly referred to as a match rate. The inability to geocode addresses can lead to a loss of study population causing sample bias and reduced statistical power in detecting important associations. Several investigators have provided statistics related to match rates [11–17]. Researchers have found that differences in these rates are dependent on population density [18, 19]. This is because street reference files, such as the U.S. Census TIGER (Topologically Intergrated Geographic Encoding and Referencing) files or commercially enhanced TIGER files, often contain more complete address information in more densely populated areas. Gregorio et al. [20] analyzed the match rates of breast cancer cases from the Connecticut Tumor Registry and found that women of color and women living in low income neighborhoods were more likely to be successfully geocoded compared to white women and women living in higher income areas. Investigators should be aware that the geographic differences in match rates can alter study results. For example, if more cases are matched in inner city minority neighborhoods, the disease incidence may appear higher in these areas due to larger subject loss in other areas.

Achieving high match rates is dependent on accurate and complete address information of the study subjects and the street reference files. Many types of problems can occur in both, such as: spelling errors; street suffix, prefix and abbreviation inconsistencies; and erroneous ZIP code information. Reference files also contain errors such as missing, incomplete, and incorrect street segments and address ranges. The North American Association of Central Cancer Registries provide an extensive overview and guideline of the standardization and geocoding of patient addresses, problems encountered, and recommendations for improving the geocoding process of disease registries [21]. Match rates alone are not sufficient to evaluate a geocoding result. Some investigators have also provided statistics related to the percent of geocoded addresses misclassified to the correct town [13], census area [22, 16], and land parcel [22]. The level of misclassification will change depending on the geographic scale of the regions used.

Very limited published information exists on positional error in automated street level geocoding. Hertz, of the California Department of Health Services, conducted a pilot study to assess geocoding accuracy of 70 addresses (A. Hertz, personal correspondence, 2002). In his study, Hertz used aerial photos to determine the true location of each address and geocoded the same group using three different commercial products. Hertz found positional error to be in a range of 20–80 m depending on the product used and had some extreme outliers over 250 m. Researchers at the University of Connecticut compared the locations of addresses geocoded using the U.S. Census Bureau’s TIGER [23] files to ground truth locations of approximately 536 addresses in Stratford, Connecticut. Four of these addresses were located more than 500 feet (152 m) from the correct location (E. Cromley, unpublished manuscript, 1997). In a recently published study, Bonner et al. [24] found differences between urban and non-urban addresses when examining distances between the geocoded and GPS determined locations. They found 89 percent of the addresses were within 100 meters in urban areas of Erie and Niagara Counties, NY, while in the non-urban areas 69 percent were within 100 meters.

This study had several objectives. The primary objective was to evaluate positional error in automated geocoding of residential addresses. We measured positional error by calculating the distance between geocoded locations provided by a commonly available off-the-shelf product and their corresponding true locations. This commercial product uses a proprietary enhanced version of the TIGER files. The second objective was to evaluate how this error varies between urban, suburban, and rural population densities. A third objective was to determine if the error can be reduced by adjusting default settings in the geocoding software. The street offset setting allows the user to change the default for how far a geocoded address is placed from a street centerline while the corner inset setting determines how far a geocoded address is placed along a street from an intersection. The final objective was to compare the error observed in the traditional geocoding method, which relies on linear interpolation, to a point geocoding method using property parcel data.

Methods

Data

We acquired residential addresses from the New York State Office of Real Property Services (NYSORPS). These represent the types of addresses we frequently geocode in health studies. The data included 1999 property parcel records for the New York State Capital District counties of Albany, Rensselaer, Saratoga, and Schenectady [25]. The City of Watervliet and the Town of Westerlo were excluded as they were not available at the time we processed the data. Local governments compile these data to assess town and school property taxes. Each record contains parcel level information, such as: street number and name, property use, billing information, and coordinates for the approximate centroid of the parcel. Towns vary in their method of determining the location of the parcel centroids. Some are derived visually from paper maps, which have a horizontal positional accuracy of ± 10 feet (3 m) [25]. Figure 1 provides an example of property parcel points overlaid on high resolution aerial orthoimagery. We further restricted analysis to residential properties classified as single, two or three-family houses. This selection included 215,007 addresses.

Figure 1
figure 1

Residential parcel points and high resolution aerial imagery. Property parcel points from the NYSORPS. Each circle represents the approximate centroid of a property parcel classified as residential.

Full size image

Using the property centroid, each address was assigned a population density class of urban, suburban, or rural. The most densely populated cities in the Capital District were classified as urban and included Albany, Schenectady, Troy, Rensselaer, Cohoes, Mechanicville and Green Island. The population density of these cities ranged from 1,059 persons/km2 to 2,490 persons/km2 [26]. The remaining areas were partitioned into suburban and rural areas by census tract. Suburban areas consisted of census tracts having greater than 250 persons/km2, while rural areas contained census tracts with less than 250 persons/km2. The four county study area and associated population density assignments are shown in Figure 2.

Figure 2
figure 2

Study area by population density class. Densely populated cities were classified as urban. Census tracts were used to partition the remaining areas into suburban (>250 persons/km2) and rural areas (<250 persons/km2).

Full size image

Geocoding

In order to successfully geocode a residential address, a valid street number, street name and ZIP code is required. NYSORPS property data contain parcel specific street number and name information, but lack the ZIP code of the parcel address. We could not reliably assign parcel ZIP codes to 3,145 addresses (1.5%) in our residential property file. This group was excluded from further analysis and should have no effect on the overall results since they represent a very small portion of the addresses in the four county area.

MapMarker Plus Version 6.0 [27] was used to match the residential address records to the software’s street reference files. The reference files used in this product were dated July-August 2000 and enhanced by Geographic Data Technology of Lebanon, New Hampshire. We did not include any record for further analyses unless it could be matched to the street reference files by exact house number, street name, and ZIP code. Using these criteria, MapMarker successfully geocoded 170,819 (81%) addresses. Match rates by population density class are summarized in Table 1.

Table 1 Geocoding match rates by population density. Values are based on exact matching of house number, street name, and ZIP code.

Full size table

In order to measure positional error, we determined the true location for a random sample of 1,000 addresses from each of the three population density classes for a total sample size of 3,000 addresses. This selection was drawn from the group that matched exactly on street number, street name, and ZIP code. We define the «true» location of each address as the point that visually represented the approximate center of the house using 1 m resolution digitally enhanced aerial orthoimagery. The orthoimagery was flown from 1994–98 and has a horizontal accuracy of 10 m [28]. Through this method, 2,674 (89%) addresses of the study group were assigned true locations.

Closely spaced homes were the most common problem in identifying the true location in urban areas. One meter resolution orthoimagery made it difficult to delineate some of the building rooftops. A more common problem in suburban addresses was dark rooftops surrounded by dense canopy cover from trees. In rural areas, detached garages, barns, and other large outbuildings made it difficult to distinguish the actual house.

Overall, we found only small differences in our ability to assign a true location between the three density classes. Four individuals were involved in creating true locations for the study sample addresses. A QA/QC assessment was performed on a random sample of 100 addresses to compare their decisions of where to place the true location. Results showed that discrepancies between all individuals were minimal, averaging only 3.3 m.

Fieldwork was completed in the summer of 2001 for the remaining 326 addresses which could not be confidently identified using in-house techniques. Staff used real time Global Positioning System technology and mapping software as a navigational aid to locate the address and identify the correct structure for that address. As with the in-house procedure, the point was then manually placed in the center of the correct structure using aerial imagery.

Analyses

Once true locations of all 3,000 addresses in our sample were determined, we calculated the straight-line distance between coordinates of the true locations and the automated geocoded points. This allowed us to compute the positional error, by population density, from traditional automated geocoding.

Without knowing the optimal settings, geocoding was initially performed using a street offset and corner inset of zero. We adjusted the default offset and inset settings in MapMarker to see if the positional error in the geocoded addresses could be reduced. The sample address file was re-geocoded using 5 m iterations of these values and compared to true locations to determine the optimal combination.

As an alternative to traditional methods relying on street centerline files, we calculated the distance between the true locations and the property parcel centroids assigned by local governments. This allowed us to compare the positional error between automated geocoding and using parcel data to locate addresses. An example of the three locations for each address is shown in Figure 3.

Figure 3
figure 3

Measuring positional error using two methods. Distances are measured from the true locations (triangles) to the automated geocoded points (squares) and to the residential parcel points (circles) to determine the positional error.

Full size image

We also investigated whether directional bias in the error could be introduced by data conversion issues, such as inconsistent projections or datums in the various GIS layers. A rose diagram was constructed using the directional error of the 3,000 addresses. We also calculated the angle of the errors to determine if the direction of the errors were uniform for both the automated geocoded points and the property parcel points using the modified Rayleigh test [29].

Results

We found substantial differences in positional error between the automated geocoded points and the corresponding true locations. In rural areas, 95 percent of the addresses geocoded to within 2,872 m of their true location, while in suburban areas the same percent of addresses geocoded to within 421 m. Urban areas showed the least error, where 95 percent of the addresses geocoded to within 152 m of their true location. The mean error for rural areas was 614 m, 143 m for suburban areas and 58 m in the urban area. Table 2 summarizes the error in automated geocoding using TIGER based files by percentile and density class. We also provide the root mean square error (RMSE). The RMSE provides a measure of the variation of this error following the National Standard for Reporting Spatial Data Accuracy [30]. The cumulative density distribution plot in Figure 4 can be used to estimate the percent error at any distance. Addresses having errors in excess of 5 km were examined more closely. It appeared that many of these large errors are due to inaccurate ZIP code boundary information in the software’s reference files. This resulted in addresses being placed in an adjacent ZIP code several kilometers from their true location.

Table 2 TIGER based positional error. Positional error is calculated by measuring the distance between address locations determined by automated geocoding methods using enhanced TIGER files and the true location of the houses. RMSE = Root Mean Square Error (radial). N = 1000 for each density class.

Full size table

Figure 4
figure 4

TIGER based positional error cumulative density distribution. This plot can be used to estimate the percent error at any distance for the three density classifications. The vertical dashed lines show the error distance at the 95th percentile.

Full size image

We found the optimal combination of the street offset and corner inset for the entire sample to be 15 m and 50 m respectively. This combination of values, however, only reduced the overall mean positional error from 272 to 265 m. Optimal values were actually determined for the rural, suburban and urban areas separately, but provided little additional benefit from using an average setting for all density areas. Using unique values for each area provided an additional reduction in the mean error of 2.1 m in rural areas, 0.1 m in the suburban areas, and 0.7 m in urban areas.

The use of property parcel coordinates significantly reduced the positional error. In rural areas, 95 percent of the parcel points were within 195 m of the true location. In suburban areas, this distance was 39 m and in urban areas was 21 m. The mean positional error of the parcel points for rural areas was reduced to 55 m compared to 614 m found in automated geocoding. The mean parcel error for suburban areas declined to 15 m from 143 m, while in urban areas the mean parcel error was reduced to 10 m from 58 m. Table 3 summarizes the parcel based positional error by percentile and density class. The scatter diagram in Figure 5 illustrates the dramatic differences between positional error using parcel points and traditional methods relying on enhanced TIGER files. As expected, the greatest improvements were seen in the rural areas.

Table 3 Parcel based positional error. Positional error is calculated by measuring the distance between property parcel locations and the true location of the houses. RMSE = Root Mean Square Error (radial). N = 1000 for each density class.

Full size table

Figure 5
figure 5

Scatter diagram of positional error by geocoding method and population density. Each point represents one residential address and there are 1000 addresses for each plot. The true location of each house is set to the center of the circles. The positional errors by density class of TIGER based geocoded addresses as measured from true location are shown in a,b,c; The positional error by density class of parcel-based points as measured from true location are shown in d,e,f.

Full size image

A visual inspection of the rose diagram showed that the directions of the error were well dispersed. The Rayleigh test confirmed that the angles of the errors were uniform for both the automated geocoded points and the parcel points.

Discussion

This project used address data typical of that which are geocoded for health studies. We calculated error only for the addresses which had an exact match on house number, street name and ZIP code to the reference files. If we considered the addresses that matched on less stringent criteria, both match rates and positional error would have increased. Yu showed that small improvements in achieving higher match rates by relaxing the matching criteria results in large decreases in positional accuracy [17]. Researchers often sacrifice positional error in order to reduce subject loss from lower match rates when resources are limited for accurately geocoding study subjects.

Several factors explain the positional error in the geocoded locations. The original TIGER files have a horizontal positional accuracy of ± 167 feet (51 m) [31]. The geocoding engine used in this project incorporates enhanced versions of these files. We are unaware of the improvement in geometric accuracy of these street centerlines over original TIGER files. Although it is difficult to measure, we feel that positional accuracy of the enhanced files represents a significant source of positional error in the geocoded addresses. Further research is needed to quantify this contribution to the error.

A more dominant source of error originates in the interpolation algorithms used to determine an address along a street centerline. Address ranges can be incorrect or reversed in the reference files, which causes houses to be geocoded to either the wrong side or wrong end of the street. Larger positional error was observed in rural areas. Generally, rural areas consist of longer streets with fewer intersections. The software must interpolate where to place an address based on the street numbers assigned to the ends of each street segment. As the street segments increase in length, the interpolation error will also increase. In a study of vehicle accident locations, Levine et al. reached a similar conclusion that geocoding error is a function of street segment length and urban areas typically contained shorter segments [11]. Since the software often assumes uniform intervals between street numbers along a street segment, interpolation errors increase when homes are not evenly spaced along a street. Parcels tend to be larger and less consistent in size in less densely populated areas. The median parcel size in our random sample was found to be 472 m2 in the urban areas, 1214 m2 in the suburban areas and 3035 m2 in the rural areas. The variation in parcel size showed a similar trend. In those properties classified urban, the standard deviation was 445 m2, for suburban was 5024 m2, while in rural areas increased to 56,046 m2. Finally, there is a greater variation in the distance houses are located from the street centerlines in rural areas. In the urban settings, a common problem was row type housing or condominiums. Reference files space the addresses uniformly along the street when in fact the addresses are clustered together.

A spatial non-stationary process is evident if statistical parameters such as the mean and variance change with location. Non-stationarity of the positional error may have some important implications in environmental health studies. For example, in urban areas where the error is small we may notice an association between an environmental risk factor and a particular health outcome. In other areas having greater error, associations may be more difficult to detect. In addition, some types of environmental exposures, such as exposures to air pollution from traffic or exposures to agricultural pesticides, are associated with population density. If the level of error varies as the level of exposure changes, the study parameters which estimate the relationship between a risk factor and a health outcome may also be impacted. Global statistical methods perform poorly at uncovering important associations in which the statistical parameters vary locally due to non-stationarity. [32]. This has lead to an increase in the use of local spatial statistical methods for detecting clustering and localized associations between health outcomes and risk factors.

Though no systematic directional bias in our random sample of addresses was found, we did not determine if systematic error may be present in localized areas. Addresses on a particular street, in close proximity to each other, or within the same ZIP code may all have error of similar direction and distance. For example, the geocoding software may place all the addresses in a local area at some distance from the true street location if a street is misnamed, has incorrect address ranges, or if a ZIP code is incorrect in the street reference file. Burra et al. [10] demonstrated that very localized geocoding errors in which less than one percent of mortality cases are placed in the wrong census area can lead to differences in up to 75 percent of comparative mortality figures in Hamilton, Ontario, census tracts. Once they had more accurately geocoded the cases they found that approximately 80 percent of the difference in number of cases occurred in only 4 of the 88 census tracts studied. In addition, the size and shape of the clusters that were detected using the local Moran I statistic changed when the geocoding errors were corrected. This was a result of errors being concentrated in localized areas. Further work is needed to measure the strength of the spatial autocorrelation of the geocoding errors by distance and direction.

We attempted to reduce the positional error by optimizing the offset and inset default values in the software. Changing these values contributed very little to reducing overall error. Previous work by Ratcliffe [22] also did not yield significant reduction in the positional error by altering the offset and inset distances.

The use of property parcel points provides one solution for reducing error when the level of error in traditional geocoding methods is not acceptable. The parcel data clearly contains more accurate locations for the individual houses compared to TIGER based files. Parcel centroids are rarely at the exact location of the house. In urban areas the centroid will more closely represent the location of the actual house because of smaller parcels and more uniform spacing of homes. In rural areas this becomes less likely. The use of parcel data may also help to improve match rates since the parcel data is updated on a yearly basis for tax purposes, while commonly used street centerline files are often updated less frequently.

Though the use of parcel points provides greater positional accuracy, the parcel addresses are often not standardized. Residential and commercial addresses are collected by thousands of local governments across the country. This can lead to a lack of standardization in the way addresses are stored in the data files. The challenge is to standardize the millions of New York addresses and add a ZIP code to each property parcel record. Commercially available software programs are available which can be used to help standardize the parcel addresses. Once standardized, linkage to health outcome data could be achieved more efficiently and with the same effort as using currently available TIGER based files.

We considered using data from local county emergency E911 systems to improve geocoding accuracy. However, we found that each county in New York State developed their own E911 system for providing route directions to emergency responders. These systems range from simple text based to more elaborate systems using GIS. The files used in E911 systems come from a variety of sources. Some counties rely exclusively on TIGER based files, some use real property assessment data, while others use files from telephone or electric utility companies. The county E911 data is often considered either confidential or proprietary depending on the source. For example, E911 systems often contain the addresses of unlisted telephone numbers. The advantages of using New York State real property data are that the format is more consistent across the state and is available through freedom of information requests. In addition, most of the counties and municipalities report the data directly to NYSORPS. This minimizes the number of requests needed in developing a statewide reference file.

There are some limitations in our study. Since the TIGER files are often derived from data provided by state and local governments, the geometric accuracy and address range completeness may differ in other areas. For this reason, it is difficult to predict if the magnitude of the geocoding error resulting from positional inaccuracy and interpolation error would be similar in other areas of the country. However, we would expect that interpolation issues contributing to positional error will remain the dominant source and correlate highly with population density in most areas. This is due to such issues as longer street segments and houses being spaced further apart in less densely populated areas. In addition to population density, there may be other predictors of positional error such as population growth or sociodemographic variables. Further research is needed in this regard. This study assumes our true locations to be error free. We recognize there is some positional error in the true locations assigned. However, this error is quite small compared to the error caused by the automated geocoding process and should not have a major impact on our results.

We only provide results from one geocoding package. We are uncertain of how the results would change if other products were used on the same set of address data. Most products we are aware of rely on the use of TIGER or enhanced TIGER files. As the geometric accuracy and completeness of the street centerline files improve, we would expect positional error to decrease. However, because houses are often not spaced evenly along streets, there will continue to be greater error using linear interpolation techniques compared to using parcel points to locate addresses.

Conclusions

It is important that researchers determine if the level of error caused by a chosen method of geocoding may affect the results of their project. In the past, researchers appeared to pay little attention to understanding positional error from geocoding. Foote and Huebner report that only recently has more attention been devoted to problems introduced by error, inaccuracy, and imprecision in spatial data and how this can «make or break» a GIS project [33]. The location derived from the geocoding process is often used as input to other operations such as assignment of exposure or socioeconomic class. These assignments are often based on models which also have inherent error. When multiple operations are strung together, errors are often compounded making it difficult to evaluate the accuracy of the final result [34, 35]. Burra et al. [10] suggest that small geocoding errors, when combined with other types of error in the data, may be amplified into large errors in the final results. Though researchers may be aware that error propagates through the various analyses, they are unable to estimate the accuracy of the final results without first recording the errors of intermediate operations such as geocoding.

Krieger et al. [16] recommends «that all public health projects involving geocoding evaluate and report on methods to verify the accuracy of their geocoding methodology». If the error caused by traditional methods is not acceptable, one consideration is the use of property data to geocode health data.

We are currently conducting further analyses to determine the implications positional error has on the misclassification of individuals with respect to exposure. Copeland et al. [36] provides examples of how to measure the underlying true value of a study’s odds ratio or relative risk if the sensitivity and specificity of a classification procedure can be measured. We also need to examine whether the errors are random and bias study results towards the null, or whether there are systematic errors which could lead to erroneous positive results.

References

  1. Geschwind SA, Stolwijk JAJ, Bracken M, Fitzgerald E, Stark A, Olsen C, Melius J: Risk of congenital malformations associated with proximity to hazardous waste sites. Am J Epidemiol. 1992, 135: 1197-1207.

    PubMed 
    CAS 

    Google Scholar 

  2. English P, Neutra R, Scalf R, Sullivan M, Waller L, Zhu L: Examining associations between childhood asthma and traffic flow using a geographic information system. Environ Health Perspect. 1999, 107: 761-767.

    Article 
    PubMed 
    CAS 
    PubMed Central 

    Google Scholar 

  3. Lewis-Michl EL, Melius JM, Kallenbach LR, Ju CL, Talbot TO, Orr MF, Lauridsen PE: Breast cancer risk and residence near industry or traffic in Nassau and Suffolk Counties, Long Island, New York. Arch Environ Health. 1996, 51: 255-265.

    Article 
    PubMed 
    CAS 

    Google Scholar 

  4. Reynolds P, Von Behren JV, Gunier RB, Goldberg DE, Hertz A, Smith DF: Childhood cancer incidence rates and hazardous air pollutants in California: An exploratory analysis. Environ Health Perspect. 2003, 111: 663-668.

    Article 
    PubMed 
    CAS 
    PubMed Central 

    Google Scholar 

  5. Kitto ME, Kunz CO, Green JG: Development and distribution of radon risk maps in New York State. J Radioanal Nucl Chem. 2001, 249: 153-157. 10.1023/A:1013284514208.

    Article 
    CAS 

    Google Scholar 

  6. Rushton G, Lolonis P: Exploratory spatial analysis of birth defect rates in an urban population. Stat Med. 1996, 15: 717-726. 10.1002/(SICI)1097-0258(19960415)15:7/9<717::AID-SIM243>3.0.CO;2-0.

    Article 
    PubMed 
    CAS 

    Google Scholar 

  7. Talbot TO, Kulldorff M, Forand SP, Haley VB: Evaluation of spatial filters to create smoothed maps of health data. Stat Med. 2000, 19: 2399-2408. 10.1002/1097-0258(20000915/30)19:17/18<2399::AID-SIM577>3.3.CO;2-I.

    Article 
    PubMed 
    CAS 

    Google Scholar 

  8. Anselin L: Local indicators of spatial association — LISA. Geogr Anal. 1995, 27: 93-115.

    Article 

    Google Scholar 

  9. Kulldorff M, Nagarwalla N: Spatial disease clusters: detection and inference. Stat Med. 1995, 14: 799-810.

    Article 
    PubMed 
    CAS 

    Google Scholar 

  10. Burra T, Jerrett M, Burnett RT, Anderson M: Conceptual and practical issues in the detection of local disease clusters: a study of mortality in Hamilton, Ontario. Can Geogr. 2002, 46: 160-171.

    Article 

    Google Scholar 

  11. Levine N, Kim KE: The location of motor vehicle crashes in Honolulu: a methodology for geocoding intersections. Comput Environ Urban. 1998, 22: 557-576. 10.1016/S0198-9715(98)00034-9.

    Article 

    Google Scholar 

  12. Dearwent SM, Jacobs RR, Halbert JB: Locational uncertainty in georeferencing public health datasets. J Expo Anal Environ Epidemiol. 2001, 11: 329-334. 10.1038/sj.jea.7500173.

    Article 
    PubMed 
    CAS 

    Google Scholar 

  13. Fulcomer MC, Bastardi MM, Raza H, Duffy M, Dufficy E, Sass MM: Assessing the accuracy of geocoding using address data from birth certificates: New Jersey, 1989 to 1996. http://www.atsdr.cdc.gov/gis/conference98/proceedings/proceedings.html (accessed 2003). In proceedings of the Third National Geographic Information Systems in Public Health Conference, San Diego, August 18-20 1998, 547-560.

  14. Krieger N, Chen JT, Waterman PD, Soobader MJ, Subramanian SV, Carson R: Geocoding and monitoring of US socioeconomic inequalities in mortality and cancer incidence: Does the choice of area-based measure and geographic level matter? The Public Health Disparities Geocoding Project. Am J Epidemiol. 2002, 156: 471-482. 10.1093/aje/kwf068.

    Article 
    PubMed 

    Google Scholar 

  15. Krieger N, Waterman P, Chen JT, Soobader MJ, Subramanian SV, Carson R: ZIP code caveat: Bias due to spatiotemporal mismatches between ZIP codes and US census-defined geographic areas. The Public Health Disparities Geocoding Project. Am J Public Health. 2002, 92: 1100-1102.

    Article 
    PubMed 
    PubMed Central 

    Google Scholar 

  16. Krieger N, Waterman P, Lemieux K, Zierler S, Hogan JW: On the wrong side of the tracts? Evaluating the accuracy of geocoding in public health research. Am J Public Health. 2001, 91: 1114-1116.

    Article 
    PubMed 
    CAS 
    PubMed Central 

    Google Scholar 

  17. Yu Lixin: Development and evaluation of a famework for assessing the efficiency and accuracy of street address geocoding strategies. 1996, PhD thesis. University at Albany, State University of New York — Rockefeller College of Public Affairs and Policy, 1-164.

    Google Scholar 

  18. Nie J, Bonner MR, Vito D, Willett NH, Freudenheim JL: Validation of TIGER (Topologically Integrated Geographic Encoding and Referencing System) to geocode addresses for epidemiologic research. Am J Epidemiol. 2001, Suppl 179: 647-

    Google Scholar 

  19. Howe HL: Geocoding NY State Cancer Registry. Am J Public Health. 1986, 76: 1459-1460.

    Article 
    PubMed 
    CAS 
    PubMed Central 

    Google Scholar 

  20. Gregorio DI, Cromley E, Mrozinski R, Walsh SJ: Subject loss in spatial analysis of breast cancer. Health Place. 1999, 5: 173-177. 10.1016/S1353-8292(99)00004-0.

    Article 
    PubMed 
    CAS 

    Google Scholar 

  21. Using Geographic Information Systems Technology in the Collection, Analysis, and Presentation of Cancer Registry Data: A Handbook of Basic Practices. Edited by: Wiggins. 2002, Springfield (IL), North American Association of Central Cancer Registries,

  22. Ratcliffe JH: On the accuracy of TIGER-type geocoded address data in relation to cadastral and census areal units. Int J Geogr Inf Sci. 2001, 15: 473-485. 10.1080/13658810110047221.

    Article 

    Google Scholar 

  23. US Bureau of the Census: TIGER/Line 1997. CD-TGR97-01. 1998, Washington, DC, US Department of Commerce

    Google Scholar 

  24. Bonner MR, Han D, Nie J, Rogerson P, Vena JE, Freudenheim JL: Positional accuracy of geocoded addresses in epidemiologic research. Epidemiology. 2003, 14: 408-412. 10.1097/00001648-200307000-00006.

    PubMed 

    Google Scholar 

  25. New York State Office of Real Property Services: 1999 Real Property Data. 2000, NYS Office of Real Property Services

    Google Scholar 

  26. US Bureau of the Census: 1990 Census of population and housing summary tape file 1A. 1991, Prepared by Bureau of the Census, Washington, DC

    Google Scholar 

  27. MapInfo Corporation: MapMarker Plus — Version 6.0. 2000, Troy, NY

    Google Scholar 

  28. New York State Department of State: New York State 2000 Digitally Enhanced OrthoImagery. 1999, NYS Department of State

    Google Scholar 

  29. Mardia KV, Jupp PE: Directional Statistics. 2000, Chichester, John Wiley & Sons Ltd

    Google Scholar 

  30. Federal Geographic Control Subcommittee: Geospatial Positioning Accuracy Standards. FGDC-STD-007. 1998, Reston, Virginia, Federal Geographic Data Committee

    Google Scholar 

  31. US Bureau of the Census: TIGER/Line Files 1997 Technical Documentation. 1997, Washington, DC, US Department of Commerce

    Google Scholar 

  32. Fotheringham AS, Brunsdon C, Charlton M: Quantitative Geography. Perspectives on Spatial Data Analysis. 2000, London, SAGE Publications Ltd

    Google Scholar 

  33. Foote KE, Huebner DJ: Error, Accuracy, and Precision. 2000, http://www.colorado.edu/geography/gcraft/notes/error/error.html (accessed 2003). The Geographer’s Craft Project, Dept. of Geography, University of Colorado at Boulder

    Google Scholar 

  34. Griffith DA, Haining RP, Arbia G: Chapter 2: Uncertainty and error propagation in map analyses involving arithmetic and overlay operations: inventory and prospects. Spatial Accuracy Assessment; Land Information Uncertainity in Natural Resources. 1999, Michigan, Sleeping Bear Press, Inc., 11-25.

    Google Scholar 

  35. Heuvelink GBM: Chapter 14: Propagation of error in spatial modelling with GIS. Geographical Information Systems. Volume1. Edited by: Longley PA, Goodchild MF, Maguire DJ and Rhind DW. 1999, New York, John Wiley & Sons, Inc., 207-217. 2nd

    Google Scholar 

  36. Copeland KT, Checkoway H, McMichael AJ, Holbrook RH: Bias due to misclassification in the estimation of relative risk. Am J Epidemiol. 1977, 105: 488-495.

    PubMed 
    CAS 

    Google Scholar 

Download references

Acknowledgements

We thank Chris Pantea and Valerie Haley for their assistance with statistical analysis, Pat Steen and Frank Schoonbeck for their assistance in fieldwork, and Jim Bowers and Deepa Varadarajulu for their assistance in determining photo corrected true locations for residential addresses. We thank Syni-An Hwang, Steve Forand, Francis Boscoe, and Gwen Babcock for providing editorial comments on this manuscript.

Author information

Authors and Affiliations

  1. Geographic Research and Analysis Section, Bureau of Environmental and Occupational Epidemiology, New York State Department of Health, 547 River Street, Room 200, 12180-2216, Troy, NY, USA

    Michael R Cayo & Thomas O Talbot

Authors

  1. Michael R Cayo

    You can also search for this author in
    PubMed Google Scholar

  2. Thomas O Talbot

    You can also search for this author in
    PubMed Google Scholar

Corresponding author

Correspondence to
Michael R Cayo.

Additional information

Authors’ contributions

This project was a joint collaboration between authors MRC and TOT. Both contributed to all phases of design concepts, data acquisition, processing, fieldwork, and analysis. Both authors prepared and approved the final manuscript and figures.

Authors’ original submitted files for images

Rights and permissions

About this article

Cite this article

Cayo, M.R., Talbot, T.O. Positional error in automated geocoding of residential addresses.
Int J Health Geogr 2, 10 (2003). https://doi.org/10.1186/1476-072X-2-10

Download citation

  • Received:

  • Accepted:

  • Published:

  • DOI: https://doi.org/10.1186/1476-072X-2-10

Keywords

  • Census Tract
  • Street Segment
  • True Location
  • Positional Error
  • Match Rate

Одной из ключевых технологий, используемых в современных приложениях и сервисах, является геокодирование. Геокодирование — это процесс преобразования адресов или названий местоположений в географические координаты (широту и долготу). Это позволяет разработчикам создавать интерактивные карты, маршрутные планировщики, сервисы поиска ближайших мест, и многое другое.

Один из самых популярных геокодеров — это сервис Google Maps Geocoding API. Он предоставляет разработчикам возможность использовать мощный инструмент геокодирования, который может выполнять поиск адресов или местоположений, а также предоставлять дополнительную информацию о них.

Однако, при работе с Google Maps Geocoding API разработчики могут столкнуться с ошибкой «Invalid API key» при выполнении прямого геокодирования. Что это значит и как ее исправить?

Первоначально, необходимо понять, что API ключ — это уникальный идентификатор, который выдается разработчику при регистрации приложения на платформе Google Cloud. Этот ключ необходим для авторизации запросов к сервисам Google, включая Google Maps Geocoding API.

Ошибку «Invalid API key» можно получить в нескольких случаях. Обычно это происходит, когда API ключ отсутствует, недействителен, истек или доступ к сервису был отключен.

Первым шагом для исправления этой ошибки является проверка наличия и правильности API ключа. Убедитесь, что вы правильно скопировали и вставили ключ в свой код. Также проверьте, не истек ли срок действия ключа или не был ли отключен доступ к сервису. Если ключ недействителен или истек, необходимо получить новый ключ.

Если API ключ правильный, но ошибка все равно возникает, может понадобиться проверить настройки аутентификации и авторизации в панели управления Google Cloud. Убедитесь, что ваше приложение имеет право использовать Google Maps Geocoding API и что все необходимые разрешения установлены.

Еще одним возможным источником проблемы может быть ограничение на использование API ключа. Google Maps Geocoding API предоставляет определенное количество бесплатных запросов в месяц, после чего может начисляться оплата за использование. Убедитесь, что вы не превысили лимит бесплатных запросов или что у вас есть достаточное количество средств на вашем аккаунте Google Cloud для покрытия затрат.

Если все настройки и ключи были проверены и исправлены, а ошибка все равно возникает, возможно, проблема заключается в коде вашего приложения. Проверьте ваш код на наличие ошибок, опечаток или неправильных параметров запроса. Возможно, эти ошибки приводят к некорректной передаче API ключа или неправильно сформированным запросам.

Также стоит отметить, что в зависимости от используемого языка программирования и библиотеки, есть различные способы взаимодействия с Google Maps Geocoding API. У вас может быть несовместимость версий библиотеки с API, что также может вызвать ошибку «Invalid API key». Проверьте документацию и примеры использования API для вашего языка программирования, чтобы убедиться, что вы используете правильную версию библиотеки и правильно формируете запросы к сервису.

В заключение, ошибка «Invalid API key» с прямым геокодированием в Google Maps Geocoding API может быть вызвана несколькими причинами, от неправильного API ключа до настроек в панели управления Google Cloud или ошибок в коде. Проверьте каждый из этих аспектов и исправьте возможные ошибки. Если проблема все равно продолжается, обратитесь в техническую поддержку Google для получения дополнительной помощи.

Power Map поддерживает несколько форматов и уровней географических данных, в том числе:

  • широта и долгота (в десятичном формате);

Данные о широте и долготе

  • адрес;

  • город;

  • район;

  • область или край;

  • почтовый индекс;

  • страна или регион.

Чтобы отобразить данные, в списке полей выберите столбцы, определяющие географическое положение, и укажите географический уровень, который они представляют. Power Map отображает эти данные.

Например, Power Map автоматически определяет и сопоставляет столбцы в этом наборе данных с географическими полями.

Структура данных для Power Map

В данном случае Power Map начинает геокодирование данных на основе адреса, например:

География и уровень карты в области задач

После проверки соответствие полей географическим уровням в разделе Geography (География) и нажатия кнопки «Далее» Power Map автоматически начинается отрезок данных с помощью Bing. Вы увидите ход выполнения в панели состояния, и сможете вносить изменения в список полей и глобус, Power Map географические данные.

Состояние Power Map на Панели Bing

Если имеется несколько географических уровней, вы можете быстро просмотреть на карте данные на другом уровне. В нашем примере при выборе уровня Улица визуализируются данные по улицам, например:

Power Map с данными по улицам

При выборе уровня Область визуализируются данные по областям, например:

Power Map с данными по штатам

Изменение географических полей

Чтобы изменить географические поля, отображаемые по умолчанию на карте, выберите другие поля в списке География. Они автоматически появятся в области Уровень географии и карты, в которой вы можете проверить и изменить уровень отображения на карте.

Распространенные ошибки геокодирования

В процессе геокодирования могут возникать конфликты. Например, Power Map может показывать сообщение об ошибке, если не удается сопоставить некоторые географические поля. Это возможно, если имеется несколько городов с одинаковым именем в разных областях, например Советск.

Power Map и Bing пытаются найти решение, просматривая вспомогательные данные, чтобы определить местонахождение города из каждой строки данных, — они проверяют область, страну или регион, край и другие географические поля. Если дополнительные данные есть, город появляется на карте, но иногда строки пропускаются. Чтобы избежать подобных конфликтов, попробуйте добавить столбцы с дополнительными данными (например, почтовым индексом или страной), тогда Power Map сможет использовать эти сведения для более точного определения местонахождения.

Нужна дополнительная помощь?

Нужны дополнительные параметры?

Изучите преимущества подписки, просмотрите учебные курсы, узнайте, как защитить свое устройство и т. д.

В сообществах можно задавать вопросы и отвечать на них, отправлять отзывы и консультироваться с экспертами разных профилей.

Содержание страницы

Вы научились получать информацию о координатах GPS с устройства и отображать ее на экране.

В этой главе вы узнаете следующее:

  • Обработка ошибок GPS: Получение информации GPS-это процесс, подверженный ошибкам. Как вы справляетесь с ошибками?
  • Улучшение результатов GPS: Как повысить точность результатов GPS, которые вы получаете.
  • Обратное геокодирование: получение адреса для заданного набора GPS — координат.
  • Тестирование на устройстве: тестирование на устройстве, чтобы убедиться, что ваше приложение обрабатывает реальные сценарии.
  • Поддержка различных размеров экрана: настройка пользовательского интерфейса для работы на устройствах iOS с различными размерами экрана.

Обрабатывать ошибки GPS

Получение GPS-координат подвержено ошибкам. Возможно, вы находитесь где-то там, где нет четкой прямой видимости неба-например, внутри или в районе с большим количеством высоких зданий, — блокируя сигнал GPS.

Возможно, вокруг вас не так много Wi-Fi-маршрутизаторов, или они еще не каталогизированы, так что Wi-Fi-радио тоже не очень помогает определить местоположение. И, конечно, ваш сотовый сигнал может быть настолько слабым, что триангуляция вашего местоположения также не даст особенно хороших результатов.

Все это при условии, что на вашем устройстве действительно есть GPS или сотовое радио. Я просто вышел со своим iPod touch, чтобы захватить координаты и получить несколько фотографий для этого приложения. В центре города ему не удалось зафиксировать свое местоположение. Мой iPhone работал лучше, но все равно не был идеальным.

Мораль этой истории заключается в том, что ваши приложения, ориентированные на местоположение, лучше знают, как справляться с ошибками и плохими показаниями. Нет никаких гарантий, что вы сможете установить местоположение, а если и сможете, то это все равно может занять несколько секунд.

Именно здесь программное обеспечение встречается с реальным миром. Вы должны добавить в приложение код обработки ошибок, чтобы пользователи знали о проблемах с получением этих координат.

Код обработки ошибок

  • Добавьте эти две переменные экземпляра в CurrentLocationViewController.swift:
var updatingLocation = false
var lastLocationError: Error?

locationManager(_:didFailWithError:) Изменение на следующее :

func locationManager(
  _ manager: CLLocationManager, 
  didFailWithError error: Error
) {
  print("didFailWithError \(error.localizedDescription)")

  if (error as NSError).code == CLError.locationUnknown.rawValue {
    return
  }
  lastLocationError = error
  stopLocationManager()
  updateLabels()
}

Диспетчер местоположений может сообщать об ошибках для различных сценариев. Вы можете посмотреть на code свойство Error объекта, чтобы узнать, с каким типом ошибки вы имеете дело. Вам нужно сначала привести NSError, так как это подкласс Error, который на самом деле содержит свойство code.

Некоторые из возможных ошибок в расположении ядра:

  • CLError.locationUnknown — местоположение в настоящее время неизвестно, но Основное местоположение будет продолжать пытаться.
  • CLError.denied — пользователь отказал приложению в разрешении на использование геолокационных служб.
  • CLError.network — произошла ошибка, связанная с сетью.

Есть и другие, но вы поняли, в чем дело. Куча причин для того, чтобы что-то пошло не так!

Примечание: Эти коды ошибок определены в CLError перечислении. Напомним , что перечисление или enum— это список значений и имен для этих значений.

Коды ошибок, используемые Core Location, имеют простые целочисленные значения. Вместо того чтобы использовать значения 0, 1, 2 и так далее в вашей программе, Core Location дала им символические имена с помощью CLError перечисления. Это делает эти коды более понятными, и у вас меньше шансов выбрать неправильный.

Чтобы преобразовать эти имена обратно в целочисленное значение, вы запрашиваете rawValue.

В своей обновленной locationManager(_:didFailWithError:)версии вы делаете:

if (error as NSError).code == CLError.locationUnknown.rawValue {
  return
}

Ошибка CLError.locationUnknown означает, что менеджер местоположений не смог получить местоположение прямо сейчас, но это не значит, что все потеряно. Возможно, потребуется еще секунда или около того, чтобы получить восходящую связь со спутником GPS. В то же время он дает вам знать, что на данный момент он не может получить никакой информации о местоположении.

Когда вы получите эту ошибку, вы просто будете продолжать попытки, пока не найдете местоположение или не получите более серьезную ошибку.

В случае более серьезной ошибки вы сохраняете объект error в новой переменной экземпляра, lastLocationError:

lastLocationError = error

Таким образом, позже вы сможете посмотреть, с какой ошибкой вы имели дело. Это пригодится в updateLabels()будущем . Вскоре вы измените этот метод, чтобы показать ошибку пользователю, потому что не хотите оставлять его в неведении о таких вещах.

Упражнение: Можете ли вы объяснить, почему lastLocationError это необязательно?

Ответ: Когда ошибки нет, lastLocationErrorзначения иметь не будет. Другими словами, это может быть nil, и переменные, которые могут бытьnil, должны быть опционными в Swift.

Наконец, обновление locationManager(_:didFailWithError:)добавляет новый вызов метода:

stopLocationManager()

Остановка обновления местоположения

Если получение местоположения кажется невозможным для того места, где пользователь в данный момент находится на земном шаре, то вам нужно сказать менеджеру местоположений, чтобы он остановился. Чтобы сэкономить заряд батареи, приложение должно выключить радиоприемники iPhone, как только они ему больше не понадобятся.

Если бы это было пошаговое навигационное приложение, вы бы продолжали работать с диспетчером местоположений даже в случае сетевой ошибки, потому что, кто знает, на пару метров вперед вы могли бы получить действительное местоположение.

Для этого приложения пользователю просто нужно будет снова нажать кнопку «Получить мое местоположение», если он захочет попробовать в другом месте.

  • Добавьте stopLocationManager() метод:

func stopLocationManager() { if updatingLocation { locationManager.stopUpdatingLocation() locationManager.delegate = nil updatingLocation = false } }

Существует ifоператор, который проверяет, является ли переменная экземпляра boolean переменной updatingLocation``trueor false. Если это так false, то диспетчер местоположений в данный момент не активен, и нет необходимости останавливать его.

Причина наличия этой переменной updatingLocation заключается в том, что вы собираетесь изменить внешний вид кнопки Get My Location и метки сообщения о состоянии, когда приложение пытается получить исправление местоположения, чтобы пользователь знал, что приложение работает над ним.

  • Введите дополнительный код, updateLabels() чтобы показать сообщение об ошибке.:

func updateLabels() { if let location = location { . . . } else { . . . // Remove the following line messageLabel.text = "Tap 'Get My Location' to Start" // The new code starts here: let statusMessage: String if let error = lastLocationError as NSError? { if error.domain == kCLErrorDomain && error.code == CLError.denied.rawValue { statusMessage = "Location Services Disabled" } else { statusMessage = "Error Getting Location" } } else if !CLLocationManager.locationServicesEnabled() { statusMessage = "Location Services Disabled" } else if updatingLocation { statusMessage = "Searching..." } else { statusMessage = "Tap 'Get My Location' to Start" } messageLabel.text = statusMessage } }

Новый код определяет, что нужно поместить messageLabel в верхнюю часть экрана. Он использует кучу if утверждений, чтобы выяснить, каков текущий статус приложения.

Если диспетчер местоположений выдал ошибку, на этикетке появится сообщение об ошибке.

Первая ошибка , которую он проверяет, находится CLError.deniedв домене ошибокkCLErrorDomain, что означает ошибки расположения ядра. В этом случае пользователь не дал этому приложению разрешения на использование геолокационных служб. Это вроде как противоречит цели этого приложения, но это может случиться, и вы все равно должны проверить это. Если код ошибки-это что-то другое, то вы просто говорите “Ошибка получения местоположения”, так как это обычно означает, что не было никакого способа получить исправление местоположения.

Даже если ошибки не было, получить координаты местоположения все равно было бы невозможно, если бы пользователь полностью отключил службы определения местоположения на своем устройстве, а не только для этого приложения. Вы проверяете эту ситуацию с locationServicesEnabled() помощью метода CLLocationManager.

Предположим, ошибок не было и все работает нормально, тогда метка состояния скажет “Поиск…” до того, как будет получен первый объект местоположения.

Если ваше устройство может быстро получить исправление местоположения, то этот текст будет виден только в течение доли секунды, но часто для получения этого первого исправления местоположения может потребоваться некоторое время. Никто не любит ждать, поэтому приятно сообщить пользователю, что приложение активно ищет его местоположение. Это то, для чего вы используете updatingLocationлогическое значение.

Примечание: Вы помещаете всю эту логику в один метод, потому что это позволяет легко изменить экран, когда что-то изменилось. Получил место? Просто позвонитеupdateLabels(), чтобы обновить содержимое экрана. Получили ошибку? Давайте updateLabels()разберемся…

Начать обновление местоположения

  • Также добавьте новый startLocationManager()метод — я предлагаю вам поместить его прямо выше stopLocationManager(), чтобы сохранить связанные функции вместе.:

func startLocationManager() { if CLLocationManager.locationServicesEnabled() { locationManager.delegate = self locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters locationManager.startUpdatingLocation() updatingLocation = true } }

Запуск диспетчера местоположений раньше происходил в методе getLocation()action. Однако, поскольку теперь у stopLocationManager()вас есть метод, имеет смысл переместить начальный код в собственный метод, просто чтобы все было симметрично.

Единственное отличие от предыдущего заключается в том, что при этом проверяется, включены ли службы определения местоположения, и вы устанавливаете переменную updatingLocationв trueзначение, действительно ли вы запустили обновления местоположения.

Изменение на getLocation():

@IBAction func getLocation() { . . . if authStatus == .denied || authStatus == .restricted { . . . } // New code below, replacing existing code after this point startLocationManager() updateLabels() }

Есть еще одно крошечное изменение. Предположим, произошла ошибка, и никакое местоположение не может быть получено, но затем вы немного походите вокруг, и появляется действительное местоположение. В этом случае неплохо бы удалить старый код ошибки.

  • В нижней части locationManager(_:didUpdateLocations:)добавьте следующую строку непосредственно перед вызовомupdateLabels():

lastLocationError = nil

Это очищает старое состояние ошибки. После получения действительной координаты любая предыдущая ошибка, с которой вы могли столкнуться, больше не применима.

  • Запустите приложение и нажмите Получить мое местоположение. Пока приложение ожидает входящих координат, надпись вверху должна гласить “Поиск…” до тех пор, пока оно не найдет правильную координату или не обнаружит фатальную ошибку.

Приложение ждет получения GPS - координат

Приложение ждет получения GPS — координат

Поиграйте некоторое время с настройками местоположения симулятора и посмотрите, что происходит, когда вы выбираете разные локации.

Обратите внимание, что изменение местоположения симулятора на Нет больше не является ошибкой. Это все еще возвращает код .locationUnknown ошибки, но вы игнорируете его, потому что это не фатальная ошибка.

В идеале вы должны тестировать не только в симуляторе, но и на своем устройстве, так как таким образом вы с большей вероятностью столкнетесь с реальными ошибками.

Улучшение результатов GPS

Круто, вы знаете, как получить CLLocationобъект из основного местоположения, и вы можете обрабатывать ошибки. И что теперь?

Ну, вот в чем дело: вы видели в симуляторе, что Core Location продолжает давать вам новые объекты местоположения снова и снова, даже если координаты, возможно, не изменились. Это потому, что пользователь может быть в движении, и в этом случае его GPS-координаты действительно меняются.

Однако вы не создаете навигационное приложение. Таким образом, для MyLocations вы просто хотите получить достаточно точное местоположение, а затем вы можете сказать менеджеру местоположений прекратить отправку обновлений.

Это важно, потому что получение обновлений местоположения требует большого заряда батареи, так как для этого устройство должно поддерживать питание своих GPS /Wi-Fi/ сотовых радиостанций. Этому приложению не нужно постоянно запрашивать GPS-координаты, поэтому оно должно остановиться, когда местоположение будет достаточно точным.

Проблема в том, что вы не всегда можете получить нужную точность, поэтому вам нужно это обнаружить. Когда последние пару координат, которые вы получили, не увеличиваются в точности, это, вероятно, так же хорошо, как и должно быть, и вы должны отключить питание радио.

Получение результатов для определенного уровня точности

Изменение на следующее locationManager(_:didUpdateLocations:): :

func locationManager(
  _ manager: CLLocationManager, 
  didUpdateLocations locations: [CLLocation]
) {
  let newLocation = locations.last!
  print("didUpdateLocations \(newLocation)")

  // 1
  if newLocation.timestamp.timeIntervalSinceNow < -5 {
    return
  }

  // 2
  if newLocation.horizontalAccuracy < 0 {
    return
  }

  // 3
  if location == nil || location!.horizontalAccuracy > newLocation.horizontalAccuracy {

    // 4
    lastLocationError = nil
    location = newLocation

    // 5
    if newLocation.horizontalAccuracy <= locationManager.desiredAccuracy {
      print("*** We're done!")
      stopLocationManager()
    }
    updateLabels()
  }
}

Давайте рассмотрим эти изменения один за другим:

  1. Если время, в которое был определен данный объект местоположения, слишком велико — в данном случае 5 секунд, — то это кэшированный результат. Вместо того чтобы возвращать новое исправление местоположения, менеджер местоположений может сначала дать вам самое последнее найденное местоположение, предполагая, что вы, возможно, не сильно переместились за последние несколько секунд — очевидно, это не учитывает людей с реактивными ранцами. Вы просто проигнорируете эти кэшированные местоположения, если они слишком старые.
  2. Чтобы определить, являются ли новые показания более точными, чем предыдущие, вы будете использовать horizontalAccuracy свойство объекта location. Однако иногда местоположения могут иметь значение a horizontalAccuracy меньше 0. В этом случае эти измерения недействительны, и вы должны игнорировать их.
  3. Именно здесь вы определяете, является ли новое чтение более полезным, чем предыдущее. Вообще говоря, Core Location начинается с довольно неточных показаний, а затем с течением времени дает вам все более и более точные данные. Однако никаких гарантий нет — поэтому вы не можете предполагать, что следующее чтение действительно всегда будет более точным. Обратите внимание, что большее значение точности означает меньшую точность — в конце концов, точность до 100 метров хуже, чем точность до 10 метров. Вот почему вы проверяете, больше ли предыдущее чтение , location!.horizontalAccuracy чем новое чтение, newLocation.horizontalAccuracy.
    Вы также проверяете location == nil.
    Напомним, что locationэто необязательная переменная экземпляра, в которой хранится CLLocation объект, полученный в предыдущем вызове didUpdateLocations. Если locationnil, то это самое первое обновление местоположения, которое вы получаете, и в этом случае вы должны продолжить.
    Итак, если это самое первое считывание местоположения (location is nil) или новое местоположение более точное, чем предыдущее, вы переходите к шагу 4. В противном случае вы игнорируете это обновление местоположения.
  4. Вы уже видели эту часть раньше. Он очищает любую предыдущую ошибку и сохраняет новый CLLocationобъект в locationпеременной.
  5. Если точность нового местоположения равна или превышает желаемую точность, вы можете закрыть его на сегодня и перестать запрашивать обновления у менеджера местоположения. Когда вы запустили диспетчер местоположений startLocationManager(), вы установили желаемую точность на 10 метров (kCLLocationAccuracyNearestTenMeters), что достаточно хорошо для этого приложения.

Короткое замыкание

Поскольку location — это необязательный объект, вы не можете получить доступ к его свойствам напрямую — сначала вам нужно его развернуть. Вы можете сделать это с if letпомощью , но если вы уверены, что это не nilтак, вы также можете принудительно развернуть его !.

Вот что вы делаете в этой линии:

if location == nil || location!.horizontalAccuracy > newLocation.horizontalAccuracy {

Вы написали location!.horizontalAccuracy с восклицательным знаком, а не просто location.horizontalAccuracy.

Но что , если location == nil тогда не удастся развернуть силу? Не в этом случае, потому что силовое разворачивание никогда не выполняется.

Оператор || (логическое или) проверяет, истинно ли одно из этих двух условий. Если первое условие истинно (location is nil), оно не будет оценивать второе условие. Это называется коротким замыканием. Приложению нет необходимости проверять второе условие, если первое уже истинно.

Таким образом, приложение будет смотреть только тогдаlocation!.horizontalAccuracy, когда locationгарантированно не будет nil. Сносит тебе крышу, а?

  • Запустите приложение. Сначала установите местоположение симулятора равным None, затем нажмите Get My Location. На экране появилась надпись “Поиск…”.
  • Переключите местоположение на Apple, но больше не нажимайте кнопку «Получить мое местоположение». Через некоторое время экран обновляется с помощью GPS-координат по мере их поступления.

Если вы проверите консоль Xcode, вы получите около 10 обновлений местоположения, прежде чем он скажет: “ * * * Мы закончили!” и обновления местоположения прекратятся.

Примечание: Вполне возможно, что описанные выше шаги не сработают для вас. Если на экране не написано “Поиск…”, а вместо этого показан старый набор координат, то Симулятор сохраняет старые данные о местоположении. Кажется, это происходит, когда вы выбираете местоположение из Xcode, используя стрелку в области отладки вместо меню функций симулятора.

Самый быстрый способ исправить это — выйти из симулятора и запустить приложение снова — это запускает новый симулятор. Если вы не можете заставить его работать, не беспокойтесь, это не так уж важно. Просто имейте в виду, что Симулятор иногда может быть привередливым.

Вы, как разработчик, можете определить с консоли, когда обновление местоположения прекратится, но очевидно, что пользователь этого не увидит.

Кнопка «Местоположение тега» становится видимой, как только получено первое местоположение, так что пользователь может сразу же начать сохранять это местоположение в своей библиотеке, но на данный момент местоположение может быть недостаточно точным.

Поэтому приятно показать пользователю, когда приложение нашло наиболее точное местоположение.

Обновите пользовательский интерфейс

Чтобы сделать это более ясным, вы собираетесь переключить кнопку “Получить мое местоположение”, чтобы сказать “Стоп”, когда захват местоположения активен, и переключить ее обратно на «Получить мое местоположение», когда это будет сделано. Это дает пользователю хорошую визуальную подсказку. Позже вы также покажете анимированный счетчик активности, который сделает это еще более очевидным.

Чтобы изменить состояние кнопки, вы добавите configureGetButton() метод.

  • Добавьте следующий метод в CurrentLocationViewController.swift:

func configureGetButton() { if updatingLocation { getButton.setTitle("Stop", for: .normal) } else { getButton.setTitle("Get My Location", for: .normal) } }

Все очень просто: если приложение в данный момент обновляет местоположение, то заголовок кнопки становится Stop, в противном случае — Get My Location.

Теперь вам нужно позвонить configureGetButton() из нескольких разных мест в вашем коде. Если вы присмотритесь, то заметите , что везде, где вы вызываете updateLabels(), вам также нужно вызвать новый метод. Так что с таким же успехом можно вызвать новый метод изнутри updateLabels(), не так ли?

  • Добавить вызов configureGetButton() в конце updateLabels():
func updateLabels() {
  . . .
  configureGetButton()
}
  • Запустите приложение еще раз и выполните тот же тест, что и раньше. Кнопка меняется на Стоп, когда вы ее нажимаете. Когда больше нет обновлений местоположения, он переключается обратно.

Когда кнопка говорит “Стоп”, вы, естественно, ожидаете, что сможете нажать ее, чтобы прервать обновление местоположения. Это особенно важно, когда вы вообще не получаете никаких координат. В конце концов Core Location может выдать ошибку, но как пользователь вы, возможно, не захотите этого ждать.

Однако в настоящее время нажатие кнопки Stop ничего не останавливает. Вы должны измениться getLocation() для этого, так как любое нажатие на кнопку вызывает этот метод.

  • Войдя в getLocation() систему , замените строку вызовом на startLocationManager()следующую:

if updatingLocation { stopLocationManager() } else { location = nil lastLocationError = nil startLocationManager() }

Опять же, вы используете updatingLocation флаг, чтобы определить, в каком состоянии находится приложение.

Если кнопка нажата, когда приложение уже выполняет выборку местоположения, вы останавливаете диспетчер местоположений.

Обратите внимание, что вы также очищаете старое местоположение и объекты ошибок, прежде чем начать поиск нового местоположения.

BOS Запустите приложение. Теперь нажатие кнопки «Стоп» положит конец обновлениям местоположения. После нажатия кнопки Stop вы больше не увидите обновлений в консоли.

Примечание: Если кнопка «Стоп» появляется недостаточно долго, чтобы вы могли нажать ее, сначала установите значение «Нет», нажмите «Получить мое местоположение» несколько раз, а затем снова выберите местоположение Apple.

Обратное геокодирование

GPS-координаты, с которыми вы до сих пор имели дело, — это просто цифры. Координаты 37.332440904, -122.03051218 на самом деле не так уж много значат, но адрес 1 Infinite Loop в Купертино, штат Калифорния, действительно значит.

Используя процесс, известный как обратное геокодирование, вы можете превратить набор координат в удобочитаемый адрес. Регулярное или “прямое” геокодирование делает обратное: оно превращает адрес в координаты GPS. Вы можете сделать и то, и другое с помощью iOS SDK, но для MyLocations вы будете делать только обратное.

Вы будете использовать CLGeocoderобъект, чтобы превратить данные о местоположении в удобочитаемый адрес, а затем отобразить этот адрес на экране.

Сделать это довольно легко, но есть некоторые правила. Вы не должны посылать тонну этих запросов на обратное геокодирование одновременно. Процесс обратного геокодирования происходит на сервере, размещенном компанией Apple, и обработка этих запросов обходится им в пропускную способность и процессорное время. Если вы завалите их серверы запросами, Apple не обрадуется.

Предполагается, что MyLocations используется только изредка. Таким образом, теоретически его пользователи не будут рассылать спам по серверам Apple, но вы все равно должны ограничить запросы геокодирования одним запросом за раз и по одному разу для каждого уникального местоположения. В конце концов, нет смысла повторно геокодировать один и тот же набор координат снова и снова.

Обратное геокодирование требует активного подключения к Интернету, и все, что вы можете сделать, чтобы предотвратить ненужное использование радиостанций iPhone, хорошо для ваших пользователей.

Осуществление

  • Добавьте следующие свойства в CurrentLocationViewController.swift:

let geocoder = CLGeocoder() var placemark: CLPlacemark? var performingReverseGeocoding = false var lastGeocodingError: Error?

Они отражают то, что вы сделали для менеджера местоположения. CLGeocoder это объект, который будет выполнять геокодирование, и CLPlacemark — это объект, который содержит результаты адреса.

Переменная placemark должна быть необязательной, потому что она не будет иметь никакого значения, когда еще нет местоположения, или когда местоположение не соответствует уличному адресу — я не думаю, что он ответит “Пустыня Сахара, Африка”, но, честно говоря, у меня не было возможности попробовать.

Вы устанавливаете performingReverseGeocoding``trueзначение, когда выполняется операция геокодирования, и lastGeocodingErrorбудете содержать Errorобъект, если что-то пошло не так или nilесли ошибки нет.

Вы поставите геокодер работать в locationManager(didUpdateLocations):

`func locationManager(
_ manager: CLLocationManager,
didUpdateLocations locations: [CLLocation]
) {
. . .
if location == nil || location!.horizontalAccuracy > newLocation.horizontalAccuracy {
. . .
if newLocation.horizontalAccuracy <= locationManager.desiredAccuracy {
. . .
}
updateLabels()
// The new code begins here:
if !performingReverseGeocoding {
print(«*** Going to geocode»)

  performingReverseGeocoding = true

  geocoder.reverseGeocodeLocation(newLocation) {placemarks, error in
    if let error = error {
      print("*** Reverse Geocoding error: \(error.localizedDescription)")
      return
    }
    if let places = placemarks {
      print("*** Found places: \(places)")
    }
  }
}
// End of the new code

}
}`

Приложение должно выполнять только один запрос обратного геокодирования за один раз. Итак, сначала вы проверяете, занят ли он, глядя на performingReverseGeocodingпеременную. Затем вы запускаете геокодер.

Код выглядит достаточно простым, не так ли? Обратите внимание на закрытие в конце вызова reverseGeocodeLocation— это трейлинг-закрытие, похожее на то, что вы видели раньше несколько раз.

Закрытия

В отличие от диспетчера местоположений, CLGeocoderон не использует делегат для возврата результатов операции. Вместо этого он использует замыкание. Закрытие — важная функция Swift, и вы можете ожидать увидеть их повсюду-для программистов Objective-C закрытие похоже на “блок”.

Замыкания также могут иметь параметры, и здесь параметрами для замыкания являются placemarksand error, оба из которых являются опционными, потому что либо одно, либо другое может быть nilв зависимости от ситуации.

Таким образом, хотя весь код внутри замыкания выводит либо список мест, либо ошибку, вам нужно развернуть каждый необязательный параметр, прежде чем сделать это, чтобы убедиться, что у вас есть значение.

В отличие от остальной части кода locationManager(_:didUpdateLocations:), код в закрытии выполняется не сразу. В конце концов, вы можете распечатать результаты геокодирования только после его завершения, а это может произойти через несколько секунд.

Закрытие сохраняется для последующего использования CLGeocoderобъектом и выполняется только после CLGeocoderтого, как найден адрес или обнаружена ошибка.

Так почему же CLGeocoderиспользуется закрытие вместо делегата?

Проблема с использованием делегата для предоставления обратной связи заключается в том, что вам нужно написать один или несколько отдельных методов. Например, для CLLocationManagerсуществуют методы locationManager(_:didUpdateLocations:)и.locationManager(_:didFailWithError:)

Создавая отдельные методы, вы удаляете код, который обрабатывает ответ, от кода, который делает запрос. С другой стороны, с помощью замыканий вы можете поместить этот код обработки в одно и то же место. Это делает код более компактным и легким для чтения. Некоторые API делают и то, и другое, и у вас есть выбор между использованием закрытия или становлением делегатом.

Поэтому, когда вы пишете,

geocoder.reverseGeocodeLocation(newLocation) {placemarks, error in // put your statements here }

вы говорите CLGeocoderобъекту, что хотите выполнить обратное геокодирование местоположения и что код в закрытии должен быть выполнен, как только геокодирование будет завершено.

Само закрытие-это:

{ placemarks, error in // put your statements here }

Элементы перед inключевым словом — placemarksи error— являются параметрами для этого замыкания и работают точно так же, как параметры для метода или функции.

Когда геокодер находит результат для объекта местоположения, который вы ему дали, он вызывает закрытие и выполняет инструкции внутри. placemarksПараметр будет содержать массив CLPlacemarkобъектов, описывающих адресную информацию, а errorпеременная-сообщение об ошибке на случай, если что-то пойдет не так.

Замыкания-это в основном тот же принцип, что и использование методов делегата, за исключением того, что вы помещаете код не в отдельный метод, а в замыкание.

Ничего страшного, если закрытие заставило вас прямо сейчас почесать голову. Вы увидите, как они будут использоваться еще много раз в следующих главах.

BOS Запустите приложение и выберите место. Как только первое местоположение найдено, вы можете увидеть в консоли, что обратный геокодер заработал через секунду или две:

didUpdateLocations <+37.33233141,-122.03121860> +/- 5.00m (speed 0.00 mps / course -1.00) @ 7/24/21, 8:05:35 AM Eastern Daylight Time *** Going to geocode *** Found places: [Apple Campus, Apple Campus, 1 Infinite Loop, Cupertino, CA 95014, United States @ <+37.33233141,-122.03121860> +/- 100.00m, region CLCircularRegion (identifier:'<+37.33213110,-122.02990105> radius 279.38', center:<+37.33213110,-122.02990105>, radius:279.38m)]

Если вы выберете местоположение Apple, то увидите, что некоторые показания местоположения дублируются; геокодер выполняет только первое из них. Только когда точность считывания улучшается, приложение снова меняет геокодирование. Мило!

Примечание: Несколько читателей ранее сообщали, что если вы находитесь в Китае и пытаетесь изменить геокодирование адреса, который находится за пределами Китая, вы можете получить ошибку и placemarksбудете nilею . Если это случится с вами, попробуйте вместо этого найти место в Китае.

Обработка ошибок обратного геокодирования

BOS Замените содержимое замыкания геокодирования следующим:

`self.lastGeocodingError = error
if error == nil, let places = placemarks, !places.isEmpty {
self.placemark = places.last!
} else {
self.placemark = nil
}

self.performingReverseGeocoding = false
self.updateLabels()`

Как и в случае с диспетчером местоположений, вы сохраняете объект error, чтобы ссылаться на него позже — на этот раз вы используете другую переменную экземпляра lastGeocodingError.

Следующая строка делает то, чего вы раньше не видели:

if error == nil, let places = placemarks, !places.isEmpty {

Вы знаете, что if letэто используется для разворачивания опций. Здесь placemarksэто необязательно, поэтому его нужно развернуть, прежде чем вы сможете его использовать, иначе вы рискуете разбить приложение, когда placemarksоно есть nil. Развернутый placemarksмассив получает временное имя places.

!places.isEmptyБит говорит, что мы должны вводить этот ifоператор только в том случае, если массив объектов placemark не пуст.

Вы должны прочитать эту строку так::

if there’s no error and the unwrapped placemarks array is not empty {

Конечно, Свифт не говорит по-английски, поэтому вы должны выразить это в терминах, которые Свифт понимает.

Вы также могли бы написать это как три разных вложенных ifоператора:

if error == nil { if let places = placemarks { if !places.isEmpty {

Но так же легко объединить все эти условия в одно ifцелое .

Здесь вы немного занимаетесь защитным программированием: сначала вы специально проверяете, есть ли в массиве какие-либо объекты. Если ошибки нет, то у него должен быть хотя бы один объект, но вы не будете верить, что он всегда будет. Хорошие разработчики-параноики!

Если все три условия выполнены — ошибки нет, placemarksмассива нет nil, и внутри этого массива есть хотя бы один CLPlacemark— то вы берете последний из этих CLPlacemarkобъектов:

self.placemark = places.last!

lastСвойство ссылается на последний элемент массива. Это необязательно, потому что нет последнего элемента, если массив пуст. В качестве альтернативы вы также можете писатьplaces[places.count - 1], но это не так аккуратно.

Обычно в массиве будет только один CLPlacemarkобъект, но существует странная ситуация, когда одна координата местоположения может ссылаться на несколько адресов. Это приложение может обрабатывать только один адрес за раз. Итак, вы просто выберете последний вариант, который обычно является единственным.

Если во время геокодирования произошла ошибка, вы устанавливаете self.placemarkзначение nil.

Обратите внимание, что вы не сделали этого для местоположений. Если там была ошибка, вы сохранили предыдущий объект location, потому что он действительно может быть правильным или достаточно хорошим, и это лучше, чем ничего.

Но для адреса это имеет меньше смысла. Вы не хотите показывать старый адрес, только адрес, соответствующий текущему местоположению, или вообще никакого адреса.

В мобильной разработке ничто не гарантировано. Вы можете получить координаты обратно, а можете и не получить, а если и получите, то они могут быть не очень точными. Обратное геокодирование, вероятно, будет успешным, если есть какой-то тип доступного сетевого подключения, но вы также должны быть готовы справиться со случаем, когда его нет.

И помните, что не все GPS — координаты соответствуют реальным уличным адресам-в пустыне Сахара нет угла 52-й улицы и Бродвея.

Примечание: Заметили ли вы, что внутри замыкания вы selfссылались на свойства и методы контроллера представления? Это быстрое требование.

Говорят, что замыкания захватывают все переменные, которые они используют, и selfявляются одним из них. Вы можете забыть об этом немедленно, если хотите; просто знайте, что Swift требует, чтобы все захваченные переменные были явно упомянуты.

Как вы уже видели, вне замыкания вы можете selfссылаться на свойства и методы, но это не обязательно. Тем не менее, вы получите ошибку компилятора, если вы оставите selfвнутри закрытия. Так что у вас нет особого выбора.

Отображение адреса

Давайте покажем адрес пользователю.

Изменение наupdateLabels():

func updateLabels() { if let location = location { . . . // Add this block if let placemark = placemark { addressLabel.text = string(from: placemark) } else if performingReverseGeocoding { addressLabel.text = "Searching for Address..." } else if lastGeocodingError != nil { addressLabel.text = "Error Finding Address" } else { addressLabel.text = "No Address Found" } // End new code } else { . . . } }

Поскольку вы выполняете поиск адреса только после того, как приложение имеет действительное местоположение, вам просто нужно изменить код внутри первой ifветви. Если вы нашли адрес, вы показываете его пользователю, в противном случае вы показываете сообщение о состоянии.

Код для форматирования CLPlacemarkобъекта в строку помещается в его собственный метод, просто чтобы код был читабельным.

BOS Добавьте string(from:)метод:

func string(from placemark: CLPlacemark) -> String { // 1 var line1 = "" // 2 if let tmp = placemark.subThoroughfare { line1 += tmp + " " } // 3 if let tmp = placemark.thoroughfare { line1 += tmp } // 4 var line2 = "" if let tmp = placemark.locality { line2 += tmp + " " } if let tmp = placemark.administrativeArea { line2 += tmp + " " } if let tmp = placemark.postalCode { line2 += tmp } // 5 return line1 + "\n" + line2 }

Давайте рассмотрим это подробнее:

  1. Адрес будет состоять из двух строк текста — создайте новую строковую переменную для первой строки текста.
  2. Если метка имеет a subThoroughfare, добавьте ее в строку. Это необязательное свойство, поэтому вы if letсначала разворачиваете его. Просто чтобы вы знали, subThoroughfareэто причудливое название для номера дома.
  3. Добавление названия thoroughfareулицы или названия улицы делается аналогично. Обратите внимание, что вы кладете пространство между ними, subThoroughfareчтобы они не склеивались вместе.
  4. Та же логика применима и ко второй строке текста. При этом добавляется населенный пункт (город), административный район (штат или провинция) и почтовый индекс (или почтовый индекс) с пробелами между ними, где это уместно.
  5. Наконец, две строки объединяются или складываются вместе с символом новой строки между ними. \nДобавляет разрыв строки (или новую строку) в строку.

Войдите getLocation(), очистите переменные placemarkandlastGeocodingError, чтобы начать с чистого листа. Поставьте это прямо над призывом кstartLocationManager():

placemark = nil lastGeocodingError = nil

BOS Запустите приложение еще раз. Через несколько секунд после того, как местоположение найдено, метка адреса также должна быть заполнена.

Обратное геокодирование находит адрес для GPS - координат

Обратное геокодирование находит адрес для GPS — координат

Довольно часто в адресе отсутствуют номера улиц или другие детали. CLPlacemarkОбъект может содержать неполную информацию, поэтому все его свойства являются необязательными. Геокодирование-это не точная наука!

Упражнение: Если вы выберете локации City Bicycle Ride или City Run из меню функций симулятора, вы увидите в консоли, что приложение прыгает через целую кучу разных координат — оно имитирует кого-то, перемещающегося из одного места в другое. Однако координаты на экране и адресная метка меняются не так часто. Почему это так?

Ответ: Логика майлокаций была разработана для того, чтобы найти наиболее точный набор координат для стационарного положения. Вы обновляете locationпеременную только тогда, когда появляется новый набор координат, более точный, чем предыдущие показания. Любые новые показания с более высоким или тем же horizontalAccuracyзначением просто игнорируются, независимо от того, каковы фактические координаты.

С опциями City Bicycle Ride и City Run приложение получает не одни и те же координаты с возрастающей точностью, а серию совершенно разных координат. Это означает, что это приложение не очень хорошо работает, когда вы находитесь в движении, если только вы не нажмете Стоп и не попробуете еще раз. С другой стороны, приложение также не было предназначено для захвата меняющихся местоположений.

Примечание: Если вы играете с разными локациями в симуляторе или из меню отладчика Xcode и застряли, то самый быстрый способ отклеиться — сбросить симулятор. Иногда он просто не хочет переезжать на новое место, даже если вы ему скажете, а потом вы должны показать ему, кто здесь хозяин!

Тестирование на устройстве

Когда я впервые написал этот код, я тестировал его только на симуляторе. Там все работало нормально. Затем я поставил его на свой iPod touch, и знаете что? Не очень хорошо.

Проблема с iPod touch заключается в том, что у него нет GPS, поэтому для определения местоположения он полагается только на Wi-Fi. Но Wi-Fi, возможно, не сможет дать вам точность до десяти метров; в лучшем случае я получу +/- 100 метров.

Прямо сейчас вы останавливаете обновление местоположения только тогда, когда точность считывания попадает в пределах desiredAccuracyзаданной настройки — чего на самом деле никогда не произойдет на моем iPod touch.

Это говорит о том, что вы не всегда можете полагаться на симулятор для тестирования своих приложений. Вам нужно поместить их на свое устройство и протестировать в дикой природе, особенно при использовании зависящих от устройства функций, таких как API-интерфейсы на основе местоположения. Если у вас более одного устройства, то протестируйте их все!

Чтобы справиться с этой ситуацией, вы усовершенствуете метод didUpdateLocationsделегата.

Первое исправление

Изменение наlocationManager(_:didUpdateLocations:):

`func locationManager(
_ manager: CLLocationManager,
didUpdateLocations locations: [CLLocation]
) {
. . .

if newLocation.horizontalAccuracy < 0 {
return
}

// New section #1
var distance = CLLocationDistance(Double.greatestFiniteMagnitude)
if let location = location {
distance = newLocation.distance(from: location)
}
// End of new section #1
if location == nil || location!.horizontalAccuracy > newLocation.horizontalAccuracy {
. . .
if newLocation.horizontalAccuracy <= locationManager.desiredAccuracy { . . . // New section #2 if distance > 0 {
performingReverseGeocoding = false
}
// End of new section #2
}
if !performingReverseGeocoding {
. . .
}
updateLabels()
// New section #3
} else if distance < 1 { let timeInterval = newLocation.timestamp.timeIntervalSince(location!.timestamp) if timeInterval > 10 {
print(«*** Force done!»)
stopLocationManager()
updateLabels()
}
// End of new sectiton #3
}
}`

Сейчас это довольно длинный метод, но были добавлены только три выделенных раздела. Это первый из них:

var distance = CLLocationDistance(Double.greatestFiniteMagnitude) if let location = location { distance = newLocation.distance(from: location) }

Это вычисляет расстояние между новым чтением и предыдущим чтением, если оно было. Мы можем использовать это distanceдля измерения того, улучшаются ли наши обновления местоположения.

Если предыдущего чтения не было, то расстояние есть Double.greatestFiniteMagnitude. Это встроенная константа, представляющая максимальное значение, которое Doubleможет иметь значение. Этот маленький трюк дает ему гигантское расстояние, если это самое первое чтение. Вы делаете это так, чтобы любое из следующих вычислений все еще работало, даже если вы еще не смогли вычислить истинное расстояние.

Вы также добавляете ifоператор позже, когда останавливаете диспетчер местоположений:

if distance > 0 { performingReverseGeocoding = false }

Это приводит к обратному геокодированию конечного местоположения, даже если приложение уже выполняет другой запрос геокодирования.

Вам абсолютно нужен адрес для этого конечного местоположения, так как это самое точное местоположение, которое вы нашли. Но если какое-то предыдущее местоположение все еще подвергалось обратному геокодированию, этот шаг обычно пропускался. Просто установив значение performingReverseGeocodingto false, вы всегда заставляете геокодировать эту конечную координату.

Конечно, если distanceравно 0, то это местоположение совпадает с местоположением из предыдущего чтения, и вам больше не нужно его реверсировать геокодированием.

Реальное улучшение можно найти в последнем новом разделе:

} else if distance < 1 { let timeInterval = newLocation.timestamp.timeIntervalSince(location!.timestamp) if timeInterval > 10 { print("*** Force done!") stopLocationManager() updateLabels() } }

Если координата этого считывания существенно не отличается от предыдущего считывания и прошло более 10 секунд с тех пор, как вы получили это исходное считывание, то самое время повесить шляпу и остановиться.

Можно с уверенностью предположить, что вы не получите лучшей координаты, чем эта, и можете перестать извлекать местоположение.

Это улучшение было необходимо для того, чтобы через некоторое время мой iPod touch перестал сканировать. Он не давал мне местоположения с большей точностью, чем +/- 100 метров, но повторял одно и то же снова и снова.

Я выбрал ограничение по времени в 10 секунд, потому что это, казалось, давало хорошие результаты.

Обратите внимание, что вы не просто говорите:

} else if distance == 0 {

Расстояние между последующими показаниями никогда не бывает точно равно 0. Это может быть что-то вроде 0.0017632. Вместо того чтобы проверять, равно ли 0, лучше проверить, меньше ли определенное расстояние, в данном случае один метр.

Кстати, вы заметили, как вы location!разворачивали его, прежде чем получить доступ к свойству timestamp? Когда вы находитесь внутри этого else-if, значение locationгарантированно неnilбудет, поэтому безопасно принудительно развернуть необязательный параметр.

BOS Запустите приложение и проверьте, что все по-прежнему работает. Возможно, будет трудно воссоздать эту ситуацию на симуляторе, но попробуйте сделать это на своем устройстве внутри дома и посмотрите, какой вывод вы видите в консоли.

Второе исправление

Есть еще одно улучшение, которое вы можете сделать, чтобы повысить надежность этой логики, а именно установить тайм-аут на все это. Вы можете сказать iOS, чтобы она выполнила метод через минуту. Если к этому времени приложение еще не нашло местоположение, вы останавливаете диспетчер местоположений и показываете сообщение об ошибке.

BOS Сначала добавьте новую переменную экземпляра.:

var timer: Timer?

Затем измените наstartLocationManager():

func startLocationManager() { if CLLocationManager.locationServicesEnabled() { . . . timer = Timer.scheduledTimer( timeInterval: 60, target: self, selector: #selector(didTimeOut), userInfo: nil, repeats: false) } }

Новые строки настраивают объект таймера, который отправляет didTimeOutсообщение selfчерез 60 секунд; didTimeOutэто имя метода.

Селектор-это термин, который Objective-C использует для описания имени метода, а #selector()синтаксис-это способ создания селектора в Swift.

Изменение наstopLocationManager():

func stopLocationManager() { if updatingLocation { . . . if let timer = timer { timer.invalidate() } } }

Вы должны отменить таймер в случае, если диспетчер местоположений будет остановлен до того, как сработает тайм-аут. Это происходит, когда достаточно точное местоположение найдено в течение одной минуты после запуска или когда пользователь нажимает кнопку Остановки.

Наконец, добавьте методdidTimeOut():

@objc func didTimeOut() { print("*** Time out") if location == nil { stopLocationManager() lastLocationError = NSError( domain: "MyLocationsErrorDomain", code: 1, userInfo: nil) updateLabels() } }

В этом методе есть что — то новое — раньше был новый @objcатрибутfunc-что бы это могло быть?

Помните, как #selectorвыглядит концепция Objective-C? (Как вы могли забыть, что это было всего несколько абзацев назад, верно?) Таким образом, когда вы используете #selectorдля определения метода вызов, этот метод должен быть доступен не только из Swift, но и из Objective-C. @objcАтрибут позволяет идентифицировать метод — или класс, или свойство, или даже перечисление — как доступный из Objective-C.

Итак, это то, для чего вы сделали didTimeOut— объявили его доступным из Objective-C.

didTimeOut() всегда вызывается через одну минуту, независимо от того, получили ли вы действительное местоположение или нет — если stopLocationManager()только сначала не отменит таймер.

Если после этой минуты действительного местоположения все еще нет, вы останавливаете диспетчер местоположений, создаете свой собственный код ошибки и обновляете экран.

Создавая свой собственный NSErrorобъект и помещая его в переменную lastLocationErrorэкземпляра, вам не нужно менять какую-либо логику updateLabels().

Однако вы должны убедиться, что домен ошибки не kCLErrorDomainпотому, что этот объект ошибки исходит не из основного местоположения, а из вашего собственного приложения.

Домен ошибок — это просто строка, так MyLocationsErrorDomainчто сойдет. Для кода я выбрал 1. На данный момент значение кода не имеет значения, потому что у вас есть только одна пользовательская ошибка, но вы можете себе представить, что когда ваше приложение станет больше, вам может понадобиться несколько кодов ошибок.

Обратите внимание, что вам не всегда нужно использовать NSErrorобъект; есть и другие способы сообщить остальной части вашего кода о том, что произошла ошибка. В этом случае updateLabels()я уже использовал an NSErrorв любом случае, так что наличие собственного объекта error просто имело смысл.

BOS Запустите приложение. Установите для местоположения симулятора значение None и нажмите Get My Location.

Через минуту область отладки должна сказать “*** Тайм-аут”, и кнопка «Стоп» возвращается, чтобы узнать мое местоположение. На экране также должно появиться сообщение об ошибке:

Ошибка после тайм - аута

Ошибка после тайм — аута

Просто получить простое местоположение из Основного местоположения и найти соответствующий уличный адрес оказалось намного сложнее, чем казалось. Есть много разных ситуаций, с которыми нужно справляться. Ничто не гарантировано, и все может пойти не так — разработка iOS иногда требует стальных нервов!

Напомним, что приложение может либо:

  • Найдите местоположение с нужной точностью,
  • Найдите местоположение, которое не так точно, как вам хотелось бы, и не получает более точных показаний,
  • Вообще не находит места,
  • Или слишком долго искать место.

Теперь код обрабатывает все эти ситуации, но я уверен, что он еще не идеален. Без сомнения, логику можно было бы еще подправить, но для целей этой книги она подойдет.

Надеюсь, вам ясно, что если вы выпускаете приложение, основанное на местоположении, вам нужно провести много полевых испытаний!

Необходимые возможности устройства

Вкладка Информация может содержать ключ «Необходимые возможности устройства«, в котором перечислены аппаратные средства, необходимые вашему приложению для запуска. Это ключ, который App Store использует для определения того, может ли пользователь установить ваше приложение на свое устройство.

Если вашему приложению требуются дополнительные функции, такие как Основное местоположение для получения местоположения пользователя, вы должны перечислить их здесь.

  • Выберите вкладку Информация, добавьте новую строку и установите ключ в соответствии с требуемыми возможностями устройства.

Значение нового ключа — это массив. Если вы развернете список элементов массива, то заметите, что по умолчанию он пуст.

BOS Щелкните двуглавую стрелку в конце поля значение для пустого элемента массива, чтобы получить список возможных значений. Выберите Службы определения местоположения из списка:

Добавление геолокационных сервисов в Info.plist

Добавление геолокационных сервисов в Info.plist

Вы также можете добавить GPS, чтобы приложение требовало GPS — приемника. Но если вы это сделаете, пользователи не смогут установить приложение на iPod touch или на некоторые iPad.

P.S. Теперь вы можете вынуть print()утверждения из приложения или просто прокомментировать их. Лично мне нравится держать их там, так как они удобны для отладки. В приложении, которое вы планируете загрузить в App Store, вы обязательно захотите удалить print()операторы по завершении разработки.

Атрибуты и свойства

Большинство атрибутов в инспекторах Interface Builder непосредственно соответствуют свойствам выбранного объекта. Например, a UILabelимеет следующие атрибуты:

Они непосредственно связаны со следующими свойствами:

И так далее… Как вы можете видеть, имена не всегда могут быть точно такими же (“Строки” иnumberOfLines), но вы можете легко выяснить, какое свойство сочетается с каким атрибутом.

Вы можете найти эти свойства в документации для UILabel. В меню Справка Xcode выберите пункт Документация разработчика. Введите “uilabel” в поле поиска, чтобы открыть ссылку на класс для UILabel:

В документации для UILabel не перечислены свойства для всех атрибутов инспекторов. Например, в инспекторе атрибутов есть раздел с именем “Вид”. Атрибуты в этом разделе исходят из UIView того , что является базовым классом UILabel. Поэтому, если вы не можете найти свойство в UILabel классе, вам может потребоваться проверить документацию в разделе “Наследуется от”, который находится в разделе **»Отношения **UILabel» документации.

Описание

Сервис геокодирования портала не смог обработать запрос на создание или публикацию информации в файле CSV.

Решение

Убедитесь, что сервис геокодирования портала запущен.

Проверьте, что информация о местоположениях в файле CSV корректна и может быть геокодирована.

Если функционирование сервиса геокодирования, используемого для геокодирования элемета, обеспечено, убедитесь, что пользователь, который подал запрос, имеет права доступа к сервису геокодирования.


Отзыв по этому разделу?

Понравилась статья? Поделить с друзьями:
  • Ошибка во время запуска помешала игре запустится майнкрафт
  • Ошибка геокодирования спар
  • Ошибка гидравлического контура кофемашина saeco aulika
  • Ошибка генерации сертификата при получении эп
  • Ошибка выдачи репликации 2146893022 0x80090322